diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | data/script.js | 32 | ||||
-rwxr-xr-x | util/jsgen.pl | 90 |
3 files changed, 71 insertions, 52 deletions
@@ -12,6 +12,7 @@ - Removed XML sitemap - Added image dimensions to screenshot thumbail <img> 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('<exact translation key>',<more arguments> + * or + * mt('<exact translation key>') + * 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 /<perl regex>/ + * 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<rlst_rstat.length; i++) { - var val = mt('_rlst_rstat_'+rlst_rstat[i]); + var val = mt('_rlst_rstat_'+rlst_rstat[i]); // l10n /_rlst_rstat_\d+/ if(st[0] && st[0].indexOf(val) >= 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<rlst_vstat.length; i++) { - var val = mt('_rlst_vstat_'+rlst_vstat[i]); + var val = mt('_rlst_vstat_'+rlst_vstat[i]); // l10n /_rlst_vstat_\d+/ if(st[1] && st[1].indexOf(val) >= 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; } |