]> git.mxchange.org Git - flightgear.git/commitdiff
Move locale code to separate module.
authorThorstenB <brehmt@gmail.com>
Sat, 21 Apr 2012 18:17:42 +0000 (20:17 +0200)
committerThorstenB <brehmt@gmail.com>
Sat, 21 Apr 2012 18:17:42 +0000 (20:17 +0200)
Introduce convenience methods to handle localized string resources
and obtain strings.

src/GUI/gui.cxx
src/GUI/menubar.cxx
src/GUI/menubar.hxx
src/Main/CMakeLists.txt
src/Main/fg_init.cxx
src/Main/globals.cxx
src/Main/globals.hxx
src/Main/locale.cxx [new file with mode: 0644]
src/Main/locale.hxx [new file with mode: 0644]
src/Main/main.cxx
src/Main/options.cxx

index f659d325a47e26263b115dccad93b4c8292d2ae3..851f5dbb3a2e7cc5fde27e29515d91b565b367de 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <Main/main.hxx>
 #include <Main/globals.hxx>
+#include <Main/locale.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/WindowSystemAdapter.hxx>
 #include <GUI/new_gui.hxx>
@@ -78,8 +79,7 @@ public:
         FGFontCache *fc = globals->get_fontcache();
         fc->initializeFonts();
         puFont *GuiFont
-            = fc->get(globals->get_locale()->getStringValue("font",
-                                                            "typewriter.txf"),
+            = fc->get(globals->get_locale()->getDefaultFont("typewriter.txf"),
                       15);
         puSetDefaultFonts(*GuiFont, *GuiFont);
         guiFnt = puGetDefaultLabelFont();
index 4295f808b988236bcb41c94546eedb45aae293eb..444795fd592d938fec73b72105a9bfddc1de5f12 100644 (file)
@@ -4,9 +4,30 @@
 
 
 #include "menubar.hxx"
+#include <Main/locale.hxx>
+#include <Main/globals.hxx>
+
+FGMenuBar::FGMenuBar()
+{
+    // load locale's menu resources (default and current language)
+    globals->get_locale()->loadResource("menu");
+}
 
 FGMenuBar::~FGMenuBar ()
 {
 }
 
+const char*
+FGMenuBar::getLocalizedLabel(SGPropertyNode* node)
+{
+    const char* name = node->getStringValue("name", 0);
+
+    const char* translated = globals->get_locale()->getLocalizedString(name, "menu");
+    if (translated)
+        return translated;
+
+    // return default
+    return node->getStringValue("label");
+}
+
 // end of menubar.cxx
index fa3f43ca506292ec282a2714bc46a61159ca47a1..df3b9cf60cb6f53acd987e83ae89510b52f341fb 100644 (file)
@@ -3,6 +3,7 @@
 #ifndef __MENUBAR_HXX
 #define __MENUBAR_HXX 1
 
+class SGPropertyNode;
 
 /**
  * XML-configured menu bar interface
@@ -15,7 +16,7 @@
 class FGMenuBar
 {
 public:
-
+    FGMenuBar();
 
     /**
      * Destructor.
@@ -45,6 +46,13 @@ public:
      */
     virtual bool isVisible () const = 0;
 
+    /**
+     * Read a menu label from the menu's property tree.
+     * Take care of mapping it to the appropriate translation, if available.
+     * Returns an UTF-8 encoded string.
+     */
+    const char* getLocalizedLabel(SGPropertyNode* node);
+
 };
 
 #endif // __MENUBAR_HXX
index c155f527ec2d11413a971953e2c2892e2beaa124..d136da9cbca8ec599e50d25833a6ecc6c785654a 100644 (file)
@@ -21,6 +21,7 @@ set(SOURCES
        fg_props.cxx
        fgviewer.cxx
        globals.cxx
+       locale.cxx
        logger.cxx
        main.cxx
        options.cxx
@@ -43,6 +44,7 @@ set(HEADERS
        fg_props.hxx
        fgviewer.hxx
        globals.hxx
+       locale.hxx
        logger.hxx
        main.hxx
        options.hxx
index 6c255bdc16d6f02cc7d7de89725ea7d7098537bd..21f0624b5b89c7169925f128ab30c9d0b65d1ac4 100644 (file)
@@ -149,136 +149,6 @@ string fgBasePackageVersion() {
     return version;
 }
 
-//
-// Select the proper language based on the given locale/language name.
-//
-static SGPropertyNode* findLocale(SGPropertyNode *intl, const char* language)
-{
-    vector<SGPropertyNode_ptr> localeList = intl->getChildren("locale");
-    for (unsigned int i = 0; i < localeList.size(); i++) {
-
-       vector<SGPropertyNode_ptr> lang = localeList[i]->getChildren("lang");
-       for (unsigned int j = 0; j < lang.size(); j++) {
-
-          if (!strcmp(lang[j]->getStringValue(), language)) {
-             return localeList[i];
-          }
-       }
-    }
-    return NULL;
-}
-
-// Initialize the localization
-SGPropertyNode *fgInitLocale(const char *language) {
-   SGPropertyNode *c_node = NULL, *d_node = NULL;
-   SGPropertyNode *intl = fgGetNode("/sim/intl");
-
-   SG_LOG(SG_GENERAL, SG_INFO, "Selecting language: " << language );
-
-   // localization not defined
-   if (!intl)
-      return NULL;
-
-   c_node = findLocale(intl, language);
-   if (!c_node)
-   {
-       /* be tolerant about locale names, i.e. instead of "de_DE.utf8" also
-        * consider "de_DE" ... */
-       string l = language;
-       size_t pos = l.find(".");
-       if ((pos != string::npos)&&(pos>0))
-           c_node = findLocale(intl, l.substr(0, pos).c_str());
-
-       /* finally consider country alone, i.e. "de" */
-       pos = l.find("_");
-       if ((!c_node)&&(pos != string::npos)&&(pos>0))
-           c_node = findLocale(intl, l.substr(0, pos).c_str());
-   }
-
-
-   // Get the defaults
-   d_node = intl->getChild("locale");
-   if (!c_node)
-      c_node = d_node;
-
-   // Check for localized font
-   SGPropertyNode *font_n = c_node->getNode("font", true);
-   if ( !strcmp(font_n->getStringValue(), "") )
-      font_n->setStringValue(d_node->getStringValue("font", "typewriter.txf"));
-
-
-   //
-   // Load the default strings
-   //
-   SGPath d_path( globals->get_fg_root() );
-
-   const char *d_path_str = d_node->getStringValue("strings");
-   if (!d_path_str) {
-      SG_LOG(SG_GENERAL, SG_ALERT, "No path in " << d_node->getPath() << "/strings.");
-      return NULL;
-   }
-
-   d_path.append(d_path_str);
-   SG_LOG(SG_GENERAL, SG_INFO, "Reading localized strings from " << d_path.str());
-
-   SGPropertyNode *strings = c_node->getNode("strings");
-   try {
-      readProperties(d_path.str(), strings);
-   } catch (const sg_exception &) {
-      SG_LOG(SG_GENERAL, SG_ALERT, "Unable to read the localized strings");
-      return NULL;
-   }
-
-   //
-   // Load the language specific strings
-   //
-   if (c_node != d_node) {
-      SGPath c_path( globals->get_fg_root() );
-
-      const char *c_path_str = c_node->getStringValue("strings");
-      if (!c_path_str) {
-         SG_LOG(SG_GENERAL, SG_ALERT, "No path in " << c_node->getPath() << "/strings");
-         return NULL;
-      }
-
-      c_path.append(c_path_str);
-      SG_LOG(SG_GENERAL, SG_INFO, "Reading localized strings from " << c_path.str());
-
-      try {
-         readProperties(c_path.str(), strings);
-      } catch (const sg_exception &) {
-         SG_LOG(SG_GENERAL, SG_ALERT,
-                 "Unable to read the localized strings from " << c_path.str());
-         return NULL;
-      }
-   }
-
-   return c_node;
-}
-
-
-
-// Initialize the localization routines
-bool fgDetectLanguage() {
-    const char *language = ::getenv("LANG");
-
-    if (language == NULL) {
-        SG_LOG(SG_GENERAL, SG_INFO, "Unable to detect the language" );
-        language = "C";
-    }
-
-    SGPropertyNode *locale = fgInitLocale(language);
-    if (!locale) {
-       SG_LOG(SG_GENERAL, SG_ALERT,
-              "No internationalization settings specified in preferences.xml" );
-
-       return false;
-    }
-
-    globals->set_locale( locale );
-
-    return true;
-}
 
 template <class T>
 bool fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p))
@@ -561,11 +431,6 @@ bool fgInitConfig ( int argc, char **argv )
     fgLoadProps("preferences.xml", globals->get_props());
     SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
 
-    // Detect the required language as early as possible
-    if ( !fgDetectLanguage() ) {
-        return false;
-    }
-
     globals->loadUserSettings(dataPath);
 
     // Scan user config files and command line for a specified aircraft.
index 25eb5194b97248037d490fb31fc9046d3ef2b37d..8adcd57ca5e201bd55c9d575209a81eb83d29796 100644 (file)
@@ -59,6 +59,7 @@
 #include "globals.hxx"
 #include "renderer.hxx"
 #include "viewmgr.hxx"
+#include "locale.hxx"
 
 #include "fg_props.hxx"
 #include "fg_io.hxx"
@@ -122,7 +123,7 @@ FGGlobals *globals;
 FGGlobals::FGGlobals() :
     props( new SGPropertyNode ),
     initial_state( NULL ),
-    locale( NULL ),
+    locale( new FGLocale(props) ),
     renderer( new FGRenderer ),
     subsystem_mgr( new SGSubsystemMgr ),
     event_mgr( new SGEventMgr ),
@@ -211,6 +212,9 @@ FGGlobals::~FGGlobals()
     delete carrierlist;
     delete channellist;
     delete sound;
+
+    delete locale;
+    locale = NULL;
 }
 
 
index 9be19ff66d5157e20ea67959ff066786a129a627..2788455e25acfd38efa3ea5bf2dc3bdeb97887ff 100644 (file)
@@ -61,6 +61,7 @@ class FGControls;
 class FGFlightPlanDispatcher;
 class FGNavList;
 class FGTACANList;
+class FGLocale;
 class FGModelMgr;
 class FGRouteMgr;
 class FGScenery;
@@ -86,7 +87,7 @@ private:
     SGPropertyNode_ptr initial_state;
 
     // localization
-    SGPropertyNode_ptr locale;
+    FGLocale* locale;
 
     FGRenderer *renderer;
     SGSubsystemMgr *subsystem_mgr;
@@ -255,8 +256,7 @@ public:
     inline SGPropertyNode *get_props () { return props; }
     inline void set_props( SGPropertyNode *n ) { props = n; }
 
-    inline SGPropertyNode *get_locale () { return locale; }
-    inline void set_locale( SGPropertyNode *n ) { locale = n; }
+    inline FGLocale* get_locale () { return locale; }
 
     inline SGCommandMgr *get_commands () { return commands; }
 
diff --git a/src/Main/locale.cxx b/src/Main/locale.cxx
new file mode 100644 (file)
index 0000000..cd868ca
--- /dev/null
@@ -0,0 +1,294 @@
+// locale.cxx -- FlightGear Localization Support
+//
+// Written by Thorsten Brehm, started April 2012.
+//
+// Copyright (C) 2012 Thorsten Brehm - brehmt (at) gmail com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include <simgear/props/props_io.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include "fg_props.hxx"
+#include "locale.hxx"
+
+using std::vector;
+using std::string;
+
+FGLocale::FGLocale(SGPropertyNode* root) :
+    _intl(root->getNode("/sim/intl",0, true)),
+    _defaultLocale(_intl->getChild("locale",0, true))
+{
+}
+
+FGLocale::~FGLocale()
+{
+}
+
+// Search property tree for matching locale description
+SGPropertyNode*
+FGLocale::findLocaleNode(const string& language)
+{
+    SG_LOG(SG_GENERAL, SG_INFO, "Searching language resource for locale: " << language);
+
+    SGPropertyNode* node = NULL;
+
+    // remove character encoding from the locale spec, i.e. "de_DE.utf8" => "de_DE"
+    size_t pos = language.find(".");
+    if ((pos != string::npos)&&(pos>0))
+    {
+        node = findLocaleNode(language.substr(0, pos));
+        if (node)
+            return node;
+    }
+
+    // try country's default resource, i.e. "de_DE" => "de"
+    pos = language.find("_");
+    if ((pos != string::npos)&&(pos>0))
+    {
+        node = findLocaleNode(language.substr(0, pos));
+        if (node)
+            return node;
+    }
+
+    // search locale using full string
+    vector<SGPropertyNode_ptr> localeList = _intl->getChildren("locale");
+
+    for (size_t i = 0; i < localeList.size(); i++)
+    {
+       vector<SGPropertyNode_ptr> langList = localeList[i]->getChildren("lang");
+
+       for (size_t j = 0; j < langList.size(); j++)
+       {
+          if (!language.compare(langList[j]->getStringValue()))
+             return localeList[i];
+       }
+    }
+
+    return NULL;
+}
+
+// Select the language. When no language is given (NULL),
+// a default is determined matching the system locale.
+bool
+FGLocale::selectLanguage(const char *language)
+{
+    // Use environment setting when no language is given.
+    if ((language == NULL)||(language[0]==0))
+        language = ::getenv("LANG");
+
+    // Use plain C locale if nothing is available.
+    if (language == NULL)
+    {
+        SG_LOG(SG_GENERAL, SG_INFO, "Unable to detect the language" );
+        language = "C";
+    }
+
+    SGPropertyNode *locale = findLocaleNode(language);
+    if (!locale)
+    {
+       SG_LOG(SG_GENERAL, SG_ALERT,
+              "No internationalization settings specified in preferences.xml" );
+       return false;
+    }
+
+    _currentLocale = locale;
+    return true;
+}
+
+// Load strings for requested resource and locale.
+// Result is stored below "strings" in the property tree of the given locale.
+bool
+FGLocale::loadResource(SGPropertyNode* localeNode, const char* resource)
+{
+    SGPath path( globals->get_fg_root() );
+
+    SGPropertyNode* stringNode = localeNode->getNode("strings", 0, true);
+
+    const char *path_str = stringNode->getStringValue(resource, NULL);
+    if (!path_str)
+    {
+        SG_LOG(SG_GENERAL, SG_ALERT, "No path in " << stringNode->getPath() << "/" << resource << ".");
+        return NULL;
+    }
+
+    path.append(path_str);
+    SG_LOG(SG_GENERAL, SG_INFO, "Reading localized strings for '" <<
+           localeNode->getStringValue("lang", "<none>")
+           <<"' from " << path.str());
+
+    // load the actual file
+    try
+    {
+        readProperties(path.str(), stringNode->getNode(resource, 0, true));
+    } catch (const sg_exception &e)
+    {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Unable to read the localized strings from " << path.str() <<
+               ". Error: " << e.getFormattedMessage());
+        return false;
+    }
+
+   return true;
+}
+
+// Load strings for requested resource (for current and default locale).
+// Result is stored below "strings" in the property tree of the locales.
+bool
+FGLocale::loadResource(const char* resource)
+{
+    // load defaults first
+    bool Ok = loadResource(_defaultLocale, resource);
+
+    // also load language specific resource, unless identical
+    if ((_currentLocale!=0)&&
+        (_defaultLocale != _currentLocale))
+    {
+        Ok &= loadResource(_currentLocale, resource);
+    }
+
+    return Ok;
+}
+
+const char*
+FGLocale::getLocalizedString(SGPropertyNode *localeNode, const char* id, const char* context)
+{
+    SGPropertyNode *n = localeNode->getNode("strings",0, true)->getNode(context);
+    if (n)
+        return n->getStringValue(id, NULL);
+    return NULL;
+}
+
+const char*
+FGLocale::getLocalizedString(const char* id, const char* resource, const char* Default)
+{
+    if (id && resource)
+    {
+        const char* s = NULL;
+        if (_currentLocale)
+            s = getLocalizedString(_currentLocale, id, resource);
+        if (s && s[0]!=0)
+            return s;
+
+        if (_defaultLocale)
+            s = getLocalizedString(_defaultLocale, id, resource);
+        if (s && s[0]!=0)
+            return s;
+    }
+    return Default;
+}
+
+simgear::PropertyList
+FGLocale::getLocalizedStrings(SGPropertyNode *localeNode, const char* id, const char* context)
+{
+    SGPropertyNode *n = localeNode->getNode("strings",0, true)->getNode(context);
+    if (n)
+    {
+        return n->getChildren(id);
+    }
+    return simgear::PropertyList();
+}
+
+simgear::PropertyList
+FGLocale::getLocalizedStrings(const char* id, const char* resource)
+{
+    if (id && resource)
+    {
+        if (_currentLocale)
+        {
+            simgear::PropertyList s = getLocalizedStrings(_currentLocale, id, resource);
+            if (s.size())
+                return s;
+        }
+
+        if (_defaultLocale)
+        {
+            simgear::PropertyList s = getLocalizedStrings(_defaultLocale, id, resource);
+            if (s.size())
+                return s;
+        }
+    }
+    return simgear::PropertyList();
+}
+
+// Check for localized font
+const char*
+FGLocale::getDefaultFont(const char* fallbackFont)
+{
+    const char* font = NULL;
+    if (_currentLocale)
+    {
+        font = _currentLocale->getStringValue("font", "");
+        if (font[0] != 0)
+            return font;
+    }
+    if (_defaultLocale)
+    {
+        font = _defaultLocale->getStringValue("font", "");
+        if (font[0] != 0)
+            return font;
+    }
+
+    return fallbackFont;
+}
+
+// Simple UTF8 to Latin1 encoder.
+void FGLocale::utf8toLatin1(string& s)
+{
+    size_t pos = 0;
+
+    // map '0xc3..' utf8 characters to Latin1
+    while ((string::npos != (pos = s.find('\xc3',pos)))&&
+           (pos+1 < s.size()))
+    {
+        char c='*';
+        unsigned char p = s[pos+1];
+        if ((p>=0x80)&&(p<0xc0))
+            c = 0x40 + p;
+        char v[2];
+        v[0]=c;
+        v[1]=0;
+        s.replace(pos, 2, v);
+        pos++;
+    }
+
+#ifdef DEBUG_ENCODING
+    printf("'%s': ", s.c_str());
+    for (pos = 0;pos<s.size();pos++)
+        printf("%02x ", (unsigned char) s[pos]);
+    printf("\n");
+#endif
+
+    // hack: also map some Latin2 characters to plain-text ASCII
+    pos = 0;
+    while ((string::npos != (pos = s.find('\xc5',pos)))&&
+           (pos+1 < s.size()))
+    {
+        char c='*';
+        unsigned char p = s[pos+1];
+        switch(p)
+        {
+            case 0x82:c='l';break;
+            case 0x9a:c='S';break;
+            case 0x9b:c='s';break;
+            case 0xba:c='z';break;
+            case 0xbc:c='z';break;
+        }
+        char v[2];
+        v[0]=c;
+        v[1]=0;
+        s.replace(pos, 2, v);
+        pos++;
+    }
+}
diff --git a/src/Main/locale.hxx b/src/Main/locale.hxx
new file mode 100644 (file)
index 0000000..27623fb
--- /dev/null
@@ -0,0 +1,101 @@
+// locale.hxx -- FlightGear Localization Support
+//
+// Written by Thorsten Brehm, started April 2012.
+//
+// Copyright (C) 2012 Thorsten Brehm - brehmt (at) gmail com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#ifndef __FGLOCALE_HXX
+#define __FGLOCALE_HXX
+
+#include <string>
+
+#include <simgear/props/props.hxx>
+
+///////////////////////////////////////////////////////////////////////////////
+// FGLocale  //////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class FGLocale
+{
+public:
+    FGLocale(SGPropertyNode* root);
+    virtual ~FGLocale();
+
+    /**
+     * Select the locale's primary language. When no language is given (NULL),
+     * a default is determined matching the system locale.
+     */
+    bool        selectLanguage      (const char* language = NULL);
+
+    /**
+     * Load strings for requested resource, i.e. "menu", "options", "dialogs".
+     * Loads data for current and default locale (the latter is the fallback).
+     * Result is stored below the "strings" node in the property tree of the
+     * respective locale.
+     */
+    bool        loadResource        (const char* resource);
+
+    /**
+     * Obtain a single string from the localized resource matching the given identifier.
+     * Selected context refers to "menu", "options", "dialog" etc.
+     */
+    const char* getLocalizedString  (const char* id, const char* resource, const char* Default=NULL);
+
+    /**
+      * Obtain a list of strings from the localized resource matching the given identifier.
+      * Selected context refers to "menu", "options", "dialog" etc.
+      * Returns a list of (string) properties.
+      */
+    simgear::PropertyList getLocalizedStrings(const char* id, const char* resource);
+
+    /**
+     * Obtain default font for current locale.
+     */
+    const char* getDefaultFont      (const char* fallbackFont);
+
+    /**
+     * Simple UTF8 to Latin1 encoder.
+     */
+    static void utf8toLatin1        (std::string& s);
+
+protected:
+    /**
+     * Find property node matching given language.
+     */
+    SGPropertyNode* findLocaleNode      (const std::string& language);
+
+    /**
+     * Load resource data for given locale node.
+     */
+    bool            loadResource        (SGPropertyNode* localeNode, const char* resource);
+
+    /**
+     * Obtain a single string from locale node matching the given identifier and context.
+     */
+    const char*     getLocalizedString  (SGPropertyNode *localeNode, const char* id, const char* context);
+
+    /**
+     * Obtain a list of strings from locale node matching the given identifier and context.
+     */
+    simgear::PropertyList getLocalizedStrings(SGPropertyNode *localeNode, const char* id, const char* context);
+
+    SGPropertyNode_ptr _intl;
+    SGPropertyNode_ptr _currentLocale;
+    SGPropertyNode_ptr _defaultLocale;
+};
+
+#endif // __FGLOCALE_HXX
index 5535060d557180964e19f2df109d27441868cc9c..dc6043af8f30c1039882bea1031dc79c9fd3eae9 100644 (file)
@@ -499,7 +499,7 @@ int fgMainInit( int argc, char **argv ) {
 #endif
     SG_LOG( SG_GENERAL, SG_INFO, "FlightGear:  Version "
             << version );
-  SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR << std::endl );
+    SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR << std::endl );
 
     // Allocate global data structures.  This needs to happen before
     // we parse command line options
index 4ed3f3252f91b40ad1e79a8d1a57357198d4f233..aba0650fe994eafa87db03f49c8ea324615c9785 100644 (file)
@@ -60,6 +60,7 @@
 #include "viewmgr.hxx"
 #include "main.hxx"
 #include <Main/viewer.hxx>
+#include <Main/locale.hxx>
 #include <Environment/presets.hxx>
 
 #include <osg/Version>
@@ -1971,11 +1972,10 @@ string_list Options::valuesForOption(const std::string& key) const
 
 void Options::processOptions()
 {
-  // establish locale before showing help
-  if (isOptionSet("language")) {
-      globals->set_locale( fgInitLocale( valueForOption("language").c_str() ) );
-  }
-    
+  // establish locale before showing help (this selects the default locale,
+  // when no explicit option was set)
+  globals->get_locale()->selectLanguage(valueForOption("language").c_str());
+
   // now FG_ROOT is setup, process various command line options that bail us
   // out quickly, but rely on aircraft / root settings
   if (p->showHelp) {
@@ -2064,12 +2064,12 @@ void Options::showUsage() const
 {
   fgOptLogLevel( "alert" );
   
-  SGPropertyNode *locale = globals->get_locale();
+  FGLocale *locale = globals->get_locale();
   SGPropertyNode options_root;
   
   SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
   cout << endl;
-  
+
   try {
     fgLoadProps("options.xml", &options_root);
   } catch (const sg_exception &) {
@@ -2080,17 +2080,23 @@ void Options::showUsage() const
     
     exit(-1);
   }
-  
+
   SGPropertyNode *options = options_root.getNode("options");
   if (!options) {
     SG_LOG( SG_GENERAL, SG_ALERT,
            "Error reading options.xml: <options> directive not found." );
     exit(-1);
   }
-  
-  SGPropertyNode *usage = locale->getNode(options->getStringValue("usage"));
+
+  if (!locale->loadResource("options"))
+  {
+      cout << "Unable to read the language resource." << endl;
+      exit(-1);
+  }
+
+  const char* usage = locale->getLocalizedString(options->getStringValue("usage"), "options");
   if (usage) {
-    cout << usage->getStringValue() << endl;
+    cout << usage << endl;
   }
   
   vector<SGPropertyNode_ptr>section = options->getChildren("section");
@@ -2131,21 +2137,17 @@ void Options::showUsage() const
           msg += tmp + '\n';
           msg.append(32, ' ');
         }
-        // There may be more than one <description> tag assosiated
+        // There may be more than one <description> tag associated
         // with one option
         
         vector<SGPropertyNode_ptr> desc;
         desc = option[k]->getChildren("description");
         if (desc.size() > 0) {
           for ( unsigned int l = 0; l < desc.size(); l++) {
-            
-            // There may be more than one translation line.
-            
             string t = desc[l]->getStringValue();
-            SGPropertyNode *n = locale->getNode("strings");
-            vector<SGPropertyNode_ptr>trans_desc =
-            n->getChildren(t.substr(8).c_str());
-            
+
+            // There may be more than one translation line.
+            vector<SGPropertyNode_ptr>trans_desc = locale->getLocalizedStrings(t.c_str(),"options");
             for ( unsigned int m = 0; m < trans_desc.size(); m++ ) {
               string t_str = trans_desc[m]->getStringValue();
               
@@ -2171,19 +2173,18 @@ void Options::showUsage() const
       }
     }
     
-    SGPropertyNode *name;
-    name = locale->getNode(section[j]->getStringValue("name"));
-    
+    const char* name = locale->getLocalizedString(section[j]->getStringValue("name"),"options");
     if (!msg.empty() && name) {
-      cout << endl << name->getStringValue() << ":" << endl;
+      cout << endl << name << ":" << endl;
       cout << msg;
       msg.erase();
     }
   }
   
   if ( !p->verbose ) {
-    cout << endl;
-    cout << "For a complete list of options use --help --verbose" << endl;
+    const char* verbose_help = locale->getLocalizedString(options->getStringValue("verbose-help"),"options");
+    if (verbose_help)
+        cout << endl << verbose_help << endl;
   }
 #ifdef _MSC_VER
   std::cout << "Hit a key to continue..." << std::endl;