3 # Copyright (C) 2010 Tamil s.a.r.l.
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 # WARNING: Any other tested YAML library fails to work properly in this
26 use YAML::Syck qw( Dump LoadFile );
28 use FindBin qw( $Bin );
30 $YAML::Syck::ImplicitTyping = 1;
33 my ($self, $lang) = @_;
35 $self->{lang} = $lang;
36 $self->{po_path_lang} = $self->{context}->config('intrahtdocs') .
37 "/prog/$lang/modules/admin/preferences";
42 my ($class, $lang, $pref_only, $verbose) = @_;
46 my $context = C4::Context->new();
47 $self->{context} = $context;
48 $self->{path_pref_en} = $context->config('intrahtdocs') .
49 '/prog/en/modules/admin/preferences';
50 set_lang( $self, $lang ) if $lang;
51 $self->{pref_only} = $pref_only;
52 $self->{verbose} = $verbose;
53 $self->{process} = "$Bin/tmpl_process3.pl " . ($verbose ? '' : '-q');
54 $self->{path_po} = "$Bin/po";
57 # Get all .pref file names
58 opendir my $fh, $self->{path_pref_en};
59 my @pref_files = grep { /.pref/ } readdir($fh);
61 $self->{pref_files} = \@pref_files;
63 # Get all available language codes
64 opendir $fh, $self->{path_po};
65 my @langs = map { ($_) =~ /(.*)-i-opac/ }
66 grep { $_ =~ /.*-opac-/ } readdir($fh);
68 $self->{langs} = \@langs;
70 # Map for both interfaces opac/intranet
71 $self->{interface} = {
73 dir => $context->config('opachtdocs') . '/prog',
74 suffix => '-i-opac-t-prog-v-3006000.po',
77 dir => $context->config('intrahtdocs') . '/prog',
78 suffix => '-i-staff-t-prog-v-3006000.po',
89 my $context = C4::Context->new;
90 my $trans_path = $Bin . '/po';
91 my $trans_file = "$trans_path/" . $self->{lang} . "-pref.po";
97 my ($self, $id, $comment) = @_;
101 $p->comment( $p->comment . "\n" . $comment );
104 $po->{$id} = Locale::PO->new(
105 -comment => $comment,
114 my ($self, $comment, $prefs) = @_;
116 for my $pref ( @$prefs ) {
118 for my $element ( @$pref ) {
119 if ( ref( $element) eq 'HASH' ) {
120 $pref_name = $element->{pref};
124 for my $element ( @$pref ) {
125 if ( ref( $element) eq 'HASH' ) {
126 while ( my ($key, $value) = each(%$element) ) {
127 next unless $key eq 'choices';
128 next unless ref($value) eq 'HASH';
129 for my $ckey ( keys %$value ) {
130 my $id = $self->{file} . "#$pref_name# " . $value->{$ckey};
131 $self->po_append( $id, $comment );
135 elsif ( $element && $pref_name ) {
136 $self->po_append( $self->{file} . "#$pref_name# $element", $comment );
144 my ($self, $id) = @_;
146 my $po = $self->{po}->{$id};
148 return Locale::PO->dequote($po->msgstr);
152 sub update_tab_prefs {
153 my ($self, $pref, $prefs) = @_;
155 for my $p ( @$prefs ) {
158 for my $element ( @$p ) {
159 if ( ref( $element) eq 'HASH' ) {
160 $pref_name = $element->{pref};
164 for my $i ( 0..@$p-1 ) {
165 my $element = $p->[$i];
166 if ( ref( $element) eq 'HASH' ) {
167 while ( my ($key, $value) = each(%$element) ) {
168 next unless $key eq 'choices';
169 next unless ref($value) eq 'HASH';
170 for my $ckey ( keys %$value ) {
171 my $id = $self->{file} . "#$pref_name# " . $value->{$ckey};
172 my $text = $self->get_trans_text( $id );
173 $value->{$ckey} = $text if $text;
177 elsif ( $element && $pref_name ) {
178 my $id = $self->{file} . "#$pref_name# $element";
179 my $text = $self->get_trans_text( $id );
180 $p->[$i] = $text if $text;
187 sub get_po_from_prefs {
190 for my $file ( @{$self->{pref_files}} ) {
191 my $pref = LoadFile( $self->{path_pref_en} . "/$file" );
192 $self->{file} = $file;
193 # Entries for tab titles
194 $self->po_append( $self->{file}, $_ ) for keys %$pref;
195 while ( my ($tab, $tab_content) = each %$pref ) {
196 if ( ref($tab_content) eq 'ARRAY' ) {
197 $self->add_prefs( $tab, $tab_content );
200 while ( my ($section, $sysprefs) = each %$tab_content ) {
201 my $comment = "$tab > $section";
202 $self->po_append( $self->{file} . " " . $section, $comment );
203 $self->add_prefs( $comment, $sysprefs );
212 # Write .po entries into a file put in Koha standard po directory
213 Locale::PO->save_file_fromhash( $self->po_filename, $self->{po} );
214 print "Saved in file: ", $self->po_filename, "\n" if $self->{verbose};
218 sub get_po_merged_with_en {
221 # Get po from current 'en' .pref files
222 $self->get_po_from_prefs();
223 my $po_current = $self->{po};
225 # Get po from previous generation
226 my $po_previous = Locale::PO->load_file_ashash( $self->po_filename );
228 for my $id ( keys %$po_current ) {
229 my $po = $po_previous->{Locale::PO->quote($id)};
231 my $text = Locale::PO->dequote( $po->msgstr );
232 $po_current->{$id}->msgstr( $text );
239 print "Update '", $self->{lang},
240 "' preferences .po file from 'en' .pref files\n" if $self->{verbose};
241 $self->get_po_merged_with_en();
249 unless ( -r $self->{po_path_lang} ) {
250 print "Koha directories hierarchy for ", $self->{lang}, " must be created first\n";
254 # Get the language .po file merged with last modified 'en' preferences
255 $self->get_po_merged_with_en();
257 for my $file ( @{$self->{pref_files}} ) {
258 my $pref = LoadFile( $self->{path_pref_en} . "/$file" );
259 $self->{file} = $file;
260 # First, keys are replaced (tab titles)
263 $self->get_trans_text( $self->{file} ) || $_ => $pref->{$_}
267 while ( my ($tab, $tab_content) = each %$pref ) {
268 if ( ref($tab_content) eq 'ARRAY' ) {
269 $self->update_tab_prefs( $pref, $tab_content );
272 while ( my ($section, $sysprefs) = each %$tab_content ) {
273 $self->update_tab_prefs( $pref, $sysprefs );
276 for my $section ( keys %$tab_content ) {
277 my $id = $self->{file} . " $section";
278 my $text = $self->get_trans_text($id);
279 my $nsection = $text ? $text : $section;
280 $ntab->{$nsection} = $tab_content->{$section};
282 $pref->{$tab} = $ntab;
284 my $file_trans = $self->{po_path_lang} . "/$file";
285 print "Write $file\n" if $self->{verbose};
286 open my $fh, ">", $file_trans;
287 print $fh Dump($pref);
294 print "Install templates\n" if $self->{verbose};
295 while ( my ($interface, $tmpl) = each %{$self->{interface}} ) {
297 " Install templates '$interface\n",
298 " From: $tmpl->{dir}/en/\n",
299 " To : $tmpl->{dir}/$self->{lang}\n",
300 " With: $self->{path_po}/$self->{lang}$tmpl->{suffix}\n"
302 my $lang_dir = "$tmpl->{dir}/$self->{lang}";
303 mkdir $lang_dir unless -d $lang_dir;
305 "$self->{process} install " .
306 "-i $tmpl->{dir}/en/ " .
307 "-o $tmpl->{dir}/$self->{lang} ".
308 "-s $self->{path_po}/$self->{lang}$tmpl->{suffix} -r"
316 print "Update templates\n" if $self->{verbose};
317 while ( my ($interface, $tmpl) = each %{$self->{interface}} ) {
319 " Update templates '$interface'\n",
320 " From: $tmpl->{dir}/en/\n",
321 " To : $self->{path_po}/$self->{lang}$tmpl->{suffix}\n"
323 my $lang_dir = "$tmpl->{dir}/$self->{lang}";
324 mkdir $lang_dir unless -d $lang_dir;
326 "$self->{process} update " .
327 "-i $tmpl->{dir}/en/ " .
328 "-s $self->{path_po}/$self->{lang}$tmpl->{suffix} -r"
336 $self->get_po_from_prefs();
344 print "Create templates\n" if $self->{verbose};
345 while ( my ($interface, $tmpl) = each %{$self->{interface}} ) {
347 " Create templates .po files for '$interface'\n",
348 " From: $tmpl->{dir}/en/\n",
349 " To : $self->{path_po}/$self->{lang}$tmpl->{suffix}\n"
352 "$self->{process} create " .
353 "-i $tmpl->{dir}/en/ " .
354 "-s $self->{path_po}/$self->{lang}$tmpl->{suffix} -r"
361 return unless $self->{lang};
362 $self->install_tmpl() unless $self->{pref_only};
363 $self->install_prefs();
369 opendir( my $dh, $self->{path_po} );
370 my @files = grep { $_ =~ /-i-opac-t-prog-v-3006000.po$/ }
372 @files = map { $_ =~ s/-i-opac-t-prog-v-3006000.po$//; $_ } @files;
378 my @langs = $self->{lang} ? ($self->{lang}) : $self->get_all_langs();
379 for my $lang ( @langs ) {
380 $self->set_lang( $lang );
381 $self->update_tmpl() unless $self->{pref_only};
382 $self->update_prefs();
389 return unless $self->{lang};
390 $self->create_tmpl() unless $self->{pref_only};
391 $self->create_prefs();
401 LangInstaller.pm - Handle templates and preferences translation
405 my $installer = LangInstaller->new( 'fr-FR' );
406 $installer->create();
407 $installer->update();
408 $installer->install();
409 for my $lang ( @{$installer->{langs} ) {
410 $installer->set_lang( $lan );
411 $installer->install();
418 Create a new instance of the installer object.
422 For the current language, create .po files for templates and preferences based
423 of the english ('en') version.
427 For the current language, update .po files.
431 For the current langage C<$self->{lang}, use .po files to translate the english
432 version of templates and preferences files and copy those files in the
433 appropriate directory.
437 =item translate create F<lang>
439 Create 3 .po files in F<po> subdirectory: (1) from opac pages templates, (2)
440 intranet templates, and (3) from preferences.
444 =item F<lang>-opac.po
446 Contains extracted text from english (en) OPAC templates found in
447 <KOHA_ROOT>/koha-tmpl/opac-tmpl/prog/en/ directory.
449 =item F<lang>-intranet.po
451 Contains extracted text from english (en) intranet templates found in
452 <KOHA_ROOT>/koha-tmpl/intranet-tmpl/prog/en/ directory.
454 =item F<lang>-pref.po
456 Contains extracted text from english (en) preferences. They are found in files
457 located in <KOHA_ROOT>/koha-tmpl/intranet-tmpl/prog/en/admin/preferences
462 =item pref-trans update F<lang>
464 Update .po files in F<po> directory, named F<lang>-*.po.
466 =item pref-trans install F<lang>