Bugzilla – Attachment 132508 Details for
Bug 24975
Refactor database translations
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24975: Refactor database translations
Bug-24975-Refactor-database-translations.patch (text/plain), 125.33 KB, created by
Martin Renvoize (ashimema)
on 2022-03-30 06:37:33 UTC
(
hide
)
Description:
Bug 24975: Refactor database translations
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2022-03-30 06:37:33 UTC
Size:
125.33 KB
patch
obsolete
>From 0254273bc61589d8eaaf778d7594d53378d9f1ee Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Wed, 25 Mar 2020 11:33:26 +0100 >Subject: [PATCH] Bug 24975: Refactor database translations >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >This is an attempt to make the process of translating database strings >(like itemtype descriptions) easier for developers and translators. > >For developers by reducing the amount of code needed to enable >translations for a new kind of object (authorised values, letters, news, >...). >For translators by providing a single entry point for all translatable >strings > >Table `localization` is replaced by two new tables `l10n_source` and >`l10n_target`. `l10n_source` contains the original text while >`l10n_target` contains the corresponding translations > >`l10n_source` is automatically updated whenever an itemtype is >inserted, updated, or deleted, so it is always up to date (this is done >in Koha::Schema::Result::ItemType). >It means that if you delete an itemtype, translations get deleted too. >It also means that if you change an itemtype's description, translations >are lost (not sure if this should be fixed, since if description >changes, translations should probably be changed too) > >It adds a new subroutine in Koha::I18N, `db_t`, which returns the >translation for a given context and string, according to the current >language. Translations are stored in memcached (if enabled). > >So instead of having to declare a new subroutine >Koha::ItemType::translated_description, you can write > db_t('itemtype', $itemtype->description) > >In templates you can write > [% ItemTypes.t(itemtype.description) %] > >There's also a new page, accessible from the administration main page, >"Localization". It displays all translatable strings and allow to >translate them for all enabled languages. > >Test plan: >1. Before applying the patch, make sure you have translated some > itemtypes. Translations should be kept by the updatedatabase script. > Before applying the updatedatabase you may want to comment the > 'DROP TABLE localization' statement if you want to keep this table >2. Apply patch, run updatedatabase.pl, run update_dbix_class_files.pl > and reload starman >3. Go to Admin » Localization, verify that you have your itemtypes and > their translations. >4. Verify that the filter is working (it filters on the source column > only). >5. Translate some strings by clicking on one of the 'Translate' link, > entering some text and clicking on the 'Save' button. You can remove > a translation by emptying the text box. >6. Add a new item type. Verify that it appears in the Localization page >7. Change the description of this item type. Verify that the new > description appears in Localization page and that the old description > is gone >8. Delete this item type and verify that its description no longer > appears in Localization page >9. Navigate through Koha (intranet and opac) in multiple languages and > verify that item types are translated (if not, please verify in > master too, not all occurrences were translated) > >Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> > >https://bugs.koha-community.org/show_bug.cgi?id=24875 >--- > C4/Biblio.pm | 3 +- > C4/Items.pm | 11 +- > C4/Search.pm | 11 +- > Koha/DBIx/Component/L10nSource.pm | 73 ++++ > Koha/I18N.pm | 49 +++ > Koha/ItemType.pm | 51 +-- > Koha/ItemTypes.pm | 31 -- > Koha/Localization.pm | 28 -- > Koha/Localizations.pm | 34 -- > Koha/Schema/Result/Itemtype.pm | 54 ++- > Koha/Schema/Result/ItemtypeLocalization.pm | 32 -- > Koha/Template/Plugin/ItemTypes.pm | 11 +- > acqui/orderreceive.pl | 1 + > admin/itemtypes.pl | 4 +- > admin/localization.pl | 20 - > admin/smart-rules.pl | 32 +- > authorities/authorities.pl | 8 +- > catalogue/getitem-ajax.pl | 3 +- > catalogue/itemsearch.pl | 9 +- > catalogue/moredetail.pl | 7 +- > catalogue/search.pl | 18 +- > cataloguing/addbiblio.pl | 5 +- > cataloguing/additem.pl | 5 + > circ/transferstoreceive.pl | 3 +- > course_reserves/add_items.pl | 2 +- > .../data/mysql/atomicupdate/bug-24975.perl | 48 +++ > installer/data/mysql/kohastructure.sql | 22 ++ > .../prog/en/includes/admin-menu.inc | 1 + > .../prog/en/includes/html_helpers.inc | 3 +- > .../prog/en/modules/admin/admin-home.tt | 3 + > .../prog/en/modules/admin/itemtypes.tt | 6 +- > .../prog/en/modules/admin/localization.tt | 371 ++++++------------ > .../prog/en/modules/admin/smart-rules.tt | 14 +- > .../prog/en/modules/catalogue/advsearch.tt | 3 +- > .../prog/en/modules/catalogue/detail.tt | 5 +- > .../course_reserves/add_items-step2.tt | 5 +- > .../course_reserves/batch_add_items.tt | 2 +- > .../en/modules/reports/acquisitions_stats.tt | 3 +- > .../prog/en/modules/reports/bor_issues_top.tt | 2 +- > .../prog/en/modules/reports/cat_issues_top.tt | 3 +- > .../prog/en/modules/reports/catalogue_out.tt | 3 +- > .../en/modules/reports/catalogue_stats.tt | 3 +- > .../en/modules/reports/issues_avg_stats.tt | 3 +- > .../prog/en/modules/reports/issues_stats.tt | 3 +- > .../prog/en/modules/reports/itemslost.tt | 2 +- > .../prog/en/modules/reports/reserves_stats.tt | 3 +- > .../en/modules/serials/subscription-add.tt | 9 +- > .../modules/serials/subscription-batchedit.tt | 2 +- > .../serials/subscription-bib-search.tt | 3 +- > .../prog/en/modules/tools/export.tt | 3 +- > .../prog/en/modules/virtualshelves/shelves.tt | 3 +- > .../bootstrap/en/includes/opac-topissues.inc | 3 +- > .../en/modules/opac-readingrecord.tt | 3 +- > .../bootstrap/en/modules/opac-reserve.tt | 4 +- > .../bootstrap/en/modules/opac-shelves.tt | 5 +- > labels/label-item-search.pl | 13 - > opac/opac-detail.pl | 9 +- > opac/opac-readingrecord.pl | 5 +- > opac/opac-reserve.pl | 8 +- > opac/opac-search.pl | 14 +- > opac/opac-shelves.pl | 2 +- > opac/opac-user.pl | 2 +- > reports/acquisitions_stats.pl | 2 +- > reports/bor_issues_top.pl | 2 +- > reports/cat_issues_top.pl | 2 +- > reports/catalogue_out.pl | 2 +- > reports/catalogue_stats.pl | 2 +- > reports/issues_avg_stats.pl | 2 +- > reports/issues_stats.pl | 7 +- > reports/itemslost.pl | 2 +- > reports/reserves_stats.pl | 5 +- > reserve/request.pl | 2 +- > serials/subscription-add.pl | 3 +- > serials/subscription-bib-search.pl | 3 +- > svc/bib_profile | 2 +- > svc/checkouts | 3 +- > svc/holds | 3 +- > svc/localization | 129 +++--- > t/db_dependent/Koha/ItemTypes.t | 44 +-- > tools/batchMod.pl | 1 + > tools/export.pl | 2 +- > virtualshelves/shelves.pl | 2 +- > 82 files changed, 593 insertions(+), 728 deletions(-) > create mode 100644 Koha/DBIx/Component/L10nSource.pm > delete mode 100644 Koha/Localization.pm > delete mode 100644 Koha/Localizations.pm > delete mode 100644 Koha/Schema/Result/ItemtypeLocalization.pm > create mode 100644 installer/data/mysql/atomicupdate/bug-24975.perl > >diff --git a/C4/Biblio.pm b/C4/Biblio.pm >index c4de6b064d..807258e2aa 100644 >--- a/C4/Biblio.pm >+++ b/C4/Biblio.pm >@@ -108,6 +108,7 @@ use Koha::Authority::Types; > use Koha::Acquisition::Currencies; > use Koha::Biblio::Metadatas; > use Koha::Holds; >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::MarcOverlayRules; > use Koha::Plugins; >@@ -1447,7 +1448,7 @@ sub GetAuthorisedValueDesc { > #---- itemtypes > if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "itemtypes" ) { > my $itemtype = Koha::ItemTypes->find( $value ); >- return $itemtype ? $itemtype->translated_description : q||; >+ return $itemtype ? db_t('itemtype', $itemtype->description) : q||; > } > > if ( $tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "cn_source" ) { >diff --git a/C4/Items.pm b/C4/Items.pm >index 6fe676814a..4d48aedb1f 100644 >--- a/C4/Items.pm >+++ b/C4/Items.pm >@@ -65,6 +65,7 @@ use Koha::DateUtils qw( dt_from_string output_pref ); > use Koha::Database; > > use Koha::Biblioitems; >+use Koha::I18N; > use Koha::Items; > use Koha::ItemTypes; > use Koha::SearchEngine; >@@ -730,7 +731,6 @@ sub GetItemsInfo { > serial.serialseq, > serial.publisheddate, > itemtypes.description, >- COALESCE( localization.translation, itemtypes.description ) AS translated_description, > itemtypes.notforloan as notforloan_per_itemtype, > holding.branchurl, > holding.branchcode, >@@ -751,14 +751,11 @@ sub GetItemsInfo { > . (C4::Context->preference('item-level_itypes') ? 'items.itype' : 'biblioitems.itemtype'); > $query .= q| > LEFT JOIN tmp_holdsqueue USING (itemnumber) >- LEFT JOIN localization ON itemtypes.itemtype = localization.code >- AND localization.entity = 'itemtypes' >- AND localization.lang = ? > |; > > $query .= " WHERE items.biblionumber = ? ORDER BY home.branchname, items.enumchron, LPAD( items.copynumber, 8, '0' ), items.dateaccessioned DESC" ; > my $sth = $dbh->prepare($query); >- $sth->execute($language, $biblionumber); >+ $sth->execute($biblionumber); > my $i = 0; > my @results; > my $serial; >@@ -1722,11 +1719,11 @@ sub PrepareItemrecordDisplay { > > #----- itemtypes > } elsif ( $subfield->{authorised_value} eq "itemtypes" ) { >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > push @authorised_values, ""; > while ( my $itemtype = $itemtypes->next ) { > push @authorised_values, $itemtype->itemtype; >- $authorised_lib{$itemtype->itemtype} = $itemtype->translated_description; >+ $authorised_lib{$itemtype->itemtype} = db_t('itemtype', $itemtype->description); > } > if ($defaultvalues && $defaultvalues->{'itemtype'}) { > $defaultvalue = $defaultvalues->{'itemtype'}; >diff --git a/C4/Search.pm b/C4/Search.pm >index 85a02bf5a2..3624bbb96c 100644 >--- a/C4/Search.pm >+++ b/C4/Search.pm >@@ -27,6 +27,7 @@ use C4::XSLT qw( XSLTParse4Display ); > use C4::Reserves qw( GetReserveStatus ); > use C4::Charset qw( SetUTF8Flag ); > use Koha::AuthorisedValues; >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Libraries; > use Koha::Logger; >@@ -529,9 +530,7 @@ sub getRecords { > && ref( $itemtypes->{$one_facet} ) eq > "HASH" ) > { >- $facet_label_value = >- $itemtypes->{$one_facet} >- ->{translated_description}; >+ $facet_label_value = db_t('itemtype', $itemtypes->{$one_facet}->{description}); > } > } > >@@ -1652,7 +1651,7 @@ sub searchResults { > my $notforloan_authorised_value = $av->count ? $av->next->authorised_value : undef; > > #Get itemtype hash >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > my %itemtypes = map { $_->{itemtype} => $_ } @{ $itemtypes->unblessed }; > > #search item field code >@@ -1734,7 +1733,7 @@ sub searchResults { > # add imageurl to itemtype if there is one > $oldbiblio->{imageurl} = $itemtype ? getitemtypeimagelocation( $search_context->{'interface'}, $itemtype->{imageurl} ) : q{}; > # Build summary if there is one (the summary is defined in the itemtypes table) >- $oldbiblio->{description} = $itemtype ? $itemtype->{translated_description} : q{}; >+ $oldbiblio->{description} = $itemtype ? db_t('itemtype', $itemtype->{description}) : q{}; > > # Pull out the items fields > my @fields = $marcrecord->field($itemtag); >@@ -1800,7 +1799,7 @@ sub searchResults { > foreach my $code ( keys %subfieldstosearch ) { > $item->{$code} = $field->subfield( $subfieldstosearch{$code} ); > } >- $item->{description} = $itemtypes{ $item->{itype} }{translated_description} if $item->{itype}; >+ $item->{description} = db_t('itemtype', $itemtypes{ $item->{itype} }{description}) if $item->{itype}; > > # OPAC hidden items > if ($is_opac) { >diff --git a/Koha/DBIx/Component/L10nSource.pm b/Koha/DBIx/Component/L10nSource.pm >new file mode 100644 >index 0000000000..9d4ea398d9 >--- /dev/null >+++ b/Koha/DBIx/Component/L10nSource.pm >@@ -0,0 +1,73 @@ >+package Koha::DBIx::Component::L10nSource; >+ >+use Modern::Perl; >+use base 'DBIx::Class'; >+ >+=head1 NAME >+ >+Koha::DBIx::Component::L10nSource >+ >+=head1 SYNOPSIS >+ >+ __PACKAGE__->load_components('+Koha::DBIx::Component::L10nSource') >+ >+ sub insert { >+ my $self = shift; >+ my $result = $self->next::method(@_); >+ my @sources = $self->result_source->resultset->get_column('label')->all; >+ $self->update_l10n_source('somecontext', @sources); >+ return $result; >+ } >+ >+ sub update { >+ my $self = shift; >+ my $is_column_changed = $self->is_column_changed('label'); >+ my $result = $self->next::method(@_); >+ if ($is_column_changed) { >+ my @sources = $self->result_source->resultset->get_column('label')->all; >+ $self->update_l10n_source('somecontext', @sources); >+ } >+ return $result; >+ } >+ >+ sub delete { >+ my $self = shift; >+ my $result = $self->next::method(@_); >+ my @sources = $self->result_source->resultset->get_column('label')->all; >+ $self->update_l10n_source('somecontext', @sources); >+ return $result; >+ } >+ >+=head1 METHODS >+ >+=head2 update_l10n_source >+ >+ $self->update_l10n_source($context, @sources) >+ >+Ensure that all sources in C<@sources>and only them are present in l10n_source >+for a given C<$context> >+ >+=cut >+ >+sub update_l10n_source { >+ my ($self, $context, @sources) = @_; >+ >+ my $l10n_source_rs = $self->result_source->schema->resultset('L10nSource')->search({ context => $context }); >+ >+ # Insert missing l10n_source rows >+ foreach my $source (@sources) { >+ my $count = $l10n_source_rs->search({ source => $source })->count; >+ if ($count == 0) { >+ $l10n_source_rs->create({ source => $source }); >+ } >+ } >+ >+ # Remove l10n_source rows that do not match an existing source >+ my %sources = map { $_ => undef } @sources; >+ my @l10n_sources = grep { !exists $sources{$_->source} } $l10n_source_rs->all; >+ foreach my $l10n_source (@l10n_sources) { >+ $l10n_source->delete; >+ } >+} >+ >+1; >diff --git a/Koha/I18N.pm b/Koha/I18N.pm >index 464911cb2d..8fc0aae957 100644 >--- a/Koha/I18N.pm >+++ b/Koha/I18N.pm >@@ -35,6 +35,8 @@ use Locale::Messages qw( > ); > use POSIX qw(); > use Koha::Cache::Memory::Lite; >+use Koha::Caches; >+use Koha::Database; > > use parent 'Exporter'; > our @EXPORT = qw( >@@ -51,6 +53,8 @@ our @EXPORT = qw( > N__n > N__p > N__np >+ >+ db_t > ); > > our $textdomain = 'Koha'; >@@ -222,4 +226,49 @@ sub _expand { > return $text; > } > >+=head2 db_t >+ >+ db_t($context, $source) >+ db_t('itemtype', $itemtype->description) >+ >+Search for a translation in l10n_target table and return it if found >+Return source string otherwise >+ >+=cut >+ >+sub db_t { >+ my ($context, $source) = @_; >+ >+ my $cache = Koha::Caches->get_instance(); >+ my $language = C4::Languages::getlanguage(); >+ my $cache_key = sprintf('%s:%s', $context, $language); >+ >+ my $translations = $cache->get_from_cache($cache_key); >+ unless ($translations) { >+ my $schema = Koha::Database->new->schema; >+ my $rs = $schema->resultset('L10nTarget'); >+ >+ my @targets = $rs->search( >+ { >+ 'l10n_source.context' => $context, >+ language => $language, >+ }, >+ { >+ join => 'l10n_source', >+ prefetch => 'l10n_source', >+ result_class => 'DBIx::Class::ResultClass::HashRefInflator', >+ }, >+ ); >+ $translations = { map { $_->{l10n_source}->{source} => $_->{translation} } @targets }; >+ >+ $cache->set_in_cache($cache_key, $translations); >+ } >+ >+ if (exists $translations->{$source}) { >+ return $translations->{$source}; >+ } >+ >+ return $source; >+} >+ > 1; >diff --git a/Koha/ItemType.pm b/Koha/ItemType.pm >index 4b77433e8e..9d88c9e004 100644 >--- a/Koha/ItemType.pm >+++ b/Koha/ItemType.pm >@@ -22,7 +22,6 @@ use C4::Koha qw( getitemtypeimagelocation ); > use C4::Languages; > use Koha::Database; > use Koha::CirculationRules; >-use Koha::Localizations; > > use base qw(Koha::Object Koha::Object::Limit::Library); > >@@ -45,50 +44,6 @@ sub image_location { > return C4::Koha::getitemtypeimagelocation( $interface, $self->SUPER::imageurl ); > } > >-=head3 translated_description >- >-=cut >- >-sub translated_description { >- my ( $self, $lang ) = @_; >- if ( my $translated_description = eval { $self->get_column('translated_description') } ) { >- # If the value has already been fetched (eg. from sarch_with_localization), >- # do not search for it again >- # Note: This is a bit hacky but should be fast >- return $translated_description >- ? $translated_description >- : $self->description; >- } >- $lang ||= C4::Languages::getlanguage; >- my $translated_description = Koha::Localizations->search({ >- code => $self->itemtype, >- entity => 'itemtypes', >- lang => $lang >- })->next; >- return $translated_description >- ? $translated_description->translation >- : $self->description; >-} >- >-=head3 translated_descriptions >- >-=cut >- >-sub translated_descriptions { >- my ( $self ) = @_; >- my @translated_descriptions = Koha::Localizations->search( >- { entity => 'itemtypes', >- code => $self->itemtype, >- } >- )->as_list; >- return [ map { >- { >- lang => $_->lang, >- translation => $_->translation, >- } >- } @translated_descriptions ]; >-} >- > =head3 can_be_deleted > > my $can_be_deleted = Koha::ItemType->can_be_deleted(); >@@ -152,15 +107,15 @@ sub parent { > > } > >-=head3 children_with_localization >+=head3 children > > Returns the ItemType objects of the children of this type or undef. > > =cut > >-sub children_with_localization { >+sub children { > my ( $self ) = @_; >- return Koha::ItemTypes->search_with_localization({ parent_type => $self->itemtype }); >+ return Koha::ItemTypes->search({ parent_type => $self->itemtype }); > } > > =head3 type >diff --git a/Koha/ItemTypes.pm b/Koha/ItemTypes.pm >index 13caa648a8..5cc28842b6 100644 >--- a/Koha/ItemTypes.pm >+++ b/Koha/ItemTypes.pm >@@ -31,37 +31,6 @@ Koha::ItemTypes - Koha ItemType Object set class > > =head1 API > >-=head2 Class methods >- >-=cut >- >-=head3 search_with_localization >- >-my $itemtypes = Koha::ItemTypes->search_with_localization >- >-=cut >- >-sub search_with_localization { >- my ( $self, $params, $attributes ) = @_; >- >- my $language = C4::Languages::getlanguage(); >- $Koha::Schema::Result::Itemtype::LANGUAGE = $language; >- $attributes->{order_by} = 'translated_description' unless exists $attributes->{order_by}; >- $attributes->{join} = 'localization'; >- $attributes->{'+select'} = [ >- { >- coalesce => [qw( localization.translation me.description )], >- -as => 'translated_description' >- } >- ]; >- if(defined $params->{branchcode}) { >- my $branchcode = delete $params->{branchcode}; >- $self->search_with_library_limits( $params, $attributes, $branchcode ); >- } else { >- $self->SUPER::search( $params, $attributes ); >- } >-} >- > =head2 Internal methods > > =head3 type >diff --git a/Koha/Localization.pm b/Koha/Localization.pm >deleted file mode 100644 >index 3f698303c4..0000000000 >--- a/Koha/Localization.pm >+++ /dev/null >@@ -1,28 +0,0 @@ >-package Koha::Localization; >- >-# This file is part of Koha. >-# >-# Koha is free software; you can redistribute it and/or modify it >-# under the terms of the GNU General Public License as published by >-# the Free Software Foundation; either version 3 of the License, or >-# (at your option) any later version. >-# >-# Koha is distributed in the hope that it will be useful, but >-# WITHOUT ANY WARRANTY; without even the implied warranty of >-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >-# GNU General Public License for more details. >-# >-# You should have received a copy of the GNU General Public License >-# along with Koha; if not, see <http://www.gnu.org/licenses>. >- >-use Modern::Perl; >- >-use Koha::Database; >- >-use base qw(Koha::Object); >- >-sub _type { >- return 'Localization'; >-} >- >-1; >diff --git a/Koha/Localizations.pm b/Koha/Localizations.pm >deleted file mode 100644 >index 8720334acd..0000000000 >--- a/Koha/Localizations.pm >+++ /dev/null >@@ -1,34 +0,0 @@ >-package Koha::Localizations; >- >-# This file is part of Koha. >-# >-# Koha is free software; you can redistribute it and/or modify it >-# under the terms of the GNU General Public License as published by >-# the Free Software Foundation; either version 3 of the License, or >-# (at your option) any later version. >-# >-# Koha is distributed in the hope that it will be useful, but >-# WITHOUT ANY WARRANTY; without even the implied warranty of >-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >-# GNU General Public License for more details. >-# >-# You should have received a copy of the GNU General Public License >-# along with Koha; if not, see <http://www.gnu.org/licenses>. >- >-use Modern::Perl; >- >-use Koha::Database; >- >-use Koha::Localization; >- >-use base qw(Koha::Objects); >- >-sub _type { >- return 'Localization'; >-} >- >-sub object_class { >- return 'Koha::Localization'; >-} >- >-1; >diff --git a/Koha/Schema/Result/Itemtype.pm b/Koha/Schema/Result/Itemtype.pm >index 1e14063e1d..9aba59a46e 100644 >--- a/Koha/Schema/Result/Itemtype.pm >+++ b/Koha/Schema/Result/Itemtype.pm >@@ -342,22 +342,7 @@ __PACKAGE__->add_columns( > '+automatic_checkin' => { is_boolean => 1 }, > ); > >-# Use the ItemtypeLocalization view to create the join on localization >-our $LANGUAGE; >-__PACKAGE__->has_many( >- "localization" => "Koha::Schema::Result::ItemtypeLocalization", >- sub { >- my $args = shift; >- >- die "no lang specified!" unless $LANGUAGE; >- >- return ({ >- "$args->{self_alias}.itemtype" => { -ident => "$args->{foreign_alias}.code" }, >- "$args->{foreign_alias}.lang" => $LANGUAGE, >- }); >- >- } >-); >+__PACKAGE__->load_components('+Koha::DBIx::Component::L10nSource'); > > sub koha_object_class { > 'Koha::ItemType'; >@@ -366,4 +351,41 @@ sub koha_objects_class { > 'Koha::ItemTypes'; > } > >+sub insert { >+ my $self = shift; >+ >+ my $result = $self->next::method(@_); >+ >+ my @sources = $self->result_source->resultset->get_column('description')->all; >+ $self->update_l10n_source('itemtype', @sources); >+ >+ return $result; >+} >+ >+sub update { >+ my $self = shift; >+ >+ my $is_description_changed = $self->is_column_changed('description'); >+ >+ my $result = $self->next::method(@_); >+ >+ if ($is_description_changed) { >+ my @sources = $self->result_source->resultset->get_column('description')->all; >+ $self->update_l10n_source('itemtype', @sources); >+ } >+ >+ return $result; >+} >+ >+sub delete { >+ my $self = shift; >+ >+ my $result = $self->next::method(@_); >+ >+ my @sources = $self->result_source->resultset->get_column('description')->all; >+ $self->update_l10n_source('itemtype', @sources); >+ >+ return $result; >+} >+ > 1; >diff --git a/Koha/Schema/Result/ItemtypeLocalization.pm b/Koha/Schema/Result/ItemtypeLocalization.pm >deleted file mode 100644 >index d5966128c3..0000000000 >--- a/Koha/Schema/Result/ItemtypeLocalization.pm >+++ /dev/null >@@ -1,32 +0,0 @@ >-package Koha::Schema::Result::ItemtypeLocalization; >- >-use base 'DBIx::Class::Core'; >- >-use Modern::Perl; >- >-__PACKAGE__->table_class('DBIx::Class::ResultSource::View'); >- >-__PACKAGE__->table('itemtype_localizations'); >-__PACKAGE__->result_source_instance->is_virtual(1); >-__PACKAGE__->result_source_instance->view_definition( >- "SELECT localization_id, code, lang, translation FROM localization WHERE entity='itemtypes'" >-); >- >-__PACKAGE__->add_columns( >- "localization_id", >- { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, >- "code", >- { data_type => "varchar", is_nullable => 0, size => 64 }, >- "lang", >- { data_type => "varchar", is_nullable => 0, size => 25 }, >- "translation", >- { data_type => "text", is_nullable => 1 }, >-); >- >-__PACKAGE__->belongs_to( >- "itemtype", >- "Koha::Schema::Result::Itemtype", >- { code => 'itemtype' } >-); >- >-1; >diff --git a/Koha/Template/Plugin/ItemTypes.pm b/Koha/Template/Plugin/ItemTypes.pm >index 5b3cf1edeb..6239473ea5 100644 >--- a/Koha/Template/Plugin/ItemTypes.pm >+++ b/Koha/Template/Plugin/ItemTypes.pm >@@ -22,6 +22,7 @@ use Modern::Perl; > use Template::Plugin; > use base qw( Template::Plugin ); > >+use Koha::I18N; > use Koha::ItemTypes; > > sub GetDescription { >@@ -30,11 +31,17 @@ sub GetDescription { > return q{} unless $itemtype; > my $parent; > $parent = $itemtype->parent if $want_parent; >- return $parent ? $parent->translated_description . "->" . $itemtype->translated_description : $itemtype->translated_description; >+ return $parent ? $self->t($parent->description) . "->" . $self->t($itemtype->description) : $self->t($itemtype->description); > } > > sub Get { >- return Koha::ItemTypes->search_with_localization->unblessed; >+ return Koha::ItemTypes->search->unblessed; >+} >+ >+sub t { >+ my ($self, $description) = @_; >+ >+ return db_t('itemtype', $description); > } > > 1; >diff --git a/acqui/orderreceive.pl b/acqui/orderreceive.pl >index e1b76d3273..1f0243527a 100755 >--- a/acqui/orderreceive.pl >+++ b/acqui/orderreceive.pl >@@ -74,6 +74,7 @@ use Koha::Acquisition::Booksellers; > use Koha::Acquisition::Currencies qw( get_active ); > use Koha::Acquisition::Orders; > use Koha::DateUtils qw( dt_from_string ); >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Patrons; > >diff --git a/admin/itemtypes.pl b/admin/itemtypes.pl >index 44e9ad5445..6063348b9e 100755 >--- a/admin/itemtypes.pl >+++ b/admin/itemtypes.pl >@@ -32,7 +32,6 @@ use C4::Auth qw( get_template_and_user ); > use C4::Output qw( output_html_with_http_headers ); > use Koha::ItemTypes; > use Koha::ItemType; >-use Koha::Localizations; > > my $input = CGI->new; > my $searchfield = $input->param('description'); >@@ -60,7 +59,6 @@ if ( $op eq 'add_form' ) { > my $parent_types = Koha::ItemTypes->search({parent_type=>undef,itemtype => {'!='=>$itemtype_code}}); > my $imagesets = C4::Koha::getImageSets( checked => ( $itemtype ? $itemtype->imageurl : undef ) ); > my $searchcategory = GetAuthorisedValues("ITEMTYPECAT"); >- my $translated_languages = C4::Languages::getTranslatedLanguages( "both", C4::Context->preference('template') ); > $template->param( > itemtype => $itemtype, > parent_type => $parent_type, >@@ -68,7 +66,7 @@ if ( $op eq 'add_form' ) { > is_a_parent => $itemtype ? Koha::ItemTypes->search({parent_type=>$itemtype_code})->count : 0, > imagesets => $imagesets, > searchcategory => $searchcategory, >- can_be_translated => ( scalar(@$translated_languages) > 1 ? 1 : 0 ), >+ branches_loop => \@branches_loop, > ); > } elsif ( $op eq 'add_validate' ) { > my $is_a_modif = $input->param('is_a_modif'); >diff --git a/admin/localization.pl b/admin/localization.pl >index 58205d8df7..61fd116c05 100755 >--- a/admin/localization.pl >+++ b/admin/localization.pl >@@ -21,9 +21,6 @@ use Modern::Perl; > use C4::Auth qw( get_template_and_user ); > use C4::Output qw( output_html_with_http_headers ); > >-use Koha::Localization; >-use Koha::Localizations; >- > use CGI qw( -utf8 ); > > my $query = CGI->new; >@@ -36,27 +33,10 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > } > ); > >-my $entity = $query->param('entity'); >-my $code = $query->param('code'); >-my $rs = Koha::Localizations->search( { entity => $entity, code => $code } ); >-my @translations; >-while ( my $s = $rs->next ) { >- push @translations, >- { id => $s->localization_id, >- entity => $s->entity, >- code => $s->code, >- lang => $s->lang, >- translation => $s->translation, >- }; >-} >- > my $translated_languages = C4::Languages::getTranslatedLanguages( 'intranet', C4::Context->preference('template') ); > > $template->param( >- translations => \@translations, > languages => $translated_languages, >- entity => $entity, >- code => $code, > ); > > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/admin/smart-rules.pl b/admin/smart-rules.pl >index b7f2ae643e..979f59d784 100755 >--- a/admin/smart-rules.pl >+++ b/admin/smart-rules.pl >@@ -671,7 +671,7 @@ $template->param( > > my $patron_categories = Koha::Patron::Categories->search({}, { order_by => ['description'] }); > >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > > my $humanbranch = ( $branch ne '*' ? $branch : undef ); > >@@ -698,36 +698,6 @@ output_html_with_http_headers $input, $cookie, $template->output; > > exit 0; > >-# sort by patron category, then item type, putting >-# default entries at the bottom >-sub by_category_and_itemtype { >- unless (by_category($a, $b)) { >- return by_itemtype($a, $b); >- } >-} >- >-sub by_category { >- my ($a, $b) = @_; >- if ($a->{'default_humancategorycode'}) { >- return ($b->{'default_humancategorycode'} ? 0 : 1); >- } elsif ($b->{'default_humancategorycode'}) { >- return -1; >- } else { >- return $a->{'humancategorycode'} cmp $b->{'humancategorycode'}; >- } >-} >- >-sub by_itemtype { >- my ($a, $b) = @_; >- if ($a->{default_translated_description}) { >- return ($b->{'default_translated_description'} ? 0 : 1); >- } elsif ($b->{'default_translated_description'}) { >- return -1; >- } else { >- return lc $a->{'translated_description'} cmp lc $b->{'translated_description'}; >- } >-} >- > sub strip_non_numeric { > my $string = shift; > $string =~ s/\s//g; >diff --git a/authorities/authorities.pl b/authorities/authorities.pl >index 3b4a5d64be..8a8f650378 100755 >--- a/authorities/authorities.pl >+++ b/authorities/authorities.pl >@@ -32,6 +32,7 @@ use MARC::File::XML; > use C4::Biblio qw( TransformHtmlToMarc ); > use Koha::Authority::Types; > use Koha::ItemTypes; >+use Koha::I18N; > use vars qw( $tagslib); > use vars qw( $authorised_values_sth); > use vars qw( $is_a_modif ); >@@ -81,10 +82,13 @@ sub build_authorized_values_list { > } > } > elsif ( $category eq "itemtypes" ) { >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > while ( my $itemtype = $itemtypes->next ) { >+ push @authorised_values, "" >+ unless ( $tagslib->{$tag}->{$subfield}->{mandatory} >+ && ( $value || $tagslib->{$tag}->{$subfield}->{defaultvalue} ) ); > push @authorised_values, $itemtype->itemtype; >- $authorised_lib{$itemtype->itemtype} = $itemtype->translated_description; >+ $authorised_lib{$itemtype->itemtype} = db_t('itemtype', $itemtype->description); > } > } > else { # "true" authorised value >diff --git a/catalogue/getitem-ajax.pl b/catalogue/getitem-ajax.pl >index 9dad680e0c..43e5a0945c 100755 >--- a/catalogue/getitem-ajax.pl >+++ b/catalogue/getitem-ajax.pl >@@ -27,6 +27,7 @@ use C4::Output qw( output_with_http_headers ); > use Koha::Libraries; > > use Koha::AuthorisedValues; >+use Koha::I18N; > use Koha::Items; > use Koha::ItemTypes; > >@@ -75,7 +76,7 @@ if($itemnumber) { > > my $itemtype = Koha::ItemTypes->find( $item->effective_itemtype ); > # We should not do that here, but call ->itemtype->description when needed instea >- $item_unblessed->{itemtype} = $itemtype->description; # FIXME Should not it be translated_description? >+ $item_unblessed->{itemtype} = db_t('itemtype', $itemtype->description); > } > > my $json_text = to_json( $item_unblessed, { utf8 => 1 } ); >diff --git a/catalogue/itemsearch.pl b/catalogue/itemsearch.pl >index e18524307c..e632f0a8c8 100755 >--- a/catalogue/itemsearch.pl >+++ b/catalogue/itemsearch.pl >@@ -28,6 +28,7 @@ use C4::Koha qw( GetAuthorisedValues ); > > use Koha::AuthorisedValues; > use Koha::Biblios; >+use Koha::I18N; > use Koha::Item::Search::Field qw(GetItemSearchFields); > use Koha::ItemTypes; > use Koha::Libraries; >@@ -277,7 +278,13 @@ if ( defined $format ) { > # Display the search form > > my @branches = map { value => $_->branchcode, label => $_->branchname }, Koha::Libraries->search( {}, { order_by => 'branchname' } )->as_list; >-my @itemtypes = map { value => $_->itemtype, label => $_->translated_description }, Koha::ItemTypes->search_with_localization->as_list; >+my @itemtypes; >+foreach my $itemtype ( Koha::ItemTypes->search->as_list ) { >+ push @itemtypes, { >+ value => $itemtype->itemtype, >+ label => db_t('itemtype', $itemtype->description), >+ }; >+} > > my @ccodes = Koha::AuthorisedValues->get_descriptions_by_koha_field({ kohafield => 'items.ccode' }); > foreach my $ccode (@ccodes) { >diff --git a/catalogue/moredetail.pl b/catalogue/moredetail.pl >index cff2460a27..50d1dc8ae7 100755 >--- a/catalogue/moredetail.pl >+++ b/catalogue/moredetail.pl >@@ -36,6 +36,7 @@ use Koha::AuthorisedValues; > use Koha::Biblios; > use Koha::Items; > use Koha::Patrons; >+use Koha::I18N; > > my $query=CGI->new; > >@@ -142,9 +143,9 @@ my $ccodes = > my $copynumbers = > { map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => $fw, kohafield => 'items.copynumber' } ) }; > >-my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > >-$data->{'itemtypename'} = $itemtypes->{ $data->{'itemtype'} }->{'translated_description'} >+$data->{'itemtypename'} = db_t('itemtype', $itemtypes->{ $data->{'itemtype'} }->{description}); > if $data->{itemtype} && exists $itemtypes->{ $data->{itemtype} }; > foreach ( keys %{$data} ) { > $template->param( "$_" => defined $data->{$_} ? $data->{$_} : '' ); >@@ -154,7 +155,7 @@ foreach ( keys %{$data} ) { > foreach my $item (@items){ > $item->{object} = Koha::Items->find( $item->{itemnumber} ); > $item->{'collection'} = $ccodes->{ $item->{ccode} } if $ccodes && $item->{ccode} && exists $ccodes->{ $item->{ccode} }; >- $item->{'itype'} = $itemtypes->{ $item->{'itype'} }->{'translated_description'} if exists $itemtypes->{ $item->{'itype'} }; >+ $item->{'itype'} = db_t('itemtype', $itemtypes->{ $item->{'itype'} }->{description}) if exists $itemtypes->{ $item->{'itype'} }; > $item->{'replacementprice'} = $item->{'replacementprice'}; > if ( defined $item->{'copynumber'} ) { > $item->{'displaycopy'} = 1; >diff --git a/catalogue/search.pl b/catalogue/search.pl >index ef7f49088f..1f102a45ed 100755 >--- a/catalogue/search.pl >+++ b/catalogue/search.pl >@@ -156,6 +156,7 @@ use Koha::SearchEngine::Search; > use Koha::SearchEngine::QueryBuilder; > use Koha::Virtualshelves; > use Koha::SearchFields; >+use Koha::I18N; > > use URI::Escape; > >@@ -502,7 +503,7 @@ my $facets; # this object stores the faceted results that display on the left-ha > my $results_hashref; > > eval { >- my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > ( $error, $results_hashref, $facets ) = $searcher->search_compat( > $query, $simple_query, \@sort_by, \@servers, > $results_per_page, $offset, undef, $itemtypes, >@@ -729,7 +730,14 @@ sub prepare_adv_search_types { > # the index parameter is different for item-level itemtypes > my $itype_or_itemtype = > ( C4::Context->preference("item-level_itypes") ) ? 'itype' : 'itemtype'; >- my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes = { >+ map { >+ $_->{itemtype} => { >+ %$_, >+ description => db_t( 'itemtype', $_->{description} ), >+ } >+ } @{ Koha::ItemTypes->search->unblessed } >+ }; > > my ( $cnt, @result ); > foreach my $advanced_srch_type (@advanced_search_types) { >@@ -741,8 +749,8 @@ sub prepare_adv_search_types { > my @itypesloop; > foreach my $thisitemtype ( > sort { >- $itemtypes->{$a}->{'translated_description'} >- cmp $itemtypes->{$b}->{'translated_description'} >+ $itemtypes->{$a}->{'description'} >+ cmp $itemtypes->{$b}->{'description'} > } keys %$itemtypes > ) > { >@@ -750,7 +758,7 @@ sub prepare_adv_search_types { > number => $cnt++, > ccl => "$itype_or_itemtype,phr", > code => $thisitemtype, >- description => $itemtypes->{$thisitemtype}->{'translated_description'}, >+ description => $itemtypes->{$thisitemtype}->{'description'}, > imageurl => getitemtypeimagelocation( > 'intranet', $itemtypes->{$thisitemtype}->{'imageurl'} > ), >diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl >index 036764417c..560e55aa44 100755 >--- a/cataloguing/addbiblio.pl >+++ b/cataloguing/addbiblio.pl >@@ -56,6 +56,7 @@ use Koha::Patrons; > use MARC::File::USMARC; > use MARC::File::XML; > use URI::Escape qw( uri_escape_utf8 ); >+use Koha::I18N; > > if ( C4::Context->preference('marcflavour') eq 'UNIMARC' ) { > MARC::File::XML->default_record_format('UNIMARC'); >@@ -192,10 +193,10 @@ sub build_authorized_values_list { > push @authorised_values, ""; > > my $itemtype; >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > while ( $itemtype = $itemtypes->next ) { > push @authorised_values, $itemtype->itemtype; >- $authorised_lib{$itemtype->itemtype} = $itemtype->translated_description; >+ $authorised_lib{$itemtype->itemtype} = db_t('itemtype', $itemtype->description); > } > $value = $itemtype unless ($value); > } >diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl >index 1ad9edb503..c9c2cf0355 100755 >--- a/cataloguing/additem.pl >+++ b/cataloguing/additem.pl >@@ -37,6 +37,7 @@ use C4::Circulation qw( barcodedecode LostItem ); > use C4::Barcodes; > use C4::Barcodes::ValueBuilder; > use Koha::DateUtils qw( dt_from_string ); >+use Koha::I18N; > use Koha::Items; > use Koha::ItemTypes; > use Koha::Libraries; >@@ -92,6 +93,10 @@ if( $input->param('itemnumber') && !$input->param('biblionumber') ){ > > my $biblio = Koha::Biblios->find($biblionumber); > >+my $input = new CGI; >+my $error = $input->param('error'); >+my $biblionumber = $input->param('biblionumber'); >+my $itemnumber = $input->param('itemnumber'); > my $op = $input->param('op') || q{}; > my $hostitemnumber = $input->param('hostitemnumber'); > my $marcflavour = C4::Context->preference("marcflavour"); >diff --git a/circ/transferstoreceive.pl b/circ/transferstoreceive.pl >index 939891211d..d2daa3b539 100755 >--- a/circ/transferstoreceive.pl >+++ b/circ/transferstoreceive.pl >@@ -28,6 +28,7 @@ use C4::Members; > use Date::Calc qw( Add_Delta_Days Date_to_Days Today ); > > use C4::Reserves; >+use Koha::I18N; > use Koha::Items; > use Koha::ItemTypes; > use Koha::Libraries; >@@ -87,7 +88,7 @@ while ( my $library = $libraries->next ) { > my $itemtype = Koha::ItemTypes->find( $item->effective_itemtype ); > > $getransf{'datetransfer'} = $num->{'datesent'}; >- $getransf{'itemtype'} = $itemtype->description; # FIXME Should not it be translated_description? >+ $getransf{'itemtype'} = db_t('itemtype', $itemtype->description); > %getransf = ( > %getransf, > title => $biblio->title, >diff --git a/course_reserves/add_items.pl b/course_reserves/add_items.pl >index 10b74a40cc..2a36736ca2 100755 >--- a/course_reserves/add_items.pl >+++ b/course_reserves/add_items.pl >@@ -98,7 +98,7 @@ if ( $action eq 'lookup' and $item ) { > > ccodes => GetAuthorisedValues('CCODE'), > locations => GetAuthorisedValues('LOC'), >- itypes => $itemtypes, # FIXME We certainly want to display the translated_description in the template >+ itypes => $itemtypes, > return => $return, > ); > >diff --git a/installer/data/mysql/atomicupdate/bug-24975.perl b/installer/data/mysql/atomicupdate/bug-24975.perl >new file mode 100644 >index 0000000000..748b9b7b8f >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug-24975.perl >@@ -0,0 +1,48 @@ >+$DBversion = 'XXX'; >+if( CheckVersion( $DBversion ) ) { >+ $dbh->do(q{ >+ CREATE TABLE IF NOT EXISTS l10n_source ( >+ l10n_source_id INT(11) NOT NULL AUTO_INCREMENT, >+ context VARCHAR(100) NULL DEFAULT NULL, >+ source TEXT NOT NULL, >+ PRIMARY KEY (l10n_source_id), >+ KEY context_source (context, source(60)) >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; >+ }); >+ >+ $dbh->do(q{ >+ CREATE TABLE IF NOT EXISTS l10n_target ( >+ l10n_target_id INT(11) NOT NULL AUTO_INCREMENT, >+ l10n_source_id INT(11) NOT NULL, >+ language VARCHAR(10) NOT NULL, >+ translation TEXT NOT NULL, >+ PRIMARY KEY (l10n_target_id), >+ UNIQUE KEY l10n_source_language (l10n_source_id, language), >+ FOREIGN KEY l10n_source (l10n_source_id) REFERENCES l10n_source (l10n_source_id) >+ ON DELETE CASCADE ON UPDATE CASCADE >+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; >+ }); >+ >+ # Populate l10n_source and l10n_target for itemtypes >+ $dbh->do(q{ >+ INSERT INTO l10n_source (context, source) >+ SELECT DISTINCT 'itemtype', description FROM itemtypes >+ }); >+ >+ if (TableExists('localization')) { >+ $dbh->do(q{ >+ INSERT INTO l10n_target (l10n_source_id, language, translation) >+ SELECT DISTINCT l10n_source_id, lang, translation >+ FROM localization >+ JOIN itemtypes ON (localization.code = itemtypes.itemtype) >+ JOIN l10n_source ON (itemtypes.description = l10n_source.source AND l10n_source.context = 'itemtype') >+ WHERE entity = 'itemtypes' >+ }); >+ >+ $dbh->do('DROP TABLE localization'); >+ } >+ >+ >+ SetVersion( $DBversion ); >+ print "Upgrade to $DBversion done (Bug 24975 - l10n_source, l10n_target)\n"; >+} >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 69b3613963..9cf2214776 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -3203,6 +3203,28 @@ CREATE TABLE `keyboard_shortcuts` ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; > /*!40101 SET character_set_client = @saved_cs_client */; > >+ >+DROP TABLE IF EXISTS l10n_source; >+CREATE TABLE l10n_source ( >+ l10n_source_id INT(11) NOT NULL AUTO_INCREMENT, >+ context VARCHAR(100) NULL DEFAULT NULL, >+ source TEXT NOT NULL, >+ PRIMARY KEY (l10n_source_id), >+ KEY context_source (context, source(60)) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; >+ >+DROP TABLE IF EXISTS l10n_target; >+CREATE TABLE l10n_target ( >+ l10n_target_id INT(11) NOT NULL AUTO_INCREMENT, >+ l10n_source_id INT(11) NOT NULL, >+ language VARCHAR(10) NOT NULL, >+ translation TEXT NOT NULL, >+ PRIMARY KEY (l10n_target_id), >+ UNIQUE KEY l10n_source_language (l10n_source_id, language), >+ FOREIGN KEY l10n_source (l10n_source_id) REFERENCES l10n_source (l10n_source_id) >+ ON DELETE CASCADE ON UPDATE CASCADE >+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; >+ > -- > -- Table structure for table `language_descriptions` > -- >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >index b6992f86d8..238f13ebf8 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc >@@ -166,6 +166,7 @@ > [% IF ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts ) %] > <li><a href="/cgi-bin/koha/admin/adveditorshortcuts.pl">Keyboard shortcuts</a></li> > [% END %] >+ <li><a href="/cgi-bin/koha/admin/localization.pl">Localization</a></li> > </ul> > [% END %] > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >index 4f4f461e0e..df3b1f7aed 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc >@@ -1,3 +1,4 @@ >+[% USE ItemTypes %] > [% BLOCK options_for_libraries %] > [% FOREACH l IN libraries %] > [% IF l.selected %] >@@ -64,7 +65,7 @@ > [% ELSE %] > <option value="[% itemtype.itemtype | html %]"> > [% END %] >- [% itemtype.translated_description | html %] >+ [% ItemTypes.t(itemtype.description) | html %] > </option> > [% END %] > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index afdae6c399..20c1052088 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -268,6 +268,9 @@ > <dt><a href="/cgi-bin/koha/admin/adveditorshortcuts.pl">Keyboard shortcuts</a></dt> > <dd>Define which keys trigger actions in the advanced cataloging editor</dd> > [% END %] >+ >+ <dt><a href="/cgi-bin/koha/admin/localization.pl">Localization</a></dt> >+ <dd>Translate user-defined strings</dd> > </dl> > [% END %] > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt >index d395f946b7..0553bed1d7 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt >@@ -1,5 +1,6 @@ > [% USE raw %] > [% USE Asset %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE Branches %] > [% USE AuthorisedValues %] >@@ -200,9 +201,6 @@ Item types › Administration › Koha > <li> > <label for="description" class="required">Description: </label> > <input type="text" id="description" name="description" size="48" value="[% itemtype.description | html %]" required="required" /> <span class="required">Required</span> >- [% IF can_be_translated %] >- <a href="/cgi-bin/koha/admin/localization.pl?entity=itemtypes&code=[% itemtype.itemtype | uri %]" title="Translate item type [% itemtype.itemtype | html %]" rel="gb_page_center[600,500]"><i class="fa fa-pencil"></i> Translate into other languages</a> >- [% END %] > </li> > <li> > <label for="searchcategory">Search category: </label> >@@ -443,7 +441,7 @@ Item types › Administration › Koha > <th scope="row">Item type</th> > <td>[% itemtype.itemtype | html %]</td> > </tr> >- <tr><th scope="row">Description</th><td>[% itemtype.translated_description | html %]</td></tr> >+ <tr><th scope="row">Description</th><td>[% ItemTypes.t(itemtype.description) | html %]</td></tr> > [% UNLESS Koha.Preference('noItemTypeImages') && Koha.Preference('OpacNoItemTypeImages') %] > <tr> > <th scope="row">Image</th> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt >index 2f8522a451..1cde049e10 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt >@@ -1,277 +1,162 @@ >-[% USE raw %] >-[% USE Asset %] >+[% USE JSON.Escape %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Localization › Koha</title> >-[% INCLUDE 'doc-head-close.inc' popup => 1 %] >-<style>#localization { margin-top: 1em; }</style> >+[% INCLUDE 'doc-head-close.inc' %] >+<style> >+ #localization { margin-top: 1em; } >+ >+ .add-translation-block { >+ margin-bottom: 5px; >+ } >+ >+ .add-translation-block form { >+ display: inline-flex; >+ align-items: center; >+ } >+ code { >+ background-color: lightgrey; >+ font-weight: bold; >+ display: inline-block; >+ padding: 2px 4px; >+ } >+</style> > </head> > > <body id="admin_localization" class="admin"> >- <div class="container-fluid"> >- <div class="row"> >- <div class="col-sm-12"> >-<form id="add_translation" method="post"> >- <input type="hidden" name="entity" value="[% entity | html %]" /> >- <input type="hidden" name="code" value="[% code | html %]" /> >- <input type="hidden" name="interface" value="[% interface_side | html %]" /> >- <fieldset class="rows clearfix"> >- <ol> >- <li> >- <span class="label">Authorized value:</span> >- [% code | html %] >- </li> >- <li> >- <label for="lang">Language:</label> >- <select name="lang" id="lang"> >- [% FOR language IN languages %] >- [% FOR sublanguage IN language.sublanguages_loop %] >- [% IF language.plural %] >- <option value="[% sublanguage.rfc4646_subtag | html %]">[% sublanguage.native_description | html %] [% sublanguage.region_description | html %] ([% sublanguage.rfc4646_subtag | html %])</option> >- [% ELSE %] >- <option value="[% sublanguage.rfc4646_subtag | html %]">[% sublanguage.native_description | html %] ([% sublanguage.rfc4646_subtag | html %])</option> >- [% END %] >- [% END %] >- [% END %] >- </select> >- </li> >- <li> >- <label for="translation">Translation:</label> >- <input type="text" size="40" name="translation" id="translation" /> >- </li> >- <li> >- <span class="label"> </span> >- <input type="submit" value="Add" /> >- </li> >- </ol> >- </fieldset> >-</form> >- </div> <!-- /.col-sm-12 --> >- </div> <!-- /.row --> >+ [% INCLUDE 'header.inc' %] >+ [% INCLUDE 'prefs-admin-search.inc' %] > >- <div class="row"> >- <div class="col-sm-12"> >-<div id="messages"></div> >- </div> <!-- /.col-sm-12 --> >- </div> <!-- /.row --> >+ <div id="breadcrumbs"> >+ <a href="/cgi-bin/koha/mainpage.pl">Home</a> >+ › >+ <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> >+ › >+ Localization >+ </div> >+ >+ <div class="main container-fluid"> > > <div class="row"> >- <div class="col-sm-12"> >-<table id="localization"> >- <thead> >- <tr> >- <th>Id</th> >- <th>Entity</th> >- <th>Code</th> >- <th>Language</th> >- <th>Translation</th> >- <th class="NoSort"> </th> >- </tr> >- </thead> >- <tbody> >- [% FOR t IN translations %] >- <tr id="row_id_[% t.id | html %]" data-id="[% t.id | html %]"> >- <td>[% t.id | html %]</td> >- <td>[% t.entity | html %]</td> >- <td>[% t.code | html %]</td> >- <td class="lang">[% t.lang | html %]</td> >- <td class="translation" contenteditable="true">[% t.translation | html %]</td> >- <td class="actions"><a href="#" class="delete"><i class="fa fa-trash"></i> Delete</a></td> >- </tr> >- [% END %] >- </tbody> >-</table> >- </div> <!-- /.col-sm-12 --> >- </div> <!-- /.row --> >- </div> <!-- /.container-fluid --> >+ <div class="col-sm-10 col-sm-push-2"> >+ <main> >+ <h2>Localization</h2> >+ >+ <table id="localization"> >+ <thead> >+ <tr> >+ <th>Context</th> >+ <th>Source</th> >+ <th>Translations</th> >+ </tr> >+ </thead> >+ <tbody> >+ </tbody> >+ </table> >+ </main> >+ </div> >+ >+ <div class="col-sm-2 col-sm-pull-10"> >+ <aside> >+ [% INCLUDE 'admin-menu.inc' %] >+ </aside> >+ </div> >+ </div> >+ </div> > > [% MACRO jsinclude BLOCK %] > [% INCLUDE 'datatables.inc' %] > <script> > >- function show_message( params ) { >- var type = params.type; >- var data = params.data; >- var messages = $("#messages"); >- var message; >- if ( type == 'success_on_update' ) { >- message = $('<div class="dialog message"></div>'); >- message.text(_("Entity %s (code %s) for lang %s has correctly been updated with '%s'").format(data.entity, data.code, data.lang, data.translation)); >- } else if ( type == 'error_on_update' ) { >- message = $('<div class="dialog alert"></div>'); >- if ( data.error_code == 'already_exists' ) { >- message.text(_("A translation already exists for this language.")); >- } else { >- message.text(_("An error occurred when updating this translation.")); >- } >- } else if ( type == 'success_on_delete' ) { >- message = $('<div class="dialog message"></div>'); >- message.text(_("The translation (id %s) has been removed successfully").format(data.id)); >- } else if ( type == 'error_on_delete' ) { >- message = $('<div class="dialog alert"></div>'); >- message.text(_("An error occurred when deleting this translation")); >- } else if ( type == 'success_on_insert' ) { >- message = $('<div class="dialog message"></div>'); >- message.text(_("Translation (id %s) has been added successfully").format(data.id)); >- } else if ( type == 'error_on_insert' ) { >- message = $('<div class="dialog alert"></div>'); >- if ( data.error_code == 'already_exists' ) { >- message.text(_("A translation already exists for this language.")); >- } else { >- message.text(_("An error occurred when adding this translation")); >- } >- } >- >- $(messages).append(message); >- >- setTimeout(function(){ >- message.hide() >- }, 3000); >- } >- > function send_update_request( data, cell ) { > $.ajax({ > data: data, > type: 'PUT', > url: '/cgi-bin/koha/svc/localization', > success: function (data) { >- if ( data.error ) { >- $(cell).css('background-color', '#FF0000'); >- show_message({ type: 'error_on_update', data: data }); >- } else if ( data.is_changed == 1 ) { >- $(cell).css('background-color', '#00FF00'); >- show_message({ type: 'success_on_update', data: data }); >- } >- >- if ( $(cell).hasClass('lang') ) { >- $(cell).text(data.lang) >- } else if ( $(cell).hasClass('translation') ) { >- $(cell).text(data.translation) >- } >- }, >- error: function (data) { >- $(cell).css('background-color', '#FF9090'); >- if ( $(cell).hasClass('lang') ) { >- $(cell).text(data.lang) >- } else if ( $(cell).hasClass('translation') ) { >- $(cell).text(data.translation) >- } >- show_message({ type: 'error_on_update', data: data }); >- }, >- }); >- } >- >- function send_delete_request( id, cell ) { >- $.ajax({ >- type: 'DELETE', >- url: '/cgi-bin/koha/svc/localization/?id='+id, >- success: function (data) { >- $("#localization").DataTable().row( '#row_id_' + id ).remove().draw(); >- show_message({ type: 'success_on_delete', data: data }); >- }, >- error: function (data) { >- $(cell).css('background-color', '#FF9090'); >- show_message({ type: 'error_on_delete', data: data }); >+ $("#localization").DataTable().draw(false); > }, > }); > } > > $(document).ready(function() { >- $(".dialog").hide(); >- > var table = $("#localization").DataTable($.extend(true, {}, dataTablesDefaults, { >- "dom": 't', >- "columnDefs": [ >- { 'sortable': false, 'targets': [ 'NoSort' ] } >- ], >- 'bPaginate': false, >- 'autoWidth': false, >- })); >- >- var languages_select = $('<select name="lang" id="lang"></select>'); >- [% FOR language IN languages %] >- [% FOR sublanguage IN language.sublanguages_loop %] >- var option; >- [% IF language.plural %] >- option = $('<option value="[% sublanguage.rfc4646_subtag | html %]">[% sublanguage.native_description | html %] [% sublanguage.region_description | html %] ([% sublanguage.rfc4646_subtag | html %])</option>'); >- $(languages_select).append(option); >- [% ELSE %] >- option = $('<option value="[% sublanguage.rfc4646_subtag | html %]">[% sublanguage.native_description | html %] ([% sublanguage.rfc4646_subtag | html %])</option>'); >- [% END %] >- $(languages_select).append(option); >- [% END %] >- [% END %] >- >- $("td.translation").on('focus', function(){ >- $(this).css('background-color', ''); >- }); >- $("td.lang").on('click', function(){ >- var td = this; >- var lang = $(td).text(); >- $(td).css('background-color', ''); >- var my_select = $(languages_select).clone(); >- $(my_select).find('option[value="' + lang + '"]').attr('selected', 'selected'); >- $(my_select).on('click', function(e){ >- e.stopPropagation(); >- }); >- $(my_select).on('change', function(){ >- var tr = $(this).parent().parent(); >- var id = $(tr).data('id'); >- var lang = $(this).find('option:selected').val(); >- var data = "id=" + encodeURIComponent(id) + "&lang=" + encodeURIComponent(lang); >- send_update_request( data, td ); >- }); >- $(my_select).on('blur', function(){ >- $(td).html(lang); >- }); >- $(this).html(my_select); >- }); >- >- $("td.translation").on('blur', function(){ >- var tr = $(this).parent(); >- var id = $(tr).data('id'); >- var translation = $(this).text(); >- var data = "id=" + encodeURIComponent(id) + "&translation=" + encodeURIComponent(translation); >- send_update_request( data, this ); >- }); >- >- $("body").on("click", "a.delete", function(e){ >- e.preventDefault(); >- if ( confirm(_("Are you sure you want to delete this translation?")) ) { >- var td = $(this).parent(); >- var tr = $(td).parent(); >- var id = $(tr).data('id'); >- send_delete_request( id, td ); >- } >- }); >- >- $("#add_translation").on('submit', function(e){ >- e.preventDefault(); >- var entity = $(this).find('input[name="entity"]').val(); >- var code = $(this).find('input[name="code"]').val(); >- var lang = $(this).find('select[name="lang"] option:selected').val(); >- var translation = $(this).find('input[name="translation"]').val(); >- var data = "entity=" + encodeURIComponent(entity) + "&code=" + encodeURIComponent(code) + "&lang=" + encodeURIComponent(lang) + "&translation=" + encodeURIComponent(translation); >- $.ajax({ >- data: data, >- type: 'POST', >+ autoWidth: true, >+ serverSide: true, >+ ordering: false, >+ ajax: { > url: '/cgi-bin/koha/svc/localization', >- success: function (data) { >- if ( data.error ) { >- show_message({ type: 'error_on_insert', data: data }); >- } else { >- var new_row = table.row.add( [ data.id, data.entity, data.code, data.lang, data.translation, "<a href=\"#\" class=\"delete\"><i class=\"fa fa-trash\"></i> Delete</a>" ] ).draw().node(); >- $( new_row ).attr("id", "row_id_" + data.id ).data("id", data.id ); >- show_message({ type: 'success_on_insert', data: data }); >- } >+ }, >+ columns: [ >+ { >+ name: 'context', >+ data: 'context', >+ }, >+ { >+ name: 'source', >+ data: 'source', > }, >- error: function (data) { >- show_message({ type: 'error_on_insert', data: data }); >+ { >+ name: 'targets', >+ data: 'l10n_targets', >+ render: function (data, type, row, meta) { >+ const languages = [% languages.json %]; >+ const translations = Object.fromEntries(data.map(translation => [translation.language, translation])); >+ let output = ''; >+ for (const language of languages) { >+ const div = $('<div>'); >+ div.addClass('add-translation-block'); >+ const languageCode = $('<code>').text(language.rfc4646_subtag); >+ const translationSpan = $('<span>'); >+ if (translations[language.rfc4646_subtag]) { >+ const translation = translations[language.rfc4646_subtag].translation; >+ translationSpan.text(translation); >+ } else { >+ languageCode.html('<del>' + languageCode.text() + '</del>'); >+ } >+ const translateLink = $('<a>'); >+ translateLink.text('Translate'); >+ translateLink.addClass('add-translation'); >+ translateLink.attr('href', '#'); >+ translateLink.attr('data-l10n-source-id', row.l10n_source_id); >+ translateLink.attr('data-language', language.rfc4646_subtag); >+ translateLink.attr('data-source', row.source); >+ if (translations[language.rfc4646_subtag]) { >+ translateLink.attr('data-translation', translations[language.rfc4646_subtag].translation); >+ } >+ >+ div.append(languageCode, ' ', translationSpan, ' ', translateLink); >+ >+ output += ' ' + div[0].outerHTML; >+ } >+ >+ return output; >+ }, > }, >+ ], >+ })); >+ >+ $('#localization').on('click', '.add-translation', function (ev) { >+ ev.preventDefault(); >+ const form = $('<form>'); >+ const textarea = $('<textarea>').attr('rows', '1'); >+ textarea.text(ev.target.getAttribute('data-translation')); >+ form.append(textarea); >+ form.append('<button type="submit">Save</button>'); >+ const l10n_source_id = ev.target.getAttribute('data-l10n-source-id'); >+ const language = ev.target.getAttribute('data-language'); >+ form.on('submit', function (ev) { >+ ev.preventDefault(); >+ send_update_request({ >+ id: l10n_source_id, >+ lang: language, >+ translation: textarea.val(), >+ }); > }); >+ $(ev.target).hide(); >+ $(ev.target).after(form); > }); >- > }); > </script> > [% END %] >-[% INCLUDE 'popup-bottom.inc' %] >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >index 0ee352fcb0..81dc9a018f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/smart-rules.tt >@@ -396,16 +396,16 @@ > <option value="*">All</option> > [% FOREACH itemtypeloo IN itemtypeloop %] > [% NEXT IF itemtypeloo.parent_type %] >- [% SET children = itemtypeloo.children_with_localization %] >+ [% SET children = itemtypeloo.children %] > [% IF children.count %] >- <optgroup label="[% itemtypeloo.translated_description | html %]"> >- <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %] (All)</option> >+ <optgroup label="[% ItemTypes.t(itemtypeloo.description) | html %]"> >+ <option value="[% itemtypeloo.itemtype | html %]">[% ItemTypes.t(itemtypeloo.description) | html %] (All)</option> > [% FOREACH child IN children %] >- <option value="[% child.itemtype | html %]">[% child.translated_description | html %]</option> >+ <option value="[% child.itemtype | html %]">[% ItemTypes.t(child.description) | html %]</option> > [% END %] > </optgroup> > [% ELSE %] >- <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option> >+ <option value="[% itemtypeloo.itemtype | html %]">[% ItemTypes.t(itemtypeloo.description) | html %]</option> > [% END %] > [% END %] > </select> >@@ -1094,7 +1094,7 @@ > [% IF holdallowed || hold_fulfillment_policy || returnbranch %] > <tr> > <td> >- [% i.translated_description | html %] >+ [% ItemTypes.t(i.description) | html %] > </td> > <td> > [% IF holdallowed == 'from_any_library' %] >@@ -1139,7 +1139,7 @@ > <td> > <select name="itemtype"> > [% FOREACH itemtypeloo IN itemtypeloop %] >- <option value="[% itemtypeloo.itemtype | html %]">[% itemtypeloo.translated_description | html %]</option> >+ <option value="[% itemtypeloo.itemtype | html %]">[% ItemTypes.t(itemtypeloo.description) | html %]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/advsearch.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/advsearch.tt >index 23ef320fb6..4d9eb1c611 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/advsearch.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/advsearch.tt >@@ -1,4 +1,5 @@ > [% USE raw %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE Asset %] > [% USE Branches %] >@@ -198,7 +199,7 @@ > [% END %] > > [% END %] >- [% itemtypeloo.description | html %] >+ [% ItemTypes.t(itemtypeloo.description) | html %] > </label> > </td> > [% IF ( loop.last ) %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >index 5eca90dcf2..b645229d77 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt >@@ -1,5 +1,6 @@ > [% USE raw %] > [% USE Asset %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE KohaDates %] > [% USE KohaPlugins %] >@@ -370,9 +371,9 @@ > [% IF ( item_level_itypes ) %] > <td class="itype"> > [% IF !noItemTypeImages && item.imageurl %] >- <img src="[% item.imageurl | html %]" alt="[% item.translated_description | html %]" title="[% item.translated_description | html %]" /> >+ <img src="[% item.imageurl | html %]" alt="[% ItemTypes.t(item.description) | html %]" title="[% ItemTypes.t(item.description) | html %]" /> > [% END %] >- <span class="itypedesc">[% item.translated_description | html %]</span> >+ <span class="itypedesc">[% ItemTypes.t(item.description) | html %]</span> > </td> > [% END %] > <td class="location">[% UNLESS ( singlebranchmode ) %][% Branches.GetName( item.branchcode ) | html %] [% END %]</td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/add_items-step2.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/add_items-step2.tt >index 2efd1a2a2c..47cc059c7d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/add_items-step2.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/add_items-step2.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>[% IF is_edit || course_reserve %]Edit item[% ELSE %]Add items[% END %] › Course reserves › Koha</title> >@@ -79,9 +80,9 @@ > <option value=""></option> > [% FOREACH it IN itypes %] > [% IF it.itemtype == course_item.itype %] >- <option value="[% it.itemtype | html %]" selected="selected">[% it.description | html %]</option> >+ <option value="[% it.itemtype | html %]" selected="selected">[% ItemTypes.t(it.description) | html %]</option> > [% ELSE %] >- <option value="[% it.itemtype | html %]">[% it.description | html %]</option> >+ <option value="[% it.itemtype | html %]">[% ItemTypes.t(it.description) | html %]</option> > [% END %] > [% END %] > </select> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/batch_add_items.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/batch_add_items.tt >index 153f51c6ef..e191546345 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/batch_add_items.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/course_reserves/batch_add_items.tt >@@ -56,7 +56,7 @@ > <option value=""></option> > > [% FOREACH it IN ItemTypes.Get() %] >- <option value="[% it.itemtype | html %]">[% it.description | html %]</option> >+ <option value="[% it.itemtype | html %]">[% ItemTypes.t(it.description) | html %]</option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/acquisitions_stats.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/acquisitions_stats.tt >index 8ae84ad28f..f1f19ced81 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/acquisitions_stats.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/acquisitions_stats.tt >@@ -1,3 +1,4 @@ >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>[% IF ( do_it ) %]Acquisitions statistics › Results[% ELSE %]Acquisitions statistics[% END %] › Reports › Koha</title> >@@ -218,7 +219,7 @@ > <select name="Filter" id="itemtypes"> > <option value="">All item types</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/bor_issues_top.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/bor_issues_top.tt >index 9bdf3897e7..fee3a79844 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/bor_issues_top.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/bor_issues_top.tt >@@ -144,7 +144,7 @@ > <li> > <label for="documenttype">Item type: </label><select name="Filter" id="documenttype"><option value="" > Any item type</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]" >[% itemtype.translated_description | html %] </option> >+ <option value="[% itemtype.itemtype | html %]" >[% ItemTypes.t(itemtype.description) | html %] </option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/cat_issues_top.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/cat_issues_top.tt >index 96bb85d177..4676aeb40d 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/cat_issues_top.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/cat_issues_top.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Most-circulated items[% IF ( do_it ) %] › Results[% END %] › Reports › Koha</title> >@@ -120,7 +121,7 @@ > <li> > <label for="documenttype">Item type: </label><select name="Filter" id="documenttype"><option value="" > Any item type</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]" >[% itemtype.translated_description | html %] </option> >+ <option value="[% itemtype.itemtype | html %]" >[% ItemTypes.t(itemtype.description) | html %] </option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_out.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_out.tt >index 522f5cbcca..75a83cc0bc 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_out.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_out.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Items with no checkouts › Reports › Koha</title> > [% INCLUDE 'doc-head-close.inc' %] >@@ -112,7 +113,7 @@ > <label for="documenttype">Item type: </label><select name="Filter" id="documenttype"> > <option value="">Any item type</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_stats.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_stats.tt >index 8a63209b21..cdcb8afea9 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_stats.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/catalogue_stats.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>[% IF ( do_it ) %]Catalog statistics › Results[% ELSE %]Catalog statistics[% END %] › Reports › Koha</title> >@@ -134,7 +135,7 @@ > <td><select name="Filter" id="[% item_itype | html %]"> > <option value=""> </option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_avg_stats.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_avg_stats.tt >index 8b02e551e9..e91b63111c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_avg_stats.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_avg_stats.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Average loan time › Reports › Koha</title> >@@ -170,7 +171,7 @@ > <select name="Filter" id="itemtypes"> > <option value=""></option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[%- itemtype.itemtype | html -%]">[%- itemtype.translated_description | html -%]</option> >+ <option value="[%- itemtype.itemtype | html -%]">[%- ItemTypes.t(itemtype.description) | html -%]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_stats.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_stats.tt >index 4dd120b2f5..bac52ce40c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_stats.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/issues_stats.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Circulation statistics[% IF ( do_it ) %] › Results[% END %] › Reports › Koha</title> >@@ -196,7 +197,7 @@ > <td><select name="Filter" id="itemtype"> > <option value=""> </option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt >index 11552c85fb..a7f69a5dac 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt >@@ -155,7 +155,7 @@ > <li><label for="itemtypesfilter">Item type: </label><select name="itemtypesfilter" id="itemtypesfilter"> > <option value="">All</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select></li> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tt >index 978c24be36..2201938e7e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tt >@@ -1,4 +1,5 @@ > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Holds statistics[% IF ( do_it ) %] › Results[% END %] › Reports › Koha</title> >@@ -198,7 +199,7 @@ > <td><select name="filter_items.itype" id="itype"> > <option value=""> </option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt >index 23c0a851a8..5712861fa1 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-add.tt >@@ -1,6 +1,7 @@ > [% USE raw %] > [% USE To %] > [% USE Asset %] >+[% USE ItemTypes %] > [% USE KohaDates %] > [% USE Branches %] > [% USE Koha %] >@@ -205,9 +206,9 @@ fieldset.rows table { clear: none; margin: 0; } > <option value=""></option> > [% FOREACH type IN typeloop %] > [% IF ( type.selected ) %] >- <option value="[% type.code | html %]" selected="selected">[% type.value | html %]</option> >+ <option value="[% type.code | html %]" selected="selected">[% ItemTypes.t(type.value) | html %]</option> > [% ELSE %] >- <option value="[% type.code | html %]">[% type.value | html %]</option> >+ <option value="[% type.code | html %]">[% ItemTypes.t(type.value) | html %]</option> > [% END %] > [% END %] > </select> >@@ -219,9 +220,9 @@ fieldset.rows table { clear: none; margin: 0; } > <option value=""></option> > [% FOREACH previous IN previoustypeloop %] > [% IF ( previous.selected ) %] >- <option value="[% previous.code | html %]" selected="selected">[% previous.value | html %]</option> >+ <option value="[% previous.code | html %]" selected="selected">[% ItemTypes.t(previous.value) | html %]</option> > [% ELSE %] >- <option value="[% previous.code | html %]">[% previous.value | html %]</option> >+ <option value="[% previous.code | html %]">[% ItemTypes.t(previous.value) | html %]</option> > [% END %] > [% END %] > </select> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-batchedit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-batchedit.tt >index 360b18e41d..10394c30cc 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-batchedit.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-batchedit.tt >@@ -119,7 +119,7 @@ > <select id="itemtype" name="itemtype"> > <option value="">No change</option> > [% FOREACH itemtype IN ItemTypes.Get() %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-bib-search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-bib-search.tt >index 40f29226b6..9288f93cde 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-bib-search.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/serials/subscription-bib-search.tt >@@ -1,3 +1,4 @@ >+[% USE ItemTypes %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Catalog search › Serials › Koha</title> > [% INCLUDE 'doc-head-close.inc' %] >@@ -25,7 +26,7 @@ > <option value="">All</option> > [%- FOREACH itemtypeloo IN itemtypeloop %] > <option value="[% itemtypeloo.code | html %]"> >- [% itemtypeloo.description | html %] >+ [% ItemTypes.t(itemtypeloo.description) | html %] > </option> > [%- END %] > </select> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt >index fee9ea6132..503bdff815 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/export.tt >@@ -1,6 +1,7 @@ > [% USE raw %] > [% USE Asset %] > [% USE Branches %] >+[% USE ItemTypes %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] > <title>Export data › Tools › Koha</title> >@@ -80,7 +81,7 @@ > <select name="itemtype" id="itemtype"> > <option value="">-- All --</option> > [% FOREACH itemtype IN itemtypes %] >- <option value="[% itemtype.itemtype | html %]">[% itemtype.translated_description | html %]</option> >+ <option value="[% itemtype.itemtype | html %]">[% ItemTypes.t(itemtype.description) | html %]</option> > [% END %] > </select> > </li> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >index b5462a8ac3..cfb9a45b34 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >@@ -1,5 +1,6 @@ > [% USE raw %] > [% USE Asset %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE KohaDates %] > [% SET footerjs = 1 %] >@@ -259,7 +260,7 @@ > </td> > [% END %] > [% UNLESS ( item_level_itypes ) %]<td> >- [% UNLESS ( noItemTypeImages || !itemsloo.imageurl ) %]<img src="[% itemsloo.imageurl | html %]" alt="[% itemsloo.description | html %]" title="[% itemsloo.description | html %]" />[% END %][% itemsloo.description | html %] >+ [% UNLESS ( noItemTypeImages || !itemsloo.imageurl ) %]<img src="[% itemsloo.imageurl | html %]" alt="[% ItemTypes.t(itemsloo.description) | html %]" title="[% ItemTypes.t(itemsloo.description) | html %]" />[% END %][% ItemTypes.t(itemsloo.description) | html %] > </td>[% END %] > <td> > [% IF ( itemsloo.XSLTBloc ) %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-topissues.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-topissues.inc >index 11e0b4cf6d..26db63fc68 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-topissues.inc >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-topissues.inc >@@ -1,3 +1,4 @@ >+[% USE ItemTypes %] > [% USE Koha %] > [% USE Branches %] > [% PROCESS 'html_helpers.inc' %] >@@ -37,7 +38,7 @@ > [% ELSE %] > <option value="[% itemtype.itemtype | html %]"> > [% END %] >- [% itemtype.translated_description | html %] >+ [% ItemTypes.t(itemtype.description) | html %] > </option> > [% END %] > </select> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-readingrecord.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-readingrecord.tt >index a3ad4f4e3d..39b92c5b18 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-readingrecord.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-readingrecord.tt >@@ -1,4 +1,5 @@ > [% USE raw %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE KohaDates %] > [% USE TablesSettings %] >@@ -160,7 +161,7 @@ > [% END %] > [% END %] > <span class="tdlabel">Item type:</span> >- [% issue.translated_description | html %]</td> >+ [% ItemTypes.t(issue.description) | html %]</td> > <td> > <span class="tdlabel">Call number:</span> > [% issue.itemcallnumber | html %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >index 45e7b2041c..2adb4cce14 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-reserve.tt >@@ -224,7 +224,7 @@ > <li class="itype"> > <span class="label">Item type: </span> > [% IF ( bibitemloo.imageurl ) %]<img src="[% bibitemloo.imageurl | html %]" alt="" />[% END %] >- [% bibitemloo.translated_description | html %] >+ [% ItemTypes.t(bibitemloo.description) | html %] > </li> > [% END %] > >@@ -406,7 +406,7 @@ > <img src="[% itemLoo.imageurl | html %]" alt="" /> > [% END %] > [% END %] >- [% itemLoo.translated_description | html %] >+ [% ItemTypes.t(itemLoo.description) | html %] > </td> > [% END %] > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt >index 18e9ac2e70..369efc157e 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt >@@ -1,5 +1,6 @@ > [% USE raw %] > [% USE Asset %] >+[% USE ItemTypes %] > [% USE Koha %] > [% USE AdditionalContents %] > [% SET OpacNav = AdditionalContents.get( location => "OpacNav", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %] >@@ -383,9 +384,9 @@ > [% UNLESS ( item_level_itypes ) %] > <td> > [% UNLESS ( Koha.Preference('OpacNoItemTypeImages') ) %] >- <img src="[% itemsloo.imageurl | html %]" alt="[% itemsloo.description | html %]" title="[% itemsloo.description | html %]" /> >+ <img src="[% itemsloo.imageurl | html %]" alt="[% ItemTypes.t(itemsloo.description) | html %]" title="[% ItemTypes.t(itemsloo.description) | html %]" /> > [% END %] >- [% itemsloo.description | html %] >+ [% ItemTypes.t(itemsloo.description) | html %] > </td> > [% END %] > <td> >diff --git a/labels/label-item-search.pl b/labels/label-item-search.pl >index b07be0aa47..a25e2c4c98 100755 >--- a/labels/label-item-search.pl >+++ b/labels/label-item-search.pl >@@ -217,20 +217,7 @@ else { > flagsrequired => { catalogue => 1 }, > } > ); >- my $itemtypes = Koha::ItemTypes->search; >- my @itemtypeloop; >- while ( my $itemtype = $itemtypes->next ) { >- # FIXME This must be improved: >- # - pass the iterator to the template >- # - display the translated_description >- my %row = ( >- value => $itemtype->itemtype, >- description => $itemtype->description, >- ); >- push @itemtypeloop, \%row; >- } > $template->param( >- itemtypeloop => \@itemtypeloop, > batch_id => $batch_id, > type => $type, > ); >diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl >index 00c52eb5aa..49b8e5852f 100755 >--- a/opac/opac-detail.pl >+++ b/opac/opac-detail.pl >@@ -74,6 +74,7 @@ use Koha::Biblios; > use Koha::RecordProcessor; > use Koha::AuthorisedValues; > use Koha::CirculationRules; >+use Koha::I18N; > use Koha::Items; > use Koha::ItemTypes; > use Koha::Acquisition::Orders; >@@ -236,7 +237,7 @@ if ($session->param('busc')) { > { > my ($arrParamsBusc, $offset, $results_per_page, $patron) = @_; > >- my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > my @servers; > @servers = @{$arrParamsBusc->{'server'}} if $arrParamsBusc->{'server'}; > @servers = ("biblioserver") unless (@servers); >@@ -540,12 +541,12 @@ my $HideMARC = $record_processor->filters->[0]->should_hide_marc( > interface => 'opac', > } ); > >-my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > # imageurl: > my $itemtype = $dat->{'itemtype'}; > if ( $itemtype ) { > $dat->{'imageurl'} = getitemtypeimagelocation( 'opac', $itemtypes->{$itemtype}->{'imageurl'} ); >- $dat->{'description'} = $itemtypes->{$itemtype}->{translated_description}; >+ $dat->{'description'} = db_t('itemtype', $itemtypes->{$itemtype}->{description}); > } > > my $shelflocations = >@@ -724,7 +725,7 @@ if ( not $viewallitems and @items > $max_items_to_display ) { > } > if (exists $itm->{itype} && defined($itm->{itype}) && exists $itemtypes->{ $itm->{itype} }) { > $itm->{'imageurl'} = getitemtypeimagelocation( 'opac', $itemtypes->{ $itm->{itype} }->{'imageurl'} ); >- $itm->{'description'} = $itemtypes->{ $itm->{itype} }->{translated_description}; >+ $itm->{'description'} = db_t('itemtype', $itemtypes->{ $itm->{itype} }->{description}); > } > foreach (qw(ccode materials enumchron copynumber itemnotes location_description uri)) { > $itemfields{$_} = 1 if ($itm->{$_}); >diff --git a/opac/opac-readingrecord.pl b/opac/opac-readingrecord.pl >index 927c37b275..5b7b7ff9ab 100755 >--- a/opac/opac-readingrecord.pl >+++ b/opac/opac-readingrecord.pl >@@ -54,7 +54,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > } > ); > >-my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > > # get the record > my $order = $query->param('order') || ''; >@@ -83,8 +83,7 @@ my $opac_summary_html = C4::Context->preference('OPACMySummaryHTML'); > foreach my $issue ( @{$issues} ) { > $issue->{normalized_isbn} = GetNormalizedISBN( $issue->{isbn} ); > if ( $issue->{$itype_attribute} ) { >- $issue->{translated_description} = >- $itemtypes->{ $issue->{$itype_attribute} }->{translated_description}; >+ $issue->{description} = $itemtypes->{ $issue->{$itype_attribute} }->{description}; > $issue->{imageurl} = > getitemtypeimagelocation( 'opac', > $itemtypes->{ $issue->{$itype_attribute} }->{imageurl} ); >diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl >index b8ffca4e44..57daf6fb50 100755 >--- a/opac/opac-reserve.pl >+++ b/opac/opac-reserve.pl >@@ -97,7 +97,7 @@ if ( $reservefee > 0){ > $template->param( RESERVE_CHARGE => $reservefee); > } > >-my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > > # There are two ways of calling this script, with a single biblio num > # or multiple biblio nums. >@@ -443,13 +443,13 @@ foreach my $biblioNum (@biblionumbers) { > $biblioLoopIter{reqholdnotes}=0; #TODO: For future use > > if (!$itemLevelTypes && $biblioData->{itemtype}) { >- $biblioLoopIter{translated_description} = $itemtypes->{$biblioData->{itemtype}}{translated_description}; >+ $biblioLoopIter{description} = $itemtypes->{$biblioData->{itemtype}}{description}; > $biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$biblioData->{itemtype}}{imageurl}; > } > > foreach my $itemInfo (@{$biblioData->{itemInfos}}) { > if ($itemLevelTypes && $itemInfo->{itype}) { >- $itemInfo->{translated_description} = $itemtypes->{$itemInfo->{itype}}{translated_description}; >+ $itemInfo->{description} = $itemtypes->{$itemInfo->{itype}}{description}; > $itemInfo->{imageurl} = getitemtypeimagesrc() . "/". $itemtypes->{$itemInfo->{itype}}{imageurl}; > } > >@@ -490,7 +490,7 @@ foreach my $biblioNum (@biblionumbers) { > $itemLoopIter->{copynumber} = $itemInfo->{copynumber}; > $itemLoopIter->{itemnotes} = $itemInfo->{itemnotes}; > if ($itemLevelTypes) { >- $itemLoopIter->{translated_description} = $itemInfo->{translated_description}; >+ $itemLoopIter->{description} = $itemInfo->{description}; > $itemLoopIter->{itype} = $itemInfo->{itype}; > $itemLoopIter->{imageurl} = $itemInfo->{imageurl}; > } >diff --git a/opac/opac-search.pl b/opac/opac-search.pl >index 230cc266e9..ae7f698359 100755 >--- a/opac/opac-search.pl >+++ b/opac/opac-search.pl >@@ -57,6 +57,7 @@ use C4::External::BakerTaylor qw( image_url link_url ); > > use Koha::CirculationRules; > use Koha::Libraries; >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Ratings; > use Koha::Virtualshelves; >@@ -225,14 +226,13 @@ $template->param(search_languages_loop => $languages_limit_loop,); > > # load the Type stuff > my $itemtypes = GetItemTypesCategorized; >-# add translated_description to itemtypes > foreach my $itemtype ( keys %{$itemtypes} ) { > # Itemtypes search categories don't have (yet) translated descriptions, they are auth values (and could still have no descriptions too BZ 18400) > # If 'iscat' (see ITEMTYPECAT) then there is no itemtype and the description is not translated >- my $translated_description = $itemtypes->{$itemtype}->{iscat} >+ my $description = $itemtypes->{$itemtype}->{iscat} > ? $itemtypes->{$itemtype}->{description} >- : Koha::ItemTypes->find($itemtype)->translated_description; >- $itemtypes->{$itemtype}->{translated_description} = $translated_description || $itemtypes->{$itemtype}->{description} || q{}; >+ : db_t('itemtype', Koha::ItemTypes->find($itemtype)->description); >+ $itemtypes->{$itemtype}->{description} = $description || $itemtypes->{$itemtype}->{description} || q{}; > } > > # the index parameter is different for item-level itemtypes >@@ -244,7 +244,7 @@ my @advanced_search_types = split(/\|/, $advanced_search_types); > > my $hidingrules = C4::Context->yaml_preference('OpacHiddenItems') // {}; > >-my @sorted_itemtypes = sort { $itemtypes->{$a}->{translated_description} cmp $itemtypes->{$b}->{translated_description} } keys %$itemtypes; >+my @sorted_itemtypes = sort { $itemtypes->{$a}->{description} cmp $itemtypes->{$b}->{description} } keys %$itemtypes; > foreach my $advanced_srch_type (@advanced_search_types) { > $advanced_srch_type =~ s/^\s*//; > $advanced_srch_type =~ s/\s*$//; >@@ -257,7 +257,7 @@ foreach my $advanced_srch_type (@advanced_search_types) { > my %row =( number=>$cnt++, > ccl => "$itype_or_itemtype,phr", > code => $thisitemtype, >- description => $itemtypes->{$thisitemtype}->{translated_description}, >+ description => $itemtypes->{$thisitemtype}->{description}, > imageurl=> getitemtypeimagelocation( 'opac', $itemtypes->{$thisitemtype}->{'imageurl'} ), > cat => $itemtypes->{$thisitemtype}->{'iscat'}, > hideinopac => $itemtypes->{$thisitemtype}->{'hideinopac'}, >@@ -565,7 +565,7 @@ if ($tag) { > $pasarParams .= '&count=' . uri_escape_utf8($results_per_page); > $pasarParams .= '&simple_query=' . uri_escape_utf8($simple_query); > $pasarParams .= '&query_type=' . uri_escape_utf8($query_type) if ($query_type); >- my $itemtypes_nocategory = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes_nocategory = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > eval { > ($error, $results_hashref, $facets) = $searcher->search_compat($query,$simple_query,\@sort_by,\@servers,$results_per_page,$offset,undef,$itemtypes_nocategory,$query_type,$scan,1); > }; >diff --git a/opac/opac-shelves.pl b/opac/opac-shelves.pl >index 4c76116bca..6e0d6f02f9 100755 >--- a/opac/opac-shelves.pl >+++ b/opac/opac-shelves.pl >@@ -328,7 +328,7 @@ if ( $op eq 'view' ) { > $itemtype = Koha::ItemTypes->find( $itemtype ); > if( $itemtype ) { > $this_item->{imageurl} = C4::Koha::getitemtypeimagelocation( 'opac', $itemtype->imageurl ); >- $this_item->{description} = $itemtype->description; #FIXME Should not it be translated_description? >+ $this_item->{description} = $itemtype->description; > $this_item->{notforloan} = $itemtype->notforloan; > } > $this_item->{'coins'} = $biblio->get_coins; >diff --git a/opac/opac-user.pl b/opac/opac-user.pl >index 5bc84c5b3f..5e6c682a53 100755 >--- a/opac/opac-user.pl >+++ b/opac/opac-user.pl >@@ -189,7 +189,7 @@ my $count = 0; > my $overdues_count = 0; > my @overdues; > my @issuedat; >-my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > my $pending_checkouts = $patron->pending_checkouts->search({}, { order_by => [ { -desc => 'date_due' }, { -asc => 'issue_id' } ] }); > my $are_renewable_items = 0; > if ( $pending_checkouts->count ) { # Useless test >diff --git a/reports/acquisitions_stats.pl b/reports/acquisitions_stats.pl >index c804f72abe..b13602eff9 100755 >--- a/reports/acquisitions_stats.pl >+++ b/reports/acquisitions_stats.pl >@@ -191,7 +191,7 @@ else { > $ccode_avlist = GetAuthorisedValues($ccode_subfield_structure->{authorised_value}); > } > >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > $template->param( > booksellers => $booksellers, > itemtypes => $itemtypes, # FIXME Should use the TT plugin instead >diff --git a/reports/bor_issues_top.pl b/reports/bor_issues_top.pl >index 912798ea7b..60a2413ee7 100755 >--- a/reports/bor_issues_top.pl >+++ b/reports/bor_issues_top.pl >@@ -102,7 +102,7 @@ my @mime = ( map { {type =>$_} } (split /[;:]/, 'CSV') ); # FIXME translation > my $delims = GetDelimiterChoices; > > my $patron_categories = Koha::Patron::Categories->search_with_library_limits({}, {order_by => ['categorycode']}); >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > $template->param( > mimeloop => \@mime, > CGIseplist => $delims, >diff --git a/reports/cat_issues_top.pl b/reports/cat_issues_top.pl >index 23666f314c..b2e279df63 100755 >--- a/reports/cat_issues_top.pl >+++ b/reports/cat_issues_top.pl >@@ -103,7 +103,7 @@ if ($do_it) { > my $CGIsepChoice=GetDelimiterChoices; > > #doctype >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > > #ccode > my $ccodes = GetAuthorisedValues('CCODE'); >diff --git a/reports/catalogue_out.pl b/reports/catalogue_out.pl >index 51961790a8..68b5aea70c 100755 >--- a/reports/catalogue_out.pl >+++ b/reports/catalogue_out.pl >@@ -54,7 +54,7 @@ if ($do_it) { > exit; # in either case, exit after do_it > } > >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > $template->param( > itemtypes => $itemtypes, > ); >diff --git a/reports/catalogue_stats.pl b/reports/catalogue_stats.pl >index c3795df6d2..5d4b978e03 100755 >--- a/reports/catalogue_stats.pl >+++ b/reports/catalogue_stats.pl >@@ -113,7 +113,7 @@ if ($do_it) { > my $dbh = C4::Context->dbh; > my $count=0; > >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > > my @authvals = map { { code => $_->{authorised_value}, description => $_->{lib} } } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.ccode' }, { order_by => ['description'] } ); > my @locations = map { { code => $_->{authorised_value}, description => $_->{lib} } } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.location' }, { order_by => ['description'] } ); >diff --git a/reports/issues_avg_stats.pl b/reports/issues_avg_stats.pl >index 7be36a54c2..fbd180e33c 100755 >--- a/reports/issues_avg_stats.pl >+++ b/reports/issues_avg_stats.pl >@@ -116,7 +116,7 @@ if ($do_it) { > } else { > my $patron_categories = Koha::Patron::Categories->search({}, {order_by => ['description']}); > >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > > my $dbh = C4::Context->dbh; > my $req = $dbh->prepare("select distinctrow sort1 from borrowers where sort1 is not null order by sort1"); >diff --git a/reports/issues_stats.pl b/reports/issues_stats.pl >index ca0b8ec100..abc44addfe 100755 >--- a/reports/issues_stats.pl >+++ b/reports/issues_stats.pl >@@ -29,6 +29,7 @@ use C4::Reports qw( GetDelimiterChoices ); > > use Koha::AuthorisedValues; > use Koha::DateUtils qw( dt_from_string output_pref ); >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Patron::Attribute::Types; > >@@ -80,7 +81,7 @@ $sep = "\t" if ($sep eq 'tabulation'); > $template->param(do_it => $do_it, > ); > >-our $itemtypes = Koha::ItemTypes->search_with_localization->unblessed; >+our $itemtypes = Koha::ItemTypes->search->unblessed; > > our @patron_categories = Koha::Patron::Categories->search_with_library_limits({}, {order_by => ['description']})->as_list; > >@@ -350,7 +351,7 @@ sub calculate { > $cell{rowtitle_display} = > ( $line =~ /ccode/ ) ? $ccodes->{$celvalue} > : ( $line =~ /location/ ) ? $locations->{$celvalue} >- : ( $line =~ /itemtype/ ) ? $itemtypes_map->{$celvalue}->{translated_description} >+ : ( $line =~ /itemtype/ ) ? db_t('itemtype', $itemtypes_map->{$celvalue}->{description}) > : $celvalue; # default fallback > if ( $line =~ /sort1/ ) { > foreach (@$Bsort1) { >@@ -439,7 +440,7 @@ sub calculate { > $cell{coltitle_display} = > ( $column =~ /ccode/ ) ? $ccodes->{$celvalue} > : ( $column =~ /location/ ) ? $locations->{$celvalue} >- : ( $column =~ /itemtype/ ) ? $itemtypes_map->{$celvalue}->{translated_description} >+ : ( $column =~ /itemtype/ ) ? db_t('itemtype', $itemtypes_map->{$celvalue}->{description}); > : $celvalue; # default fallback > if ( $column =~ /sort1/ ) { > foreach (@$Bsort1) { >diff --git a/reports/itemslost.pl b/reports/itemslost.pl >index 901ff5a8d9..a856550036 100755 >--- a/reports/itemslost.pl >+++ b/reports/itemslost.pl >@@ -145,7 +145,7 @@ if ( $op eq 'export' ) { > } > > # getting all itemtypes >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > > my $csv_profiles = Koha::CsvProfiles->search({ type => 'sql', used_for => 'export_lost_items' }); > >diff --git a/reports/reserves_stats.pl b/reports/reserves_stats.pl >index 94bd5dad8b..06fce11a6c 100755 >--- a/reports/reserves_stats.pl >+++ b/reports/reserves_stats.pl >@@ -29,6 +29,7 @@ use C4::Reports qw( GetDelimiterChoices ); > use C4::Members; > use Koha::AuthorisedValues; > use Koha::DateUtils qw( dt_from_string output_pref ); >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Libraries; > use Koha::Patron::Categories; >@@ -122,7 +123,7 @@ if ($do_it) { > > my $dbh = C4::Context->dbh; > >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > > # location list > my @locations; >@@ -308,7 +309,7 @@ sub display_value { > my $display_value = > ( $crit =~ /ccode/ ) ? $ccodes->{$value} > : ( $crit =~ /location/ ) ? $locations->{$value} >- : ( $crit =~ /itemtype/ ) ? Koha::ItemTypes->find( $value )->translated_description >+ : ( $crit =~ /itemtype/ ) ? db_t('itemtype', Koha::ItemTypes->find( $value )->description) > : ( $crit =~ /branch/ ) ? Koha::Libraries->find($value)->branchname > : ( $crit =~ /reservestatus/ ) ? reservestatushuman($value) > : $value; # default fallback >diff --git a/reserve/request.pl b/reserve/request.pl >index 15067821cc..ca3844f794 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -72,7 +72,7 @@ my $itemtypes = { > map { > $_->itemtype => > { %{ $_->unblessed }, image_location => $_->image_location } >- } Koha::ItemTypes->search_with_localization->as_list >+ } Koha::ItemTypes->search->as_list > }; > > # Select borrowers infos >diff --git a/serials/subscription-add.pl b/serials/subscription-add.pl >index d10c20c69d..76149855df 100755 >--- a/serials/subscription-add.pl >+++ b/serials/subscription-add.pl >@@ -144,9 +144,8 @@ $template->param( > additional_field_values => \%additional_field_values, > ); > >-my $typeloop = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $typeloop = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > >-# FIXME We should use the translated_description for item types > my @typearg = > map { { code => $_, value => $typeloop->{$_}{'description'}, selected => ( ( $subs->{itemtype} and $_ eq $subs->{itemtype} ) ? "selected=\"selected\"" : "" ), } } sort keys %{$typeloop}; > my @previoustypearg = >diff --git a/serials/subscription-bib-search.pl b/serials/subscription-bib-search.pl >index 8791f037da..5f407a2e27 100755 >--- a/serials/subscription-bib-search.pl >+++ b/serials/subscription-bib-search.pl >@@ -193,10 +193,9 @@ else { > ); > > # load the itemtypes >- my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > my @itemtypesloop; > # FIXME This is uselessly complex, the iterator should be send to the template >- # FIXME The translated_description should be used > foreach my $thisitemtype ( > sort { > $itemtypes->{$a}->{'description'} >diff --git a/svc/bib_profile b/svc/bib_profile >index 46ebe37963..b459e5743d 100755 >--- a/svc/bib_profile >+++ b/svc/bib_profile >@@ -113,7 +113,7 @@ sub _get_bib_number_tag { > > sub _get_biblioitem_itemtypes { > my $result = shift; >- my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+ my $itemtypes = { map { $_->{itemtype} => $_ } @{ Koha::ItemTypes->search->unblessed } }; > my $sth = $dbh->prepare_cached("SELECT tagfield, tagsubfield > FROM marc_subfield_structure > WHERE frameworkcode = '' >diff --git a/svc/checkouts b/svc/checkouts >index 07e95c301a..21ccabcad3 100755 >--- a/svc/checkouts >+++ b/svc/checkouts >@@ -30,6 +30,7 @@ use C4::Context; > use Koha::AuthorisedValues; > use Koha::DateUtils qw( dt_from_string output_pref ); > use Koha::Items; >+use Koha::I18N; > use Koha::ItemTypes; > > my $input = CGI->new; >@@ -146,7 +147,7 @@ my $item_level_itypes = C4::Context->preference('item-level_itypes'); > my $claims_returned_lost_value = C4::Context->preference('ClaimReturnedLostValue'); > my $confirm_parts_required = C4::Context->preference("CircConfirmItemParts"); > >-my $itemtypes = { map { $_->{itemtype} => $_->{translated_description} } @{ Koha::ItemTypes->search_with_localization->unblessed } }; >+my $itemtypes = { map { $_->{itemtype} => db_t('itemtypes', $_->{itemtype}) } @{ Koha::ItemTypes->search->unblessed } }; > > my @checkouts_today; > my @checkouts_previous; >diff --git a/svc/holds b/svc/holds >index c02602c0ff..f474464f48 100755 >--- a/svc/holds >+++ b/svc/holds >@@ -29,6 +29,7 @@ use C4::Context; > > use Koha::DateUtils qw( dt_from_string output_pref ); > use Koha::Holds; >+use Koha::I18N; > use Koha::ItemTypes; > use Koha::Libraries; > >@@ -81,7 +82,7 @@ while ( my $h = $holds_rs->next() ) { > my $itemtype_limit; > if ( $h->itemtype ) { > my $itemtype = Koha::ItemTypes->find( $h->itemtype ); >- $itemtype_limit = $itemtype->translated_description; >+ $itemtype_limit = db_t('itemtype', $itemtype->description); > } > > my $libraries = Koha::Libraries->search({}, { order_by => ['branchname'] })->unblessed; >diff --git a/svc/localization b/svc/localization >index 6eed60632c..8972857625 100755 >--- a/svc/localization >+++ b/svc/localization >@@ -4,101 +4,82 @@ use Modern::Perl; > use Encode qw( encode ); > > use C4::Service; >-use Koha::Localizations; >+use Koha::Caches; >+use Koha::Database; > >-our ( $query, $response ) = C4::Service->init( parameters => 'manage_itemtypes' ); >+our ( $query, $response ) = C4::Service->init( parameters => 'parameters_remaining_permissions' ); > > sub get_translations { >- my $rs = Koha::Localizations->search({ entity => $query->param('entity'), code => $query->param('code') }); >- my @translations; >- while ( my $s = $rs->next ) { >- push @translations, { >- id => $s->localization_id, >- entity => $s->entity, >- code => $s->code, >- lang => $s->lang, >- translation => $s->translation, >- } >- } >- $response->param( translations => \@translations ); >- C4::Service->return_success( $response ); >-} >+ my $draw = $query->param('draw'); >+ my $start = $query->param('start'); >+ my $length = $query->param('length'); >+ my $search = $query->param('search[value]'); > >-sub update_translation { >- my $id = $query->param('id'); >- my $translation = $query->param('translation'); >- my $lang = $query->param('lang'); >+ my $schema = Koha::Database->new->schema; >+ my $rs = $schema->resultset('L10nSource'); >+ my $recordsTotal = $rs->count; > >- my $localization = Koha::Localizations->find( $id ); >- if ( defined $lang and $localization->lang ne $lang ) { >- $localization->lang( $lang ) >- } >- if ( defined $translation and $localization->translation ne $translation ) { >- $localization->translation( $translation ) >- } >- my %params; >- my $is_changed; >- if ( $localization->is_changed ) { >- $is_changed = 1; >- unless ( Koha::Localizations->search( { entity => $localization->entity, code => $localization->code, lang => $lang, localization_id => { '!=' => $localization->localization_id }, } )->count ) { >- $localization->store; >- } else { >- $params{error} = 1; >- $params{error_code} = 'already_exists'; >+ my $cond = {}; >+ if ($search) { >+ my @and; >+ my @words = split /\s+/, $search; >+ foreach my $word (@words) { >+ push @and, \['source LIKE ? COLLATE utf8mb4_unicode_ci', "%$word%"]; > } >+ $cond->{-and} = \@and; > } >+ >+ $rs = $rs->search($cond); >+ my $recordsFiltered = $rs->count; >+ >+ my @sources = $rs->search({}, { >+ prefetch => 'l10n_targets', >+ result_class => 'DBIx::Class::ResultClass::HashRefInflator', >+ rows => $length, >+ offset => $start, >+ order_by => { -asc => ['context', 'source'] }, >+ }); >+ > $response->param( >- %params, >- id => $localization->localization_id, >- entity => $localization->entity, >- code => $localization->code, >- lang => $localization->lang, >- translation => $localization->translation, >- is_changed => $is_changed, >+ draw => $draw, >+ recordsTotal => $recordsTotal, >+ recordsFiltered => $recordsFiltered, >+ data => \@sources, > ); > C4::Service->return_success( $response ); > } > >-sub add_translation { >- my $entity = $query->param('entity'); >- my $code = $query->param('code'); >- my $lang = $query->param('lang'); >+sub update_translation { >+ my $id = $query->param('id'); > my $translation = $query->param('translation'); >+ my $lang = $query->param('lang'); > >- unless ( Koha::Localizations->search({entity => $entity, code => $code, lang => $lang, })->count ) { >- my $localization = Koha::Localization->new( >- { >- entity => $entity, >- code => $code, >- lang => $lang, >- translation => $translation, >- } >- ); >- $localization->store; >- $response->param( >- id => $localization->localization_id, >- entity => $localization->entity, >- code => $localization->code, >- lang => $localization->lang, >- translation => $localization->translation, >- ); >+ my $schema = Koha::Database->new->schema; >+ my $rs = $schema->resultset('L10nTarget'); > >+ if (defined $translation && $translation ne '') { >+ $rs->update_or_create({ >+ l10n_source_id => $id, >+ language => $lang, >+ translation => $translation, >+ }, { >+ key => 'l10n_source_language', >+ }); > } else { >- $response->param( error => 1, error_code => 'already_exists', ); >+ $rs->search({ >+ l10n_source_id => $id, >+ language => $lang, >+ })->delete; > } >- C4::Service->return_success( $response ); >-} > >-sub delete_translation { >- my $id = $query->param('id'); >- Koha::Localizations->find($id)->delete; >- $response->param( id => $id ); >+ my $source = $schema->resultset('L10nSource')->find($id); >+ my $cache_key = sprintf('%s:%s', $source->context, $lang); >+ Koha::Caches->get_instance()->clear_from_cache($cache_key); >+ > C4::Service->return_success( $response ); > } > > C4::Service->dispatch( >- [ 'GET /', [ 'id' ], \&get_translations ], >+ [ 'GET /', [], \&get_translations ], > [ 'PUT /', [ 'id' ], \&update_translation ], >- [ 'POST /', [ 'entity', 'code', 'lang', 'translation' ], \&add_translation ], >- [ 'DELETE /', ['id'], \&delete_translation ], > ); >diff --git a/t/db_dependent/Koha/ItemTypes.t b/t/db_dependent/Koha/ItemTypes.t >index aecd8d971b..3b3e5c19de 100755 >--- a/t/db_dependent/Koha/ItemTypes.t >+++ b/t/db_dependent/Koha/ItemTypes.t >@@ -67,31 +67,6 @@ my $child3 = $builder->build_object({ > } > }); > >-Koha::Localization->new( >- { >- entity => 'itemtypes', >- code => $child1->itemtype, >- lang => 'en', >- translation => 'b translated itemtype desc' >- } >-)->store; >-Koha::Localization->new( >- { >- entity => 'itemtypes', >- code => $child2->itemtype, >- lang => 'en', >- translation => 'a translated itemtype desc' >- } >-)->store; >-Koha::Localization->new( >- { >- entity => 'something_else', >- code => $child2->itemtype, >- lang => 'en', >- translation => 'another thing' >- } >-)->store; >- > my $type = Koha::ItemTypes->find($child1->itemtype); > ok( defined($type), 'first result' ); > is_deeply( $type->unblessed, $child1->unblessed, "We got back the same object" ); >@@ -103,22 +78,11 @@ is_deeply( $type->unblessed, $child2->unblessed, "We got back the same object" ) > > t::lib::Mocks::mock_preference('language', 'en'); > t::lib::Mocks::mock_preference('OPACLanguages', 'en'); >-my $itemtypes = Koha::ItemTypes->search_with_localization; >+my $itemtypes = Koha::ItemTypes->search; > is( $itemtypes->count, $initial_count + 4, 'We added 4 item types' ); >-my $first_itemtype = $itemtypes->next; >-is( >- $first_itemtype->translated_description, >- 'a translated itemtype desc', >- 'item types should be sorted by translated description' >-); >- >-my $children = $parent1->children_with_localization; >-my $first_child = $children->next; >-is( >- $first_child->translated_description, >- 'a translated itemtype desc', >- 'item types should be sorted by translated description' >-); >+ >+my $children = $parent1->children; >+is ($children->count, 3, 'parent type has 3 children'); > > my $item_type = $builder->build_object({ class => 'Koha::ItemTypes' }); > >diff --git a/tools/batchMod.pl b/tools/batchMod.pl >index ef6dec19b8..b2ea231e2b 100755 >--- a/tools/batchMod.pl >+++ b/tools/batchMod.pl >@@ -32,6 +32,7 @@ use Encode qw( encode_utf8 ); > > use Koha::Database; > use Koha::DateUtils qw( dt_from_string ); >+use Koha::I18N; > use Koha::Exception; > use Koha::Biblios; > use Koha::Items; >diff --git a/tools/export.pl b/tools/export.pl >index 4fe6ce5cc5..b4dcc41215 100755 >--- a/tools/export.pl >+++ b/tools/export.pl >@@ -267,7 +267,7 @@ if ( $op eq "export" ) { > > else { > >- my $itemtypes = Koha::ItemTypes->search_with_localization; >+ my $itemtypes = Koha::ItemTypes->search; > > my $authority_types = Koha::Authority::Types->search( {}, { order_by => ['authtypecode'] } ); > >diff --git a/virtualshelves/shelves.pl b/virtualshelves/shelves.pl >index 0ff8d9d332..f83c384e68 100755 >--- a/virtualshelves/shelves.pl >+++ b/virtualshelves/shelves.pl >@@ -285,7 +285,7 @@ if ( $op eq 'view' ) { > $this_item->{author} = $biblio->author; > $this_item->{dateadded} = $content->dateadded; > $this_item->{imageurl} = $itemtype ? C4::Koha::getitemtypeimagelocation( 'intranet', $itemtype->imageurl ) : q{}; >- $this_item->{description} = $itemtype ? $itemtype->description : q{}; #FIXME Should this be translated_description ? >+ $this_item->{description} = $itemtype ? $itemtype->description : q{}; > $this_item->{notforloan} = $itemtype->notforloan if $itemtype; > $this_item->{'coins'} = $biblio->get_coins; > $this_item->{'normalized_upc'} = GetNormalizedUPC( $record, $marcflavour ); >-- >2.20.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 24975
:
101703
|
101786
|
102387
|
102388
|
102513
|
102514
|
102688
|
102701
|
132388
|
132508
|
132509
|
132510
|
132511
|
132512
|
132513
|
132514
|
132515
|
132516
|
132517
|
132518
|
132519
|
132520
|
132521
|
132522
|
132523
|
132524
|
132525
|
132526
|
132527
|
132528
|
132529
|
132530
|
132531
|
132532
|
132533
|
132546
|
132562
|
132563
|
132564
|
132565
|
132566
|
132567
|
132568
|
132569
|
132570
|
132571
|
132572
|
132573
|
132574
|
132575
|
149941
|
149942
|
149943
|
149944
|
149945
|
149946
|
149947
|
149948
|
149949
|
149950
|
149951
|
149952
|
149953
|
149954
|
149956
|
149957
|
150015
|
150033
|
150034