From 625871cba8a2fe71c70b3d2946a5f37993d1f263 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Thu, 25 Nov 2010 17:22:58 +0100 Subject: JS: Split script.js into a separate file for each language This greatly reduces the size of the Javascript file. The compressed size has been reduced with about 9kB, and is now a total of 14kB for en.js. A nice property of this is that more translations can be added without increasing the JS size. While I was at it, I made jsgen.pl also replace mt() function calls in cases where an exact TL string was requested without any additional arguments and/or formatting codes. This helped reduce the compressed size by about 1kB. My aim is to keep *all* the JS code of VNDB smaller than the jQuery core library, as a general "fuck you" towards users of large and bloated JS libraries. We must keep the VNDB page loading times lower than that of other sites, after all! --- .gitignore | 2 +- ChangeLog | 3 +- Makefile | 11 +++-- data/script.js | 10 ++-- lib/VNDB/Util/LayoutHTML.pm | 2 +- util/jsgen.pl | 117 +++++++++++++++++++++++--------------------- 6 files changed, 79 insertions(+), 66 deletions(-) diff --git a/.gitignore b/.gitignore index 94b0eee6..c4732a40 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /data/multi.pid /data/docs/8 /data/log/ -/static/f/script.js +/static/f/js/ /static/feeds/ /static/s/*/style.css /static/s/*/boxbg.png diff --git a/ChangeLog b/ChangeLog index 5087f702..9248b761 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,8 @@ - Improved release filter selection interface - Added Atom feeds for the recent announcements, changes and posts (located in /www/feeds and updated every 15 min. by Multi::Feed) - - Reverted to the old selection box date selector + - JS: Reverted to the old selection box date selector + - JS: Split script.js into a separate file for each language - Improved performance of update_vnpopularity() on PostgreSQL 9.0 - Added WHEN clause to all SQL TRIGGERs for which it was useful (this *requires* PostgreSQL 9.0 or up!) diff --git a/Makefile b/Makefile index 51ceb86f..8496bd9f 100644 --- a/Makefile +++ b/Makefile @@ -42,9 +42,9 @@ all: dirs js skins robots data/config.pl -dirs: static/cv static/sf static/st data/log www www/feeds +dirs: static/f/js static/cv static/sf static/st data/log www www/feeds -js: static/f/script.js +js: static/f/js/en.js skins: static/s/*/style.css @@ -54,10 +54,10 @@ static/cv static/sf static/st: mkdir $@; for i in $$(seq -w 0 1 99); do mkdir "$@/$$i"; done -data/log www www/feeds: +static/f/js data/log www www/feeds: mkdir $@ -static/f/script.js: data/script.js data/lang.txt util/jsgen.pl data/config.pl data/global.pl +static/f/js/en.js: data/script.js data/lang.txt util/jsgen.pl data/config.pl data/global.pl util/jsgen.pl static/s/%/style.css: static/s/%/conf util/skingen.pl data/style.css @@ -68,7 +68,7 @@ static/s/%/style.css: static/s/%/conf util/skingen.pl data/style.css echo 'Disallow: /' >> $@ chmod: all - chmod a-x+rw static/f/script.js + chmod a+xrw static/f/js chmod -R a-x+rwX static/{cv,sf,st} chmod a-x+rw static/s/*/{style.css,boxbg.png} @@ -149,6 +149,7 @@ update-2.13: all $(multi-start) update-2.14: all + rm static/s/script.js $(multi-stop) ${runpsql} < util/updates/update_2.14.sql $(multi-start) diff --git a/data/script.js b/data/script.js index 581b6494..696de64d 100644 --- a/data/script.js +++ b/data/script.js @@ -31,6 +31,10 @@ * l10n // * any keys matching that regex will be included. * + * In the case of an mt('') without any extra arguments, the entire + * function call may be replaced by the TL string. In such a case mt() + * behaves similar to a preprocessor macro in C. + * * The "_lang_*" keys for all languages for which we have a translation are * already included automatically. */ @@ -181,10 +185,9 @@ function shorten(v, l) { * - Only supports [_n], ~[, ~] * - When it finds [quant,_n,..], it will only return the first argument (and doesn't support ~ in an argument) * assumes that a TL structure called 'L10N_STR' is defined in the header of this file */ -var mt_curlang = byName(byId('lang_select'), 'acronym')[0].className.substr(11, 2); function mt() { var key = arguments[0]; - var val = L10N_STR[key] ? L10N_STR[key][mt_curlang] || L10N_STR[key].en : key; + var val = L10N_STR[key] ? L10N_STR[key] : key; for(var i=1; i= 0) @@ -2229,12 +2232,13 @@ if(byId('advselect') && byId('ti')) { // Language selector if(byId('lang_select')) { var d = byId('lang_select'); + var curlang = byName(d, 'acronym')[0].className.substr(11, 2); ddInit(d, 'bottom', function(lnk) { var lst = tag('ul', null); for(var i=0; i $self->{source_url}, mt '_footer_source'; end; end; # /div maincontent - script type => 'text/javascript', src => $self->{url_static}.'/f/script.js?'.$self->{version}, ''; + script type => 'text/javascript', src => $self->{url_static}.'/f/js/'.$self->{l10n}->language_tag().'.js?'.$self->{version}, ''; end; # /body end; # /html diff --git a/util/jsgen.pl b/util/jsgen.pl index 4d82bc95..fd216d7e 100755 --- a/util/jsgen.pl +++ b/util/jsgen.pl @@ -22,57 +22,57 @@ use LangFile; use VNDB::L10N; -sub l10n { - # 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; # lang1 => { key1 => .., key22 => .. }, lang2 => { .. } + +sub l10n_load { + # fetch all text from lang.txt my $lang = LangFile->new(read => "$ROOT/data/lang.txt"); - my $cur; # 0 = none/excluded, 1 = TL lines my $key; while((my $l = $lang->read())) { my $type = shift @$l; - if($type eq 'key') { - my $k = shift @$l; - $cur = grep $k =~ /$_/, @keys; - $key = $k; - } - if($type eq 'tl' && $cur) { - my($lang, $sync, $val) = @$l; - next if !$val; - $lang{$key}{$lang} = $val; - } + $key = shift @$l if $type eq 'key'; + $lang{$l->[0]}{$key} = $l->[2] if $type eq 'tl'; } +} + + +sub l10n { + my($lang, $js) = @_; - # generate JS code + # parse the .js code and replace mt()'s that can be modified in-place, otherwise add to the @keys + my @keys; + $js =~ s{(?:mt\('([a-z0-9_]+)'([,\)])|l10n /([^/]+)/)}# + my($k, $s, $q) = ($1, $2, $3); + my $v = $k ? $lang{$lang}{$k} || $lang{'en'}{$k} : ''; + if($q) { $q ne '' && push @keys, qr/$q/; '' } + elsif($s eq ')' && $v && $v !~ /[\~\[\]]/) { + $v =~ s/"/\\"/g; + $v =~ s/\n/\\n/g; + qq{"$v"} + } else { + push @keys, quotemeta($k); + "mt('$k'$s" + } + #eg; + # 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)/; + + # generate header my $r = "L10N_STR = {\n"; my $first = 1; - for my $key (sort keys %lang) { + for my $key (sort keys %{$lang{$lang}}) { + next if !grep $key =~ /$_/, @keys; $r .= ",\n" if !$first; $first = 0; - $r .= sprintf qq| %s: {\n|, $key !~ /^[a-z0-9_]+$/ ? "'$key'" : $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 .= sprintf qq| %s: "%s"|, $lang, $val; - } - $r .= "\n }"; + my $val = $lang{$lang}{$key} || $lang{'en'}{$key}; + $val =~ s/"/\\"/g; + $val =~ s/\n/\\n/g; + $r .= sprintf qq| %s: "%s"|, $key !~ /^[a-z0-9_]+$/ ? "'$key'" : $key, $val; } - $r .= "\n};\n"; - $r .= 'L10N_LANG = [ '.join(', ', map qq{"$_"}, VNDB::L10N::languages()).' ];'; - return "$r\n"; + $r .= "\n};"; + return ("$r\n", $js); } @@ -98,24 +98,31 @@ sub resolutions { sub jsgen { - # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, - # so just do everything in raw bytes instead. - open my $JS, '<', "$ROOT/data/script.js" or die $!; + l10n_load(); + my $common = ''; + $common .= resolutions(); + $common .= sprintf "rlst_rstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_rstat}}; + $common .= sprintf "rlst_vstat = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{rlst_vstat}}; + $common .= sprintf "cookie_prefix = '%s';\n", $S{cookie_prefix}; + $common .= sprintf "age_ratings = [ %s ];\n", join ',', map !defined $_ ? -1 : $_, @{$S{age_ratings}}; + $common .= sprintf "languages = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{languages}}; + $common .= sprintf "platforms = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{platforms}}; + $common .= sprintf "media = [ %s ];\n", join ', ', map qq{"$_"}, sort keys %{$S{media}}; + $common .= sprintf "release_types = [ %s ];\n", join ', ', map qq{"$_"}, sort @{$S{release_types}}; + $common .= sprintf "L10N_LANG = [ %s ];\n", join(', ', map qq{"$_"}, VNDB::L10N::languages()); + + open my $JS, '<:utf8', "$ROOT/data/script.js" or die $!; 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}; - $head .= sprintf "age_ratings = [ %s ];\n", join ',', map !defined $_ ? -1 : $_, @{$S{age_ratings}}; - $head .= sprintf "languages = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{languages}}; - $head .= sprintf "platforms = [ %s ];\n", join ', ', map qq{"$_"}, @{$S{platforms}}; - $head .= sprintf "media = [ %s ];\n", join ', ', map qq{"$_"}, sort keys %{$S{media}}; - $head .= sprintf "release_types = [ %s ];\n", join ', ', map qq{"$_"}, sort @{$S{release_types}}; - $head .= resolutions(); - open my $NEWJS, '>', "$ROOT/static/f/script.js" or die $!; - print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($head.$js) : $head.$js; - close $NEWJS; + + for my $l (VNDB::L10N::languages()) { + my($head, $body) = l10n($l, $js); + # JavaScript::Minifier::XS doesn't correctly handle perl's unicode, so manually encode + my $content = encode_utf8($head . $common . $body); + open my $NEWJS, '>', "$ROOT/static/f/js/$l.js" or die $!; + print $NEWJS $JavaScript::Minifier::XS::VERSION ? JavaScript::Minifier::XS::minify($content) : $content; + close $NEWJS; + } } jsgen; -- cgit v1.2.3