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

(-)a/misc/translator/LangInstaller.pm (-2 / +8 lines)
Lines 28-33 use Locale::PO; Link Here
28
use FindBin qw( $Bin );
28
use FindBin qw( $Bin );
29
use File::Path qw( make_path );
29
use File::Path qw( make_path );
30
use File::Copy;
30
use File::Copy;
31
use File::Slurp qw( read_file );
31
32
32
sub set_lang {
33
sub set_lang {
33
    my ($self, $lang) = @_;
34
    my ($self, $lang) = @_;
Lines 52-58 sub new { Link Here
52
    $self->{po}              = {};
53
    $self->{po}              = {};
53
    $self->{domain}          = 'Koha';
54
    $self->{domain}          = 'Koha';
54
    $self->{msgfmt}          = `which msgfmt`;
55
    $self->{msgfmt}          = `which msgfmt`;
55
    $self->{po2json}         = "$Bin/po2json";
56
    $self->{po2json}         = "yarn run po2json";
56
    $self->{gzip}            = `which gzip`;
57
    $self->{gzip}            = `which gzip`;
57
    $self->{gunzip}          = `which gunzip`;
58
    $self->{gunzip}          = `which gunzip`;
58
    chomp $self->{msgfmt};
59
    chomp $self->{msgfmt};
Lines 454-460 sub install_messages { Link Here
454
    make_path($modir);
455
    make_path($modir);
455
    system "$self->{msgfmt} -o $mofile $pofile";
456
    system "$self->{msgfmt} -o $mofile $pofile";
456
457
457
    my $js_locale_data = 'var json_locale_data = {"Koha":' . `$self->{po2json} $js_pofile` . '};';
458
    my $tmp_po = sprintf '/tmp/%s-messages.po', $self->{lang};
459
    my $po2json_cmd = sprintf '%s %s %s', $self->{po2json}, $js_pofile, $tmp_po;
460
    `$po2json_cmd`;
461
    my $json = read_file($tmp_po);
462
463
    my $js_locale_data = sprintf 'var json_locale_data = {"Koha":%s};', $json;
458
    my $progdir = C4::Context->config('intrahtdocs') . '/prog';
464
    my $progdir = C4::Context->config('intrahtdocs') . '/prog';
459
    mkdir "$progdir/$self->{lang}/js";
465
    mkdir "$progdir/$self->{lang}/js";
460
    open my $fh, '>', "$progdir/$self->{lang}/js/locale_data.js";
466
    open my $fh, '>', "$progdir/$self->{lang}/js/locale_data.js";
(-)a/misc/translator/po2json (-253 lines)
Lines 1-253 Link Here
1
#!/usr/bin/env perl
2
# PODNAME: po2json
3
# ABSTRACT: Command line tool for converting a po file into a Gettext.js compatible json dataset
4
5
# Copyright (C) 2008, Joshua I. Miller E<lt>unrtst@cpan.orgE<gt>, all
6
# rights reserved.
7
#
8
# This program is free software; you can redistribute it and/or modify it
9
# under the terms of the GNU Library General Public License as published
10
# by the Free Software Foundation; either version 2, or (at your option)
11
# any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
# Library General Public License for more details.
17
#
18
# You should have received a copy of the GNU Library General Public
19
# License along with this program; if not, write to the Free Software
20
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21
# USA.
22
23
24
use strict;
25
use JSON 2.53;
26
use Locale::PO 0.24;
27
use File::Basename qw(basename);
28
29
my $gettext_context_glue = "\004";
30
31
sub usage {
32
    return "$0 {-p} {file.po} > {outputfile.json}
33
    -p  : do pretty-printing of json data\n";
34
}
35
36
&main;
37
38
sub main
39
{
40
    my $src;
41
42
    my $pretty = 0;
43
    if ($ARGV[0] =~ /^--?p$/) {
44
        shift @ARGV;
45
        $pretty = 1;
46
    }
47
48
    if (length($ARGV[0]))
49
    {
50
        if ($ARGV[0] =~ /^-h/) {
51
            print &usage;
52
            exit 1;
53
        }
54
55
        unless (-r $ARGV[0]) {
56
            print "ERROR: Unable to read file [$ARGV[0]]\n";
57
            die &usage;
58
        }
59
60
        $src = $ARGV[0];
61
    } else {
62
        die &usage;
63
    }
64
65
    # we'll be building this data struct
66
    my $json = {};
67
68
    my $plural_form_count;
69
    # get po object stack
70
    my $pos = Locale::PO->load_file_asarray($src) or die "Can't parse po file [$src].";
71
72
73
    foreach my $po (@$pos)
74
    {
75
        my $qmsgid1 = $po->msgid;
76
        my $msgid1 = $po->dequote( $qmsgid1 );
77
78
        # on the header
79
        if (length($msgid1) == 0)
80
        {
81
            my $qmsgstr = $po->msgstr;
82
            my $cur = $po->dequote( $qmsgstr );
83
            my %cur;
84
            foreach my $h (split(/\n/, $cur))
85
            {
86
                next unless length($h);
87
                my @h = split(':', $h, 2);
88
89
                if (length($cur{$h[0]})) {
90
                    warn "SKIPPING DUPLICATE HEADER LINE: $h\n";
91
                } elsif ($h[0] =~ /#-#-#-#-#/) {
92
                    warn "SKIPPING ERROR MARKER IN HEADER: $h\n";
93
                } elsif (@h == 2) {
94
                    $cur{$h[0]} = $h[1];
95
                } else {
96
                    warn "PROBLEM LINE IN HEADER: $h\n";
97
                    $cur{$h} = '';
98
                }
99
            }
100
101
            # init header ref
102
            $$json{''} ||= {};
103
104
            # populate header ref
105
            foreach my $key (keys %cur) {
106
                $$json{''}{$key} = length($cur{$key}) ? $cur{$key} : '';
107
            }
108
109
            # save plural form count
110
            if ($$json{''}{'Plural-Forms'}) {
111
                my $t = $$json{''}{'Plural-Forms'};
112
                $t =~ s/^\s*//;
113
                if ($t =~ /nplurals=(\d+)/) {
114
                    $plural_form_count = $1;
115
                } else {
116
                    die "ERROR parsing plural forms header [$t]\n";
117
                }
118
            } else {
119
                warn "NO PLURAL FORM HEADER FOUND - DEFAULTING TO 2\n";
120
                # just default to 2
121
                $plural_form_count = 2;
122
            }
123
124
        # on a normal msgid
125
        } else {
126
            my $qmsgctxt = $po->msgctxt;
127
            my $msgctxt;
128
            $msgctxt = $po->dequote($qmsgctxt) if $qmsgctxt;
129
130
            # build the new msgid key
131
            my $msg_ctxt_id = defined($msgctxt) ? join($gettext_context_glue, ($msgctxt, $msgid1)) : $msgid1;
132
133
            # build translation side
134
            my @trans;
135
136
            # msgid plural side
137
            my $qmsgid_plural = $po->msgid_plural;
138
            my $msgid2;
139
            $msgid2 = $po->dequote( $qmsgid_plural ) if $qmsgid_plural;
140
            push(@trans, $msgid2);
141
142
            # translated string
143
            # this shows up different if we're plural
144
            if (defined($msgid2) && length($msgid2))
145
            {
146
                my $plurals = $po->msgstr_n;
147
                for (my $i=0; $i<$plural_form_count; $i++)
148
                {
149
                    my $qstr = ref($plurals) ? $$plurals{$i} : undef;
150
                    my $str;
151
                    $str  = $po->dequote( $qstr ) if $qstr;
152
                    push(@trans, $str);
153
                }
154
155
            # singular
156
            } else {
157
                my $qmsgstr = $po->msgstr;
158
                my $msgstr;
159
                $msgstr = $po->dequote( $qmsgstr ) if $qmsgstr;
160
                push(@trans, $msgstr);
161
            }
162
163
            $$json{$msg_ctxt_id} = \@trans;
164
        }
165
    }
166
167
168
    my $jsonobj = JSON->new->canonical( $ENV{CANONICAL} // 1 );    # if you dont want sorted keys, export CANONICAL=0
169
    my $basename = basename($src);
170
    $basename =~ s/\.pot?$//;
171
    if ($pretty)
172
    {
173
        print $jsonobj->pretty->encode( { $basename => $json });
174
    } else {
175
        print $jsonobj->encode($json);
176
    }
177
}
178
179
__END__
180
181
=pod
182
183
=head1 NAME
184
185
po2json - Command line tool for converting a po file into a Gettext.js compatible json dataset
186
187
=head1 VERSION
188
189
version 0.019
190
191
=head1 SYNOPSIS
192
193
 po2json /path/to/domain.po > domain.json
194
195
=head1 DESCRIPTION
196
197
This takes a PO file, as is created from GNU Gettext's xgettext, and converts it into a JSON file.
198
199
The output is an annonymous associative array. So, if you plan to load this via a <script> tag, more processing will be require (the output from this program must be assigned to a named javascript variable). For example:
200
201
    echo -n "var json_locale_data = " > domain.json
202
    po2json /path/to/domain.po >> domain.json
203
    echo ";" >> domain.json
204
205
=head1 NAME
206
207
po2json - Convert a Uniforum format portable object file to javascript object notation.
208
209
=head1 OPTIONS
210
211
 -p : pretty-print the output. Makes the output more human-readable.
212
213
=head1 BUGS
214
215
Locale::PO has a potential bug (I don't know if this actually causes a problem or not). Given a .po file with an entry like:
216
217
    msgid ""
218
    "some string"
219
    msgstr ""
220
221
When $po->dump is run on that entry, it will output:
222
223
    msgid "some string"
224
    msgstr ""
225
226
The above is removing the first linebreak. I don't know if that is significant. If so, we'll have to rewrite using a different parser (or include our own parser).
227
228
=head1 REQUIRES
229
230
 Locale::PO
231
 JSON
232
233
=head1 SEE ALSO
234
235
 Locale::PO
236
 Gettext.js
237
238
=head1 AUTHOR
239
240
Copyright (C) 2008, Joshua I. Miller E<lt>unrtst@cpan.orgE<gt>, all rights reserved. See the source code for details.
241
242
=head1 AUTHOR
243
244
Torsten Raudssus <torsten@raudss.us>
245
246
=head1 COPYRIGHT AND LICENSE
247
248
This software is copyright (c) 2012 by DuckDuckGo, Inc. L<http://duckduckgo.com/>, Torsten Raudssus <torsten@raudss.us>.
249
250
This is free software; you can redistribute it and/or modify it under
251
the same terms as the Perl 5 programming language system itself.
252
253
=cut
(-)a/package.json (-1 / +1 lines)
Lines 36-41 Link Here
36
    "minimist": "^1.2.5",
36
    "minimist": "^1.2.5",
37
    "mysql": "^2.18.1",
37
    "mysql": "^2.18.1",
38
    "pinia": "^2.0.13",
38
    "pinia": "^2.0.13",
39
    "po2json": "^0.4.5",
39
    "sass": "^1.58.1",
40
    "sass": "^1.58.1",
40
    "style-loader": "^3.3.1",
41
    "style-loader": "^3.3.1",
41
    "vue": "^3.2.31",
42
    "vue": "^3.2.31",
42
- 

Return to bug 37303