Hard Light Productions Forums

Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Test Builds => Topic started by: karajorma on July 14, 2013, 01:59:40 am

Title: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 14, 2013, 01:59:40 am
FS2 has always had support for German, French and Polish. We've often heard requests for other languages and today I decided it was time to add support for any language we can fit in under 255 characters (Chinese, Japanese, etc will have to wait unfortunately).

Support works like this. You'll need to add a new section to the start of Strings.tbl which looks like this.

Code: [Select]
#Supported Languages

$Language: German
+Extension: gr
+Non English Character Index: 164

$Language: French
+Extension: fr
+Non English Character Index: 164

$Language: Spanish
+Extension: sp
+Non English Character Index: 164

#End

the extension is used by the game to have extra folders which contain the foreign language files (i.e German voice acting etc.). The Non English Character Index is the point in the font where characters like the accents etc start appearing (at least as far as I can tell, that's what it's for).

At the moment, the only way to change languages is by manually editing the registry but hopefully the wx_Launcher guys will make it easier once this starts being used.

Here's the code changes.

Code: [Select]
Index: code/fred2/management.cpp
===================================================================
--- code/fred2/management.cpp (revision 9729)
+++ code/fred2/management.cpp (working copy)
@@ -325,7 +325,7 @@
  // NOTE : Fred should ALWAYS run in English. Otherwise it might swap in another language
  // when saving - which would cause inconsistencies when externalizing to tstrings.tbl via Exstr
  // trust me on this :)
- lcl_init(LCL_ENGLISH);
+ lcl_init(FS2_OPEN_DEFAULT_LANGUAGE);
 
  // Goober5000 - force init XSTRs (so they work, but only work in English, based on above comment)
  extern int Xstr_inited;
Index: code/freespace2/freespace.cpp
===================================================================
--- code/freespace2/freespace.cpp (revision 9729)
+++ code/freespace2/freespace.cpp (working copy)
@@ -8378,14 +8378,6 @@
 // Language autodetection stuff
 //
 
-// this layout *must* match Lcl_languages in localize.cpp in order for the
-// correct language to be detected
-int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
- 589986744, // English
- -1132430286, // German
- 0, // French
-};
-
 // default setting is "-1" to use registry setting with English as fall back
 // DO NOT change that default setting here or something uncouth might happen
 // in the localization code
@@ -8415,8 +8407,8 @@
  detect = NULL;
 
  // now compare the checksum/filesize against known #'s
- for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
- if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
+ for (idx=0; idx < (int)Lcl_languages.size(); idx++) {
+ if (Lcl_languages[idx].checksum == (int)file_checksum) {
  mprintf(( "AutoLang: Language auto-detection successful...\n" ));
  return idx;
  }
Index: code/localization/localize.cpp
===================================================================
--- code/localization/localize.cpp (revision 9729)
+++ code/localization/localize.cpp (working copy)
@@ -28,27 +28,29 @@
 // general language/localization data ---------------------
 
 // current language
-int Lcl_current_lang = LCL_ENGLISH;
+int Lcl_current_lang = FS2_OPEN_DEFAULT_LANGUAGE;
+SCP_vector<lang_info> Lcl_languages;
 
-// language info table
-typedef struct lang_info {
- char lang_name[LCL_LANG_NAME_LEN + 1]; // literal name of the language
- char lang_ext[LCL_LANG_NAME_LEN + 1]; // for adding to names on disk access
-} lang_info;
+// These are the original languages supported by FS2. The code expects these languages to be supported even if the tables don't
 
-lang_info Lcl_languages[LCL_NUM_LANGUAGES] = {
- { "English", "" }, // english
- { "German", "gr" }, // german
- { "French", "fr" }, // french
- { "Polish", "pl" }, // polish
+#define NUM_BUILTIN_LANGUAGES 4
+lang_info Lcl_builtin_languages[NUM_BUILTIN_LANGUAGES] = {
+ { "English", "", 0, 589986744}, // English
+ { "German", "gr", 164, -1132430286 }, // German
+ { "French", "fr", 164, 0 }, // French
+ { "Polish", "pl", 127 }, // Polish
 };
 
+/*
 #define DEFAULT_LANGUAGE "English"
+*/
 
+/*
 // following is the offset where special characters start in our font
 #define LCL_SPECIAL_CHARS_FR 164
 #define LCL_SPECIAL_CHARS_GR 164
 #define LCL_SPECIAL_CHARS_PL 127
+*/
 #define LCL_SPECIAL_CHARS 127
 int Lcl_special_chars;
 
@@ -148,7 +150,10 @@
 // initialize the pointer array into tstrings.tbl (call from lcl_ext_open() ONLY)
 void lcl_ext_setup_pointers();
 
+// parses the string.tbl and reports back only on the languages it found
+void parse_stringstbl_quick(char *filename);
 
+
 // ------------------------------------------------------------------------------------------------------------
 // LOCALIZE FUNCTIONS
 //
@@ -160,28 +165,51 @@
 
  char lang_string[128];
  char *ret;
- int lang, idx;
+ int lang, idx, i;
+ int rval;
 
  // initialize encryption
  encrypt_init();
 
+ // setup English
+ Lcl_languages.push_back(Lcl_builtin_languages[FS2_OPEN_DEFAULT_LANGUAGE]);
+
+ // check string.tbl to see which languages we support
+ if ( (rval = setjmp(parse_abort)) != 0 ) {
+ mprintf(("TABLES: Unable to parse '%s'!  Error code = %i.\n", "strings.tbl", rval));
+ }
+ else {
+ parse_stringstbl_quick("strings.tbl");
+ }
+
+ parse_modular_table(NOX("*-lcl.tbm"), parse_stringstbl_quick);
+
+ // if the only language we have at this point is English, we need to setup the builtin languages as we might be dealing with an old style strings.tbl
+ // which doesn't support anything beyond the builtin languages. Note, we start at i = 1 because we added English above.
+ if ((int)Lcl_languages.size() == 1) {
+ for (i=1; i<NUM_BUILTIN_LANGUAGES; i++) {
+ Lcl_languages.push_back(Lcl_builtin_languages[i]);
+ }
+ }
+
  // read the language from the registry
  if(lang_init < 0){
  memset(lang_string, 0, 128);
  // default to DEFAULT_LANGUAGE (which should be English so we don't have to put German text
  // in tstrings in the #default section)
- ret = os_config_read_string(NULL, "Language", DEFAULT_LANGUAGE);
+ ret = os_config_read_string(NULL, "Language", Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name);
 
  if(ret == NULL){
- Int3();
- strcpy_s(lang_string, DEFAULT_LANGUAGE);
- } else {
- strcpy_s(lang_string, ret);
- }
+ Warning(LOCATION, "Default language not found. Defaulting to %s", Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name);
+ ret = Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name;
+ }
 
+ strcpy_s(lang_string, ret);
+
+
  // look it up
  lang = -1;
- for(idx=0; idx<LCL_NUM_LANGUAGES; idx++){
+ for(idx = 0; idx < (int)Lcl_languages.size(); idx++){
  if(!stricmp(Lcl_languages[idx].lang_name, lang_string)){
  lang = idx;
  break;
@@ -191,7 +219,7 @@
  lang = 0;
  }
  } else {
- Assert((lang_init >= 0) && (lang_init < LCL_NUM_LANGUAGES));
+ Assert((lang_init >= 0) && (lang_init < (int)Lcl_languages.size()));
  lang = lang_init;
  }
 
@@ -221,6 +249,48 @@
  return Lcl_current_lang;
 }
 
+// parses the string.tbl to see which languages are supported. Doesn't read in any strings.
+void parse_stringstbl_quick(char *filename)
+{
+ lang_info language;
+ int lang_idx;
+ int i;
+
+ // make sure localization is NOT running
+ lcl_ext_close();
+
+ read_file_text(filename, CF_TYPE_TABLES);
+ reset_parse();
+
+ if (optional_string("#Supported Languages")) {
+ while (required_string_either("#End","$Language:")) {
+ required_string("$Language:");
+ stuff_string(language.lang_name, F_NAME, LCL_LANG_NAME_LEN + 1);
+ required_string("+Extension:");
+ stuff_string(language.lang_ext, F_NAME, LCL_LANG_NAME_LEN + 1);
+ required_string("+Non English Character Index:");
+ stuff_ubyte(&language.special_char_offset);
+
+ lang_idx = -1;
+
+ // see if we already have this language
+ for (i = 0; i < (int)Lcl_languages.size(); i++) {
+ if (!strcmp(Lcl_languages[i].lang_name, language.lang_name)) {
+ strcpy_s(Lcl_languages[i].lang_ext, language.lang_ext);
+ Lcl_languages[i].special_char_offset = language.special_char_offset;
+ lang_idx = i;
+ break;
+ }
+ }
+
+ // if we have a new language, add it.
+ if (lang_idx == -1) {
+ Lcl_languages.push_back(language);
+ }
+ }
+ }
+}
+
 void parse_stringstbl(char *filename)
 {
  char chr, buf[4096];
@@ -395,35 +465,16 @@
 
  nprintf(("General", "Setting language to %s\n", Lcl_languages[lang].lang_name));
 
+ Assertion((Lcl_current_lang >= 0) && (Lcl_current_lang < (int)Lcl_languages.size()), "Attempt to set language to an invalid language");
+
  // flag the proper language as being active
- Lcl_fr = 0;
- Lcl_gr = 0;
- Lcl_pl = 0;
- Lcl_english = 0;
- switch(lang){
- case LCL_ENGLISH:
- Lcl_english = 1;
- Lcl_special_chars = LCL_SPECIAL_CHARS;
- break;
- case LCL_FRENCH:
- Lcl_fr = 1;
- Lcl_special_chars = LCL_SPECIAL_CHARS_FR;
- break;
- case LCL_GERMAN:
- Lcl_gr = 1;
- Lcl_special_chars = LCL_SPECIAL_CHARS_GR;
- break;
- case LCL_POLISH:
- Lcl_pl = 1;
- Lcl_special_chars = LCL_SPECIAL_CHARS_PL;
- break;
- }
+ Lcl_special_chars = Lcl_languages[Lcl_current_lang].special_char_offset;
 
  // set to 0, so lcl_ext_open() knows to reset file pointers
  Lcl_pointer_count = 0;
 
  // reset file pointers to the proper language-section
- if(Lcl_current_lang != LCL_DEFAULT_LANGUAGE){
+ if(Lcl_current_lang != FS2_OPEN_DEFAULT_LANGUAGE){
  lcl_ext_setup_pointers();
  }
 }
@@ -504,7 +555,7 @@
  Assert(Lcl_ext_file == NULL);
 
  // if we're running in the default language, do nothing
- if(Lcl_current_lang == LCL_DEFAULT_LANGUAGE){
+ if(Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE){
  return;
  }
 
@@ -524,7 +575,7 @@
  }
 
  // if we're running in the default language, do nothing
- if(Lcl_current_lang == LCL_DEFAULT_LANGUAGE){
+ if(Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE){
  return;
  }
 
@@ -673,7 +724,7 @@
  }
 
  // if the localization file is not open, or we're running in the default language, return the original string
- if ( (Lcl_ext_file == NULL) || (str_id < 0) || (Lcl_current_lang == LCL_DEFAULT_LANGUAGE) ) {
+ if ( (Lcl_ext_file == NULL) || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
  if ( strlen(text_str) > (uint)max_len )
  error_display(0, "Token too long: [%s].  Length = %i.  Max is %i.\n", text_str, strlen(text_str), max_len);
 
@@ -759,7 +810,7 @@
  }
 
  // if the localization file is not open, or we're running in the default language, return the original string
- if ( (Lcl_ext_file == NULL) || (str_id < 0) || (Lcl_current_lang == LCL_DEFAULT_LANGUAGE) ) {
+ if ( (Lcl_ext_file == NULL) || (str_id < 0) || (Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE) ) {
  out = text_str;
 
  if (id != NULL)
@@ -1274,7 +1325,7 @@
  // seek to the currently active language
  memset(language_string, 0, 128);
  strcpy_s(language_string, "#");
- if(!stricmp(DEFAULT_LANGUAGE, Lcl_languages[Lcl_current_lang].lang_name)){
+ if(Lcl_current_lang == FS2_OPEN_DEFAULT_LANGUAGE){
  strcat_s(language_string, "default");
  } else {
  strcat_s(language_string, Lcl_languages[Lcl_current_lang].lang_name);
@@ -1348,7 +1399,7 @@
 
 void lcl_get_language_name(char *lang_name)
 {
- Assert(LCL_NUM_LANGUAGES == 3);
+ Assert(Lcl_current_lang < (int)Lcl_languages.size());
 
  strcpy(lang_name, Lcl_languages[Lcl_current_lang].lang_name);
 }
Index: code/localization/localize.h
===================================================================
--- code/localization/localize.h (revision 9729)
+++ code/localization/localize.h (working copy)
@@ -18,21 +18,35 @@
 // LOCALIZE DEFINES/VARS
 //
 
+
+#define FS2_OPEN_DEFAULT_LANGUAGE 0
+
+/*
 // language defines
 #define LCL_NUM_LANGUAGES 4 // keep this up to date
-#define LCL_ENGLISH 0
 #define LCL_GERMAN 1
 #define LCL_FRENCH 2
 #define LCL_POLISH 3
+*/
 
-#define LCL_DEFAULT_LANGUAGE LCL_ENGLISH
+// for language name strings
+#define LCL_LANG_NAME_LEN 32
 
+// language info table
+typedef struct lang_info {
+ char lang_name[LCL_LANG_NAME_LEN + 1]; // literal name of the language
+ char lang_ext[LCL_LANG_NAME_LEN + 1]; // the extension used for adding to names on disk access
+ ubyte special_char_offset; // where in the font do we have the special characters for this language
+ int checksum; // used for language auto-detection
+} lang_info;
+
+extern SCP_vector<lang_info> Lcl_languages;
+
+//#define LCL_DEFAULT_LANGUAGE LCL_ENGLISH
+
 // following is the offset where special characters start in our font
 extern int Lcl_special_chars;
 
-// for language name strings
-#define LCL_LANG_NAME_LEN 32
-
 // use these to replace *_BUILD values
 // only 1 will be active at a time
 extern int Lcl_fr;

And you can find the builds here (http://fs2downloads.com/Misc-Downloads/Builds/Multi_Language_Support_build.7z).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Phantom Hoover on July 14, 2013, 02:12:35 am
Unicode support would be a character set too far, I assume?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 14, 2013, 03:09:46 am
I was under the impression that unicode was already being worked on. This was something I could do in a few hours which was necessary for when we have unicode support anyway, so why not do it sooner rather than later? :)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Iss Mneur on July 14, 2013, 11:57:47 am
I a few concerns.

It looks like this patch adds about 12 lines of commented out code.

This Warning doesn't really make sense. I am assuming its more like, "Preferred language not found" but if that is the case I don't know why this is a warning.
Code: [Select]
+   Warning(LOCATION, "Default language not found. Defaulting to %s", Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name);
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Dragon on July 14, 2013, 03:56:12 pm
Maybe "Selected language not found"? That'd make more sense (unless I misunderstood what it does, that is).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 14, 2013, 07:02:05 pm
This Warning doesn't really make sense. I am assuming its more like, "Preferred language not found" but if that is the case I don't know why this is a warning.
Code: [Select]
+   Warning(LOCATION, "Default language not found. Defaulting to %s", Lcl_languages[FS2_OPEN_DEFAULT_LANGUAGE].lang_name);


This is the result of changing a rather weird little from an Int3() in the original code into something a little less crashy. It really is doing what it says, failing to find the default language and therefore setting it to the default language. The original code did this

Code: [Select]
ret = os_config_read_string(NULL, "Language", DEFAULT_LANGUAGE);

and would then Int3() if ret was NULL. As far as I can tell, that is actually a legal return from the os_config_read_string() function but you really shouldn't be getting it at that point in the game. I'll change the error message to reflect that there is some sort of registry / ini file error going on.


BTW, people who use foreign language versions of FS2, can you please check this out. I especially want to know if I've caused any problems for the Polish version of Freespace cause V seem to have done something rather strange there (There are no Polish entries in Strings.tbl or Tstrings.tbl).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on July 14, 2013, 10:21:16 pm
For the sake of not requiring improper English in tables, "+Non English Character Index" should be changed to "+Non-English Character Index" (with a hyphen between "Non" and "English").
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 14, 2013, 11:27:59 pm
Yeah. I noticed that earlier and it's already changed in my local copy. :) I just couldn't be bothered to build everything again before posting.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Iss Mneur on July 14, 2013, 11:36:15 pm
This is the result of changing a rather weird little from an Int3() in the original code into something a little less crashy. It really is doing what it says, failing to find the default language and therefore setting it to the default language. The original code did this

Code: [Select]
ret = os_config_read_string(NULL, "Language", DEFAULT_LANGUAGE);

and would then Int3() if ret was NULL. As far as I can tell, that is actually a legal return from the os_config_read_string() function but you really shouldn't be getting it at that point in the game. I'll change the error message to reflect that there is some sort of registry / ini file error going on.
Okay.

No.  The only way for os_config_read_string to return NULL is if the default is NULL.  Since we specify the default the only way that we could have a NULL in the default is NULL, and since the default comes from the global initialization, we would have rampant memory corruption, which should probably warrant more than just a Warning, I would think.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 15, 2013, 07:44:04 am
Actually there is one other way. It does a quick return if a certain variable hasn't been set. I didn't chase down that variable and see what can cause it to be unset though.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Rodo on July 15, 2013, 09:06:51 am
Sorry to butt in, but I'm kinda interested in this

the extension is used by the game to have extra folders which contain the foreign language files (i.e German voice acting etc.).

Which files exactly should those folders contain?, could we have a list of the possible files as an example or maybe a list of types of files supported/expected by fso?

Also, thanks for taking the time to do this :yes:
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 15, 2013, 09:26:08 am
To be honest I'm not certain (I don't have the code in front of me at the moment). I'd like to hear from the Germany and French users on this one.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on July 15, 2013, 03:15:35 pm
Oh, well done with this. :yes:
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Iss Mneur on July 15, 2013, 07:43:07 pm
Actually there is one other way. It does a quick return if a certain variable hasn't been set. I didn't chase down that variable and see what can cause it to be unset though.
I see.  You are still pretty much screwed if you are trying to read config data when the registry code was not initialized.  The SCP_UNIX equivalent doesn't even check.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 15, 2013, 08:45:54 pm
It probably should error out in those situations then.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Flaser on July 16, 2013, 11:42:50 am
Just a quick question, is the engine still limited to the built in Bank Gothic font for all displayed text messages?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Iss Mneur on July 16, 2013, 01:12:09 pm
Just a quick question, is the engine still limited to the built in Bank Gothic font for all displayed text messages?
No. You can substitute any font you want.  Search the forum for "font builder".  There is also work on TTF font support though I am not sure of the status of that (check the test builds forum).  IIRC Diaspora has a custom font that is similar to the one used on the show.

However, as far as I know, any font that you build is still restricted to the strict ASCII latin characters (that is, the 26 upper case, the 26 lowercase, the 10 digits and about 10 symbols) as far a character set goes, which is what the subtitle of this thread is referring to.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on July 17, 2013, 07:40:26 am
I don't think it is limited actually. Just that the characters over a certain value are reserved for other languages. That's what +Non-English Character Index: is for, setting where those characters start from.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 04, 2013, 01:09:31 pm
Does this currently provide a way for different languages to use different sets of fonts? If the FreeSpace font format doesn't support more than 256 characters, then this feature would be needed for a mod to support, say, both German and Russian. Also, I believe the font files included with non-English versions of FS2 are different from the ones in the English version, seeing as how playing the English version in German causes accented letters to display improperly. With this feature, mods could include those those altered fonts specifically for non-English languages.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: mjn.mixael on September 04, 2013, 01:44:40 pm
This would go nicely with the TTF support... :)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 04, 2013, 07:44:36 pm
Does this currently provide a way for different languages to use different sets of fonts? If the FreeSpace font format doesn't support more than 256 characters, then this feature would be needed for a mod to support, say, both German and Russian. Also, I believe the font files included with non-English versions of FS2 are different from the ones in the English version, seeing as how playing the English version in German causes accented letters to display improperly. With this feature, mods could include those those altered fonts specifically for non-English languages.

I didn't include support for that. All I did was expand the existing FS2 system to allow other languages to be used since I now had table files for Spanish. I was waiting for proper support for other fonts to be added before I attempted anything more than that.

I will point out that it would be helpful if I can find someone who has a foreign language version of Freespace 2 who can get me those versions of the files so that I can see the differences.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: niffiwan on September 04, 2013, 08:34:49 pm
I will point out that it would be helpful if I can find someone who has a foreign language version of Freespace 2 who can get me those versions of the files so that I can see the differences.

Getting SCP members access to non-English versions of FS2 would be a great help for internationalisation efforts. I noticed this page @ GOG (http://www.gog.com/wishlist/site/more_languages_for_games). Maybe some votes for Freespace 2 would encourage them to add the German/French/Polish versions? (hopefully you could download any language as part of the one purchase)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 05, 2013, 05:13:38 am
Posted a comment on there. I'd appreciate it if someone could get me the file in the meanwhile though. Okay technically I don't own the French or German versions but I bought Freespace 2 three times so it's not like I didn't give :v: their money's worth. :D
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: MetalDestroyer on September 06, 2013, 04:05:42 am
Freespace 1 and his extension Silent Threat have French, but not Freespace 2. I bought those games at day one, and Freespace 2 never have French langage for subtitle and voice acting. All the content of Freespace 2 is in english.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 06, 2013, 05:17:15 am
Actually it does have partial French support built in to the engine and also to the table files. Simply edit your registry to have the language set to French instead of English and you'll see what I mean.

If that doesn't work, use a very recent nightly, one from after this was committed.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: MetalDestroyer on September 06, 2013, 05:26:42 am
Can I edit this value directly into the launcher ? Or I should really go to regedit ?
I'll give you more info this evening.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 06, 2013, 10:15:48 am
The launcher can't edit those values so you do need to use regedit. As I said above, hopefully we'll see this being added to the launcher at a later date.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: MetalDestroyer on September 06, 2013, 01:06:04 pm
Ok, unfortunately, I don't find the key associated to language. Could you tell me what is the key name I have to create and with which type ?

(http://tof.canardpc.com/view/45505ad6-ff35-47c4-8af1-af948dceb7ab.jpg)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 06, 2013, 01:26:03 pm
Ok, unfortunately, I don't find the key associated to language. Could you tell me what is the key name I have to create and with which type ?
The name should be "Language" and the type should be "String Value" or "REG_SZ" (or whatever your version of Windows calls it). Once that's created, set its value to the English name of the language you want (in your case, "French"). I've attached an image of what this should look like.

[attachment deleted by ninja]
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: MetalDestroyer on September 06, 2013, 02:12:52 pm
Ok, now, I reread the whole thread, and I don't know what you want exactly Karajorma ? Do you want a copy of my string.tbl and tstring.tbl ? Or is there some kind of stuff to do with a specific build ?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 06, 2013, 09:59:53 pm
Copies of the tables would be useful as I can check them for differences against the ones I have. I'd be interested in seeing if there are any other files which differ in the German, Polish or French versions.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 06, 2013, 10:13:37 pm
I'd be interested in seeing if there are any other files which differ in the German, Polish or French versions.
I made a program with this very goal in mind. The thread is here (http://www.hard-light.net/forums/index.php?topic=85492.0).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 06, 2013, 11:13:52 pm
Thanks, I can see that being very helpful.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: MetalDestroyer on September 07, 2013, 05:01:14 am
Ok, here the tables:
http://www.mediafire.com/download/a22sa7wtmqfbosy/tables_french.rar

I'll run VPLogger laters since I don't have tangox.vp. I remember I didn't do a full install.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 07, 2013, 04:41:41 pm
I got the German version of font01.vf (the only font file that's different); it's in the zip file linked to here (http://www.hard-light.net/forums/index.php?topic=85492.0) at the bottom of the original post. It turns out that, while this font is suitable for German, it's not suitable for English since it messes up the HUD slightly if the game is played in English. Additionally, the German version has a wider kills gauge to fit the longer text.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 08, 2013, 10:46:21 pm
To help you guys see what characters are in the font files, as well as what the characters' indices are, I have ripped all of the characters from the font files. Here they are:
https://www.dropbox.com/s/3iwoymnmwpg9ydu/fs_font_chars.zip?dl=1 (https://www.dropbox.com/s/3iwoymnmwpg9ydu/fs_font_chars.zip?dl=1)

The two versions of font01 are the most important here. In the regular font01 (the English one), you'll notice that all the characters up to index 126 are the ASCII characters. From index 127 onward are special symbols used mainly for the HUD. In the German version of the font (which I named font01-gr), those symbols start at index 164 (the accented characters appear before that). Do 127 and 164 sound familiar to you? That's right, these numbers are the indices defined in localize.cpp and the new language definition structure. They specify the starting index of the special symbols, not the accented characters.

With that in mind, and considering that this feature was only recently committed, I propose renaming "Non-English Character Index" to something like "Special Character Offset" (similar to what it's called in localize.h, line 31) to make it less misleading.


EDIT:
Quote
the extension is used by the game to have extra folders which contain the foreign language files (i.e German voice acting etc.).
This seems to be broken, and it probably always has been. Based on the code and debug messages that I added (patch below), the game appears to apply language extensions in this manner:
Code: [Select]
[original path name]\[language extension]\[original file name]

example: data\voice\special\gr\message.wav

The patch below adds debug messages to the function that I believe is meant to add the language extension. When I tried it, the only messages generated from this that I saw had to do with font files, but the paths were anything but the fonts folder. Change the language setting to German, then try this patch out and then look at the debug log to see what I mean.
Code: [Select]
Index: code/localization/localize.cpp
===================================================================
--- code/localization/localize.cpp (revision 9774)
+++ code/localization/localize.cpp (working copy)
@@ -502,6 +502,7 @@
 // maybe add localized directory to full path with file name when opening a localized file
 int lcl_add_dir_to_path_with_filename(char *current_path, uint path_max)
 {
+ mprintf(("Old path: %s\n", current_path));
  // if the disk extension is 0 length, don't add enything
  if (strlen(Lcl_languages[Lcl_current_lang].lang_ext) <= 0) {
  return 1;
@@ -530,6 +531,7 @@
  strcat_s(current_path, path_max, temp);
 
  delete [] temp;
+ mprintf(("New path: %s\n\n", current_path));
  return 1;
 }
 

Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 09, 2013, 07:44:28 pm
This is one reason why I wanted the German and French files in the first place. :)

Thanks a lot Yarn, I'll review and add in the changes I can later today.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 14, 2013, 05:58:46 am
This seems to be broken, and it probably always has been. Based on the code and debug messages that I added (patch below), the game appears to apply language extensions in this manner:
Code: [Select]
[original path name]\[language extension]\[original file name]

example: data\voice\special\gr\message.wav

The patch below adds debug messages to the function that I believe is meant to add the language extension. When I tried it, the only messages generated from this that I saw had to do with font files, but the paths were anything but the fonts folder. Change the language setting to German, then try this patch out and then look at the debug log to see what I mean.

The reason for the strange output appears to be that line 389 of font.cpp was set to
Code: [Select]
fp = cfopen( typeface, "rb", CFILE_NORMAL, CF_TYPE_ANY, localize ); instead of
Code: [Select]
fp = cfopen( typeface, "rb", CFILE_NORMAL, CF_TYPE_FONT, localize ); which meant that the game checked all over the place for fonts rather than just in the fonts folder.

Where are the German voice files placed?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 14, 2013, 10:13:04 am
Where are the German voice files placed?
Do you mean where they are in the German retail version? If so, then they're in the same place as the English voice files (e.g., in-mission voices are in data\voice\special). In fact, no files from the German version are placed in a "gr" folder, even though retail does indeed support this feature, at least for fonts (I tested it recently).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 14, 2013, 12:13:03 pm
Fonts appear to be the only thing it does support actually. I'll see if I can expand that so that it can find German voice files in both data\voice\special and data\voice\special\gr. Doing that with the tables as well would allow you to have a properly multilingual install where the only requirement to switch languages is a change in the registry.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 14, 2013, 12:38:40 pm
Fonts appear to be the only thing it does support actually. I'll see if I can expand that so that it can find German voice files in both data\voice\special and data\voice\special\gr. Doing that with the tables as well would allow you to have a properly multilingual install where the only requirement to switch languages is a change in the registry.
I would further expand this to all voices (including command briefings, briefings, debriefings, and personas), fiction, and HUD graphics (since kills1.ani in the German version is much wider to fit the text).
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 14, 2013, 07:22:41 pm
Yeah, I meant to say that the special folder was an example and I'd be doing it with other folders too.

I'll also need to look into tables and missions since the German versions of these are different and I could see the need for this with other languages. Help.tbl is the worst offender and the question there is whether it's better to make the game parse table files separately for a different language (which would have a knock on effect in multiplayer) or simply make it possible to have multiple languages in the tables themselves.

EDIT : Well I looked into it but there is one major issue that is worth talking about. There is a problem with altering cfile to look for localised versions in this way.

Suppose Diaspora had German language files in the gr folders. Then we notice a bug with one of the English language files and release a patch to fix a few of the voices. Since these files are now in a VP with higher priority than the main VP, the English voice files will be found first. The game will then look for a German version in the patch VP file fail to find it and return the English version as the correct one to use. This results in a game with mostly German voice acting but the patched voices will be in English.*

The only way to solve this is to include all the German voices in the patch even though they didn't change or to change CFILE so that it checks through all the VPs for German versions first and only then revert to English. Changing CFILE looks pretty simple, merely requiring that I reorder a for loop but it opens a whole new can of worms. If instead of a voice file the issue is with a table file which has both English and German versions then now we have maintenance issues. Fixing the English table doesn't solve the problem because the German version would be found first and would still have the bug. This doesn't sound like too big a problem (simply release German versions of the table too) until you consider what happens if someone decides to add a German table to the media VPs. Doing so would break every single mod that has it's own version of that table.


So basically I though I'd better post this and ask for some suggestions on what to do before I start altering anything. 


*It should be noted that this scenario is a problem right now. A patched voice would break the current German version of FS2 too. Even though it doesn't use /gr/ folders.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: AdmiralRalwood on September 15, 2013, 12:33:30 am
The only way to solve this is to include all the German voices in the patch even though they didn't change or to change CFILE so that it checks through all the VPs for German versions first and only then revert to English. Changing CFILE looks pretty simple, merely requiring that I reorder a for loop but it opens a whole new can of worms. If instead of a voice file the issue is with a table file which has both English and German versions then now we have maintenance issues. Fixing the English table doesn't solve the problem because the German version would be found first and would still have the bug. This doesn't sound like too big a problem (simply release German versions of the table too) until you consider what happens if someone decides to add a German table to the media VPs. Doing so would break every single mod that has it's own version of that table.
How about look for any German version of the file in any VP, but only in that specific folder? In your example, that would give the mod's modified English table priority over the German MediaVPs table.

Basically, for loop hierarchy like this:
Code: [Select]
for folder in folders:
    for language in languages:
        for vp_file in vp_files:
            blah

instead of like this:
Code: [Select]
for language in languages:
    for folder in folders:
        for vp_file in vp_files:
            blah

(Apologies for horrible psuedocode and also not having looked at the source to see what it's actually doing.)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 20, 2013, 08:44:42 pm
Adding support for this is proving to be a bigger problem than I had expected.

I can add support for loose folders pretty easily, the issue is .vp files. The game only adds files into its map of what the vp file contains if the folder it's in matches one of the hardcoded pathtypes. If the folder doesn't match one of them, the file is ignored. That means that all the foreign language folders will be completely ignored. I can't even add pathtypes on the fly because the strings.tbl that tells the game which languages are supported could very easily be within the vp!

The only solution I can think of is to say that strings.tbl must be outside of the vp for it to work (or to create a new table that always lives outside the vp and does the same thing).

If anyone has a better idea, I'm all ears.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on September 20, 2013, 10:21:06 pm
I would suggest emailing Taylor and see what he has to say.  He has worked extensively on the CFILE system (like just about everything else) in the past.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 22, 2013, 09:16:18 pm
I'm not certain the issue is actually CFILE. It's more a chicken and egg situation. CFILE can't index the extra language folders to the vp unless it can read the strings.tbl folder but it can only read once it's indexed the vp files.

Short of doing more than one pass of all the vp files I can't see any way round that.

I don't mind speaking to Taylor but I don't have his email address on my phone and I won't have net access on my PC for a few days.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on September 22, 2013, 09:19:25 pm
Maybe do more than one pass at first, and from then on (once strings.tbl has been read) do only one pass.

Alternatively, you could make a list of every single two-character language code and always index all of them.  But that would probably be too inefficient.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 23, 2013, 03:31:14 am
I'd rather avoid hardcoding the support for languages. I don't much like the idea of needing a new build should we forget one.

Similarly there is an issue with parsing until we find a string.tbl, we have no way of knowing if somewhere else in the vp files there is a string .tbm which adds another language.

At least if we insist on loose files we can find them all before we start parsing. Or we could do loose files + vp files with a certain name.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: chief1983 on September 23, 2013, 09:51:36 am
Is a multi-pass approach that big of a deal?  It's only done at load time, and checking to see if a certain filename is in a .vp isn't that big of a performance hit is it?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 23, 2013, 11:48:20 am
It seems like a bit of a waste to index all the vps in the game, find an instance of only one or two files and then throw the whole lot away and do it again.

But if that's the approach everyone else is happy with, I don't mind doing it. I just didn't want to implement it that way and then have everyone complain at me.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: chief1983 on September 23, 2013, 12:17:16 pm
My only thought was that perhaps a multi-pass approach implemented now might solve other similar future problems too.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 23, 2013, 07:25:08 pm
Well it's probably worth seeing how long the game takes to index the vps, I definitely don't want to add to the start up time for something most users won't ever see (since they use English) and which even the foreign users will only see once mods start supporting it.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: FUBAR-BDHR on September 25, 2013, 09:22:22 am
Where exactly are the non-english voice files going to be stored?  It seems that if they are put anywhere under data/voice that it will cause issues as from my experience the entire voice folder including all subdirectories are searched for any voice file.  I've seen files found in a non standard folder like data/special/music be found and play. 

Since this needs removed from the registry (lets face it one mod/TC having language support and another not has and is going to cause things to blow up) why not create a new data/localization directory and add the language subdirectoires there.  Make the directory names whatever the language is.  For instance data/localization/german for German.  The language would be passed by the launcher or command line and that directory would be set in cfile based on the name passed.  If no name or an invalid name is passed it's skipped.  Other languages in the data/localizaton folder would be ignored just like things in data/docs, data/freddocs, data/whatever that isn't read by cfile.  Of course if the localization folder exists it would need to look there first and ignore the data/voice folder entry if it already exists.  If a specified file doesn't exist in localization then the question becomes should it fall back to English?  My opinion would be yes as there are a lot of cases where voice files aren't really voices (things like radio static). 

Now to take this a step further I would suggest a data/localization/<language>/voice data/localization/<language>/sounds data/localization/<language>/music data/localization/<language>/subtitles (this one doesn't exist yet but I was planning on adding a folder for subtitles since there is no default location for them they get thrown into maps, effects, interface etc).  This would allow you not only the ability to localize voice acting but subtitles, have translated music if there is voice in that, and any sound effects that contain voices. 
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 26, 2013, 12:07:47 am
The game is actually already set up to have voice files for german in Data/Voice/Special/Gr etc. It doesn't work currently in the case of loose files cause of a stupid bug in the code. VP files are similarly crippled by the bug described above.

If the game is finding files in subfolders of voice/special. It really shouldn't be. In fact as far as VP files go it won't even index them as being part of the VP at all. If it is finding files in the wrong folders this is actually a bug.

As for having a localisation folder. I did think about it but in the end I wasn't much of a fan. It require rewriting all the current localisation code and I really don't see much of a point since I can't see how it would prevent any bugs which aren't currently an issue.

That said, a localisation folder might be a solution for the issue I'm facing now that avoids the need to reparse every VP file. So I will look into it.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: FUBAR-BDHR on September 26, 2013, 09:05:07 am
Well a quick search does turn up the use of CF_TYPE_ANY in audiostr.cpp.  Not sure if that would cause it. 

In any case while having the voice files under a subdirectroy might take care of voice localization it doesn't do anything for other things that also could need localization.  Wouldn't it be better to set it up to handle that now before people start widely using it then to try to shoehorn it in later? 
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 26, 2013, 11:59:30 am
The problem is that you'd need to completely rewrite the Pathtypes code since it assumes everything is in data. You'd need to teach it that data/localisation has the same path structure. And I don't think that would be a trivial change.

Whereas the gr/fr/ etc folders simply require altering the code to consider looking in the subfolders of the existing pathtypes.

Basically as far as I can see it's much, much easier to implement things the way :v: wanted to than completely rewrite the way Pathtypes works.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: FUBAR-BDHR on September 26, 2013, 12:08:13 pm
I really don't see the difference in altering the code to look in data/voice/special/gr vs /data/localizaion/voice/special/gr.  Did :v: even transloate anything besides the special voices and text?  What about briefings, debriefings, etc? 
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 27, 2013, 07:29:37 pm
I'm not sure what they translated but we shouldn't be limited by that since their translation isn't in localisation folders, but simply replaces the English version like a mod.

I think ideally you should be able to replace any English in the game with another language. Both in sound and text.

I really don't see enough difference between having the German version of a table in data/tables/gr or data/localisation/tables to justify rewriting the entire pathtypes code (and risking the resulting bugs). If I'm missing something, I really can't see what it is.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on September 28, 2013, 01:49:04 am
I've got some important things to say about this effort, none of which are related to localized folders:


1) Currently, the "Non-English Character Index" field (which, as I said earlier, is for special symbols and not accented letters) takes only one parameter. However, as I pointed out here (http://scp.indiegames.us/mantis/view.php?id=2883#c15272), font03.vp has the special characters at a unique offset, so there's no way for a HUD gauge that uses special characters to use font03.vp and still display correctly. The "Non-English Character Index" field should somehow be expanded to take three parameters, one for each font.


2) When displaying non-ASCII characters, the game does some remapping from ISO Latin-1 to its own mapping. However, it doesn't do this with the fiction viewer. Because of this, if a default font that supports accented characters is used there, then non-ASCII characters will not display correctly.

3) For this last problem, I'll quote myself on something that we're adding to the next version of FSPort:
Quote
Most of the FreeSpace 2 multiplayer missions are still being parsed in the mission simulator. This is a problem because, with the new tstrings.tbl, the XSTR structures for many of their names now point to strings that are longer than 32 characters, causing a boatload of warnings to be thrown in the mission simulator if the language is set to Spanish.

We're going to have to block all the FS2 missions somehow. Right now, we can block single-player campaigns and their missions, but that's it. Perhaps this can be expanded somehow to block single (non-campaign) missions as well as multiplayer missions and campaigns. (If that can't be done, then we could use dummy files...)

So, yeah, the ignore-campaign feature should be expanded to cover single missions and multiplayer missions and campaigns. Also, any XSTR structures found in ignored campaigns and missions should not be translated.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on September 29, 2013, 07:57:47 pm
Since I'm on my phone i'll keep thing brief.

I don't much like the idea of splitting the special characters field into 3 in strings.tbl. I think that making it a font property defined in fonts.tbl is a better idea. If the setting isn't found, then it falls back to the language default.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: niffiwan on October 23, 2013, 05:46:17 pm
1) Currently, the "Non-English Character Index" field (which, as I said earlier, is for special symbols and not accented letters) takes only one parameter. However, as I pointed out here (http://scp.indiegames.us/mantis/view.php?id=2883#c15272), font03.vp has the special characters at a unique offset, so there's no way for a HUD gauge that uses special characters to use font03.vp and still display correctly. The "Non-English Character Index" field should somehow be expanded to take three parameters, one for each font.

I don't much like the idea of splitting the special characters field into 3 in strings.tbl. I think that making it a font property defined in fonts.tbl is a better idea. If the setting isn't found, then it falls back to the language default.

I'm currently looking at fixing mantis 2883 (http://scp.indiegames.us/mantis/view.php?id=2883).  Just to clarify, its not that you don't want to expand "struct lang_info", its more that you want the extra font offsets defined in font.tbl, with the value in strings.tbl to be a "default" value in the case that this info is not defined in fonts.tbl? (although putting the indexes in fonts.tbl sort of makes this value in string.tbl redundant?) If these values are put into fonts.tbl, I think each value will need a corresponding language entry that it refers to.  i.e. something like:

Code: [Select]
#Fonts

$Font: font01.vf
  +Language: English
  +Special Character Index: 127
  +Language: German
  +Special Character Index: 164
  +Language: French
  +Special Character Index: 164
  +Language: Polish
  +Special Character Index: 127
$Font: font02.vf
  +Language: all
  +Special Character Index: none
$Font: font03.vf
  +Language: all
  +Special Character Index: 176   (NOTE: font02 & font03 are based on the only data we have so far, i.e. English & German)

#End

(although I'm not convinced adding the special keyword "all" is worth it, "none" is required due to font02.vf, although -1 could work as well here)

Lastly, if we don't get rid of it, I'll change the "+Non English Character Index:" in strings.tbl to "+Special Character Index".



2) When displaying non-ASCII characters, the game does some remapping from ISO Latin-1 to its own mapping. However, it doesn't do this with the fiction viewer. Because of this, if a default font that supports accented characters is used there, then non-ASCII characters will not display correctly.

I've seen something in the code to do with an umlaut translaction for German (lcl_fix_umlauts), maybe that just needs to be added to the fiction viewer?  I think this is worth a new/separate mantis ticket.

3) For this last problem, I'll quote myself on something that we're adding to the next version of FSPort:
Quote
Most of the FreeSpace 2 multiplayer missions are still being parsed in the mission simulator. This is a problem because, with the new tstrings.tbl, the XSTR structures for many of their names now point to strings that are longer than 32 characters, causing a boatload of warnings to be thrown in the mission simulator if the language is set to Spanish.

We're going to have to block all the FS2 missions somehow. Right now, we can block single-player campaigns and their missions, but that's it. Perhaps this can be expanded somehow to block single (non-campaign) missions as well as multiplayer missions and campaigns. (If that can't be done, then we could use dummy files...)

So, yeah, the ignore-campaign feature should be expanded to cover single missions and multiplayer missions and campaigns. Also, any XSTR structures found in ignored campaigns and missions should not be translated.

IIRC Goober5000 made some more localisation changes after this feature went in, and I think it involved whether some strings (used as indexes) were translated or not.  So, is this still an issue?  Also, is there a case to be made for making FSO handle strings longer than 32 chars?  Or would that overflow the available space in the interface?  Anyway, the ignore-campaign change sounds a bit tricky to me, I don't believe there's anything which associates single player campaigns to single/standalone missions or multiplayer missions. 
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on October 23, 2013, 06:17:52 pm
I was thinking that we'd leave the current setting in in strings.tbl (Changed to "+Special Character Index") as the default and then have the setting in fonts.tbl work as an override for any fonts that need it. So you wouldn't need an "all" keyword since the language was already defined in strings.tbl.


I had planned to fix that all last weekend and then I got swamped with work. :(
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on October 23, 2013, 08:10:48 pm
IIRC Goober5000 made some more localisation changes after this feature went in, and I think it involved whether some strings (used as indexes) were translated or not.  So, is this still an issue?  Also, is there a case to be made for making FSO handle strings longer than 32 chars?  Or would that overflow the available space in the interface?  Anyway, the ignore-campaign change sounds a bit tricky to me, I don't believe there's anything which associates single player campaigns to single/standalone missions or multiplayer missions.

The fix I made was for something else entirely.  Originally, the tech-add-intel sexp didn't check the XSTR ID, so if you were using a different language pack you'd still be looking for the English intel name.  The problem Yarn mentions has to do with the lengths of strings after they are translated, especially if the translation indexes change.

This will need to be fixed with some sort of hack.  Adding a mission blacklist is not going to work because the problem could happen with any mission.  The best solution, I think, is to add a custom check to the mission loading screen so that any mission whose translated name overflows the string length will simply not be displayed in the menu -- or perhaps will have its English name displayed instead.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on October 23, 2013, 11:43:08 pm
I think that's just going to inspire another bug report further down the line about how some of the missions aren't displayed or are displayed in the wrong language. Even a truncated name would be better than both of those.

What are the chances of support for greater than 32 characters though?
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on October 23, 2013, 11:58:35 pm
The 32-character limit really isn't the problem.  The problem is that if you install a mod with a new tstrings.tbl, all of the XSTR indexes will be messed up.  Instead of the following mission listing...

Quote
M-01.fs2, All Alone
M-02.fs2, Forward Edge Battle Area
M-03.fs2, Blockade Run
M-04.fs2, Rebel Intercept

...you'd end up with something like this...

Quote
M-01.fs2, You survived your first sortie against the Shivans. Though we had only a small opposing force to contend with, survival is half the battle. The C.O.s of both the Carthage and Dahshor commend our squadron for the outstanding cover we provided. The Shivan Cain cruiser and its complement of fighters might have destroyed these vessels had we not intervened. Well done, pilot.
M-02.fs2, EMP Missile
M-03.fs2, Bombers should be your highest priority when protecting the Aquitaine.
M-04.fs2, credits, or check specs

That's why I favor using the English phrase, because we know for sure that the English phrase is saying the right thing even if it's not in the right language.  And the chances are still fairly good that someone will be able to recognize a mission title in English.  (Or, as I suggested earlier, doing an on-the-fly blacklist if an XSTR overflows its length.)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on October 24, 2013, 01:05:30 am
The solution of only doing something when it's over 32 characters leaves with a problem where some missions will appear with incorrect names while others won't even appear. In either case, when you run the mission they'll also be horrifically broken.

If you've installed a mod with a new string.tbl, you probably shouldn't be seeing those missions in the first place. Although I can't think of any method off the top of my head to actually test for that.


EDIT : I assume the problem is tstrings.tbl not strings.tbl. Mission names shouldn't be in strings.tbl really unless :v: did something rather stupid.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on October 24, 2013, 03:05:55 am
Yes, you'll note that my post specifies tstrings.tbl, not strings.tbl.  Yarn discovered this problem in the course of configuring ST:R for localization.

And yes, examples like EMP Missile in my list above will still satisfy the 32-character limit and make it through the filter.  You're phrasing your post as if I hadn't already thought of that. :p  That's why I also suggested defaulting to English names for all mission titles.  It's not perfect, but it will avoid hosing the mission list.

The best option would be for the code to somehow detect that the mod is using a different tstrings.tbl, but, as you say, that's a tricky problem.  One method that just came to mind is performing two lookups on the XSTR, one for the default language and one for the user's language.  If the string provided by the mission file is different from the default language string in tstrings.tbl, then lcl_ext_localize should set a flag (or even just return false).  Then it would be the responsibility of the mission loading code to skip the mission with that badly translated name.

The only risk of this method is if the untranslated string isn't exactly equal to the default language string, for whatever reason -- maybe there was a typo, or maybe there was an update that wasn't sync'd in both places.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on October 24, 2013, 03:44:33 am
Yeah, I thought of something similar about 30 seconds later but I was already out the door. :D

I think that's what we're going to have to do. Using the English names just shunts the problem one step further down the line.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on October 25, 2013, 01:48:14 am
I found a serious bug concerning *-lcl.tbm files. If it's not fixed, then modders adding additional languages will have to include their own mv_core-lcl.tbm (which will likely be called mv_root-lcl.tbm in the future) just to prevent a crash. It's also contrary to how TBMs are expected to work. The Mantis ticket is here: http://scp.indiegames.us/mantis/view.php?id=2941 (http://scp.indiegames.us/mantis/view.php?id=2941)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: karajorma on October 25, 2013, 02:55:56 am
Assigned it to myself. I'll look into this one tomorrow or Sunday.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: niffiwan on October 27, 2013, 05:42:39 am
I've created a patch to implement setting individual indexes for fonts, mostly as per my post above.  One difference is the lack of a keyword for "no index", just set 0 in this case.  See attached for a test table (which has invalid indexes for those fonts, but it gives the general idea).

Note that this requires the patch from mantis 2883 (http://scp.indiegames.us/mantis/view.php?id=2883) to be applied 1st, and because it's a patch on a non-committed-patch, I can't provide it in SVN format.  I will do so when the patch for 2883 is committed.  And I'll create & post a build for testing as well, maybe tomorrow.

SVN format patch is now provided below, and the fonts.tbl is now inline to avoid be eaten by the attachment monster... but the build is finally still MIA  :nervous:
And here (http://www.mediafire.com/?cecir2r755jv5yw) is the build.

A review of this patch would be much appreciated :)

Code: [Select]
Index: code/hud/hudtarget.cpp
===================================================================
--- code/hud/hudtarget.cpp (revision 9992)
+++ code/hud/hudtarget.cpp (working copy)
@@ -5750,6 +5750,18 @@
 {
 }
 
+void HudGaugeWeapons::initLinkIcon()
+{
+ ubyte sc = lcl_get_font_index(font_num);
+ // default to a '>' if the font has no special chars
+ // seems about the closest normal char to the triangle
+ if (sc == 0) {
+ Weapon_link_icon = ubyte ('>');
+ } else {
+ Weapon_link_icon = sc + 2;
+ }
+}
+
 void HudGaugeWeapons::initTopOffsetX(int x, int x_b)
 {
  top_offset_x[0] = x;
@@ -6000,7 +6012,7 @@
 
  // indicate if this is linked or currently armed
  if ( ((sw->current_primary_bank == i) && !(Player_ship->flags & SF_PRIMARY_LINKED)) || ((Player_ship->flags & SF_PRIMARY_LINKED) && !(Weapon_info[sw->primary_bank_weapons[i]].wi_flags3 & WIF3_NOLINK))) {
- renderPrintf(position[0] + Weapon_plink_offset_x, name_y, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + Weapon_plink_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon);
  }
 
  // either render this primary's image or its name
@@ -6064,11 +6076,11 @@
 
  if ( sw->current_secondary_bank == i ) {
  // show that this is the current secondary armed
- renderPrintf(position[0] + Weapon_sunlinked_offset_x, name_y, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + Weapon_sunlinked_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon);
 
  // indicate if this is linked
  if ( Player_ship->flags & SF_SECONDARY_DUAL_FIRE ) {
- renderPrintf(position[0] + Weapon_slinked_offset_x, name_y, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + Weapon_slinked_offset_x, name_y, EG_NULL, "%c", Weapon_link_icon);
  }
 
  // show secondary weapon's image or print its name
@@ -6679,6 +6691,17 @@
 
 }
 
+void HudGaugeWeaponList::initLinkIcon() {
+ ubyte sc = lcl_get_font_index(font_num);
+ // default to a '>' if the font has no special chars
+ // seems about the closest normal char to the triangle
+ if (sc == 0) {
+ Weapon_link_icon = ubyte ('>');
+ } else {
+ Weapon_link_icon = sc + 2;
+ }
+}
+
 void HudGaugeWeaponList::initBitmaps(char *fname_first, char *fname_entry, char *fname_last)
 {
  _background_first.first_frame = bm_load_animation(fname_first, &_background_first.num_frames);
@@ -6859,7 +6882,7 @@
 
  // indicate if this is linked or currently armed
  if ( (sw->current_primary_bank == i) || (Player_ship->flags & SF_PRIMARY_LINKED) ) {
- renderPrintf(position[0] + _plink_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + _plink_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
  }
 
  // either render this primary's image or its name
@@ -6971,11 +6994,11 @@
 
  if ( sw->current_secondary_bank == i ) {
  // show that this is the current secondary armed
- renderPrintf(position[0] + _sunlinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + _sunlinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
 
  // indicate if this is linked
  if ( Player_ship->flags & SF_SECONDARY_DUAL_FIRE ) {
- renderPrintf(position[0] + _slinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Lcl_special_chars + 2);
+ renderPrintf(position[0] + _slinked_offset_x, position[1] + text_y_offset, EG_NULL, "%c", Weapon_link_icon);
  }
 
  // show secondary weapon's image or print its name
Index: code/hud/hudreticle.cpp
===================================================================
--- code/hud/hudreticle.cpp (revision 9992)
+++ code/hud/hudreticle.cpp (working copy)
@@ -398,6 +398,16 @@
  Match_speed_offsets[0] = x;
  Match_speed_offsets[1] = y;
  Use_custom_match_speed = custom;
+
+ ubyte sc = lcl_get_font_index(font_num);
+ // NOTE: default to normal m because either
+ // a) the german font has no special m (its an a)
+ // b) the font has no special characters
+ if (sc == 0 || Lcl_gr) {
+ Match_speed_icon = ubyte ('m');
+ } else {
+ Match_speed_icon = sc + 3;
+ }
 }
 
 void HudGaugeThrottle::initBitmaps(char *fname)
@@ -567,13 +577,7 @@
  }
  } else if ( Players[Player_num].flags & PLAYER_FLAGS_MATCH_TARGET ) {
  if ( Use_custom_match_speed ) {
- if (Lcl_gr) {
- // print an m, cuz the voice says its an m. 
- // its a normal m cuz the german font has no special m (its an a)
- renderString(position[0] + Match_speed_offsets[0], position[1] + Match_speed_offsets[1], "m");
- } else {
- renderPrintf(position[0] + Match_speed_offsets[0], position[1] + Match_speed_offsets[1], "%c", Lcl_special_chars + 3);
- }
+ renderPrintf(position[0] + Match_speed_offsets[0], position[1] + Match_speed_offsets[1], "%c", Match_speed_icon);
  } else {
  int offset;
  if ( current_speed <= 9.5 ) {
@@ -582,13 +586,7 @@
  offset = 3;
  }
 
- if (Lcl_gr) {
- // print an m, cuz the voice says its an m. 
- // its a normal m cuz the german font has no special m (its an a)
- renderString(sx+offset, sy + h, "m");
- } else {
- renderPrintf(sx+offset, sy + h, "%c", Lcl_special_chars + 3);
- }
+ renderPrintf(sx+offset, sy + h, "%c", Match_speed_icon);
  }
  }
 }
Index: code/hud/hudtarget.h
===================================================================
--- code/hud/hudtarget.h (revision 9992)
+++ code/hud/hudtarget.h (working copy)
@@ -314,6 +314,7 @@
  int Weapon_sreload_offset_x;
  int Weapon_slinked_offset_x;
  int Weapon_sunlinked_offset_x;
+ ubyte Weapon_link_icon;
 
  int top_primary_h;
  int pname_start_offset_y;
@@ -340,6 +341,7 @@
  void initStartNameOffsetsY(int p_y, int s_y);
  void initPrimaryHeights(int top_h, int text_h);
  void initSecondaryHeights(int top_h, int text_h);
+ void initLinkIcon();
 
  void render(float frametime);
  void pageIn();
@@ -352,6 +354,7 @@
  hud_frames _background_first;
  hud_frames _background_entry;
  hud_frames _background_last;
+ ubyte Weapon_link_icon;
 
  int _bg_first_offset_x;
  int _bg_entry_offset_x;
@@ -379,6 +382,7 @@
  void initHeaderOffsets(int x, int y);
  void initEntryStartY(int y);
  void initEntryHeight(int h);
+ void initLinkIcon();
 
  virtual void render(float frametime);
  void pageIn();
Index: code/hud/hudreticle.h
===================================================================
--- code/hud/hudreticle.h (revision 9992)
+++ code/hud/hudreticle.h (working copy)
@@ -81,6 +81,7 @@
 
  int Match_speed_offsets[2];
  bool Use_custom_match_speed;
+ ubyte Match_speed_icon;
 
  bool Show_background;
 public:
Index: code/hud/hudparse.cpp
===================================================================
--- code/hud/hudparse.cpp (revision 9992)
+++ code/hud/hudparse.cpp (working copy)
@@ -3701,6 +3701,7 @@
  hud_gauge->lockConfigColor(lock_color);
  hud_gauge->updateColor(colors[0], colors[1], colors[2]);
  hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
+ hud_gauge->initInfinityIcon();
 
  if(ship_idx->at(0) >= 0) {
  for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
@@ -3863,6 +3864,7 @@
  hud_gauge->updateColor(colors[0], colors[1], colors[2]);
  hud_gauge->lockConfigColor(lock_color);
  hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
+ hud_gauge->initInfinityIcon();
 
  if(ship_idx->at(0) >= 0) {
  for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
@@ -4949,6 +4951,7 @@
  hud_gauge->updateColor(colors[0], colors[1], colors[2]);
  hud_gauge->lockConfigColor(lock_color);
  hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
+ hud_gauge->initLinkIcon();
 
  if(ship_idx->at(0) >= 0) {
  for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
@@ -8345,6 +8348,7 @@
  hud_gauge->updateColor(colors[0], colors[1], colors[2]);
  hud_gauge->lockConfigColor(lock_color);
  hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
+ hud_gauge->initLinkIcon();
 
  if(ship_idx->at(0) >= 0) {
  for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
@@ -8540,6 +8544,7 @@
  hud_gauge->updateColor(colors[0], colors[1], colors[2]);
  hud_gauge->lockConfigColor(lock_color);
  hud_gauge->initCockpitTarget(display_name, display_offset[0], display_offset[1], display_size[0], display_size[1], canvas_size[0], canvas_size[1]);
+ hud_gauge->initLinkIcon();
 
  if(ship_idx->at(0) >= 0) {
  for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
Index: code/radar/radarsetup.cpp
===================================================================
--- code/radar/radarsetup.cpp (revision 9992)
+++ code/radar/radarsetup.cpp (working copy)
@@ -383,6 +383,18 @@
 {
 }
 
+void HudGaugeRadar::initInfinityIcon()
+{
+ ubyte sc = lcl_get_font_index(font_num);
+ // default to a '*' if the font has no special chars
+ // nothing is really close to the infinity symbol...
+ if (sc == 0) {
+ Radar_infinity_icon = ubyte ('*');
+ } else {
+ Radar_infinity_icon = sc;
+ }
+}
+
 void HudGaugeRadar::initRadius(int w, int h)
 {
  Radar_radius[0] = w;
@@ -438,14 +450,18 @@
 
  int w,h;
  gr_set_font(FONT1);
+ ubyte sc = lcl_get_font_index(FONT1);
+ if (sc == 0) {
+ Warning(LOCATION, "1st font doesn't have a special characters index, radar may not work");
+ }
 
- Small_blip_string[0] = ubyte(SMALL_BLIP_CHAR);
+ Small_blip_string[0] = sc + 5;
  Small_blip_string[1] = 0;
  gr_get_string_size( &w, &h, Small_blip_string );
  Small_blip_offset_x = -w/2;
  Small_blip_offset_y = -h/2;
 
- Large_blip_string[0] = ubyte(LARGE_BLIP_CHAR);
+ Large_blip_string[0] = sc + 6;
  Large_blip_string[1] = 0;
  gr_get_string_size( &w, &h, Large_blip_string );
  Large_blip_offset_x = -w/2;
@@ -456,8 +472,6 @@
 
 void HudGaugeRadar::drawRange()
 {
- char buf[32];
-
  // hud_set_bright_color();
  setGaugeColor(HUD_C_BRIGHT);
 
@@ -472,8 +486,7 @@
  break;
 
  case RR_INFINITY:
- sprintf(buf, NOX("%c"), Lcl_special_chars);
- renderPrintf(position[0] + Radar_dist_offsets[RR_INFINITY][0], position[1] + Radar_dist_offsets[RR_INFINITY][1], buf);
+ renderPrintf(position[0] + Radar_dist_offsets[RR_INFINITY][0], position[1] + Radar_dist_offsets[RR_INFINITY][1], "%c", Radar_infinity_icon);
  break;
 
  default:
Index: code/radar/radarsetup.h
===================================================================
--- code/radar/radarsetup.h (revision 9992)
+++ code/radar/radarsetup.h (working copy)
@@ -15,9 +15,6 @@
 #include "hud/hudconfig.h"
 #include "hud/hud.h"
 
-#define SMALL_BLIP_CHAR (Lcl_special_chars + 5)
-#define LARGE_BLIP_CHAR (Lcl_special_chars + 6)
-
 //which radar type are we using
 //to add another radar type, begin by adding a RADAR_MODE_* define and increment MAX_RADAR_MODES
 #define RADAR_MODE_STANDARD 0
@@ -128,6 +125,7 @@
 
  char Small_blip_string[2];
  char Large_blip_string[2];
+ ubyte Radar_infinity_icon;
 public:
  HudGaugeRadar();
  HudGaugeRadar(int _gauge_object, int r, int g, int b);
@@ -136,6 +134,7 @@
  void initDistanceShortOffsets(int x, int y);
  void initDistanceLongOffsets(int x, int y);
  void initDistanceInfinityOffsets(int x, int y);
+ void initInfinityIcon();
 
  void drawRange();
  virtual void render(float frametime);
Index: code/graphics/font.cpp
===================================================================
--- code/graphics/font.cpp (revision 9992)
+++ code/graphics/font.cpp (working copy)
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <limits.h>
 
 #include "graphics/2d.h"
 #include "cfile/cfile.h"
@@ -125,14 +126,13 @@
 /**
  * Draws a character centered on x
  */
-void gr_char_centered(int x, int y, char chr)
+void gr_char_centered(int x, int y, char chr, ubyte sc1)
 {
  char str[2];
- int w, sc;
+ int w;
 
- sc = Lcl_special_chars;
  if (chr == '1')
- chr = (char)(sc + 1);
+ chr = (char)sc1;
 
  str[0] = chr;
  str[1] = 0;
@@ -143,7 +143,8 @@
 void gr_print_timestamp(int x, int y, fix timestamp)
 {
  char h[2], m[3], s[3];
- int w, c;
+ int w, c, font_num;
+ ubyte sc;
 
  int time = (int)f2fl(timestamp);  // convert to seconds
 
@@ -158,16 +159,29 @@
  gr_string(x + w, y, ":");
  gr_string(x + w * 3 + c, y, ":");
 
+ font_num = gr_get_current_fontnum();
+ if (font_num == -1) {
+ Warning(LOCATION, "Font not set - timestamps may not work correctly");
+ sc = 0;
+ } else {
+ sc = lcl_get_font_index(font_num);
+ }
+ if (sc == 0) {
+ sc = ubyte ('1'); // make do with non-mono-spaced 1
+ } else {
+ sc += 1;
+ }
+
  x += w / 2;
- gr_char_centered(x, y, h[0]);
+ gr_char_centered(x, y, h[0], sc);
  x += w + c;
- gr_char_centered(x, y, m[0]);
+ gr_char_centered(x, y, m[0], sc);
  x += w;
- gr_char_centered(x, y, m[1]);
+ gr_char_centered(x, y, m[1], sc);
  x += w + c;
- gr_char_centered(x, y, s[0]);
+ gr_char_centered(x, y, s[0], sc);
  x += w;
- gr_char_centered(x, y, s[1]);
+ gr_char_centered(x, y, s[1], sc);
 }
 
 int gr_get_font_height()
@@ -533,7 +547,7 @@
 
 void parse_fonts_tbl(char *only_parse_first_font, size_t only_parse_first_font_size)
 {
- int rval;
+ int rval, i;
  char *filename;
 
  // choose file name
@@ -579,6 +593,35 @@
  int font_id = gr_create_font(font_filename);
  if (font_id < 0) {
  Warning(LOCATION, "Could not create font from typeface '%s'!", font_filename);
+ skip_to_start_of_string_either("#End","$Font:");
+ } else {
+ while (optional_string("+Language:")) {
+ char lang_name[LCL_LANG_NAME_LEN + 1];
+ int special_char_index;
+
+ stuff_string(lang_name, F_NAME, LCL_LANG_NAME_LEN + 1);
+ required_string("+Special Character Index:");
+ stuff_int(&special_char_index);
+
+ // is the index sane?
+ // realistically, it has to be less than UCHAR_MAX to fit all the special chars, but not sure how many there are for all fonts & langs
+ // e.g. English font03.vf has 72 special chars?
+ if (special_char_index < 0 || special_char_index >= UCHAR_MAX) {
+ Error(LOCATION, "Special character index (%d) for font (%s), language (%s) is invalid, must be 0 - %u", special_char_index, font_filename, lang_name, UCHAR_MAX-1);
+ }
+
+ // find language and set the index, or if not found move to the next one
+ for (i = 0; i < (int)Lcl_languages.size(); ++i) {
+ if (!strcmp(Lcl_languages[i].lang_name, lang_name)) {
+ Lcl_languages[i].special_char_indexes[Num_fonts-1] = (ubyte)special_char_index;
+ break;
+ }
+ }
+
+ if (i >= (int)Lcl_languages.size()) {
+ Warning(LOCATION, "Ignoring font (%s) that specified an invalid language (%s); not built-in or in strings.tbl", font_filename, lang_name);
+ }
+ }
  }
  }

Code: [Select]
#Fonts

$Font: font01.vf
+Language: English
+Special Character Index: 130
+Language: French
+Special Character Index: 170
+Language: German
+Special Character Index: 170
+Language: Polish
+Special Character Index: 130
$Font: font02.vf
$Font: font03.vf
+Language: English
+Special Character Index: 140
+Language: French
+Special Character Index: 180
+Language: German
+Special Character Index: 180
+Language: Polish
+Special Character Index: 140

#End

[attachment deleted by ninja]
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on October 31, 2013, 02:34:12 am
If I'm not mistaken, fonts.tbl currently works only with subtitles and the fiction viewer. If this is true, then you'll have to expand it somehow to work with all text in the game.

It turns out that's actually wrong. Using 3.7.0, I tried using a font table to switch font01.vf and font03.vf and it did seem to work everywhere. It looks like the wiki page (http://www.hard-light.net/wiki/index.php/Fonts.tbl) is wrong in this regard. EDIT: Just tried this with 3.6.12 and it worked there too.
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: niffiwan on October 31, 2013, 05:10:02 am
yeah, the fonts.tbl parser just grabs the fonts in order and adds them to FSO.  Putting font03 1st results in it being used where-ever font01 is normally used.  The wiki obviously needs an update on that... maybe fonts04 & 05 can only used in the fiction viewer/subtitles?  Actually, better include the hud as well since many gauges let you specify whatever font you've configured.

(and I finally built & uploaded the build)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Goober5000 on October 31, 2013, 08:33:09 am
I guess I worded that wiki statement badly.  The subtitles and the fiction viewer can be manually set to any font in fonts.tbl, but all the rest of the fonts are hardcoded.  Except they are hardcoded to the first three fonts that are parsed.  (Originally they were hardcoded to just font01, font02, and font03.)
Title: Re: Support for every language (That you can fit in ASCII!)
Post by: Yarn on March 28, 2014, 01:34:39 pm
I've got a few ideas that pertain to this feature:

1) Provide a way to mark parts of tables so that they're parsed only for certain languages. Here's one way it could be done:
Code: [Select]
;;Localize: German;;

; This section is parsed only if the current language is German.

;;Localize: French;;

; This section is parsed only if the current language is French.

;;Localize: default;;

; This section is parsed only if the sections above were not parsed.
; Note that this section must come last.

;;Localize: end;; ; Anything after this is parsed regardless of the current language.
This kind of structure would be most useful in help.tbl, where most of the parameters are appropriate for only one language. It would also be useful in hud_gauges.tbl, where gauges and parts of gauges could be configured differently for certain languages. (The code already does a similar thing with the ETS letters and the number in the kills gauge.)

2) I think it would be better to have the language stuff in its own file (like languages.tbl) rather than strings.tbl. Why? Well, if you search the source code for "Lcl_gr", you'll see just how many and what kind of hacks exist for German. French and Polish also have hacks like these, though not as many. Presumably, we'll eventually want to allow modders to define some of this stuff themselves, and the best place to do that would be in the language definitions that are currently in strings.tbl. By moving the definitions to another file, we can avoid cluttering strings.tbl with things that have nothing to do with internal XSTRs (which is what strings.tbl was originally designed for). Furthermore, if this file is required to exist outside the VPs, then the problem with needing to read through the VPs multiple times would be solved.