Bugzilla – Attachment 42525 Details for
Bug 14100
Add base to make item types, branch names, sysprefs values and authorised values translatable
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14100: Generic solution for language overlay - Item types
Bug-14100-Generic-solution-for-language-overlay---.patch (text/plain), 39.46 KB, created by
Jonathan Druart
on 2015-09-14 14:27:31 UTC
(
hide
)
Description:
Bug 14100: Generic solution for language overlay - Item types
Filename:
MIME Type:
Creator:
Jonathan Druart
Created:
2015-09-14 14:27:31 UTC
Size:
39.46 KB
patch
obsolete
>From be70846a8af9fc7523566f8c2ae3dfa4e908f7a3 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@biblibre.com> >Date: Thu, 30 Apr 2015 17:30:47 +0200 >Subject: [PATCH] Bug 14100: Generic solution for language overlay - Item types > >Test plan: >1/ update the Schema (misc/devel/update_dbix_class_files.pl) >2/ Translate templates for some languages (es-DE, de-DE for instance) >3/ Enable them in the pref (search for 'lang') for the staff interface >4/ Go on the item type admin page (admin/itemtypes.pl) >5/ Edit one >6/ Click on the 'translate for other languages' link >7/ You are now on the interface to translate the item type's description >in the languages you want. So translate some :) >8/ Go back on the item type list view (admin/itemtypes.pl) >9/ You should see the original description (non translated) >10/ Switch the language >11/ You should see the translated description in the correct language. >If the description is non translated, the original description is >displayed. > >12/ On the different page where the item type is displayed, confirm that >the translated description appears. > >Think further / Todo: >1/ Update all occurrences of the item type's description (DONE) >2/ Implement for authorised values >3/ Implement for syspref value (at least textarea) >4/ Implement for branch names >5/ Centralize all the translation on a single page in the admin area >... >N/ Implement a webservice to centralize all the translations and give >the ability to sync the item types/authorised values description with >the rest of the world (push and pull). > >Signed-off-by: Josef Moravec <josef.moravec@gmail.com> >--- > C4/Items.pm | 9 +- > C4/Koha.pm | 49 ++++- > C4/Search.pm | 12 +- > Koha/Localization.pm | 28 +++ > Koha/Localizations.pm | 34 ++++ > Koha/Template/Plugin/ItemTypes.pm | 7 +- > admin/itemtypes.pl | 50 +++-- > admin/localization.pl | 64 +++++++ > authorities/authorities.pl | 16 +- > catalogue/search.pl | 2 +- > cataloguing/addbiblio.pl | 17 +- > cataloguing/additem.pl | 11 +- > .../Bug_14100-add_table_localization.sql | 8 + > installer/data/mysql/kohastructure.sql | 14 ++ > .../prog/en/modules/admin/itemtypes.tt | 23 ++- > .../prog/en/modules/admin/localization.tt | 212 +++++++++++++++++++++ > svc/checkouts | 7 +- > svc/localization | 92 +++++++++ > tools/batchMod.pl | 15 +- > 19 files changed, 581 insertions(+), 89 deletions(-) > create mode 100644 Koha/Localization.pm > create mode 100644 Koha/Localizations.pm > create mode 100755 admin/localization.pl > create mode 100644 installer/data/mysql/atomicupdate/Bug_14100-add_table_localization.sql > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt > create mode 100755 svc/localization > >diff --git a/C4/Items.pm b/C4/Items.pm >index 0e639dc..087b20d 100644 >--- a/C4/Items.pm >+++ b/C4/Items.pm >@@ -3006,13 +3006,12 @@ sub PrepareItemrecordDisplay { > > #----- itemtypes > } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { >- my $sth = $dbh->prepare( "SELECT itemtype,description FROM itemtypes ORDER BY description" ); >- $sth->execute; >+ my $itemtypes = GetItemTypes( style => 'array' ); > push @authorised_values, "" > unless ( $tagslib->{$tag}->{$subfield}->{mandatory} ); >- while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { >- push @authorised_values, $itemtype; >- $authorised_lib{$itemtype} = $description; >+ for my $itemtype ( @$itemtypes ) { >+ push @authorised_values, $itemtype->{itemtype}; >+ $authorised_lib{$itemtype->{itemtype}} = $itemtype->{translated_description}; > } > #---- class_sources > } elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "cn_source" ) { >diff --git a/C4/Koha.pm b/C4/Koha.pm >index bca12d6..8a573c0 100644 >--- a/C4/Koha.pm >+++ b/C4/Koha.pm >@@ -254,15 +254,30 @@ sub GetItemTypes { > my ( %params ) = @_; > my $style = defined( $params{'style'} ) ? $params{'style'} : 'hash'; > >+ my $language = C4::Languages::getlanguage(); > # returns a reference to a hash of references to itemtypes... > my %itemtypes; > my $dbh = C4::Context->dbh; >- my $query = qq| >- SELECT * >+ my $query = q| >+ SELECT >+ itemtypes.itemtype, >+ itemtypes.description, >+ itemtypes.rentalcharge, >+ itemtypes.notforloan, >+ itemtypes.imageurl, >+ itemtypes.summary, >+ itemtypes.checkinmsg, >+ itemtypes.checkinmsgtype, >+ itemtypes.sip_media_type, >+ COALESCE( localization.translation, itemtypes.description ) AS translated_description > FROM itemtypes >+ LEFT JOIN localization ON itemtypes.itemtype = localization.code >+ AND localization.entity = 'itemtypes' >+ AND localization.lang = ? >+ ORDER BY itemtype > |; > my $sth = $dbh->prepare($query); >- $sth->execute; >+ $sth->execute( $language ); > > if ( $style eq 'hash' ) { > while ( my $IT = $sth->fetchrow_hashref ) { >@@ -486,14 +501,30 @@ Defaults to intranet. > > sub getitemtypeinfo { > my ($itemtype, $interface) = @_; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare("select * from itemtypes where itemtype=?"); >- $sth->execute($itemtype); >- my $res = $sth->fetchrow_hashref; >+ my $dbh = C4::Context->dbh; >+ my $language = C4::Languages::getlanguage(); >+ my $it = $dbh->selectrow_hashref(q| >+ SELECT >+ itemtypes.itemtype, >+ itemtypes.description, >+ itemtypes.rentalcharge, >+ itemtypes.notforloan, >+ itemtypes.imageurl, >+ itemtypes.summary, >+ itemtypes.checkinmsg, >+ itemtypes.checkinmsgtype, >+ itemtypes.sip_media_type, >+ COALESCE( localization.translation, itemtypes.description ) AS translated_description >+ FROM itemtypes >+ LEFT JOIN localization ON itemtypes.itemtype = localization.code >+ AND localization.entity = 'itemtypes' >+ AND localization.lang = ? >+ WHERE itemtypes.itemtype = ? >+ |, undef, $language, $itemtype ); > >- $res->{imageurl} = getitemtypeimagelocation( ( ( defined $interface && $interface eq 'opac' ) ? 'opac' : 'intranet' ), $res->{imageurl} ); >+ $it->{imageurl} = getitemtypeimagelocation( ( ( defined $interface && $interface eq 'opac' ) ? 'opac' : 'intranet' ), $it->{imageurl} ); > >- return $res; >+ return $it; > } > > =head2 getitemtypeimagedir >diff --git a/C4/Search.pm b/C4/Search.pm >index e0f34bf..04e77f8 100644 >--- a/C4/Search.pm >+++ b/C4/Search.pm >@@ -1874,15 +1874,9 @@ sub searchResults { > #Build itemtype hash > #find itemtype & itemtype image > my %itemtypes; >- $bsth = >- $dbh->prepare( >- "SELECT itemtype,description,imageurl,summary,notforloan FROM itemtypes" >- ); >- $bsth->execute(); >- while ( my $bdata = $bsth->fetchrow_hashref ) { >- foreach (qw(description imageurl summary notforloan)) { >- $itemtypes{ $bdata->{'itemtype'} }->{$_} = $bdata->{$_}; >- } >+ my $itemtypes = GetItemTypes( style => 'array' ); >+ for my $itemtype ( @$itemtypes ) { >+ $itemtypes{ $itemtype->{itemtype} } = $itemtype; > } > > #search item field code >diff --git a/Koha/Localization.pm b/Koha/Localization.pm >new file mode 100644 >index 0000000..013db3a >--- /dev/null >+++ b/Koha/Localization.pm >@@ -0,0 +1,28 @@ >+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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+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 >new file mode 100644 >index 0000000..bcbd8c2 >--- /dev/null >+++ b/Koha/Localizations.pm >@@ -0,0 +1,34 @@ >+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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+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/Template/Plugin/ItemTypes.pm b/Koha/Template/Plugin/ItemTypes.pm >index 800e151..0f16601 100644 >--- a/Koha/Template/Plugin/ItemTypes.pm >+++ b/Koha/Template/Plugin/ItemTypes.pm >@@ -27,11 +27,8 @@ use C4::Koha; > sub GetDescription { > my ( $self, $itemtype ) = @_; > >- my $query = "SELECT description FROM itemtypes WHERE itemtype = ?"; >- my $sth = C4::Context->dbh->prepare($query); >- $sth->execute($itemtype); >- my $d = $sth->fetchrow_hashref(); >- return $d->{description} >+ my $itemtype = C4::Koha::getitemtypeinfo( $itemtype ); >+ return $itemtype->{translated_description}; > > } > >diff --git a/admin/itemtypes.pl b/admin/itemtypes.pl >index 3aa9c1d..25c32dd 100755 >--- a/admin/itemtypes.pl >+++ b/admin/itemtypes.pl >@@ -52,18 +52,7 @@ use C4::Context; > use C4::Auth; > use C4::Output; > >-sub StringSearch { >- my ( $searchstring, $type ) = @_; >- my $dbh = C4::Context->dbh; >- $searchstring =~ s/\'/\\\'/g; >- my @data = split( ' ', $searchstring ); >- my $sth = $dbh->prepare( >- "SELECT * FROM itemtypes WHERE (description LIKE ?) ORDER BY itemtype" >- ); >- $sth->execute("$data[0]%"); >- return $sth->fetchall_arrayref({}); # return ref-to-array of ref-to-hashes >- # like [ fetchrow_hashref(), fetchrow_hashref() ... ] >-} >+use Koha::Localizations; > > my $input = new CGI; > my $searchfield = $input->param('description'); >@@ -99,8 +88,26 @@ if ( $op eq 'add_form' ) { > #---- if primkey exists, it's a modify action, so read values to modify... > my $data; > if ($itemtype) { >- my $sth = $dbh->prepare("select * from itemtypes where itemtype=?"); >- $sth->execute($itemtype); >+ my $sth = $dbh->prepare(q| >+ SELECT >+ itemtypes.itemtype, >+ itemtypes.description, >+ itemtypes.rentalcharge, >+ itemtypes.notforloan, >+ itemtypes.imageurl, >+ itemtypes.summary, >+ itemtypes.checkinmsg, >+ itemtypes.checkinmsgtype, >+ itemtypes.sip_media_type, >+ COALESCE( localization.translation, itemtypes.description ) AS translated_description >+ FROM itemtypes >+ LEFT JOIN localization ON itemtypes.itemtype = localization.code >+ AND localization.entity='itemtypes' >+ AND localization.lang = ? >+ WHERE itemtype = ? >+ |); >+ my $language = C4::Languages::getlanguage(); >+ $sth->execute($language, $itemtype); > $data = $sth->fetchrow_hashref; > } > >@@ -249,11 +256,24 @@ elsif ( $op eq 'delete_confirmed' ) { > } > > if ( $op eq 'list' ) { >- my ($results) = StringSearch( $searchfield, 'web' ); >+ my $results = C4::Koha::GetItemTypes( style => 'array' ); > my @loop; > foreach my $itemtype ( @{$results} ) { > $itemtype->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtype->{imageurl} ); > $itemtype->{rentalcharge} = sprintf( '%.2f', $itemtype->{rentalcharge} ); >+ >+ my @translated_descriptions = Koha::Localizations->search( >+ { entity => 'itemtypes', >+ code => $itemtype->{itemtype}, >+ } >+ ); >+ $itemtype->{translated_descriptions} = [ map { >+ { >+ lang => $_->lang, >+ translation => $_->translation, >+ } >+ } @translated_descriptions ]; >+ > push( @loop, $itemtype ); > } > >diff --git a/admin/localization.pl b/admin/localization.pl >new file mode 100755 >index 0000000..061b979 >--- /dev/null >+++ b/admin/localization.pl >@@ -0,0 +1,64 @@ >+#!/usr/bin/perl >+ >+# 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 C4::Auth; >+use C4::Output; >+ >+use Koha::Localization; >+use Koha::Localizations; >+ >+use CGI qw( -utf8 ); >+ >+my $query = new CGI; >+ >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { template_name => "admin/localization.tt", >+ authnotrequired => 0, >+ flagsrequired => { parameters => 'parameters_remaining_permissions' }, >+ query => $query, >+ type => "intranet", >+ debug => 1, >+ } >+); >+ >+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/authorities/authorities.pl b/authorities/authorities.pl >index 16910c8..1753de6 100755 >--- a/authorities/authorities.pl >+++ b/authorities/authorities.pl >@@ -83,23 +83,17 @@ sub build_authorized_values_list { > push @authorised_values, $branchcode; > $authorised_lib{$branchcode} = $branchname; > } >- >- #----- itemtypes > } > elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { >- my $sth = >- $dbh->prepare( >- "select itemtype,description from itemtypes order by description"); >- $sth->execute; > push @authorised_values, "" > unless ( $tagslib->{$tag}->{$subfield}->{mandatory} > && ( $value || $tagslib->{$tag}->{$subfield}->{defaultvalue} ) ); >- >+ > my $itemtype; >- >- while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { >- push @authorised_values, $itemtype; >- $authorised_lib{$itemtype} = $description; >+ my $itemtypes = GetItemTypes( style => 'array' ); >+ for my $itemtype ( @$itemtypes ) { >+ push @authorised_values, $itemtype->{itemtype}; >+ $authorised_lib{$itemtype->{itemtype}} = $itemtype->{translated_description}; > } > $value = $itemtype unless ($value); > >diff --git a/catalogue/search.pl b/catalogue/search.pl >index 43d7f29..0bd2cc6 100755 >--- a/catalogue/search.pl >+++ b/catalogue/search.pl >@@ -266,7 +266,7 @@ foreach my $advanced_srch_type (@advanced_search_types) { > my %row =( number=>$cnt++, > ccl => "$itype_or_itemtype,phr", > code => $thisitemtype, >- description => $itemtypes->{$thisitemtype}->{'description'}, >+ description => $itemtypes->{$thisitemtype}->{translated_description}, > imageurl=> getitemtypeimagelocation( 'intranet', $itemtypes->{$thisitemtype}->{'imageurl'} ), > ); > push @itypesloop, \%row; >diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl >index 890db0f..93f092f 100755 >--- a/cataloguing/addbiblio.pl >+++ b/cataloguing/addbiblio.pl >@@ -184,26 +184,19 @@ sub build_authorized_values_list { > $authorised_lib{$thisbranch} = $branches->{$thisbranch}->{'branchname'}; > } > >- #----- itemtypes > } > elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { >- my $sth = >- $dbh->prepare( >- "select itemtype,description from itemtypes order by description"); >- $sth->execute; > push @authorised_values, "" > unless ( $tagslib->{$tag}->{$subfield}->{mandatory} > && ( $value || $tagslib->{$tag}->{$subfield}->{defaultvalue} ) ); >- >+ > my $itemtype; >- >- while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { >- push @authorised_values, $itemtype; >- $authorised_lib{$itemtype} = $description; >+ my $itemtypes = GetItemTypes( style => 'array' ); >+ for my $itemtype ( @$itemtypes ) { >+ push @authorised_values, $itemtype->{itemtype}; >+ $authorised_lib{$itemtype->{itemtype}} = $itemtype->{translated_description}; > } > $value = $itemtype unless ($value); >- >- #---- class_sources > } > elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "cn_source" ) { > push @authorised_values, "" >diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl >index 38f5d92..f331d47 100755 >--- a/cataloguing/additem.pl >+++ b/cataloguing/additem.pl >@@ -176,13 +176,12 @@ sub generate_subfield_form { > } > elsif ( $subfieldlib->{authorised_value} eq "itemtypes" ) { > push @authorised_values, "" unless ( $subfieldlib->{mandatory} ); >- my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description"); >- $sth->execute; >- while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { >- push @authorised_values, $itemtype; >- $authorised_lib{$itemtype} = $description; >+ my $itemtypes = GetItemTypes( style => 'array' ); >+ for my $itemtype ( @$itemtypes ) { >+ push @authorised_values, $itemtype->{itemtype}; >+ $authorised_lib{$itemtype->{itemtype}} = $itemtype->{translated_description}; > } >- >+ > unless ( $value ) { > my $itype_sth = $dbh->prepare("SELECT itemtype FROM biblioitems WHERE biblionumber = ?"); > $itype_sth->execute( $biblionumber ); >diff --git a/installer/data/mysql/atomicupdate/Bug_14100-add_table_localization.sql b/installer/data/mysql/atomicupdate/Bug_14100-add_table_localization.sql >new file mode 100644 >index 0000000..83bdb9d >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/Bug_14100-add_table_localization.sql >@@ -0,0 +1,8 @@ >+CREATE TABLE `localization` ( >+ localization_id int(11) NOT NULL AUTO_INCREMENT, >+ entity varchar(16) COLLATE utf8_unicode_ci NOT NULL, >+ code varchar(64) COLLATE utf8_unicode_ci NOT NULL, >+ lang varchar(25) COLLATE utf8_unicode_ci NOT NULL, >+ translation text COLLATE utf8_unicode_ci, >+ PRIMARY KEY (localization_id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index fd58258..8548c98 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -3536,6 +3536,20 @@ CREATE TABLE discharges ( > CONSTRAINT borrower_discharges_ibfk1 FOREIGN KEY (borrower) REFERENCES borrowers (borrowernumber) ON DELETE CASCADE ON UPDATE CASCADE > ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; > >+-- >+-- Table structure for table 'localization' >+-- >+ >+DROP TABLE IF EXISTS localization; >+CREATE TABLE `localization` ( >+ localization_id int(11) NOT NULL AUTO_INCREMENT, >+ entity varchar(16) COLLATE utf8_unicode_ci NOT NULL, >+ code varchar(64) COLLATE utf8_unicode_ci NOT NULL, >+ lang varchar(25) COLLATE utf8_unicode_ci NOT NULL, --could be a foreign key >+ translation text COLLATE utf8_unicode_ci, >+ PRIMARY KEY (localization_id) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; >+ > /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; > /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; > /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; >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 a3d8af4..8b48ad6 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/itemtypes.tt >@@ -20,6 +20,7 @@ Data deleted > </title> > [% INCLUDE 'doc-head-close.inc' %] > <link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >+[% INCLUDE 'greybox.inc' %] > [% INCLUDE 'datatables.inc' %] > <script type="text/javascript"> > //<![CDATA[ >@@ -124,7 +125,9 @@ Item types administration > </li> > [% END %] > <li> >- <label for="description" class="required">Description: </label><input type="text" id="description" name="description" size="48" value="[% description |html %]" required="required" /> <span class="required">Required</span></li> >+ <label for="description" class="required">Description: </label><input type="text" id="description" name="description" size="48" value="[% description |html %]" required="required" /> <span class="required">Required</span> >+ <a href="/cgi-bin/koha/admin/localization.pl?entity=itemtypes&code=[% itemtype %]" title="Translate" rel="gb_page_center[600,500]"><i class="icon-edit"></i> Translate for other languages</a> >+ </li> > [% IF ( noItemTypeImages ) %] > <li><span class="label">Image: </span>Item type images are disabled. To enable them, turn off the <a href="/cgi-bin/koha/admin/preferences.pl?op=search&searchfield=noItemTypeImages">noItemTypeImages system preference</a></li></ol> > [% ELSE %]</ol> >@@ -253,7 +256,7 @@ Item types administration > <td>[% itemtype %]</td> > </tr> > >- <tr><th scope="row">Description</th><td>[% description %]</td></tr> >+ <tr><th scope="row">Description</th><td>[% translated_description %]</td></tr> > <tr><th scope="row">Loan length</th><td>[% loanlength %]</td></tr> > <tr><th scope="row">Rental charge</th><td>[% rentalcharge %]</td></tr></table> > <form action="[% script_name %]" method="post"> >@@ -289,7 +292,21 @@ Item types administration > [% loo.itemtype %] > </a> > </td> >- <td>[% loo.description %]</td> >+ <td> >+ [% IF loo.translated_descriptions.size %] >+ [% loo.description %] (default)<br/> >+ [% FOR description IN loo.translated_descriptions %] >+ [% IF description.translation == loo.translated_description %] >+ <b>[% description.translation %]</b> >+ [% ELSE %] >+ [% description.translation %] ([% description.lang %]) >+ [% END %] >+ <br/> >+ [% END %] >+ [% ELSE %] >+ [% loo.description %] >+ [% END %] >+ </td> > <td>[% IF ( loo.notforloan ) %]Yes[% ELSE %] [% END %]</td> > <td> > [% UNLESS ( loo.notforloan ) %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt >new file mode 100644 >index 0000000..ab6ca72 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/localization.tt >@@ -0,0 +1,212 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Localization</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >+[% INCLUDE 'greybox.inc' %] >+[% INCLUDE 'datatables.inc' %] >+<script type="text/javascript"> >+//<![CDATA[ >+ >+ 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>'); >+ 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>'); >+ 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.is_changed ) { >+ $(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', '#FF0000'); >+ 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', '#FF0000'); >+ show_message({ type: 'error_on_delete', data: data }); >+ }, >+ }); >+ } >+ >+ $(document).ready(function() { >+ $(".dialog").hide(); >+ >+ var table = $("#localization").DataTable($.extend(true, {}, dataTablesDefaults, { >+ 'bPaginate': false, >+ })); >+ >+ var languages_select = $('<select name="lang"></select>'); >+ [% FOR language IN languages %] >+ var option = $('<option value="[% language.lang %]">[% language.description %]</option>'); >+ $(languages_select).append(option); >+ [% 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 ); >+ }); >+ >+ $("a.delete").on('click', function(){ >+ 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', >+ url: '/cgi-bin/koha/svc/localization', >+ success: function (data) { >+ // FIXME Should append the delete link >+ table.row.add( [ data.id, data.entity, data.code, data.lang, data.translation, "" ] ).draw(); >+ show_message({ type: 'success_on_insert', data: data }); >+ }, >+ error: function (data) { >+ show_message({ type: 'error_on_insert', data: data }); >+ }, >+ }); >+ }); >+ >+ }); >+//]]> >+</script> >+</head> >+<body id="admin_localization" class="admin"> >+<div id="main"> >+<table id="localization"> >+ <thead> >+ <tr> >+ <th>Id</th> >+ <th>Entity</th> >+ <th>Code</th> >+ <th>Lang</th> >+ <th>Translation</th> >+ <th></th> >+ </tr> >+ </thead> >+ <tbody> >+ [% FOR t IN translations %] >+ <tr id="row_id_[% t.id %]" data-id="[% t.id %]"> >+ <td>[% t.id %]</td> >+ <td>[% t.entity %]</td> >+ <td>[% t.code %]</td> >+ <td class="lang">[% t.lang %]</td> >+ <td class="translation" contenteditable="true">[% t.translation %]</td> >+ <td><a class="delete" title="Delete this translation"><i class="icon-remove"></i></a</td> >+ </tr> >+ [% END %] >+ </tbody> >+</table> >+<form id="add_translation" method="post"> >+ <input type="hidden" name="entity" value="[% entity %]" /> >+ <input type="hidden" name="code" value="[% code %]" /> >+ Lang: <select name="lang"> >+ [% FOR language IN languages %] >+ [% FOR sublanguage IN language.sublanguages_loop %] >+ [% IF language.plural %] >+ <option value="[% sublanguage.rfc4646_subtag %]">[% sublanguage.native_description %] [% sublanguage.region_description %] ([% sublanguage.rfc4646_subtag %])</option> >+ [% ELSE %] >+ <option value="[% sublanguage.rfc4646_subtag %]">[% sublanguage.native_description %] ([% sublanguage.rfc4646_subtag %])</option> >+ [% END %] >+ [% END %] >+ [% END %] >+ </select> >+ Translation: <input type="text" name="translation" /> >+ <input type="submit" value="Add" /> >+</form> >+<div id="messages"></div> >+</div> >+</body> >+</html> >diff --git a/svc/checkouts b/svc/checkouts >index cc703ae..6ecfd09 100755 >--- a/svc/checkouts >+++ b/svc/checkouts >@@ -83,9 +83,7 @@ my $sql = ' > branchname, > > items.itype, >- itemtype_item.description AS itype_description, > biblioitems.itemtype, >- itemtype_bib.description AS itemtype_description, > > borrowernumber, > surname, >@@ -103,8 +101,6 @@ my $sql = ' > LEFT JOIN biblioitems USING ( biblionumber ) > LEFT JOIN borrowers USING ( borrowernumber ) > LEFT JOIN branches ON ( issues.branchcode = branches.branchcode ) >- LEFT JOIN itemtypes itemtype_bib ON ( biblioitems.itemtype = itemtype_bib.itemtype ) >- LEFT JOIN itemtypes itemtype_item ON ( items.itype = itemtype_item.itemtype ) > WHERE borrowernumber > '; > >@@ -145,13 +141,14 @@ while ( my $c = $sth->fetchrow_hashref() ) { > my ( $renewals_count, $renewals_allowed, $renewals_remaining ) = > GetRenewCount( $c->{borrowernumber}, $c->{itemnumber} ); > >+ my $itemtype = C4::Koha::getitemtypeinfo( $item_level_itypes ? $c->{itype} : $c->{itemtype} ); > my $checkout = { > DT_RowId => $c->{itemnumber} . '-' . $c->{borrowernumber}, > title => $c->{title}, > author => $c->{author}, > barcode => $c->{barcode}, > itemtype => $item_level_itypes ? $c->{itype} : $c->{itemtype}, >- itemtype_description => $item_level_itypes ? $c->{itype_description} : $c->{itemtype_description}, >+ itemtype_description => $itemtype->{translated_description}, > location => $c->{location} ? GetAuthorisedValueByCode( 'LOC', $c->{location} ) : q{}, > itemnotes => $c->{itemnotes}, > branchcode => $c->{branchcode}, >diff --git a/svc/localization b/svc/localization >new file mode 100755 >index 0000000..ebec0e2 >--- /dev/null >+++ b/svc/localization >@@ -0,0 +1,92 @@ >+#!/usr/bin/perl >+ >+use Modern::Perl; >+ >+use C4::Service; >+use Koha::Localizations; >+ >+our ( $query, $response ) = C4::Service->init( parameters => 'parameters_remaining_permissions' ); >+ >+sub get_translations { >+ my $rs = Koha::Localizations->search({ type => $query->param('type'), code => $query->param('code') }); >+ my @translations; >+ while ( my $s = $rs->next ) { >+ push @translations, { >+ id => $s->localization_id, >+ type => $s->type, >+ code => $s->code, >+ lang => $s->lang, >+ translation => $s->translation, >+ } >+ } >+ $response->param( translations => \@translations ); >+ C4::Service->return_success( $response ); >+} >+ >+sub update_translation { >+ my $id = $query->param('id'); >+ my $translation = $query->param('translation'); >+ my $lang = $query->param('lang'); >+ 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 $is_changed; >+ if ( $localization->is_changed ) { >+ $is_changed = 1; >+ $localization->store; >+ } >+ $response->param( >+ id => $localization->localization_id, >+ entity => $localization->entity, >+ code => $localization->code, >+ lang => $localization->lang, >+ translation => $localization->translation, >+ is_changed => $is_changed, >+ ); >+ C4::Service->return_success( $response ); >+} >+ >+sub add_translation { >+ my $entity = $query->param('entity'); >+ my $code = $query->param('code'); >+ my $lang = $query->param('lang'); >+ my $translation = $query->param('translation'); >+ my $localization = Koha::Localization->new( >+ { >+ entity => $entity, >+ code => $code, >+ lang => $lang, >+ translation => $translation, >+ } >+ ); >+ $localization->store; >+ $localization->localization_id; >+ $response->param( >+ id => $localization->localization_id, >+ entity => $localization->entity, >+ code => $localization->code, >+ lang => $localization->lang, >+ translation => $localization->translation, >+ ); >+ >+ C4::Service->return_success( $response ); >+} >+ >+sub delete_translation { >+ my $id = $query->param('id'); >+ Koha::Localizations->find($id)->delete; >+ $response->param( id => $id ); >+ C4::Service->return_success( $response ); >+} >+ >+C4::Service->dispatch( >+ [ 'GET /', [ 'id' ], \&get_translations ], >+ [ 'PUT /', [ 'id' ], \&update_translation ], >+ [ 'POST /', [ 'entity', 'code', 'lang', 'translation' ], \&add_translation ], >+ [ 'DELETE /', ['id'], \&delete_translation ], >+); >diff --git a/tools/batchMod.pl b/tools/batchMod.pl >index 4ed0f10..831f9ef 100755 >--- a/tools/batchMod.pl >+++ b/tools/batchMod.pl >@@ -354,14 +354,13 @@ foreach my $tag (sort keys %{$tagslib}) { > } > $value = ""; > } >- elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { >- push @authorised_values, ""; >- my $sth = $dbh->prepare("select itemtype,description from itemtypes order by description"); >- $sth->execute; >- while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) { >- push @authorised_values, $itemtype; >- $authorised_lib{$itemtype} = $description; >- } >+ elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) { >+ push @authorised_values, ""; >+ my $itemtypes = GetItemTypes( style => 'array' ); >+ for my $itemtype ( @$itemtypes ) { >+ push @authorised_values, $itemtype->{itemtype}; >+ $authorised_lib{$itemtype->{itemtype}} = $itemtype->{translated_description}; >+ } > $value = ""; > > #---- class_sources >-- >2.1.0
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 14100
:
38727
|
40917
|
40965
|
41654
|
41659
|
41660
|
42525
|
42526
|
43110
|
43111
|
43365
|
43366
|
43367
|
43368
|
43369
|
43370
|
43394
|
43395
|
43396
|
43577
|
43602
|
43603
|
43604
|
43605
|
43606
|
43613
|
44085
|
44086
|
44087
|
44088
|
44089
|
44090
|
44094
|
44108
|
44109
|
44119
|
44151