]> git.proxmox.com Git - proxmox-i18n.git/blob - po2js.pl
re-run msgmerge for traditional Chinese translations
[proxmox-i18n.git] / po2js.pl
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Getopt::Std;
6 use Locale::PO;
7 use JSON;
8 use Encode;
9
10 # current limits:
11 # - we do not support plural. forms
12 # - no message content support
13
14 my $options = {};
15
16 getopts('t:o:v:', $options) ||
17 die "unable to parse options\n";
18
19 die "no files specified\n" if !scalar(@ARGV);
20
21 #my $filename = shift || die "no po file specified\n";
22
23 # like FNV32a, but we only return 31 bits (positive numbers)
24 sub fnv31a {
25 my ($string) = @_;
26
27 my $hval = 0x811c9dc5;
28
29 foreach my $c (unpack('C*', $string)) {
30 $hval ^= $c;
31 $hval += (
32 (($hval << 1) ) +
33 (($hval << 4) ) +
34 (($hval << 7) ) +
35 (($hval << 8) ) +
36 (($hval << 24) ) );
37 $hval = $hval & 0xffffffff;
38 }
39 return $hval & 0x7fffffff;
40 }
41
42 my $catalog = {};
43
44 foreach my $filename (@ARGV) {
45 my $href = Locale::PO->load_file_ashash($filename) ||
46 die "unable to load '$filename'\n";
47
48 my $charset;
49 my $hpo = $href->{'""'} || die "no header";
50 my $header = $hpo->dequote($hpo->msgstr);
51 if ($header =~ m|^Content-Type:\s+text/plain;\s+charset=(\S+)$|im) {
52 $charset = $1;
53 } else {
54 die "unable to get charset\n" if !$charset;
55 }
56
57
58 foreach my $k (keys %$href) {
59 my $po = $href->{$k};
60 next if $po->fuzzy(); # skip fuzzy entries
61 my $ref = $po->reference();
62
63 # skip unused entries
64 next if !$ref;
65
66 # skip entries if t is defined (pve/pmg) and the string is
67 # not used there or in the widget toolkit
68 next if $options->{t} && $ref !~ m/($options->{t}|proxmox)\-/;
69
70 my $qmsgid = decode($charset, $po->msgid);
71 my $msgid = $po->dequote($qmsgid);
72
73 my $qmsgstr = decode($charset, $po->msgstr);
74 my $msgstr = $po->dequote($qmsgstr);
75
76 next if !length($msgid); # skip header
77
78 next if !length($msgstr); # skip untranslated entries
79
80 my $digest = fnv31a($msgid);
81
82 die "duplicate digest" if $catalog->{$digest};
83
84 $catalog->{$digest} = [ $msgstr ];
85 # later, we can add plural forms to the array
86 }
87 }
88
89 my $json = to_json($catalog, {canonical => 1, utf8 => 1});
90
91 my $version = $options->{v} // ("dev-build " . localtime());
92 my $content = "// $version\n"; # write version to the beginning to better avoid stale cache
93
94 my $outfile = $options->{o};
95
96 $content .= "// Proxmox Message Catalog: $outfile\n" if $outfile;
97
98 $content .= <<__EOD;
99 __proxmox_i18n_msgcat__ = $json;
100
101 function fnv31a(text) {
102 var len = text.length;
103 var hval = 0x811c9dc5;
104 for (var i = 0; i < len; i++) {
105 var c = text.charCodeAt(i);
106 hval ^= c;
107 hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
108 }
109 hval &= 0x7fffffff;
110 return hval;
111 }
112
113 function gettext(buf) {
114 var digest = fnv31a(buf);
115 var data = __proxmox_i18n_msgcat__[digest];
116 if (!data) {
117 return buf;
118 }
119 return data[0] || buf;
120 }
121 __EOD
122
123 if ($outfile) {
124 open(my $fh, '>', $outfile) ||
125 die "unable to open '$outfile' - $!\n";
126 print $fh $content;
127 } else {
128 print $content;
129 }