FlightGear next
locale.hxx
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2012 Thorsten Brehm - brehmt (at) gmail com
2// SPDX-License-Identifier: GPL-2.0-or-later
3
8
9#ifndef __FGLOCALE_HXX
10#define __FGLOCALE_HXX
11
12#include <cstdarg> // for va_start/_end
13#include <memory>
14#include <string>
15#include <vector>
16
17#include <simgear/props/propsfwd.hxx>
18#include <simgear/misc/strutils.hxx>
19
21
22// forward decls
23class SGPath;
24
25namespace flightgear {
26 class FGTranslate;
28};
29
30namespace simgear { class Dir; }
31
32
34// FGLocale //////////////////////////////////////////////////////////////////
36
37/******************************************************************************
38 * Main concepts: default translation vs. other translations, etc.
39 *
40 * The “default translation” is made of all source strings found in the
41 * XML files present in $FG_ROOT/Translations/default/ and its
42 * `auto-extracted` subdirectory (also in aircraft and add-ons with the
43 * aircraft or add-on base directory substituted for $FG_ROOT). This
44 * translation does not correspond to any of the /sim/intl/locale[n] nodes.
45 *
46 * The default translation has only one form for any given string: the “source
47 * text” (this is what translators translate). Each of its strings is loaded
48 * in the _sourceText member of the corresponding TranslationUnit instance.
49 * Therefore, it can't have variations like singular and plural forms. It
50 * should use indeterminate style like “Here are %1 apple(s)”. Its language is
51 * referred to here as “engineering English”.
52 *
53 * Other translations are proper ones, that can have different forms depending
54 * on an integer that is optionally passed to the API functions
55 * (cf. FGTranslate::setCardinalNumber()). These translations are all loaded
56 * from XLIFF files in Translations/⟨language dir⟩ where ⟨language dir⟩ is not
57 * 'default' (for aircraft and add-ons, use the most specific variant for
58 * ⟨language dir⟩, e.g. 'fr_FR' as opposed to just 'fr': this will allow
59 * correct selection of the locale node according to locale.xml). In such
60 * translations, each _sourceText of a TranslationUnit instance has:
61 *
62 * - no translation if the string hasn't been translated yet (an empty
63 * 'target' text in the .xlf file counts as “no translation”);
64 *
65 * - exactly one translation (_targetTexts[0] in the TranslationUnit) if the
66 * string has has-plural="false" or no such attribute in the default
67 * translation;
68 *
69 * - a language-dependent number of translations that can be obtained by
70 * passing the “language id” (cf. locale.xml) to
71 * LanguageInfo::getNumberOfPluralForms() (these translations are loaded
72 * into the _targetTexts vector of TranslationUnit instances);
73 *
74 * Language selection
75 * ------------------
76 *
77 * When fgfs is started with --language=default, it uses the default
78 * translation (“engineering English”). This is normally only useful for
79 * debugging. In this case, FGLocale::selectLanguage() sets _currentLocale to
80 * the empty shared pointer. In all other cases, FGLocale::selectLanguage()
81 * chooses one of the /sim/intl/locale[n] nodes according to --language, the
82 * user-level and system-level language settings, and the
83 * /sim/intl/locale[n]/lang nodes defined in locale.xml (if no match is found,
84 * it uses the “fallback locale” which corresponds to /sim/intl/locale[0] and
85 * is proper English with plural forms). This results in one XLIFF file to be
86 * loaded if present (also for the current aircraft and for registered
87 * add-ons).
88 *
89 * When FGLocale::selectLanguage() returns and FlightGear uses the default
90 * locale:
91 *
92 * - _currentLocale is the empty shared pointer;
93 * - _languageId is the "default" string;
94 * - FlightGear did not and won't load any XLIFF file.
95 *
96 * When FGLocale::selectLanguage() returns and FlightGear does not use the
97 * default locale:
98 *
99 * - _currentLocale points to the /sim/intl/locale[n] node corresponding to
100 * the selected language;
101 * - _languageId is the string value of /sim/intl/locale[n]/language-id;
102 * - FlightGear loaded one XLIFF file indicated by
103 * /sim/intl/locale[n]/core/xliff (unless none was there: abnormal
104 * situation), and will possibly load more later from the current
105 * aircraft and add-ons.
106 *
107 * FGLocale::selectLanguage() sets /sim/intl/current-locale to the value of
108 * _currentLocaleString and /sim/intl/current-language-id to the value of
109 * _languageId. The latter determines which XLIFF files are going to be
110 * loaded, if any. Therefore, if a font has to be chosen according to the
111 * selected language, getLanguageId() or /sim/intl/current-language-id should
112 * be appropriate.
113 *
114 * Resource vs. context
115 * --------------------
116 *
117 * Both terms mean essentially the same thing here. A resource can more easily
118 * be considered as something that _contains_ translation material, however
119 * when these terms refer to a single string parameter, they mean the same
120 * thing: the resource name such as “atc”, “menu”, “options”, “sys”, “tips”,
121 * etc.
122 ******************************************************************************/
123
125{
126public:
127 FGLocale(SGPropertyNode* root);
128 virtual ~FGLocale();
129
142 bool selectLanguage(const std::string& language = {});
153 std::string getLanguageId() const;
154
167 std::string getPreferredLanguage() const;
168
171
175 std::string getLocalizedStringWithIndex(const std::string& id,
176 const std::string& context,
177 int index) const;
190 std::string getLocalizedString(const std::string& id,
191 const std::string& resource,
192 const std::string& defaultValue = {});
193
202 std::vector<std::string> getLocalizedStrings(const std::string& id,
203 const std::string& resource);
204
210 std::size_t getLocalizedStringCount(const std::string& id,
211 const std::string& context) const;
212
216 std::string getDefaultFont (const char* fallbackFont);
217
222 std::string localizedPrintf(const char* id, const char* resource, ... );
223
224 std::string vlocalizedPrintf(const char* id, const char* resource, va_list args);
225
229 static void utf8toLatin1 (std::string& s);
230
236 void clear();
237
242 SGPropertyNode_ptr selectLanguageNode(SGPropertyNode* langs) const;
243
244protected:
248 SGPropertyNode* findLocaleNode(const std::string& language);
249
261 const SGPath& xmlFile, const std::string& domain,
262 const std::string& resource);
275 void loadDefaultTranslation(const simgear::Dir& defaultTranslationDir,
276 const std::string& domain);
281
286 void loadResourcesFromAircraftOrAddonDir(const SGPath& basePath,
287 const std::string& domain);
288 void loadXLIFFFromAircraftOrAddonDir(const SGPath& basePath,
289 const std::string& domain);
299 std::string findLanguageId() const;
300
301 SGPropertyNode_ptr _intl;
302 SGPropertyNode_ptr _currentLocale;
310 std::string _languageId;
318 SGPropertyNode_ptr _fallbackLocale;
325
335 void loadXLIFF(const SGPath& basePath, SGPropertyNode* localeNode,
336 const std::string& domain);
337private:
342 static std::string removeEncodingPart(const std::string& locale);
343 std::shared_ptr<const flightgear::TranslationDomain> getDomain(
344 const std::string& domain) const;
345
346 // this is the ordered list of languages to try. It's the same as
347 // returned by getUserLanguages(), except if the user has used
348 // --language to override, that will be the first item.
349
350 string_list _languages;
351 bool _inited = false;
352
353 // Keys are domain names such as "core", "addons/⟨addonId⟩", etc.
354 using TranslationDomainRef = std::shared_ptr<flightgear::TranslationDomain>;
355 std::map<std::string, TranslationDomainRef> _domains;
356
357 // FGTranslate uses our getDomain(), which is private.
358 friend class FGTranslate;
359};
360
361// global translation wrappers
362
363std::string fgTrMsg(const char* key);
364std::string fgTrPrintfMsg(const char* key, ...);
365
366
367#endif // __FGLOCALE_HXX
Container for all TranslationResource's belonging to a domain.
void loadAircraftTranslations()
Definition locale.cxx:318
void loadDefaultTranslation(const simgear::Dir &defaultTranslationDir, const std::string &domain)
Load all default translation files from the specified directory.
Definition locale.cxx:353
std::string getLocalizedStringWithIndex(const std::string &id, const std::string &context, int index) const
Obtain a single translation with the given identifier, context and index.
Definition locale.cxx:525
std::size_t getLocalizedStringCount(const std::string &id, const std::string &context) const
Return the number of strings with a given id in the specified context.
Definition locale.cxx:547
bool selectLanguage(const std::string &language={})
Select the locale's primary language according to user-level, system-level language settings and the ...
Definition locale.cxx:197
FGLocale(SGPropertyNode *root)
Definition locale.cxx:48
friend class FGTranslate
Definition locale.hxx:358
void loadCoreResourcesForDefaultTranslation()
Load the core default translation ('atc', 'menu', 'options', 'sys', etc.).
Definition locale.cxx:310
std::string getLanguageId() const
Return the value of _languageId, which uniquely identifies the language for the LanguageInfo class (h...
Definition locale.cxx:305
std::string vlocalizedPrintf(const char *id, const char *resource, va_list args)
Definition locale.cxx:586
std::string _languageId
This is used to fetch linguistic data such as the number of plural forms for the selected locale.
Definition locale.hxx:310
static void utf8toLatin1(std::string &s)
Simple UTF8 to Latin1 encoder.
Definition locale.cxx:597
void loadAddonTranslations()
Definition locale.cxx:324
SGPropertyNode_ptr _intl
Definition locale.hxx:301
void loadResourcesFromAircraftOrAddonDir(const SGPath &basePath, const std::string &domain)
From an add-on or aircraft directory, load the default translation and, if available,...
Definition locale.cxx:339
virtual ~FGLocale()
Definition locale.cxx:54
std::string _currentLocaleString
Corresponds to user's language settings, possibly overridden by the –language value.
Definition locale.hxx:324
string_list getUserLanguages() const
Obtain user's default language settings.
Definition locale.cxx:140
std::vector< std::string > getLocalizedStrings(const std::string &id, const std::string &resource)
Obtain a list of translations that share the same tag name (id stem).
Definition locale.cxx:541
std::string localizedPrintf(const char *id, const char *resource,...)
Obtain a message string, from a localized resource ID, and use it as a printf format string.
Definition locale.cxx:577
void loadXLIFF(const SGPath &basePath, SGPropertyNode *localeNode, const std::string &domain)
Load an XLIFF 1.2 file.
Definition locale.cxx:455
void loadXLIFFFromAircraftOrAddonDir(const SGPath &basePath, const std::string &domain)
Definition locale.cxx:381
SGPropertyNode_ptr _currentLocale
Definition locale.hxx:302
SGPropertyNode * findLocaleNode(const std::string &language)
Find a property node matching the given language.
Definition locale.cxx:158
void loadResourceForDefaultTranslation(const SGPath &xmlFile, const std::string &domain, const std::string &resource)
Load default strings for the requested resource ("atc", "menu", etc.).
Definition locale.cxx:481
std::string getDefaultFont(const char *fallbackFont)
Obtain default font for current locale.
Definition locale.cxx:556
void clear()
reset all data in the locale.
Definition locale.cxx:431
SGPropertyNode_ptr selectLanguageNode(SGPropertyNode *langs) const
Given a node with children corresponding to different language / locale codes, select one based on th...
Definition locale.cxx:660
std::string findLanguageId() const
Return the appropriate value for _languageId according to _currentLocale.
Definition locale.cxx:279
SGPropertyNode_ptr _fallbackLocale
Proper locale (corresponding to a /sim/intl/locale[n] node, as opposed to the default translation) us...
Definition locale.hxx:318
std::string getLocalizedString(const std::string &id, const std::string &resource, const std::string &defaultValue={})
Obtain a single string matching the given id, with fallback.
Definition locale.cxx:533
std::string getPreferredLanguage() const
Return the preferred language according to user choice and/or settings.
Definition locale.cxx:450
Class that holds translation resources within a domain.
std::vector< std::string > string_list
Definition globals.hxx:36
std::string fgTrPrintfMsg(const char *key,...)
Definition locale.cxx:651
std::string fgTrMsg(const char *key)
Definition locale.cxx:646
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
Definition Addon.cxx:53