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