From 73a2ee4403f75e12922486ca1c12b11a74bbeb4d Mon Sep 17 00:00:00 2001 From: Yorhel Date: Tue, 2 Nov 2010 20:12:14 +0100 Subject: Automatically read L10N keys from script.js This makes jsgen.pl a bit easier to maintain, as there's not one reliable source to get the keys from (namely, the JS code itself). Also cleaned up the l10n() function in jsgen.pl to be more readable. I had expected the new .js file to be smaller because this trick may remove some keys that were previously present but unused. Unfortunately it seems the file only grew a bit larger and compression seems to be less effective now. No idea why this happened. :-( --- ChangeLog | 1 + data/script.js | 32 +++++++++++++++++---- util/jsgen.pl | 90 ++++++++++++++++++++++++++++------------------------------ 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3774e5b7..b5033e15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ - Removed XML sitemap - Added image dimensions to screenshot thumbail tags - Prefix all cookies with a configurable cookie_prefix + - Automatically read L10N keys from script.js - Bugfix: only redirect VN search to VN page if page=1 - Bugfix: remove duplicate votes when merging tags (fixes a 500) - Bugfix: Multi::Anime: don't crash when anidb returns an invalid or empty year diff --git a/data/script.js b/data/script.js index 3e2b479f..e3a1b553 100644 --- a/data/script.js +++ b/data/script.js @@ -14,6 +14,25 @@ * tvs -> VN page tag spoilers * vnr -> VN relation editor */ + +/* Internationalization note: + * The translation keys to be inserted in the header of this file are parsed + * from the source code. So when using mt(), make sure it is in the following + * format: + * mt('', + * or + * mt('') + * The single quotes and (lack of) spaces are significant! + * + * To use non-exact translation keys as argument to mt(), make sure to + * indicate which keys should be inserted in the header by adding a comment + * containing the following format: + * l10n // + * any keys matching that regex will be included. + * + * The "_lang_*" keys for all languages for which we have a translation are + * already included automatically. + */ var expanded_icon = '▾'; var collapsed_icon = '▸'; @@ -365,14 +384,14 @@ function rlDropDown(lnk) { var rs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relrstat')))); var vs = tag('ul', tag('li', tag('b', mt('_vnpage_uopt_relvstat')))); for(var i=0; i= 0) rs.appendChild(tag('li', tag('i', val))); else rs.appendChild(tag('li', tag('a', {href:'#', rl_rid:relid, rl_act:'r'+rlst_rstat[i], onclick:rlMod}, val))); } for(var i=0; i= 0) vs.appendChild(tag('li', tag('i', val))); else @@ -1039,7 +1058,7 @@ function scrAdd(id, nsfw, rel) { var tr = tag('tr', { id:'scr_tr_'+id, scr_id: id, scr_status: id?2:1, scr_rel: rel, scr_nsfw: nsfw}, tag('td', { 'class': 'thumb'}, mt('_js_loading')), tag('td', - tag('b', mt(id ? '_vnedit_scr_fetching' : '_vnedit_scr_uploading')), + tag('b', id ? mt('_vnedit_scr_fetching') : mt('_vnedit_scr_uploading')), tag('br', null), id ? null : mt('_vnedit_scr_upl_msg'), tag('br', null), @@ -1188,7 +1207,8 @@ function scrUploadComplete() { tr.scr_id = -10; } if(tr.scr_id < 0) { - alert(mt(tr.scr_id == -10 ? '_vnedit_scr_oops' : tr.scr_id == -1 ? '_vnedit_scr_errformat' : '_vnedit_scr_errempty')); + alert(tr.scr_id == -10 ? mt('_vnedit_scr_oops') : + tr.scr_id == -1 ? mt('_vnedit_scr_errformat') : mt('_vnedit_scr_errempty')); scrDel(tr); } else { tr.id = 'scr_tr_'+tr.scr_id; @@ -1231,7 +1251,7 @@ var tglSpoilers = []; function tglLoad() { for(var i=0; i<=3; i++) - tglSpoilers[i] = mt('_tagv_spoil'+i); + tglSpoilers[i] = mt('_tagv_spoil'+i); // l10n /_tagv_spoil\d+/ // tag dropdown search dsInit(byId('tagmod_tag'), '/xml/tags.xml?q=', function(item, tr) { @@ -1871,7 +1891,7 @@ if(byId('expandlist')) { var lnk = byId('expandlist'); setexpand = function() { var exp = getCookie('histexpand') == 1; - setText(lnk, mt(exp ? '_js_collapse' : '_js_expand')); + setText(lnk, exp ? mt('_js_collapse') : mt('_js_expand')); var tbl = lnk; while(tbl.nodeName.toLowerCase() != 'table') tbl = tbl.parentNode; diff --git a/util/jsgen.pl b/util/jsgen.pl index 2235d289..27cbc6da 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -22,75 +22,73 @@ use LangFile; use VNDB::L10N; -my $jskeys_lang = join '|', VNDB::L10N::languages(); -my $jskeys = qr{^(?: - _lang_(?:$jskeys_lang)| - _js_.+| - _menu_emptysearch| - _vnpage_uopt_(?:10?vote|rel.+)| - _rlst_[vr]stat_.+| - _vnedit_rel_(?:isa|of|addbut|del|none|findformat|novn|double)| - _redit_form_med_.+| - _vnedit_scr_.+| - _tagv_(?:add|spoil\d|notfound|nometa|double)| - _redit_form_vn_(?:addbut|remove|none|vnformat|notfound|double)| - _redit_form_prod_(?:addbut|remove|none|pformat|notfound|double)| - _pedit_rel_(?:addbut|del|none|findformat|notfound|double) - )$}x; - sub l10n { - # Using JSON::XS or something may be shorter and less error prone, - # although I would have less power over the output (mostly the quoting of the keys) + # parse the .js code to find the l10n keys to use + my $js = shift; + my @keys; + push @keys, $1 ? quotemeta($1) : qr/$2/ while($js =~ m{(?:mt\('([a-z0-9_]+)'[,\)]|l10n /([^/]+)/)}g); + # also add the _lang_* for all languages for which we have a translation + my $jskeys_lang = join '|', VNDB::L10N::languages(); + push @keys, qr/_lang_(?:$jskeys_lang)/; + # fetch the corresponding text from lang.txt + my %lang; # key1 => { lang1 => .., lang2 => .. }, key2 => { .. } my $lang = LangFile->new(read => "$ROOT/data/lang.txt"); - my @r; - push @r, 'L10N_STR = {'; - my $cur; # undef = none/excluded, 1 = awaiting first TL line, 2 = after first TL line - my %lang; + my $cur; # 0 = none/excluded, 1 = TL lines + my $key; while((my $l = $lang->read())) { my $type = shift @$l; if($type eq 'key') { - my $key = shift @$l; - push @r, ' }' if $cur; - $cur = $key =~ $jskeys ? 1 : undef; - if($cur) { - $r[$#r] .= ',' if $r[$#r] =~ /}$/; - # let's assume key names don't trigger a reserved word in JS - $key = qq{"$key"} if $key !~ /^[a-z_][a-z0-9_]*$/i; - push @r, qq| $key: {|; - } + my $k = shift @$l; + $cur = grep $k =~ /$_/, @keys; + $key = $k; } - $lang{$l->[0]} = 1 if $type eq 'tl'; if($type eq 'tl' && $cur) { my($lang, $sync, $val) = @$l; next if !$val; + $lang{$key}{$lang} = $val; + } + } + + # generate JS code + my $r = "L10N_STR = {\n"; + my $first = 1; + for my $key (sort keys %lang) { + $r .= ",\n" if !$first; + $first = 0; + # let's assume all L10N keys are valid JS variable names + $r .= sprintf qq| "%s": {\n|, $key; + my $firstk = 1; + for (sort keys %{$lang{$key}}) { + $r .= ",\n" if !$firstk; + $firstk = 0; + my $lang = $_; + $lang = qq{"$lang"} if $lang =~ /^(?:as|do|if|in|is)$/; # reserved two-char words + my $val = $lang{$key}{$_}; $val =~ s/"/\\"/g; $val =~ s/\n/\\n/g; - $r[$#r] .= ',' if $cur == 2; - $lang = qq{"$l->[0]"} if $lang =~ /^(?:as|do|if|in|is)$/; # reserved two-char words - push @r, qq| $lang: "$val"|; - $cur = 2; + $r .= sprintf qq| %s: "%s"|, $lang, $val; } + $r .= "\n }"; } - push @r, ' }' if $cur; - push @r, '};'; - push @r, 'L10N_LANG = [ '.join(', ', map qq{"$_"}, VNDB::L10N::languages()).' ];'; - return join "\n", @r; + $r .= "\n};\n"; + $r .= 'L10N_LANG = [ '.join(', ', map qq{"$_"}, VNDB::L10N::languages()).' ];'; + return "$r\n"; } sub jsgen { # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, # so just do everything in raw bytes instead. - my $js = encode_utf8(l10n()) . "\n"; - $js .= sprintf "rlst_rstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_rstat}}; - $js .= sprintf "rlst_vstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_vstat}}; - $js .= sprintf "cookie_prefix = '%s';\n", $S{cookie_prefix}; open my $JS, '<', "$ROOT/data/script.js" or die $!; - $js .= join '', <$JS>; + my $js .= join '', <$JS>; close $JS; + my $head = encode_utf8(l10n($js)) . "\n"; + $head .= sprintf "rlst_rstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_rstat}}; + $head .= sprintf "rlst_vstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_vstat}}; + $head .= sprintf "cookie_prefix = '%s';\n", $S{cookie_prefix}; open my $NEWJS, '>', "$ROOT/static/f/script.js" or die $!; - print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($js) : $js; + print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($head.$js) : $head.$js; close $NEWJS; } -- cgit v1.2.3