diff options
author | Eugene Sandulenko | 2010-06-15 10:44:51 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-06-15 10:44:51 +0000 |
commit | 859212df2523e8b15076d968018dbf98618fd60f (patch) | |
tree | e3f7ff62c58c9ac8a762791c0a1801b75fe1f14a /tools | |
parent | db6673c408865b201808e01ab5db796f2e794058 (diff) | |
download | scummvm-rg350-859212df2523e8b15076d968018dbf98618fd60f.tar.gz scummvm-rg350-859212df2523e8b15076d968018dbf98618fd60f.tar.bz2 scummvm-rg350-859212df2523e8b15076d968018dbf98618fd60f.zip |
Implement translation support for ScummVM GUI.
Based on patch #2903830: "Updated Translation Prototype" by alexbevi
which in turn is based on patch #1739965 by jvprat.
Currently it builds all translations right into ScummVM. Once the
feature will be accepted more widely, i.e. more translations will
pop up, it will be trivial to move translation strings to external
file.
Finished translation: Russian
Unfinished translation: Hungarian
Things which are nice to do:
- Language code -> language mapping for more user friendness
- Specifying fonts to be used with language
- Updating of interface language without restart. It will require
moving of much code to reflowLayout() methods for each dialog
The .po files must be in single byte encodings. I.e. no support
for Unicode.
svn-id: r49759
Diffstat (limited to 'tools')
-rw-r--r-- | tools/module.mk | 1 | ||||
-rwxr-xr-x | tools/po2c | 280 |
2 files changed, 280 insertions, 1 deletions
diff --git a/tools/module.mk b/tools/module.mk index 896a2e504b..2c62e427ea 100644 --- a/tools/module.mk +++ b/tools/module.mk @@ -65,7 +65,6 @@ md5scumm: tools/md5table$(EXEEXT) tools/md5table$(EXEEXT) --c++ < $(srcdir)/tools/scumm-md5.txt > $(srcdir)/engines/scumm/scumm-md5.h cp $(srcdir)/tools/scumm-md5.txt $(srcdir)/../../web/trunk/data/scumm-md5.txt - # # Rules which automatically and implicitly rebuild the credits and # MD5 tables when needed. diff --git a/tools/po2c b/tools/po2c new file mode 100755 index 0000000000..ac1744aa2c --- /dev/null +++ b/tools/po2c @@ -0,0 +1,280 @@ +#!/usr/bin/perl + +# +# po2c - Converts .po files to C code +# +# Copyright (C) 2004 Angel Ortega <angel@triptico.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# http://www.triptico.com +# + +$VERSION = "1.0.2"; + +if(scalar(@ARGV) == 0) +{ + print "Usage: po2c {po file[s]}\n"; + exit 1; +} + +%msgs = (); +%msgids = (); + +# stage 1: loading + +# arguments are .po files +foreach my $f (@ARGV) +{ + my ($lang); + my ($langDesc); + + next unless(($lang) = ($f =~ /([^\/]+)\.po$/)); + + if(open F, $f) + { + my ($msgid, $val, %a); + + while(<F>) + { + chomp; + + # ignore blank lines or comments + next if /^$/ or /^#/; + + if(/^msgid\s+\"(.*)\"\s*$/) + { + # store previous msgid + if(defined($msgid)) + { + $a{$msgid} = $val; + $msgids{$msgid} ++; + } + + # start of msgid + $val = $1; + } + elsif(/^msgstr\s+\"(.*)\"\s*$/) + { + # store previous msgid + $msgid = $val; + + # start of msgstr + $val = $1; + } + elsif(/^\"(.*)\"\s*$/) + { + # add to current value + $val .= $1; + } + } + + # store previous msgid + if(defined($msgid)) + { + $a{$msgid} = $val; + $msgids{$msgid} ++; + } + + close F; + + # add to the global message pool + $msgs{$lang} = \%a; + } +} + +# stage 2: convert the data + +# stores all sorted msgids into @msgids +@msgids = sort(keys(%msgids)); + +# travels again, storing indexes into %msgids +for(my $n = 0;$n < scalar(@msgids);$n++) +{ + $msgids{$msgids[$n]} = $n; +} + +# stage 3: dump as C code + +print "/* generated by po2c $VERSION - Do not modify */\n\n"; +print "#include <stdio.h>\n"; +print "#include <string.h>\n\n"; + +# dump first the msgid array +print "static const char * _po2c_msgids[] = {\n"; + +for(my $n = 0;$n < scalar(@msgids);$n++) +{ + print "\t/* $n */ \"" . $msgids[$n] . "\",\n"; +} + +print "\tNULL\n};\n\n"; + +# dump the lang structure +print "struct _po2c_msg {\n"; +print "\tint msgid;\n"; +print "\tconst char * msgstr;\n"; +print "};\n\n"; + +# dump now each language + +foreach my $l (keys(%msgs)) +{ + print "static struct _po2c_msg _po2c_lang_${l}\[\] = {\n"; + + # get the translation table for the language $l + my ($m) = $msgs{$l}; + +# while (my ($msgstr, $msgid) = each (%$m)) + foreach my $msgid (sort(keys(%$m))) + { + my ($msgstr) = ""; + + # make it 7-bit safe + foreach $c (split(//, $m->{$msgid})) { + if (ord($c) > 0x7f) { + $msgstr .= sprintf("\\%o", ord($c)); + } else { + $msgstr .= $c; + } + } + + print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n" + if $msgstr; + } + + print "\t{ -1, NULL }\n};\n\n"; +} + +# finally, dump the languages + +print "static struct {\n"; +print "\tconst char * lang;\n"; +print "\tconst char * charset;\n"; +print "\tstruct _po2c_msg * msgs;\n"; +print "} _po2c_langs[] = {\n"; + +foreach my $l (keys(%msgs)) +{ + $header = $msgs{$l}->{""}; + $header =~ /charset=([^\\]+)/; + $charset = $1; + print "\t{ \"" . $l . "\", \"" . $charset . "\", _po2c_lang_${l} },\n"; +} + +print "\t{ NULL, NULL, NULL }\n};\n\n"; + +print "/* code */\n"; +print << 'EOF'; + +static struct _po2c_msg * _po2c_lang=NULL; +static int _po2c_lang_size=0; +static const char * _po2c_charset=NULL; + +void po2c_setlang(const char * lang) +{ + int n; + + _po2c_lang=NULL; + _po2c_lang_size=0; + _po2c_charset=NULL; + + /* if lang is NULL or "", deactivate it */ + if(lang == NULL || *lang == '\0') + return; + + /* searches for a valid language array */ + for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++) + { + if(strcmp(lang, _po2c_langs[n].lang) == 0) { + _po2c_lang=_po2c_langs[n].msgs; + _po2c_charset=_po2c_langs[n].charset; + } + } + + /* try partial searches */ + for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++) + { + if(strncmp(lang, _po2c_langs[n].lang, 2) == 0) { + _po2c_lang=_po2c_langs[n].msgs; + _po2c_charset=_po2c_langs[n].charset; + } + } + + /* if found, count entries */ + if(_po2c_lang != NULL) + { + struct _po2c_msg * m; + + for(m=_po2c_lang;m->msgid != -1;m++) + _po2c_lang_size++; + } +} + +const char * po2c_gettext(const char * msgid) +{ + struct _po2c_msg * m; + int b, t, n, c; + + /* if no language is set or msgid is empty, return msgid as is */ + if(_po2c_lang == NULL || *msgid == '\0') + return(msgid); + + /* binary-search for the msgid */ + b=0; t=_po2c_lang_size - 1; + + while(t >= b) + { + n=(b + t) / 2; + m=&_po2c_lang[n]; + + c=strcmp(msgid, _po2c_msgids[m->msgid]); + + if(c == 0) + return(m->msgstr); + else + if(c < 0) + t=n - 1; + else + b=n + 1; + } + + return(msgid); +} + +const char * po2c_getcharset(void) +{ + if (_po2c_charset) + return _po2c_charset; + else + return "ASCII"; +} + +int po2c_getnumlangs(void) +{ + int n = 0; + while (_po2c_langs[n].lang) + n++; + + return n; +} + +const char * po2c_getlang(int num) +{ + return _po2c_langs[num].lang; +} +EOF + +exit 0; |