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.
23 # WARNING: Any other tested YAML library fails to work properly in this
25 use YAML
::Syck
qw( Dump LoadFile );
27 use FindBin
qw( $Bin );
29 $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-t-prog/ } readdir($fh);
68 $self->{langs} = \@langs;
70 # Map for both interfaces opac/intranet
71 my $opachtdocs = $context->config('opachtdocs');
72 $self->{interface} = [
75 dir => "$opachtdocs/prog",
76 suffix => '-i-opac-t-prog-v-3006000.po',
79 name => 'Intranet prog',
80 dir => $context->config('intrahtdocs') . '/prog',
81 suffix => '-i-staff-t-prog-v-3006000.po',
85 # Alternate opac themes
86 opendir $fh, $context->config('opachtdocs');
87 for ( grep { not /^\.|\.\.|prog|lib$/ } readdir($fh) ) {
88 push @{$self->{interface}}, {
90 dir => "$opachtdocs/$_",
91 suffix => "-opac-$_.po",
102 my $context = C4::Context->new;
103 my $trans_path = $Bin . '/po';
104 my $trans_file = "$trans_path/" . $self->{lang} . "-pref.po";
110 my ($self, $id, $comment) = @_;
111 my $po = $self->{po};
114 $p->comment( $p->comment . "\n" . $comment );
117 $po->{$id} = Locale::PO->new(
118 -comment => $comment,
127 my ($self, $comment, $prefs) = @_;
129 for my $pref ( @$prefs ) {
131 for my $element ( @$pref ) {
132 if ( ref( $element) eq 'HASH' ) {
133 $pref_name = $element->{pref};
137 for my $element ( @$pref ) {
138 if ( ref( $element) eq 'HASH' ) {
139 while ( my ($key, $value) = each(%$element) ) {
140 next unless $key eq 'choices';
141 next unless ref($value) eq 'HASH';
142 for my $ckey ( keys %$value ) {
143 my $id = $self->{file} . "#$pref_name# " . $value->{$ckey};
144 $self->po_append( $id, $comment );
148 elsif ( $element && $pref_name ) {
149 $self->po_append( $self->{file} . "#$pref_name# $element", $comment );
157 my ($self, $id) = @_;
159 my $po = $self->{po}->{$id};
161 return Locale::PO->dequote($po->msgstr);
165 sub update_tab_prefs {
166 my ($self, $pref, $prefs) = @_;
168 for my $p ( @$prefs ) {
171 for my $element ( @$p ) {
172 if ( ref( $element) eq 'HASH' ) {
173 $pref_name = $element->{pref};
177 for my $i ( 0..@$p-1 ) {
178 my $element = $p->[$i];
179 if ( ref( $element) eq 'HASH' ) {
180 while ( my ($key, $value) = each(%$element) ) {
181 next unless $key eq 'choices';
182 next unless ref($value) eq 'HASH';
183 for my $ckey ( keys %$value ) {
184 my $id = $self->{file} . "#$pref_name# " . $value->{$ckey};
185 my $text = $self->get_trans_text( $id );
186 $value->{$ckey} = $text if $text;
190 elsif ( $element && $pref_name ) {
191 my $id = $self->{file} . "#$pref_name# $element";
192 my $text = $self->get_trans_text( $id );
193 $p->[$i] = $text if $text;
200 sub get_po_from_prefs {
203 for my $file ( @{$self->{pref_files}} ) {
204 my $pref = LoadFile( $self->{path_pref_en} . "/$file" );
205 $self->{file} = $file;
206 # Entries for tab titles
207 $self->po_append( $self->{file}, $_ ) for keys %$pref;
208 while ( my ($tab, $tab_content) = each %$pref ) {
209 if ( ref($tab_content) eq 'ARRAY' ) {
210 $self->add_prefs( $tab, $tab_content );
213 while ( my ($section, $sysprefs) = each %$tab_content ) {
214 my $comment = "$tab > $section";
215 $self->po_append( $self->{file} . " " . $section, $comment );
216 $self->add_prefs( $comment, $sysprefs );
225 # Write .po entries into a file put in Koha standard po directory
226 Locale::PO->save_file_fromhash( $self->po_filename, $self->{po} );
227 say "Saved in file: ", $self->po_filename if $self->{verbose};
231 sub get_po_merged_with_en {
234 # Get po from current 'en' .pref files
235 $self->get_po_from_prefs();
236 my $po_current = $self->{po};
238 # Get po from previous generation
239 my $po_previous = Locale::PO->load_file_ashash( $self->po_filename );
241 for my $id ( keys %$po_current ) {
242 my $po = $po_previous->{Locale::PO->quote($id)};
244 my $text = Locale::PO->dequote( $po->msgstr );
245 $po_current->{$id}->msgstr( $text );
252 print "Update '", $self->{lang},
253 "' preferences .po file from 'en' .pref files\n" if $self->{verbose};
254 $self->get_po_merged_with_en();
262 unless ( -r $self->{po_path_lang} ) {
263 print "Koha directories hierarchy for ", $self->{lang}, " must be created first\n";
267 # Get the language .po file merged with last modified 'en' preferences
268 $self->get_po_merged_with_en();
270 for my $file ( @{$self->{pref_files}} ) {
271 my $pref = LoadFile( $self->{path_pref_en} . "/$file" );
272 $self->{file} = $file;
273 # First, keys are replaced (tab titles)
276 $self->get_trans_text( $self->{file} ) || $_ => $pref->{$_}
280 while ( my ($tab, $tab_content) = each %$pref ) {
281 if ( ref($tab_content) eq 'ARRAY' ) {
282 $self->update_tab_prefs( $pref, $tab_content );
285 while ( my ($section, $sysprefs) = each %$tab_content ) {
286 $self->update_tab_prefs( $pref, $sysprefs );
289 for my $section ( keys %$tab_content ) {
290 my $id = $self->{file} . " $section";
291 my $text = $self->get_trans_text($id);
292 my $nsection = $text ? $text : $section;
293 $ntab->{$nsection} = $tab_content->{$section};
295 $pref->{$tab} = $ntab;
297 my $file_trans = $self->{po_path_lang} . "/$file";
298 print "Write $file\n" if $self->{verbose};
299 open my $fh, ">", $file_trans;
300 print $fh Dump($pref);
307 say "Install templates" if $self->{verbose};
308 for my $trans ( @{$self->{interface}} ) {
310 " Install templates '$trans->{name}'\n",
311 " From: $trans->{dir}/en/\n",
312 " To : $trans->{dir}/$self->{lang}\n",
313 " With: $self->{path_po}/$self->{lang}$trans->{suffix}\n"
315 my $lang_dir = "$trans->{dir}/$self->{lang}";
316 mkdir $lang_dir unless -d $lang_dir;
318 "$self->{process} install " .
319 "-i $trans->{dir}/en/ " .
320 "-o $trans->{dir}/$self->{lang} ".
321 "-s $self->{path_po}/$self->{lang}$trans->{suffix} -r"
329 say "Update templates" if $self->{verbose};
330 for my $trans ( @{$self->{interface}} ) {
332 " Update templates '$trans->{name}'\n",
333 " From: $trans->{dir}/en/\n",
334 " To : $self->{path_po}/$self->{lang}$trans->{suffix}\n"
336 my $lang_dir = "$trans->{dir}/$self->{lang}";
337 mkdir $lang_dir unless -d $lang_dir;
339 "$self->{process} update " .
340 "-i $trans->{dir}/en/ " .
341 "-s $self->{path_po}/$self->{lang}$trans->{suffix} -r"
349 if ( -e $self->po_filename ) {
350 say "Preferences .po file already exists. Delete it if you want to recreate it.";
353 $self->get_po_from_prefs();
361 say "Create templates\n" if $self->{verbose};
362 for my $trans ( @{$self->{interface}} ) {
364 " Create templates .po files for '$trans->{name}'\n",
365 " From: $trans->{dir}/en/\n",
366 " To : $self->{path_po}/$self->{lang}$trans->{suffix}\n"
369 "$self->{process} create " .
370 "-i $trans->{dir}/en/ " .
371 "-s $self->{path_po}/$self->{lang}$trans->{suffix} -r"
378 return unless $self->{lang};
379 $self->install_tmpl() unless $self->{pref_only};
380 $self->install_prefs();
386 opendir( my $dh, $self->{path_po} );
387 my @files = grep { $_ =~ /-i-opac-t-prog-v-3006000.po$/ }
389 @files = map { $_ =~ s/-i-opac-t-prog-v-3006000.po$//; $_ } @files;
395 my @langs = $self->{lang} ? ($self->{lang}) : $self->get_all_langs();
396 for my $lang ( @langs ) {
397 $self->set_lang( $lang );
398 $self->update_tmpl() unless $self->{pref_only};
399 $self->update_prefs();
406 return unless $self->{lang};
407 $self->create_tmpl() unless $self->{pref_only};
408 $self->create_prefs();
418 LangInstaller.pm - Handle templates and preferences translation
422 my $installer = LangInstaller->new( 'fr-FR' );
423 $installer->create();
424 $installer->update();
425 $installer->install();
426 for my $lang ( @{$installer->{langs} ) {
427 $installer->set_lang( $lan );
428 $installer->install();
435 Create a new instance of the installer object.
439 For the current language, create .po files for templates and preferences based
440 of the english ('en') version.
444 For the current language, update .po files.
448 For the current langage C<$self->{lang}, use .po files to translate the english
449 version of templates and preferences files and copy those files in the
450 appropriate directory.
454 =item translate create F<lang>
456 Create 3 .po files in F<po> subdirectory: (1) from opac pages templates, (2)
457 intranet templates, and (3) from preferences.
461 =item F<lang>-opac.po
463 Contains extracted text from english (en) OPAC templates found in
464 <KOHA_ROOT>/koha-tmpl/opac-tmpl/prog/en/ directory.
466 =item F<lang>-intranet.po
468 Contains extracted text from english (en) intranet templates found in
469 <KOHA_ROOT>/koha-tmpl/intranet-tmpl/prog/en/ directory.
471 =item F<lang>-pref.po
473 Contains extracted text from english (en) preferences. They are found in files
474 located in <KOHA_ROOT>/koha-tmpl/intranet-tmpl/prog/en/admin/preferences
479 =item pref-trans update F<lang>
481 Update .po files in F<po> directory, named F<lang>-*.po.
483 =item pref-trans install F<lang>