+
+ // Read layout translations
+ FileName const path = libFileSearch(string(), "layouttranslations");
+ readLayoutTranslations(path);
+}
+
+
+namespace {
+
+bool readTranslations(Lexer & lex, Language::TranslationMap & trans)
+{
+ while (lex.isOK()) {
+ if (lex.checkFor("End"))
+ break;
+ if (!lex.next(true))
+ return false;
+ string const key = lex.getString();
+ if (!lex.next(true))
+ return false;
+ docstring const val = lex.getDocString();
+ trans[key] = val;
+ }
+ return true;
+}
+
+
+enum Match {
+ NoMatch,
+ ApproximateMatch,
+ ExactMatch
+};
+
+
+Match match(string const & code, Language const & lang)
+{
+ // we need to mimic gettext: code can be a two-letter code, which
+ // should match all variants, e.g. "de" should match "de_DE",
+ // "de_AT" etc.
+ // special case for chinese:
+ // simplified => code == "zh_CN", langcode == "zh_CN"
+ // traditional => code == "zh_TW", langcode == "zh_CN"
+ string const variety = lang.variety();
+ string const langcode = variety.empty() ?
+ lang.code() : lang.code() + '_' + variety;
+ string const name = lang.lang();
+ if ((code == langcode && name != "chinese-traditional")
+ || (code == "zh_TW" && name == "chinese-traditional"))
+ return ExactMatch;
+ if ((code.size() == 2) && (langcode.size() > 2)
+ && (code + '_' == langcode.substr(0, 3)))
+ return ApproximateMatch;
+ return NoMatch;
+}
+
+}
+
+
+void Languages::readLayoutTranslations(support::FileName const & filename)
+{
+ Lexer lex;
+ lex.setFile(filename);
+ lex.setContext("Languages::read");
+
+ // 1) read all translations (exact and approximate matches) into trans
+ typedef std::map<string, Language::TranslationMap> TransMap;
+ TransMap trans;
+ LanguageList::iterator const lbeg = languagelist.begin();
+ LanguageList::iterator const lend = languagelist.end();
+ while (lex.isOK()) {
+ if (!lex.checkFor("Translation")) {
+ if (lex.isOK())
+ lex.printError("Unknown layout translation tag `$$Token'");
+ break;
+ }
+ if (!lex.next(true))
+ break;
+ string const code = lex.getString();
+ bool found = false;
+ for (LanguageList::iterator lit = lbeg; lit != lend; ++lit) {
+ if (match(code, lit->second) != NoMatch) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ lex.printError("Unknown language `" + code + "'");
+ break;
+ }
+ if (!readTranslations(lex, trans[code])) {
+ lex.printError("Could not read layout translations for language `"
+ + code + "'");
+ break;
+ }
+ }
+
+ // 2) merge all translations into the languages
+ // exact translations overwrite approximate ones
+ TransMap::const_iterator const tbeg = trans.begin();
+ TransMap::const_iterator const tend = trans.end();
+ for (TransMap::const_iterator tit = tbeg; tit != tend; ++tit) {
+ for (LanguageList::iterator lit = lbeg; lit != lend; ++lit) {
+ Match const m = match(tit->first, lit->second);
+ if (m == NoMatch)
+ continue;
+ lit->second.readLayoutTranslations(tit->second,
+ m == ExactMatch);
+ }
+ }
+