From cfafd7bc2a57faa67e9c14e2db8cc807294142c8 Mon Sep 17 00:00:00 2001 From: Tomas Cohen Arazi Date: Mon, 14 Oct 2024 09:50:23 -0300 Subject: [PATCH] Bug 38164: Revert "Bug 37303: Replace po2json with a JS version" This reverts commit 4eb981635453871fa2a33396391f3f75a6baa8b1. Signed-off-by: Aleisha Amohia Signed-off-by: Victor Grousset/tuxayo Signed-off-by: Jonathan Druart Signed-off-by: Katrin Fischer (cherry picked from commit b285fd57c8c9e9c53d0945aae6fe54f3ac9f82ed) Signed-off-by: Lucas Gass --- misc/translator/LangInstaller.pm | 10 +- misc/translator/po2json | 253 +++++++++++++++++++++++++++++++ package.json | 1 - 3 files changed, 255 insertions(+), 9 deletions(-) create mode 100755 misc/translator/po2json diff --git a/misc/translator/LangInstaller.pm b/misc/translator/LangInstaller.pm index fcf78bba98..a0f323121e 100644 --- a/misc/translator/LangInstaller.pm +++ b/misc/translator/LangInstaller.pm @@ -28,7 +28,6 @@ use Locale::PO; use FindBin qw( $Bin ); use File::Path qw( make_path ); use File::Copy; -use File::Slurp qw( read_file ); sub set_lang { my ($self, $lang) = @_; @@ -53,7 +52,7 @@ sub new { $self->{po} = {}; $self->{domain} = 'Koha'; $self->{msgfmt} = `which msgfmt`; - $self->{po2json} = "yarn run po2json"; + $self->{po2json} = "$Bin/po2json"; $self->{gzip} = `which gzip`; $self->{gunzip} = `which gunzip`; chomp $self->{msgfmt}; @@ -455,12 +454,7 @@ sub install_messages { make_path($modir); system "$self->{msgfmt} -o $mofile $pofile"; - my $tmp_po = sprintf '/tmp/%s-messages.po', $self->{lang}; - my $po2json_cmd = sprintf '%s %s %s', $self->{po2json}, $js_pofile, $tmp_po; - `$po2json_cmd`; - my $json = read_file($tmp_po); - - my $js_locale_data = sprintf 'var json_locale_data = {"Koha":%s};', $json; + my $js_locale_data = 'var json_locale_data = {"Koha":' . `$self->{po2json} $js_pofile` . '};'; my $progdir = C4::Context->config('intrahtdocs') . '/prog'; mkdir "$progdir/$self->{lang}/js"; open my $fh, '>', "$progdir/$self->{lang}/js/locale_data.js"; diff --git a/misc/translator/po2json b/misc/translator/po2json new file mode 100755 index 0000000000..a04d85949f --- /dev/null +++ b/misc/translator/po2json @@ -0,0 +1,253 @@ +#!/usr/bin/env perl +# PODNAME: po2json +# ABSTRACT: Command line tool for converting a po file into a Gettext.js compatible json dataset + +# Copyright (C) 2008, Joshua I. Miller Eunrtst@cpan.orgE, all +# rights reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Library General Public License as published +# by the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. + + +use strict; +use JSON 2.53; +use Locale::PO 0.24; +use File::Basename qw(basename); + +my $gettext_context_glue = "\004"; + +sub usage { + return "$0 {-p} {file.po} > {outputfile.json} + -p : do pretty-printing of json data\n"; +} + +&main; + +sub main +{ + my $src; + + my $pretty = 0; + if ($ARGV[0] =~ /^--?p$/) { + shift @ARGV; + $pretty = 1; + } + + if (length($ARGV[0])) + { + if ($ARGV[0] =~ /^-h/) { + print &usage; + exit 1; + } + + unless (-r $ARGV[0]) { + print "ERROR: Unable to read file [$ARGV[0]]\n"; + die &usage; + } + + $src = $ARGV[0]; + } else { + die &usage; + } + + # we'll be building this data struct + my $json = {}; + + my $plural_form_count; + # get po object stack + my $pos = Locale::PO->load_file_asarray($src) or die "Can't parse po file [$src]."; + + + foreach my $po (@$pos) + { + my $qmsgid1 = $po->msgid; + my $msgid1 = $po->dequote( $qmsgid1 ); + + # on the header + if (length($msgid1) == 0) + { + my $qmsgstr = $po->msgstr; + my $cur = $po->dequote( $qmsgstr ); + my %cur; + foreach my $h (split(/\n/, $cur)) + { + next unless length($h); + my @h = split(':', $h, 2); + + if (length($cur{$h[0]})) { + warn "SKIPPING DUPLICATE HEADER LINE: $h\n"; + } elsif ($h[0] =~ /#-#-#-#-#/) { + warn "SKIPPING ERROR MARKER IN HEADER: $h\n"; + } elsif (@h == 2) { + $cur{$h[0]} = $h[1]; + } else { + warn "PROBLEM LINE IN HEADER: $h\n"; + $cur{$h} = ''; + } + } + + # init header ref + $$json{''} ||= {}; + + # populate header ref + foreach my $key (keys %cur) { + $$json{''}{$key} = length($cur{$key}) ? $cur{$key} : ''; + } + + # save plural form count + if ($$json{''}{'Plural-Forms'}) { + my $t = $$json{''}{'Plural-Forms'}; + $t =~ s/^\s*//; + if ($t =~ /nplurals=(\d+)/) { + $plural_form_count = $1; + } else { + die "ERROR parsing plural forms header [$t]\n"; + } + } else { + warn "NO PLURAL FORM HEADER FOUND - DEFAULTING TO 2\n"; + # just default to 2 + $plural_form_count = 2; + } + + # on a normal msgid + } else { + my $qmsgctxt = $po->msgctxt; + my $msgctxt; + $msgctxt = $po->dequote($qmsgctxt) if $qmsgctxt; + + # build the new msgid key + my $msg_ctxt_id = defined($msgctxt) ? join($gettext_context_glue, ($msgctxt, $msgid1)) : $msgid1; + + # build translation side + my @trans; + + # msgid plural side + my $qmsgid_plural = $po->msgid_plural; + my $msgid2; + $msgid2 = $po->dequote( $qmsgid_plural ) if $qmsgid_plural; + push(@trans, $msgid2); + + # translated string + # this shows up different if we're plural + if (defined($msgid2) && length($msgid2)) + { + my $plurals = $po->msgstr_n; + for (my $i=0; $i<$plural_form_count; $i++) + { + my $qstr = ref($plurals) ? $$plurals{$i} : undef; + my $str; + $str = $po->dequote( $qstr ) if $qstr; + push(@trans, $str); + } + + # singular + } else { + my $qmsgstr = $po->msgstr; + my $msgstr; + $msgstr = $po->dequote( $qmsgstr ) if $qmsgstr; + push(@trans, $msgstr); + } + + $$json{$msg_ctxt_id} = \@trans; + } + } + + + my $jsonobj = JSON->new->canonical( $ENV{CANONICAL} // 1 ); # if you dont want sorted keys, export CANONICAL=0 + my $basename = basename($src); + $basename =~ s/\.pot?$//; + if ($pretty) + { + print $jsonobj->pretty->encode( { $basename => $json }); + } else { + print $jsonobj->encode($json); + } +} + +__END__ + +=pod + +=head1 NAME + +po2json - Command line tool for converting a po file into a Gettext.js compatible json dataset + +=head1 VERSION + +version 0.019 + +=head1 SYNOPSIS + + po2json /path/to/domain.po > domain.json + +=head1 DESCRIPTION + +This takes a PO file, as is created from GNU Gettext's xgettext, and converts it into a JSON file. + +The output is an annonymous associative array. So, if you plan to load this via a