Move locale code to separate module.
Introduce convenience methods to handle localized string resources and obtain strings.
This commit is contained in:
parent
056b85bc1f
commit
470552fab1
11 changed files with 464 additions and 168 deletions
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
294
src/Main/locale.cxx
Normal file
294
src/Main/locale.cxx
Normal file
|
@ -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++;
|
||||
}
|
||||
}
|
101
src/Main/locale.hxx
Normal file
101
src/Main/locale.hxx
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue