Ticket #8695: translation-infrastructure.patch
File translation-infrastructure.patch, 19.4 KB (added by , 17 years ago) |
---|
-
configure
68 68 _nasm=auto 69 69 _build_hq_scalers=yes 70 70 _build_scalers=yes 71 _translation=yes 71 72 # more defaults 72 73 _backend=sdl 73 74 _ranlib=ranlib … … 345 346 --disable-mt32emu don't enable the integrated MT-32 emulator 346 347 --disable-hq-scalers exclude HQ2x and HQ3x scalers 347 348 --disable-scalers exclude scalers 349 --disable-translation don't build support for translated messages 348 350 349 351 Optional Libraries: 350 352 --with-alsa-prefix=DIR Prefix where alsa is installed (optional) … … 432 434 --enable-plugins) _build_plugins=yes ;; 433 435 --enable-mt32emu) _mt32emu=yes ;; 434 436 --disable-mt32emu) _mt32emu=no ;; 437 --enable-translation) _translation=yes ;; 438 --disable-translation) _translation=no ;; 435 439 --with-fluidsynth-prefix=*) 436 440 arg=`echo $ac_option | cut -d '=' -f 2` 437 441 FLUIDSYNTH_CFLAGS="-I$arg/include" … … 1249 1253 add_flag_to_config_mk_if_no yes 'USE_MPEG2' 1250 1254 fi 1251 1255 echo "$_mpeg2" 1252 rm -f $TMPC $TMPO$EXEEXT1253 1256 1254 1257 # 1255 1258 # Check for libfluidsynth … … 1271 1274 _def_fluidsynth='#undef USE_FLUIDSYNTH' 1272 1275 fi 1273 1276 echo "$_fluidsynth" 1274 rm -f $TMPC $TMPO$EXEEXT1275 1277 1276 1278 # 1277 1279 # Check for nasm … … 1289 1291 fi 1290 1292 1291 1293 # 1294 # Check whether to build translation support 1295 # 1296 echo_n "Building translation support... " 1297 _def_detectlang='#undef DETECTLANG' 1298 _def_termconv='#undef TERMCONV' 1299 if test "$_translation" = no ; then 1300 echo "no" 1301 _def_translation='#undef TRANSLATION' 1302 add_flag_to_config_mk_if_no yes 'ENABLE_TRANSLATION' 1303 else 1304 echo_n "yes (" 1305 _def_translation='#define TRANSLATION' 1306 add_flag_to_config_mk_if_no no 'ENABLE_TRANSLATION' 1307 1308 _detectlang=no 1309 cat > $TMPC << EOF 1310 #include <locale.h> 1311 int main(void) { setlocale(LC_ALL, ""); return 0; } 1312 EOF 1313 cc_check $LDFLAGS $CXXFLAGS && _detectlang=yes 1314 1315 if test "$_detectlang" = yes ; then 1316 echo_n "with runtime language detection, " 1317 _def_detectlang='#define DETECTLANG' 1318 1319 _termconv=no 1320 cat > $TMPC << EOF 1321 #include <langinfo.h> 1322 #include <iconv.h> 1323 int main(void) { nl_langinfo(CODESET); iconv_open(0, 0); return 0; } 1324 EOF 1325 cc_check $LDFLAGS $CXXFLAGS && _termconv=yes 1326 1327 if test "$_termconv" = yes ; then 1328 echo "with terminal conversion)" 1329 _def_termconv='#define TERMCONV' 1330 else 1331 echo "without terminal conversion)" 1332 fi 1333 else 1334 echo "without runtime language detection)" 1335 fi 1336 fi 1337 rm -f $TMPC $TMPO$EXEEXT 1338 1339 # 1292 1340 # figure out installation directories 1293 1341 # 1294 1342 test -z "$_bindir" && _bindir="$_prefix/bin" … … 1456 1504 $_def_fluidsynth 1457 1505 $_def_mt32emu 1458 1506 1507 /* Whether we should use messages translation */ 1508 $_def_translation 1509 $_def_detectlang 1510 $_def_termconv 1511 1459 1512 /* Whether we should use i386 assembly routines */ 1460 1513 $_def_nasm 1461 1514 -
common/module.mk
13 13 stream.o \ 14 14 util.o \ 15 15 system.o \ 16 translation.o \ 16 17 unzip.o 17 18 19 ifdef ENABLE_TRANSLATION 20 common/translation.cpp: common/messages.cpp 21 22 common/messages.cpp: $(wildcard po/*.po) 23 tools/po2c $^ > common/messages.cpp 24 endif 25 18 26 # Include common rules 19 27 include $(srcdir)/rules.mk -
Makefile.common
39 39 graphics \ 40 40 sound \ 41 41 common \ 42 backends 42 backends \ 43 po 43 44 44 45 ifdef USE_MT32EMU 45 46 MODULES += sound/softsynth/mt32 -
common/translation.h
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL$ 22 * $Id$ 23 */ 24 25 #ifndef COMMON_TRANSLATION_H 26 #define COMMON_TRANSLATION_H 27 28 #include "common/stdafx.h" 29 #include "common/singleton.h" 30 #include "common/str.h" 31 32 #ifdef TERMCONV 33 #include <iconv.h> 34 #endif // TERMCONV 35 36 namespace Common { 37 38 /** 39 * Message translation manager. 40 */ 41 class TranslationManager : public Singleton<TranslationManager> { 42 private: 43 char _syslang[6]; 44 45 #ifdef TERMCONV 46 iconv_t _conversion; 47 char* _convmsg; 48 int _sizeconv; 49 #endif // TERMCONV 50 51 public: 52 /** 53 * The constructor selects the translation language and determines 54 * whether there's need for character set conversions. 55 */ 56 TranslationManager(); 57 58 ~TranslationManager(); 59 60 /** 61 * Sets the current translation language to the one specified in the 62 * parameter. If the parameter is an empty string, it sets the default 63 * system language. 64 */ 65 void setLanguage(const char* lang); 66 67 /** 68 * Returns the translation into the current language of the parameter 69 * message. In case the message isn't found in the translation catalog, 70 * it returns the original untranslated message. 71 */ 72 const char* getTranslation(const char* message); 73 74 /** 75 * Converts the message into the terminal character set (which may be 76 * different than the GUI's "native" one. 77 */ 78 const char* convertTerm(const char* message); 79 }; 80 81 } // End of namespace Common 82 83 #ifdef TRANSLATION 84 #define _(str) Common::TranslationManager::instance().getTranslation(str) 85 #define _t(str) Common::TranslationManager::instance().convertTerm(_(str)) 86 #else 87 #define _(str) str 88 #define _t(str) str 89 #endif 90 91 #endif -
common/translation.cpp
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL$ 22 * $Id$ 23 */ 24 25 #include "translation.h" 26 27 DECLARE_SINGLETON(Common::TranslationManager); 28 29 #ifdef TRANSLATION 30 #include "messages.cpp" 31 #endif 32 33 #ifdef DETECTLANG 34 #include <langinfo.h> 35 #endif 36 37 #ifdef TERMCONV 38 #include <locale.h> 39 #endif 40 41 namespace Common { 42 43 44 #ifdef TRANSLATION 45 46 47 // Translation enabled 48 49 TranslationManager::TranslationManager() 50 { 51 #ifdef DETECTLANG 52 // Activating current locale settings 53 const char* locale = setlocale(LC_ALL, ""); 54 55 // Detect the language from the locale 56 if (!locale) { 57 strcpy(_syslang, "C"); 58 } else { 59 int len = strlen(locale); 60 if (len > 5) 61 len = 5; 62 strncpy(_syslang, locale, len); 63 _syslang[len] = 0; 64 } 65 #else // DETECTLANG 66 strcpy(_syslang, "C"); 67 #endif // DETECTLANG 68 69 #ifdef TERMCONV 70 _convmsg = NULL; 71 _conversion = NULL; 72 #endif // TERMCONV 73 74 //TODO: Get the language from the config 75 /*printf("domini actiu: %s\n", ConfMan.getActiveDomainName().c_str()); 76 Common::ConfigManager::Domain* dom = ConfMan.getDomain(ConfMan.kApplicationDomain); 77 printf("domini d'aplicacio: %s\n", dom->getDomainComment().c_str()); 78 printf("domini actiu: %s\n", ConfMan.get("savepath").c_str()); 79 ConfMan.set("scummvm_language", "ca");*/ 80 81 setLanguage(""); 82 83 } 84 85 TranslationManager::~TranslationManager() 86 { 87 #ifdef TERMCONV 88 iconv_close(_conversion); 89 if (_convmsg) 90 delete [] _convmsg; 91 #endif // TERMCONV 92 } 93 94 void 95 TranslationManager::setLanguage(const char* lang) 96 { 97 if (*lang == '\0') 98 po2c_setlang(_syslang); 99 else 100 po2c_setlang(lang); 101 102 #ifdef TERMCONV 103 // Get the locale character set (for terminal output) 104 const char* charset_term = nl_langinfo(CODESET); 105 106 // Get the messages character set 107 const char* charset_po = po2c_getcharset(); 108 109 // Delete previoyus conversion 110 if (_conversion) 111 iconv_close(_conversion); 112 113 // Initialize the conversion 114 _conversion = iconv_open(charset_term, charset_po); 115 #endif // TERMCONV 116 } 117 118 const char* 119 TranslationManager::getTranslation(const char* message) 120 { 121 return po2c_gettext(message); 122 } 123 124 const char* 125 TranslationManager::convertTerm(const char* message) 126 { 127 #ifdef TERMCONV 128 // Preparing conversion origin 129 size_t len = strlen(message); 130 char* msgcpy = new char[len + 1]; 131 strcpy(msgcpy, message); 132 char* msg = msgcpy; 133 char** pmsg = &msg; 134 135 // Preparing conversion destination 136 if (!_convmsg) { 137 _sizeconv = len * 2; 138 _convmsg = new char[_sizeconv]; 139 } 140 size_t len2 = _sizeconv; 141 char *conv = _convmsg; 142 char** pconv = &conv; 143 144 // Clean previous conversions 145 iconv(_conversion, NULL, NULL, pconv, &len2); 146 147 // Do the real conversion 148 size_t size = iconv(_conversion, pmsg, &len, pconv, &len2); 149 if (size == (size_t)-1) { 150 printf("error while converting\n"); 151 //TODO: test whether the buffer is smaller than needed and resize 152 } 153 154 delete [] msgcpy; 155 return _convmsg; 156 #else // TERMCONV 157 return message; 158 #endif // TERMCONV 159 } 160 161 162 #else // TRANSLATION 163 164 165 // Translation disabled 166 167 TranslationManager::TranslationManager() {} 168 169 TranslationManager::~TranslationManager() {} 170 171 void 172 TranslationManager::setLanguage(const char* lang) {} 173 174 const char* 175 TranslationManager::getTranslation(const char* message) 176 { 177 return message; 178 } 179 180 const char* 181 TranslationManager::convertTerm(const char* message) 182 { 183 return message; 184 } 185 186 #endif // TRANSLATION 187 188 189 } // End of namespace Common -
tools/README
51 51 Used to convert scumm-md5.txt into a SCUMM header file, or alternatively 52 52 PHP code for our website. 53 53 54 55 po2c 56 ---- 57 This perl script allows to convert all the translated messages in the .po 58 files into a C++ file so it can be included inside ScummVM without runtime 59 dependencies. 60 -
tools/po2c
1 #!/usr/bin/perl 2 3 # 4 # po2c - Converts .po files to C code 5 # 6 # Copyright (C) 2004 Angel Ortega <angel@triptico.com> 7 # 8 # This program is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 2 of the License, or 11 # (at your option) any later version. 12 # 13 # This program is distributed in the hope that it will be useful, 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 # GNU General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with this program; if not, write to the Free Software 20 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 # 22 # http://www.triptico.com 23 # 24 25 $VERSION = "1.0.2"; 26 27 if(scalar(@ARGV) == 0) 28 { 29 print "Usage: po2c {po file[s]}\n"; 30 exit 1; 31 } 32 33 %msgs = (); 34 %msgids = (); 35 36 # stage 1: loading 37 38 # arguments are .po files 39 foreach my $f (@ARGV) 40 { 41 my ($lang); 42 43 next unless(($lang) = ($f =~ /([^\/]+)\.po$/)); 44 45 if(open F, $f) 46 { 47 my ($msgid, $val, %a); 48 49 while(<F>) 50 { 51 chomp; 52 53 # ignore blank lines or comments 54 next if /^$/ or /^#/; 55 56 if(/^msgid\s+\"(.*)\"\s*$/) 57 { 58 # store previous msgid 59 if(defined($msgid)) 60 { 61 $a{$msgid} = $val; 62 $msgids{$msgid} ++; 63 } 64 65 # start of msgid 66 $val = $1; 67 } 68 elsif(/^msgstr\s+\"(.*)\"\s*$/) 69 { 70 # store previous msgid 71 $msgid = $val; 72 73 # start of msgstr 74 $val = $1; 75 } 76 elsif(/^\"(.*)\"\s*$/) 77 { 78 # add to current value 79 $val .= $1; 80 } 81 } 82 83 # store previous msgid 84 if(defined($msgid)) 85 { 86 $a{$msgid} = $val; 87 $msgids{$msgid} ++; 88 } 89 90 close F; 91 92 # add to the global message pool 93 $msgs{$lang} = \%a; 94 } 95 } 96 97 # stage 2: convert the data 98 99 # stores all sorted msgids into @msgids 100 @msgids = sort(keys(%msgids)); 101 102 # travels again, storing indexes into %msgids 103 for(my $n = 0;$n < scalar(@msgids);$n++) 104 { 105 $msgids{$msgids[$n]} = $n; 106 } 107 108 # stage 3: dump as C code 109 110 print "/* generated by po2c $VERSION - Do not modify */\n\n"; 111 print "#include <stdio.h>\n"; 112 print "#include <string.h>\n\n"; 113 114 # dump first the msgid array 115 print "static const char * _po2c_msgids[] = {\n"; 116 117 for(my $n = 0;$n < scalar(@msgids);$n++) 118 { 119 print "\t/* $n */ \"" . $msgids[$n] . "\",\n"; 120 } 121 122 print "\tNULL\n};\n\n"; 123 124 # dump the lang structure 125 print "struct _po2c_msg {\n"; 126 print "\tint msgid;\n"; 127 print "\tconst char * msgstr;\n"; 128 print "};\n\n"; 129 130 # dump now each language 131 132 foreach my $l (keys(%msgs)) 133 { 134 print "static struct _po2c_msg _po2c_lang_${l}[] = {\n"; 135 136 # get the translation table for the language $l 137 my ($m) = $msgs{$l}; 138 139 # while (my ($msgstr, $msgid) = each (%$m)) 140 foreach my $msgid (sort(keys(%$m))) 141 { 142 my ($msgstr) = $m->{$msgid}; 143 144 print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n" 145 if $msgstr; 146 } 147 148 print "\t{ -1, NULL }\n};\n\n"; 149 } 150 151 # finally, dump the languages 152 153 print "static struct {\n"; 154 print "\tconst char * lang;\n"; 155 print "\tconst char * charset;\n"; 156 print "\tstruct _po2c_msg * msgs;\n"; 157 print "} _po2c_langs[] = {\n"; 158 159 foreach my $l (keys(%msgs)) 160 { 161 $header = $msgs{$l}->{""}; 162 $header =~ /charset=([^\\]+)/; 163 $charset = $1; 164 print "\t{ \"" . $l . "\", \"" . $charset . "\", _po2c_lang_${l} },\n"; 165 } 166 167 print "\t{ NULL, NULL, NULL }\n};\n\n"; 168 169 print "/* code */\n"; 170 print << 'EOF'; 171 172 static struct _po2c_msg * _po2c_lang=NULL; 173 static int _po2c_lang_size=0; 174 static const char * _po2c_charset=NULL; 175 176 void po2c_setlang(const char * lang) 177 { 178 int n; 179 180 _po2c_lang=NULL; 181 _po2c_lang_size=0; 182 _po2c_charset=NULL; 183 184 /* if lang is NULL or "", deactivate it */ 185 if(lang == NULL || *lang == '\0') 186 return; 187 188 /* searches for a valid language array */ 189 for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++) 190 { 191 if(strcmp(lang, _po2c_langs[n].lang) == 0) { 192 _po2c_lang=_po2c_langs[n].msgs; 193 _po2c_charset=_po2c_langs[n].charset; 194 } 195 } 196 197 /* try partial searches */ 198 for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++) 199 { 200 if(strncmp(lang, _po2c_langs[n].lang, 2) == 0) { 201 _po2c_lang=_po2c_langs[n].msgs; 202 _po2c_charset=_po2c_langs[n].charset; 203 } 204 } 205 206 /* if found, count entries */ 207 if(_po2c_lang != NULL) 208 { 209 struct _po2c_msg * m; 210 211 for(m=_po2c_lang;m->msgid != -1;m++) 212 _po2c_lang_size++; 213 } 214 } 215 216 const char * po2c_gettext(const char * msgid) 217 { 218 struct _po2c_msg * m; 219 int b, t, n, c; 220 221 /* if no language is set or msgid is empty, return msgid as is */ 222 if(_po2c_lang == NULL || *msgid == '\0') 223 return(msgid); 224 225 /* binary-search for the msgid */ 226 b=0; t=_po2c_lang_size - 1; 227 228 while(t >= b) 229 { 230 n=(b + t) / 2; 231 m=&_po2c_lang[n]; 232 233 c=strcmp(msgid, _po2c_msgids[m->msgid]); 234 235 if(c == 0) 236 return(m->msgstr); 237 else 238 if(c < 0) 239 t=n - 1; 240 else 241 b=n + 1; 242 } 243 244 return(msgid); 245 } 246 247 const char * po2c_getcharset(void) 248 { 249 if (_po2c_charset) 250 return _po2c_charset; 251 else 252 return "ASCII"; 253 } 254 EOF 255 256 exit 0; -
po/module.mk
Property changes on: tools/po2c ___________________________________________________________________ Name: svn:executable + *
1 POTFILE := po/scummvm.pot 2 POFILES := $(wildcard po/*.po) 3 4 updatepot: 5 xgettext -f po/POTFILES -k_ -k_t --copyright-holder="ScummVM" \ 6 --msgid-bugs-address=scummvm-devel@lists.sourceforge.net \ 7 -o $(POTFILE)_ --from-code utf-8 8 sed -e 's/SOME DESCRIPTIVE TITLE/LANGUAGE translation for ScummVM/' \ 9 -e 's/UTF-8/CHARSET/' -e 's/PACKAGE/ScummVM/' $(POTFILE)_ > $(POTFILE).new 10 11 rm $(POTFILE)_ 12 if test -f $(POTFILE); then \ 13 sed -f po/remove-potcdate.sed < $(POTFILE) > $(POTFILE).1 && \ 14 sed -f po/remove-potcdate.sed < $(POTFILE).new > $(POTFILE).2 && \ 15 if cmp $(POTFILE).1 $(POTFILE).2 >/dev/null 2>&1; then \ 16 rm -f $(POTFILE).new; \ 17 else \ 18 rm -f $(POTFILE) && \ 19 mv -f $(POTFILE).new $(POTFILE); \ 20 fi; \ 21 rm -f $(POTFILE).1 $(POTFILE).2; \ 22 else \ 23 mv -f $(POTFILE).new $(POTFILE); \ 24 fi; 25 26 po/%.po: $(POTFILE) 27 msgmerge $@ $(POTFILE) -o $@.new 28 if cmp $@ $@.new >/dev/null 2>&1; then \ 29 rm -f $@.new; \ 30 else \ 31 mv -f $@.new $@; \ 32 fi; 33 34 update-translations: updatepot $(POFILES) 35 @$(foreach file, $(POFILES), echo -n $(notdir $(basename $(file)))": ";msgfmt --statistic $(file);) 36 @rm -f messages.mo 37 38 .PHONY: updatepot update-translations -
po/remove-potcdate.sed
1 # Sed script that remove the POT-Creation-Date line in the header entry 2 # from a POT file. 3 # 4 # The distinction between the first and the following occurrences of the 5 # pattern is achieved by looking at the hold space. 6 /^"POT-Creation-Date: .*"$/{ 7 x 8 # Test if the hold space is empty. 9 s/P/P/ 10 ta 11 # Yes it was empty. First occurrence. Remove the line. 12 g 13 d 14 bb 15 :a 16 # The hold space was nonempty. Following occurrences. Do nothing. 17 x 18 :b 19 } -
po/POTFILES
1 #TODO: help_string & usage_string: 2 base/commandLine.cpp 3 base/main.cpp 4 common/advancedDetector.cpp 5 common/config-file.cpp 6 common/config-manager.cpp 7 common/file.cpp 8 common/hashmap.h 9 common/iff_container.h 10 common/md5.cpp 11 common/mutex.cpp 12 common/util.cpp 13 graphics/dxa_player.cpp 14 graphics/font.cpp 15 graphics/iff.cpp 16 graphics/mpeg_player.cpp 17 graphics/surface.cpp 18 #gui/about.cpp 19 gui/browser.cpp 20 gui/chooser.cpp 21 #gui/credits.h 22 gui/debugger.cpp 23 gui/dialog.cpp 24 gui/eval.cpp 25 gui/KeysDialog.h 26 gui/KeysDialog.cpp 27 gui/launcher.cpp 28 gui/massadd.cpp 29 gui/message.h 30 gui/newgui.cpp 31 gui/options.cpp 32 gui/themebrowser.cpp 33 gui/ThemeClassic.cpp 34 gui/theme-config.cpp 35 gui/theme.cpp 36 gui/ThemeModern.cpp 37 38 #TODO: backends engines sound tools?