View | Details | Raw Unified | Return to bug 37472
Collapse All | Expand All

(-)a/misc/translator/LangInstaller.pm (-154 / +159 lines)
Lines 20-69 package LangInstaller; Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use C4::Context;
22
use C4::Context;
23
23
# WARNING: Any other tested YAML library fails to work properly in this
24
# WARNING: Any other tested YAML library fails to work properly in this
24
# script content
25
# script content
25
# FIXME Really?
26
# FIXME Really?
26
use YAML::XS;
27
use YAML::XS;
27
use Locale::PO;
28
use Locale::PO;
28
use FindBin qw( $Bin );
29
use FindBin    qw( $Bin );
29
use File::Path qw( make_path );
30
use File::Path qw( make_path );
30
use File::Copy;
31
use File::Copy;
31
use File::Slurp qw( read_file );
32
use File::Slurp qw( read_file );
32
use JSON qw( decode_json encode_json );
33
use JSON        qw( decode_json encode_json );
33
34
34
use Koha::Plugins;
35
use Koha::Plugins;
35
36
36
sub set_lang {
37
sub set_lang {
37
    my ($self, $lang) = @_;
38
    my ( $self, $lang ) = @_;
38
39
39
    $self->{lang} = $lang;
40
    $self->{lang}         = $lang;
40
    $self->{po_path_lang} = C4::Context->config('intrahtdocs') .
41
    $self->{po_path_lang} = C4::Context->config('intrahtdocs') . "/prog/$lang/modules/admin/preferences";
41
                            "/prog/$lang/modules/admin/preferences";
42
}
42
}
43
43
44
sub new {
44
sub new {
45
    my ($class, $args) = @_;
45
    my ( $class, $args ) = @_;
46
46
47
    my $lang        = $args->{lang};
47
    my $lang      = $args->{lang};
48
    my $pref_only   = $args->{pref_only};
48
    my $pref_only = $args->{pref_only};
49
    my $verbose     = $args->{verbose};
49
    my $verbose   = $args->{verbose};
50
50
51
    my $self                 = { };
51
    my $self = {};
52
52
53
    $self->{path_pref_en}    = C4::Context->config('intrahtdocs') .
53
    $self->{path_pref_en} = C4::Context->config('intrahtdocs') . '/prog/en/modules/admin/preferences';
54
                               '/prog/en/modules/admin/preferences';
55
    set_lang( $self, $lang ) if $lang;
54
    set_lang( $self, $lang ) if $lang;
56
    $self->{pref_only}       = $pref_only;
55
    $self->{pref_only}   = $pref_only;
57
    $self->{verbose}         = $verbose;
56
    $self->{verbose}     = $verbose;
58
    $self->{process}         = "$Bin/tmpl_process3.pl " . ($verbose ? '' : '-q');
57
    $self->{process}     = "$Bin/tmpl_process3.pl " . ( $verbose ? '' : '-q' );
59
    $self->{path_po}         = "$Bin/po";
58
    $self->{path_po}     = "$Bin/po";
60
    $self->{po}              = {};
59
    $self->{po}          = {};
61
    $self->{domain}          = 'Koha';
60
    $self->{domain}      = 'Koha';
62
    $self->{msgfmt}          = `which msgfmt`;
61
    $self->{msgfmt}      = `which msgfmt`;
63
    $self->{po2json}         = "yarn run po2json";
62
    $self->{po2json}     = "yarn run po2json";
64
    $self->{gzip}            = `which gzip`;
63
    $self->{gzip}        = `which gzip`;
65
    $self->{gunzip}          = `which gunzip`;
64
    $self->{gunzip}      = `which gunzip`;
66
    $self->{plugin_dirs}     = _identify_translatable_plugins();
65
    $self->{plugin_dirs} = _identify_translatable_plugins();
67
    chomp $self->{msgfmt};
66
    chomp $self->{msgfmt};
68
    chomp $self->{gzip};
67
    chomp $self->{gzip};
69
    chomp $self->{gunzip};
68
    chomp $self->{gunzip};
Lines 76-82 sub new { Link Here
76
75
77
    # Get all available language codes
76
    # Get all available language codes
78
    opendir $fh, $self->{path_po};
77
    opendir $fh, $self->{path_po};
79
    my @langs =  map { ($_) =~ /(.*)-pref/ }
78
    my @langs = map { ($_) =~ /(.*)-pref/ }
80
        grep { $_ =~ /.*-pref/ } readdir($fh);
79
        grep { $_ =~ /.*-pref/ } readdir($fh);
81
    closedir $fh;
80
    closedir $fh;
82
    $self->{langs} = \@langs;
81
    $self->{langs} = \@langs;
Lines 94-100 sub new { Link Here
94
    # OPAC themes
93
    # OPAC themes
95
    opendir my $dh, C4::Context->config('opachtdocs');
94
    opendir my $dh, C4::Context->config('opachtdocs');
96
    for my $theme ( grep { not /^\.|lib|xslt/ } readdir($dh) ) {
95
    for my $theme ( grep { not /^\.|lib|xslt/ } readdir($dh) ) {
97
        push @{$self->{interface}}, {
96
        push @{ $self->{interface} }, {
98
            name   => "OPAC $theme",
97
            name   => "OPAC $theme",
99
            dir    => "$opachtdocs/$theme",
98
            dir    => "$opachtdocs/$theme",
100
            suffix => "-opac-$theme.po",
99
            suffix => "-opac-$theme.po",
Lines 103-115 sub new { Link Here
103
102
104
    # MARC flavours (hardcoded list)
103
    # MARC flavours (hardcoded list)
105
    for ( "MARC21", "UNIMARC" ) {
104
    for ( "MARC21", "UNIMARC" ) {
105
106
        # search for strings on staff & opac marc files
106
        # search for strings on staff & opac marc files
107
        my $dirs = C4::Context->config('intrahtdocs') . '/prog';
107
        my $dirs = C4::Context->config('intrahtdocs') . '/prog';
108
        opendir $fh, C4::Context->config('opachtdocs');
108
        opendir $fh, C4::Context->config('opachtdocs');
109
        for ( grep { not /^\.|\.\.|lib$|xslt/ } readdir($fh) ) {
109
        for ( grep { not /^\.|\.\.|lib$|xslt/ } readdir($fh) ) {
110
            $dirs .= ' ' . "$opachtdocs/$_";
110
            $dirs .= ' ' . "$opachtdocs/$_";
111
        }
111
        }
112
        push @{$self->{interface}}, {
112
        push @{ $self->{interface} }, {
113
            name   => "$_",
113
            name   => "$_",
114
            dir    => $dirs,
114
            dir    => $dirs,
115
            suffix => "-marc-$_.po",
115
            suffix => "-marc-$_.po",
Lines 117-146 sub new { Link Here
117
    }
117
    }
118
118
119
    # EN YAML installer files
119
    # EN YAML installer files
120
    push @{$self->{installer}}, {
120
    push @{ $self->{installer} }, {
121
        name   => "YAML installer files",
121
        name => "YAML installer files",
122
        dirs   => [ 'installer/data/mysql/en/mandatory',
122
        dirs => [
123
                    'installer/data/mysql/en/optional'],
123
            'installer/data/mysql/en/mandatory',
124
            'installer/data/mysql/en/optional'
125
        ],
124
        suffix => "-installer.po",
126
        suffix => "-installer.po",
125
    };
127
    };
126
128
127
    # EN MARC21 YAML installer files
129
    # EN MARC21 YAML installer files
128
    push @{$self->{installer}}, {
130
    push @{ $self->{installer} }, {
129
        name   => "MARC21 YAML installer files",
131
        name => "MARC21 YAML installer files",
130
        dirs   => [ 'installer/data/mysql/en/marcflavour/marc21/mandatory',
132
        dirs => [
131
                    'installer/data/mysql/en/marcflavour/marc21/optional'],
133
            'installer/data/mysql/en/marcflavour/marc21/mandatory',
134
            'installer/data/mysql/en/marcflavour/marc21/optional'
135
        ],
132
        suffix => "-installer-MARC21.po",
136
        suffix => "-installer-MARC21.po",
133
    };
137
    };
134
138
135
    # EN UNIMARC YAML installer files
139
    # EN UNIMARC YAML installer files
136
    push @{$self->{installer}}, {
140
    push @{ $self->{installer} }, {
137
        name   => "UNIMARC YAML installer files",
141
        name => "UNIMARC YAML installer files",
138
        dirs   => [ 'installer/data/mysql/en/marcflavour/unimarc/mandatory',
142
        dirs => [
139
                    'installer/data/mysql/en/marcflavour/unimarc/optional'],
143
            'installer/data/mysql/en/marcflavour/unimarc/mandatory',
144
            'installer/data/mysql/en/marcflavour/unimarc/optional'
145
        ],
140
        suffix => "-installer-UNIMARC.po",
146
        suffix => "-installer-UNIMARC.po",
141
    };
147
    };
142
148
143
144
    bless $self, $class;
149
    bless $self, $class;
145
}
150
}
146
151
Lines 154-165 sub po_filename { Link Here
154
}
159
}
155
160
156
sub get_trans_text {
161
sub get_trans_text {
157
    my ($self, $msgid, $default) = @_;
162
    my ( $self, $msgid, $default ) = @_;
158
163
159
    my $po = $self->{po}->{Locale::PO->quote($msgid)};
164
    my $po = $self->{po}->{ Locale::PO->quote($msgid) };
160
    if ( $po and not defined( $po->fuzzy() ) ) {
165
    if ( $po and not defined( $po->fuzzy() ) ) {
161
        my $msgstr = Locale::PO->dequote($po->msgstr);
166
        my $msgstr = Locale::PO->dequote( $po->msgstr );
162
        if ($msgstr and length($msgstr) > 0) {
167
        if ( $msgstr and length($msgstr) > 0 ) {
163
            return $msgstr;
168
            return $msgstr;
164
        }
169
        }
165
    }
170
    }
Lines 168-197 sub get_trans_text { Link Here
168
}
173
}
169
174
170
sub get_translated_tab_content {
175
sub get_translated_tab_content {
171
    my ($self, $file, $tab_content) = @_;
176
    my ( $self, $file, $tab_content ) = @_;
172
177
173
    if ( ref($tab_content) eq 'ARRAY' ) {
178
    if ( ref($tab_content) eq 'ARRAY' ) {
174
        return $self->get_translated_prefs($file, $tab_content);
179
        return $self->get_translated_prefs( $file, $tab_content );
175
    }
180
    }
176
181
177
    my $translated_tab_content = {
182
    my $translated_tab_content = {
178
        map {
183
        map {
179
            my $section = $_;
184
            my $section  = $_;
180
            my $sysprefs = $tab_content->{$section};
185
            my $sysprefs = $tab_content->{$section};
181
            my $msgid = sprintf('%s %s', $file, $section);
186
            my $msgid    = sprintf( '%s %s', $file, $section );
182
187
183
            $self->get_trans_text($msgid, $section) => $self->get_translated_prefs($file, $sysprefs);
188
            $self->get_trans_text( $msgid, $section ) => $self->get_translated_prefs( $file, $sysprefs );
184
        } keys %$tab_content
189
        } keys %$tab_content
185
    };
190
    };
186
191
187
    if ( keys %$translated_tab_content != keys %$tab_content ) {
192
    if ( keys %$translated_tab_content != keys %$tab_content ) {
188
        my %duplicates;
193
        my %duplicates;
189
        for my $section (keys %$tab_content) {
194
        for my $section ( keys %$tab_content ) {
190
            push @{$duplicates{$self->get_trans_text("$file $section", $section)}}, $section;
195
            push @{ $duplicates{ $self->get_trans_text( "$file $section", $section ) } }, $section;
191
        }
196
        }
192
        for my $translation (keys %duplicates) {
197
        for my $translation ( keys %duplicates ) {
193
            if (@{$duplicates{$translation}} > 1) {
198
            if ( @{ $duplicates{$translation} } > 1 ) {
194
                warn qq(In file "$file", "$translation" is a translation for sections ") . join('", "', @{$duplicates{$translation}}) . '"';
199
                warn qq(In file "$file", "$translation" is a translation for sections ")
200
                    . join( '", "', @{ $duplicates{$translation} } ) . '"';
195
            }
201
            }
196
        }
202
        }
197
    }
203
    }
Lines 200-217 sub get_translated_tab_content { Link Here
200
}
206
}
201
207
202
sub get_translated_prefs {
208
sub get_translated_prefs {
203
    my ($self, $file, $sysprefs) = @_;
209
    my ( $self, $file, $sysprefs ) = @_;
204
210
205
    my $translated_prefs = [
211
    my $translated_prefs = [
206
        map {
212
        map {
207
            my ($pref_elt) = grep { ref($_) eq 'HASH' && exists $_->{pref} } @$_;
213
            my ($pref_elt) = grep { ref($_) eq 'HASH' && exists $_->{pref} } @$_;
208
            my $pref_name = $pref_elt ? $pref_elt->{pref} : '';
214
            my $pref_name = $pref_elt ? $pref_elt->{pref} : '';
209
215
210
            my $translated_syspref = [
216
            my $translated_syspref = [ map { $self->get_translated_pref( $file, $pref_name, $_ ); } @$_ ];
211
                map {
212
                    $self->get_translated_pref($file, $pref_name, $_);
213
                } @$_
214
            ];
215
217
216
            $translated_syspref;
218
            $translated_syspref;
217
        } @$sysprefs
219
        } @$sysprefs
Lines 221-247 sub get_translated_prefs { Link Here
221
}
223
}
222
224
223
sub get_translated_pref {
225
sub get_translated_pref {
224
    my ($self, $file, $pref_name, $syspref) = @_;
226
    my ( $self, $file, $pref_name, $syspref ) = @_;
225
227
226
    unless (ref($syspref)) {
228
    unless ( ref($syspref) ) {
227
        $syspref //= '';
229
        $syspref //= '';
228
        my $msgid = sprintf('%s#%s# %s', $file, $pref_name, $syspref);
230
        my $msgid = sprintf( '%s#%s# %s', $file, $pref_name, $syspref );
229
        return $self->get_trans_text($msgid, $syspref);
231
        return $self->get_trans_text( $msgid, $syspref );
230
    }
232
    }
231
233
232
    my $translated_pref = {
234
    my $translated_pref = {
233
        map {
235
        map {
234
            my $key = $_;
236
            my $key   = $_;
235
            my $value = $syspref->{$key};
237
            my $value = $syspref->{$key};
236
238
237
            my $translated_value = $value;
239
            my $translated_value = $value;
238
            if (($key eq 'choices' || $key eq 'multiple') && ref($value) eq 'HASH') {
240
            if ( ( $key eq 'choices' || $key eq 'multiple' ) && ref($value) eq 'HASH' ) {
239
                $translated_value = {
241
                $translated_value = {
240
                    map {
242
                    map {
241
                        my $msgid = sprintf('%s#%s# %s', $file, $pref_name, $value->{$_});
243
                        my $msgid = sprintf( '%s#%s# %s', $file, $pref_name, $value->{$_} );
242
                        $_ => $self->get_trans_text($msgid, $value->{$_})
244
                        $_ => $self->get_trans_text( $msgid, $value->{$_} )
243
                    } keys %$value
245
                    } keys %$value
244
                }
246
                };
245
            }
247
            }
246
248
247
            $key => $translated_value
249
            $key => $translated_value
Lines 259-304 sub install_prefs { Link Here
259
        exit;
261
        exit;
260
    }
262
    }
261
263
262
    $self->{po} = Locale::PO->load_file_ashash($self->po_filename("-pref.po"), 'utf8');
264
    $self->{po} = Locale::PO->load_file_ashash( $self->po_filename("-pref.po"), 'utf8' );
263
265
264
    for my $file ( @{$self->{pref_files}} ) {
266
    for my $file ( @{ $self->{pref_files} } ) {
265
        my $pref = YAML::XS::LoadFile( $self->{path_pref_en} . "/$file" );
267
        my $pref = YAML::XS::LoadFile( $self->{path_pref_en} . "/$file" );
266
268
267
        my $translated_pref = {
269
        my $translated_pref = {
268
            map {
270
            map {
269
                my $tab = $_;
271
                my $tab         = $_;
270
                my $tab_content = $pref->{$tab};
272
                my $tab_content = $pref->{$tab};
271
273
272
                $self->get_trans_text($file, $tab) => $self->get_translated_tab_content($file, $tab_content);
274
                $self->get_trans_text( $file, $tab ) => $self->get_translated_tab_content( $file, $tab_content );
273
            } keys %$pref
275
            } keys %$pref
274
        };
276
        };
275
277
276
        if ( keys %$translated_pref != keys %$pref ) {
278
        if ( keys %$translated_pref != keys %$pref ) {
277
            my %duplicates;
279
            my %duplicates;
278
            for my $tab (keys %$pref) {
280
            for my $tab ( keys %$pref ) {
279
                push @{$duplicates{$self->get_trans_text($file, $tab)}}, $tab;
281
                push @{ $duplicates{ $self->get_trans_text( $file, $tab ) } }, $tab;
280
            }
282
            }
281
            for my $translation (keys %duplicates) {
283
            for my $translation ( keys %duplicates ) {
282
                if (@{$duplicates{$translation}} > 1) {
284
                if ( @{ $duplicates{$translation} } > 1 ) {
283
                    warn qq(In file "$file", "$translation" is a translation for tabs ") . join('", "', @{$duplicates{$translation}}) . '"';
285
                    warn qq(In file "$file", "$translation" is a translation for tabs ")
286
                        . join( '", "', @{ $duplicates{$translation} } ) . '"';
284
                }
287
                }
285
            }
288
            }
286
        }
289
        }
287
290
288
        my $file_trans = $self->{po_path_lang} . "/$file";
291
        my $file_trans = $self->{po_path_lang} . "/$file";
289
        print "Write $file\n" if $self->{verbose};
292
        print "Write $file\n" if $self->{verbose};
290
        YAML::XS::DumpFile($file_trans, $translated_pref);
293
        YAML::XS::DumpFile( $file_trans, $translated_pref );
291
    }
294
    }
292
}
295
}
293
296
294
295
sub install_tmpl {
297
sub install_tmpl {
296
    my ($self, $files) = @_;
298
    my ( $self, $files ) = @_;
297
    say "Install templates" if $self->{verbose};
299
    say "Install templates" if $self->{verbose};
298
    for my $trans ( @{$self->{interface}} ) {
300
    for my $trans ( @{ $self->{interface} } ) {
299
        my @t_dirs = split(" ", $trans->{dir});
301
        my @t_dirs = split( " ", $trans->{dir} );
300
        for my $t_dir ( @t_dirs ) {
302
        for my $t_dir (@t_dirs) {
301
            my @files   = @$files;
303
            my @files  = @$files;
302
            my @nomarc = ();
304
            my @nomarc = ();
303
            print
305
            print
304
                "  Install templates '$trans->{name}'\n",
306
                "  Install templates '$trans->{name}'\n",
Lines 311-329 sub install_tmpl { Link Here
311
            my $lang_dir  = "$t_dir/$self->{lang}";
313
            my $lang_dir  = "$t_dir/$self->{lang}";
312
            $lang_dir =~ s|/en/|/$self->{lang}/|;
314
            $lang_dir =~ s|/en/|/$self->{lang}/|;
313
            mkdir $lang_dir unless -d $lang_dir;
315
            mkdir $lang_dir unless -d $lang_dir;
316
314
            # if installing MARC po file, only touch corresponding files
317
            # if installing MARC po file, only touch corresponding files
315
            my $marc     = ( $trans->{name} =~ /MARC/ )?"-m \"$trans->{name}\"":"";            # for MARC translations
318
            my $marc = ( $trans->{name} =~ /MARC/ ) ? "-m \"$trans->{name}\"" : "";    # for MARC translations
316
            # if not installing MARC po file, ignore all MARC files
319
                # if not installing MARC po file, ignore all MARC files
317
            @nomarc      = ( 'marc21', 'unimarc' ) if ( $trans->{name} !~ /MARC/ ); # hardcoded MARC variants
320
            @nomarc = ( 'marc21', 'unimarc' ) if ( $trans->{name} !~ /MARC/ );    # hardcoded MARC variants
318
321
319
            system
322
            system "$self->{process} install "
320
                "$self->{process} install " .
323
                . "-i $trans_dir "
321
                "-i $trans_dir " .
324
                . "-o $lang_dir  "
322
                "-o $lang_dir  ".
325
                . "-s $self->{path_po}/$self->{lang}$trans->{suffix} -r "
323
                "-s $self->{path_po}/$self->{lang}$trans->{suffix} -r " .
326
                . "$marc "
324
                "$marc " .
327
                . ( @files  ? ' -f ' . join ' -f ', @files  : '' )
325
                ( @files   ? ' -f ' . join ' -f ', @files : '') .
328
                . ( @nomarc ? ' -n ' . join ' -n ', @nomarc : '' );
326
                ( @nomarc  ? ' -n ' . join ' -n ', @nomarc : '');
327
        }
329
        }
328
    }
330
    }
329
331
Lines 353-404 sub translate_yaml { Link Here
353
    my $po_file = $self->po_filename( $target->{suffix} );
355
    my $po_file = $self->po_filename( $target->{suffix} );
354
    return $srcyml unless ( -e $po_file );
356
    return $srcyml unless ( -e $po_file );
355
357
356
    my $po_ref  = Locale::PO->load_file_ashash( $po_file, 'utf8' );
358
    my $po_ref = Locale::PO->load_file_ashash( $po_file, 'utf8' );
357
359
358
    my $dstyml   = YAML::XS::LoadFile( $srcyml );
360
    my $dstyml = YAML::XS::LoadFile($srcyml);
359
361
360
    # translate fields in table rows
362
    # translate fields in table rows
361
    my @tables = @{ $dstyml->{'tables'} };
363
    my @tables = @{ $dstyml->{'tables'} };
362
    for my $table ( @tables ) {                                                         # each table
364
    for my $table (@tables) {    # each table
363
        my $table_name = ( keys %$table )[0];
365
        my $table_name   = ( keys %$table )[0];
364
        my @translatable = @{ $table->{$table_name}->{translatable} };
366
        my @translatable = @{ $table->{$table_name}->{translatable} };
365
        my @rows = @{ $table->{$table_name}->{rows} };
367
        my @rows         = @{ $table->{$table_name}->{rows} };
366
        my @multiline = @{ $table->{$table_name}->{'multiline'} };                      # to check multiline values
368
        my @multiline    = @{ $table->{$table_name}->{'multiline'} };    # to check multiline values
367
        for my $row ( @rows ) {                                                         # each row
369
        for my $row (@rows) {                                            # each row
368
            for my $field ( @translatable ) {                                           # each translatable field
370
            for my $field (@translatable) {                              # each translatable field
369
                if ( @multiline and grep { $_ eq $field } @multiline ) {                # multiline fields, only notices ATM
371
                if ( @multiline and grep { $_ eq $field } @multiline ) {    # multiline fields, only notices ATM
370
                    foreach my $line ( @{$row->{$field}} ) {
372
                    foreach my $line ( @{ $row->{$field} } ) {
371
                        my @ttvar;
373
                        my @ttvar;
372
                        while ( $line =~ s/(<<.*?>>|\[\%.*?\%\]|<.*?>)/\%s/ ) {         # put placeholders, save matches
374
                        while ( $line =~ s/(<<.*?>>|\[\%.*?\%\]|<.*?>)/\%s/ ) {    # put placeholders, save matches
373
                            my $var = $1;
375
                            my $var = $1;
374
                            push @ttvar, $var;
376
                            push @ttvar, $var;
375
                        }
377
                        }
376
378
377
                        if ( $line =~ /^(\s|%s|-|[[:punct:]]|\(|\))*$/ ) {              # ignore non strings
379
                        if ( $line =~ /^(\s|%s|-|[[:punct:]]|\(|\))*$/ ) {         # ignore non strings
378
                            while ( @ttvar ) {                                          # restore placeholders
380
                            while (@ttvar) {                                       # restore placeholders
379
                                my $var = shift @ttvar;
381
                                my $var = shift @ttvar;
380
                                $line =~ s/\%s/$var/;
382
                                $line =~ s/\%s/$var/;
381
                            }
383
                            }
382
                            next;
384
                            next;
383
                        } else {
385
                        } else {
384
                            my $po = $po_ref->{"\"$line\""};                            # quoted key
386
                            my $po = $po_ref->{"\"$line\""};                       # quoted key
385
                            if ( $po  and not defined( $po->fuzzy() )                   # not fuzzy
387
                            if (
386
                                      and length( $po->msgid() ) > 2                    # not empty msgid
388
                                $po and not defined( $po->fuzzy() )                # not fuzzy
387
                                      and length( $po->msgstr() ) > 2 ) {               # not empty msgstr
389
                                and length( $po->msgid() ) > 2                     # not empty msgid
390
                                and length( $po->msgstr() ) > 2
391
                                )
392
                            {                                                      # not empty msgstr
388
                                $line = $po->dequote( $po->msgstr() );
393
                                $line = $po->dequote( $po->msgstr() );
389
                            }
394
                            }
390
                            while ( @ttvar ) {                                          # restore placeholders
395
                            while (@ttvar) {                                       # restore placeholders
391
                                my $var = shift @ttvar;
396
                                my $var = shift @ttvar;
392
                                $line =~ s/\%s/$var/;
397
                                $line =~ s/\%s/$var/;
393
                            }
398
                            }
394
                        }
399
                        }
395
                    }
400
                    }
396
                } else {
401
                } else {
397
                    next unless defined $row->{$field};                                 # next if null value
402
                    next unless defined $row->{$field};          # next if null value
398
                    my $po = $po_ref->{"\"$row->{$field}\""};                           # quoted key
403
                    my $po = $po_ref->{"\"$row->{$field}\""};    # quoted key
399
                    if ( $po  and not defined( $po->fuzzy() )                           # not fuzzy
404
                    if (
400
                              and length( $po->msgid() ) > 2                            # not empty msgid
405
                        $po and not defined( $po->fuzzy() )      # not fuzzy
401
                              and length( $po->msgstr() ) > 2 ) {                       # not empty msgstr
406
                        and length( $po->msgid() ) > 2           # not empty msgid
407
                        and length( $po->msgstr() ) > 2
408
                        )
409
                    {                                            # not empty msgstr
402
                        $row->{$field} = $po->dequote( $po->msgstr() );
410
                        $row->{$field} = $po->dequote( $po->msgstr() );
403
                    }
411
                    }
404
                }
412
                }
Lines 409-417 sub translate_yaml { Link Here
409
    # translate descriptions
417
    # translate descriptions
410
    for my $description ( @{ $dstyml->{'description'} } ) {
418
    for my $description ( @{ $dstyml->{'description'} } ) {
411
        my $po = $po_ref->{"\"$description\""};
419
        my $po = $po_ref->{"\"$description\""};
412
        if ( $po  and not defined( $po->fuzzy() )
420
        if (    $po
413
                  and length( $po->msgid() ) > 2
421
            and not defined( $po->fuzzy() )
414
                  and length( $po->msgstr() ) > 2 ) {
422
            and length( $po->msgid() ) > 2
423
            and length( $po->msgstr() ) > 2 )
424
        {
415
            $description = $po->dequote( $po->msgstr() );
425
            $description = $po->dequote( $po->msgstr() );
416
        }
426
        }
417
    }
427
    }
Lines 425-431 sub install_installer { Link Here
425
435
426
    my $intradir  = C4::Context->config('intranetdir');
436
    my $intradir  = C4::Context->config('intranetdir');
427
    my $db_scheme = C4::Context->config('db_scheme');
437
    my $db_scheme = C4::Context->config('db_scheme');
428
    my $langdir  = "$intradir/installer/data/$db_scheme/$self->{lang}";
438
    my $langdir   = "$intradir/installer/data/$db_scheme/$self->{lang}";
429
439
430
    say "Install installer files\n" if $self->{verbose};
440
    say "Install installer files\n" if $self->{verbose};
431
441
Lines 435-445 sub install_installer { Link Here
435
            ( my $tdir = "$dir" ) =~ s|/en/|/$self->{lang}/|;
445
            ( my $tdir = "$dir" ) =~ s|/en/|/$self->{lang}/|;
436
            make_path("$intradir/$tdir");
446
            make_path("$intradir/$tdir");
437
447
438
            opendir( my $dh, "$intradir/$dir" ) or die ("Can't open $intradir/$dir");
448
            opendir( my $dh, "$intradir/$dir" ) or die("Can't open $intradir/$dir");
439
            my @files = grep { ! /^\.+$/ } readdir($dh);
449
            my @files = grep { !/^\.+$/ } readdir($dh);
440
            close($dh);
450
            close($dh);
441
451
442
            for my $file ( @files ) {
452
            for my $file (@files) {
443
                if ( $file =~ /yml$/ ) {
453
                if ( $file =~ /yml$/ ) {
444
                    my $translated_yaml = translate_yaml( $self, $target, "$intradir/$dir/$file" );
454
                    my $translated_yaml = translate_yaml( $self, $target, "$intradir/$dir/$file" );
445
                    YAML::XS::DumpFile( "$intradir/$tdir/$file", $translated_yaml );
455
                    YAML::XS::DumpFile( "$intradir/$tdir/$file", $translated_yaml );
Lines 454-463 sub install_installer { Link Here
454
sub locale_name {
464
sub locale_name {
455
    my $self = shift;
465
    my $self = shift;
456
466
457
    my ($language, $region, $country) = split /-/, $self->{lang};
467
    my ( $language, $region, $country ) = split /-/, $self->{lang};
458
    $country //= $region;
468
    $country //= $region;
459
    my $locale = $language;
469
    my $locale = $language;
460
    if ($country && length($country) == 2) {
470
    if ( $country && length($country) == 2 ) {
461
        $locale .= '_' . $country;
471
        $locale .= '_' . $country;
462
    }
472
    }
463
473
Lines 467-476 sub locale_name { Link Here
467
sub install_messages {
477
sub install_messages {
468
    my ($self) = @_;
478
    my ($self) = @_;
469
479
470
    my $locale = $self->locale_name();
480
    my $locale    = $self->locale_name();
471
    my $modir = "$self->{path_po}/$locale/LC_MESSAGES";
481
    my $modir     = "$self->{path_po}/$locale/LC_MESSAGES";
472
    my $pofile = "$self->{path_po}/$self->{lang}-messages.po";
482
    my $pofile    = "$self->{path_po}/$self->{lang}-messages.po";
473
    my $mofile = "$modir/$self->{domain}.mo";
483
    my $mofile    = "$modir/$self->{domain}.mo";
474
    my $js_pofile = "$self->{path_po}/$self->{lang}-messages-js.po";
484
    my $js_pofile = "$self->{path_po}/$self->{lang}-messages-js.po";
475
485
476
    unless ( -f $pofile && -f $js_pofile ) {
486
    unless ( -f $pofile && -f $js_pofile ) {
Lines 481-487 sub install_messages { Link Here
481
    make_path($modir);
491
    make_path($modir);
482
    system "$self->{msgfmt} -o $mofile $pofile";
492
    system "$self->{msgfmt} -o $mofile $pofile";
483
493
484
    my $tmp_po = sprintf '/tmp/%s-messages.po', $self->{lang};
494
    my $tmp_po      = sprintf '/tmp/%s-messages.po', $self->{lang};
485
    my $po2json_cmd = sprintf '%s %s %s', $self->{po2json}, $js_pofile, $tmp_po;
495
    my $po2json_cmd = sprintf '%s %s %s', $self->{po2json}, $js_pofile, $tmp_po;
486
    `$po2json_cmd`;
496
    `$po2json_cmd`;
487
    my $json = read_file($tmp_po);
497
    my $json = read_file($tmp_po);
Lines 508-521 sub install_messages { Link Here
508
    my $combined_json = encode_json($js_po_data);
518
    my $combined_json = encode_json($js_po_data);
509
519
510
    my $js_locale_data = sprintf 'var json_locale_data = {"Koha":%s};', $combined_json;
520
    my $js_locale_data = sprintf 'var json_locale_data = {"Koha":%s};', $combined_json;
511
    my $progdir = C4::Context->config('intrahtdocs') . '/prog';
521
    my $progdir        = C4::Context->config('intrahtdocs') . '/prog';
512
    mkdir "$progdir/$self->{lang}/js";
522
    mkdir "$progdir/$self->{lang}/js";
513
    open my $fh, '>', "$progdir/$self->{lang}/js/locale_data.js";
523
    open my $fh, '>', "$progdir/$self->{lang}/js/locale_data.js";
514
    print $fh $js_locale_data;
524
    print $fh $js_locale_data;
515
    close $fh;
525
    close $fh;
516
526
517
    my $opachtdocs = C4::Context->config('opachtdocs');
527
    my $opachtdocs = C4::Context->config('opachtdocs');
518
    opendir(my $dh, $opachtdocs);
528
    opendir( my $dh, $opachtdocs );
519
    for my $theme ( grep { not /^\.|lib|xslt/ } readdir($dh) ) {
529
    for my $theme ( grep { not /^\.|lib|xslt/ } readdir($dh) ) {
520
        mkdir "$opachtdocs/$theme/$self->{lang}/js";
530
        mkdir "$opachtdocs/$theme/$self->{lang}/js";
521
        open my $fh, '>', "$opachtdocs/$theme/$self->{lang}/js/locale_data.js";
531
        open my $fh, '>', "$opachtdocs/$theme/$self->{lang}/js/locale_data.js";
Lines 525-537 sub install_messages { Link Here
525
}
535
}
526
536
527
sub compress {
537
sub compress {
528
    my ($self, $files) = @_;
538
    my ( $self, $files ) = @_;
529
    my @langs = $self->{lang} ? ($self->{lang}) : $self->get_all_langs();
539
    my @langs = $self->{lang} ? ( $self->{lang} ) : $self->get_all_langs();
530
    for my $lang ( @langs ) {
540
    for my $lang (@langs) {
531
        $self->set_lang( $lang );
541
        $self->set_lang($lang);
532
        opendir( my $dh, $self->{path_po} );
542
        opendir( my $dh, $self->{path_po} );
533
        my @files = grep { $_ =~ /^$self->{lang}.*po$/ } readdir $dh;
543
        my @files = grep { $_ =~ /^$self->{lang}.*po$/ } readdir $dh;
534
        foreach my $file ( @files ) {
544
        foreach my $file (@files) {
535
            say "Compress file $file" if $self->{verbose};
545
            say "Compress file $file" if $self->{verbose};
536
            system "$self->{gzip} -9 $self->{path_po}/$file";
546
            system "$self->{gzip} -9 $self->{path_po}/$file";
537
        }
547
        }
Lines 539-551 sub compress { Link Here
539
}
549
}
540
550
541
sub uncompress {
551
sub uncompress {
542
    my ($self, $files) = @_;
552
    my ( $self, $files ) = @_;
543
    my @langs = $self->{lang} ? ($self->{lang}) : $self->get_all_langs();
553
    my @langs = $self->{lang} ? ( $self->{lang} ) : $self->get_all_langs();
544
    for my $lang ( @langs ) {
554
    for my $lang (@langs) {
545
        opendir( my $dh, $self->{path_po} );
555
        opendir( my $dh, $self->{path_po} );
546
        $self->set_lang( $lang );
556
        $self->set_lang($lang);
547
        my @files = grep { $_ =~ /^$self->{lang}.*po.gz$/ } readdir $dh;
557
        my @files = grep { $_ =~ /^$self->{lang}.*po.gz$/ } readdir $dh;
548
        foreach my $file ( @files ) {
558
        foreach my $file (@files) {
549
            say "Uncompress file $file" if $self->{verbose};
559
            say "Uncompress file $file" if $self->{verbose};
550
            system "$self->{gunzip} $self->{path_po}/$file";
560
            system "$self->{gunzip} $self->{path_po}/$file";
551
        }
561
        }
Lines 553-563 sub uncompress { Link Here
553
}
563
}
554
564
555
sub install {
565
sub install {
556
    my ($self, $files) = @_;
566
    my ( $self, $files ) = @_;
557
    return unless $self->{lang};
567
    return unless $self->{lang};
558
    $self->uncompress();
568
    $self->uncompress();
559
569
560
    if ($self->{pref_only}) {
570
    if ( $self->{pref_only} ) {
561
        $self->install_prefs();
571
        $self->install_prefs();
562
    } else {
572
    } else {
563
        $self->install_tmpl($files);
573
        $self->install_tmpl($files);
Lines 567-578 sub install { Link Here
567
    }
577
    }
568
}
578
}
569
579
570
571
sub get_all_langs {
580
sub get_all_langs {
572
    my $self = shift;
581
    my $self = shift;
573
    opendir( my $dh, $self->{path_po} );
582
    opendir( my $dh, $self->{path_po} );
574
    my @files = grep { $_ =~ /-pref.(po|po.gz)$/ }
583
    my @files = grep { $_ =~ /-pref.(po|po.gz)$/ } readdir $dh;
575
        readdir $dh;
576
    @files = map { $_ =~ s/-pref.(po|po.gz)$//r } @files;
584
    @files = map { $_ =~ s/-pref.(po|po.gz)$//r } @files;
577
}
585
}
578
586
Lines 602-611 sub _identify_translatable_plugins { Link Here
602
    return \@plugin_dirs;
610
    return \@plugin_dirs;
603
}
611
}
604
612
605
606
1;
613
1;
607
614
608
609
=head1 NAME
615
=head1 NAME
610
616
611
LangInstaller.pm - Handle templates and preferences translation
617
LangInstaller.pm - Handle templates and preferences translation
612
- 

Return to bug 37472