Board index FlightGear Development

Where's translation?

FlightGear is opensource, so you can be the developer. In the need for help on anything? We are here to help you.
Forum rules
Core development is discussed on the official FlightGear-Devel development mailing list.

Bugs can be reported in the bug tracker.

Where's translation?

Postby Philosopher » Fri Feb 21, 2014 9:14 pm

Hey, for Canvas dialogs (I made one today :)), it would be really cool if the title could be translated, like menu entries (especially since they're going to be the same, usually). The problem is, I have no idea where translation is handled. Any pointers? I can find absolutely nothing that looks relevant as far as C++ code is concerned...
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: Where's translation?

Postby Hooray » Fri Feb 21, 2014 9:18 pm

There's no C++ code handling that stuff directly - it's all PropertyList-encoded XML files in $FG_ROOT/Translations - menubar.xml/options.xml etc will typically not contain hard-coded "strings" but rather references that are resolved by loading the proper language.xml as an overlay, i.e. key=value during startup - see locale.xml and

$FG_SRC//Main:
locale.cxx:191: // load resource for system messages (translations for fgfs internal messages)
options.cxx:316: // $FG_ROOT/data/Translations/string-default.xml
options.cxx:2310: // There may be more than one translation line.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11317
Joined: Tue Mar 25, 2008 8:40 am

Re: Where's translation?

Postby Philosopher » Thu Feb 27, 2014 3:51 am

Thanks for the pointers Hooray. Since compilation has been working, I'm working on exposing that, but only "options" seems to work - not "menu" nor "sys"—

Patch:
Code: Select all
diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx
index 2f1e032..bd99309 100644
--- a/src/Scripting/NasalSys.cxx
+++ b/src/Scripting/NasalSys.cxx
@@ -47,6 +47,7 @@
 #include <Main/globals.hxx>
 #include <Main/util.hxx>
 #include <Main/fg_props.hxx>
+#include <Main/locale.hxx>
 
 using std::map;
 using std::string;
@@ -300,12 +301,15 @@ static SGPropertyNode* findnode(naContext c, naRef* vec, int len, bool create=fa
             if(!naIsString(a)) {
                 naRuntimeError(c, "bad argument to setprop/getprop path: expected a string");
             }
+            char* path = naStr_data(a);
+            // Remove front slashes, since they no longer indicate "go to root node"
+            while (path[0] == '/') path++;
             naRef b = i < len-1 ? naNumValue(vec[i+1]) : naNil();
             if (!naIsNil(b)) {
-                p = p->getNode(naStr_data(a), (int)b.num, create);
+                p = p->getNode(path, (int)b.num, create);
                 i++;
             } else {
-                p = p->getNode(naStr_data(a), create);
+                p = p->getNode(path, create);
             }
             if(p == 0) return 0;
         }
@@ -678,6 +682,29 @@ static naRef f_parsexml(naContext c, naRef me, int argc, naRef* args)
     return naStr_fromdata(naNewString(c), const_cast<char*>(file), strlen(file));
 }
 
+static naRef f_getlocalized(naContext c, naRef me, int argc, naRef* args)
+{
+    const char* result;
+    FGLocale* locale = globals->get_locale();
+    if (argc < 2 || !naIsString(args[0]) || !naIsString(args[1]))
+        naRuntimeError(c, "bad arguments to getlocalized()");
+    if (!locale)
+        naRuntimeError(c, "cannot find translation module");
+    try {
+        if (argc >= 3 && naIsString(args[2])) {
+            result = locale->getLocalizedString(naStr_data(args[0]), naStr_data(args[1]), naStr_data(args[2]));
+        } else {
+            result = locale->getLocalizedString(naStr_data(args[0]), naStr_data(args[1]));
+        }
+    } catch (const string& err) {
+        naRuntimeError(c, (char *)err.c_str());
+    }
+    if (result)
+        return naStr_fromdata(naNewString(c), result, strlen(result));
+    else
+        return naNil();
+}
+
 // Return UNIX epoch time in seconds.
 static naRef f_systime(naContext c, naRef me, int argc, naRef* args)
 {
@@ -716,6 +743,7 @@ static struct { const char* name; naCFunction func; } funcs[] = {
     { "resolvepath", f_resolveDataPath },
     { "finddata", f_findDataDir },
     { "parsexml", f_parsexml },
+    { "getlocalized", f_getlocalized },
     { "systime", f_systime },
     { 0, 0 }
 };


Test script:
Code: Select all
var COMPARE = func(a,b) if (a != b) print("patch doesn't work! got "~debug.string(a)~" instead of "~debug.string(b));
var CHECK   = func(a) COMPARE(a,baseline);

var baseline = getprop("/sim/current-view/config/default-field-of-view-deg");
if (baseline == nil)
   die("uninitialized property or bad getprop() implementation");

CHECK(getprop("/sim/current-view", "config/default-field-of-view-deg"));
CHECK(getprop("/sim/current-view","/config/default-field-of-view-deg"));
CHECK(getprop("/sim/current-view","/config", "default-field-of-view-deg"));
CHECK(getprop("/sim/current-view","/config","/default-field-of-view-deg"));

var baseline = "Specify additional aircraft directory path(s)";
CHECK(getlocalized("fg-aircraft-desc", "options"));
var baseline = "Load Flight Recorder Tape";
CHECK(getlocalized("load-tape", "menu"));
var baseline = "finalizing position";
CHECK(getlocalized("finalize-position", "sys"));
var baseline = " XXXXXXXXXXX XX ";
CHECK(getlocalized("xx-asfs-ajkglidj-ao", "sys", baseline));

# Automatically check some of these simple English->English ones
foreach (baseline; ["File", "Nasal Console"]) {
   var prop_name = string.replace(baseline, " ", "-");
   for (var i=0; i<size(prop_name); i+=1)
      if (string.isupper(prop_name[i]))
         prop_name[i] += `a` - `A`;
   if (baseline == "Nasal Console" and prop_name != "nasal-console") die();
   CHECK(getlocalized(prop_name, "menu"));
}
foreach (baseline; ["General Options", "Environment Options"]) {
   var prop_name = string.replace(baseline, " ", "-");
   for (var i=0; i<size(prop_name); i+=1)
      if (string.isupper(prop_name[i]))
         prop_name[i] += `a` - `A`;
   if (baseline == "Environment Options" and prop_name != "environment-options") die();
   CHECK(getlocalized(prop_name, "options"));
}


Any ideas? It's used the exact same way in splash.cxx, lines 402-403...
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5


Return to Development

Who is online

Users browsing this forum: No registered users and 3 guests