Improve locale handling
- fgfs --language=fr-FR now works as expected for the launcher (also with --language=fr_FR as before): the value added by option --language to the _languages member of FGLocale is normalized in "underscore" style (e.g., fr_FR). - Add-on translations must now use a hyphen in their property node names in addon-metadata.xml (talking about children of <localized>): i.e., use for instance <fr-FR> there, not <fr_FR>. An exception (addons::errors::error_loading_metadata_file) is thrown if one of these nodes has a name containing an underscore.
This commit is contained in:
parent
54264e6591
commit
f105e8dfb2
3 changed files with 38 additions and 4 deletions
|
@ -73,6 +73,29 @@ static string getMaybeLocalized(const string& tag, SGPropertyNode* base, SGPrope
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SGPropertyNode* getAndCheckLocalizedNode(SGPropertyNode* addonNode,
|
||||||
|
const SGPath& metadataFile)
|
||||||
|
{
|
||||||
|
const auto localizedNode = addonNode->getChild("localized");
|
||||||
|
if (!localizedNode) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < localizedNode->nChildren(); ++i) {
|
||||||
|
const auto node = localizedNode->getChild(i);
|
||||||
|
const string& name = node->getNameString();
|
||||||
|
|
||||||
|
if (name.find('_') != string::npos) {
|
||||||
|
throw errors::error_loading_metadata_file(
|
||||||
|
"underscores not allowed in names of children of <localized> "
|
||||||
|
"(in add-on metadata file '" + metadataFile.utf8Str() + "'); "
|
||||||
|
"hyphens should be used, as in 'fr-FR' or 'en-GB'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return localizedNode;
|
||||||
|
}
|
||||||
|
|
||||||
// Static method
|
// Static method
|
||||||
Addon::Metadata
|
Addon::Metadata
|
||||||
Addon::MetadataParser::parseMetadataFile(const SGPath& addonPath)
|
Addon::MetadataParser::parseMetadataFile(const SGPath& addonPath)
|
||||||
|
@ -141,7 +164,7 @@ Addon::MetadataParser::parseMetadataFile(const SGPath& addonPath)
|
||||||
metadataFile.utf8Str() + "'");
|
metadataFile.utf8Str() + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode* localizedNode = addonNode->getChild("localized");
|
const auto localizedNode = getAndCheckLocalizedNode(addonNode, metadataFile);
|
||||||
SGPropertyNode* langStringsNode = globals->get_locale()->selectLanguageNode(localizedNode);
|
SGPropertyNode* langStringsNode = globals->get_locale()->selectLanguageNode(localizedNode);
|
||||||
|
|
||||||
SGPropertyNode *idNode = addonNode->getChild("identifier");
|
SGPropertyNode *idNode = addonNode->getChild("identifier");
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/package/Root.hxx>
|
#include <simgear/package/Root.hxx>
|
||||||
#include <simgear/package/Catalog.hxx>
|
#include <simgear/package/Catalog.hxx>
|
||||||
#include <simgear/package/Package.hxx>
|
#include <simgear/package/Package.hxx>
|
||||||
|
@ -292,7 +293,10 @@ void initApp(int& argc, char** argv, bool doInitQSettings)
|
||||||
QTranslator* translator = new QTranslator(static_qApp.get());
|
QTranslator* translator = new QTranslator(static_qApp.get());
|
||||||
// check for --langauge=xx option and prefer that over QLocale
|
// check for --langauge=xx option and prefer that over QLocale
|
||||||
// detection of the locale if it exists
|
// detection of the locale if it exists
|
||||||
auto lang = Options::getArgValue(argc, argv, "--language");
|
auto lang = simgear::strutils::replace(
|
||||||
|
Options::getArgValue(argc, argv, "--language"),
|
||||||
|
"-",
|
||||||
|
"_");
|
||||||
if (!lang.empty()) {
|
if (!lang.empty()) {
|
||||||
QString localeFile = "FlightGear_" + QString::fromStdString(lang);
|
QString localeFile = "FlightGear_" + QString::fromStdString(lang);
|
||||||
if (translator->load(localeFile, QLatin1String(":/"))) {
|
if (translator->load(localeFile, QLatin1String(":/"))) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <cstddef> // std::size_t
|
#include <cstddef> // std::size_t
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <simgear/props/props_io.hxx>
|
#include <simgear/props/props_io.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
namespace strutils = simgear::strutils;
|
||||||
|
|
||||||
FGLocale::FGLocale(SGPropertyNode* root) :
|
FGLocale::FGLocale(SGPropertyNode* root) :
|
||||||
_intl(root->getNode("/sim/intl", 0, true)),
|
_intl(root->getNode("/sim/intl", 0, true)),
|
||||||
|
@ -178,6 +180,7 @@ FGLocale::findLocaleNode(const string& localeSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try country's default resource, i.e. "de_DE" => "de"
|
||||||
const auto justTheLanguage = removeLocalePart(language);
|
const auto justTheLanguage = removeLocalePart(language);
|
||||||
if (!justTheLanguage.empty()) {
|
if (!justTheLanguage.empty()) {
|
||||||
node = findLocaleNode(justTheLanguage);
|
node = findLocaleNode(justTheLanguage);
|
||||||
|
@ -201,7 +204,8 @@ bool FGLocale::selectLanguage(const std::string& language)
|
||||||
|
|
||||||
// if we were passed a language option, try it first
|
// if we were passed a language option, try it first
|
||||||
if (!language.empty()) {
|
if (!language.empty()) {
|
||||||
_languages.insert(_languages.begin(), language);
|
const auto normalizedLang = strutils::replace(language, "-", "_");
|
||||||
|
_languages.insert(_languages.begin(), normalizedLang);
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentLocaleString = removeEncodingPart(_languages.front());
|
_currentLocaleString = removeEncodingPart(_languages.front());
|
||||||
|
@ -600,7 +604,10 @@ SGPropertyNode_ptr FGLocale::selectLanguageNode(SGPropertyNode* langs) const
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
for (auto l : _languages) {
|
for (auto l : _languages) {
|
||||||
const auto langNoEncoding = removeEncodingPart(l);
|
// Only accept the hyphen separator in PropertyList node names between
|
||||||
|
// language and territory
|
||||||
|
const auto langNoEncoding = strutils::replace(removeEncodingPart(l),
|
||||||
|
"_", "-");
|
||||||
if (langs->hasChild(langNoEncoding)) {
|
if (langs->hasChild(langNoEncoding)) {
|
||||||
return langs->getChild(langNoEncoding);
|
return langs->getChild(langNoEncoding);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue