}
-bool Language::readLayoutTranslations(Lexer & lex)
+namespace {
+
+bool readTranslations(Lexer & lex, Language::TranslationMap & trans)
{
- layoutTranslations_.clear();
while (lex.isOK()) {
if (lex.checkFor("End"))
break;
if (!lex.next(true))
return false;
docstring const val = lex.getDocString();
- layoutTranslations_[key] = val;
+ 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 Language::readLayoutTranslations(Language const & lang)
+void Language::readLayoutTranslations(Language::TranslationMap const & trans, bool replace)
{
- layoutTranslations_ = lang.layoutTranslations_;
+ TranslationMap::const_iterator const end = trans.end();
+ for (TranslationMap::const_iterator it = trans.begin(); it != end; ++it)
+ if (replace ||
+ layoutTranslations_.find(it->first) == layoutTranslations_.end())
+ layoutTranslations_[it->first] = it->second;
}
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())
if (!lex.next(true))
break;
string const code = lex.getString();
- // 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.
- Language * firstlang = 0;
- LanguageList::iterator const end = languagelist.end();
- for (LanguageList::iterator it = languagelist.begin(); it != end; ++it) {
- // special case for chinese:
- // simplified => code == "zh_CN", langcode == "zh_CN"
- // traditional => code == "zh_TW", langcode == "zh_CN"
- string const langcode = it->second.code();
- string const name = it->second.lang();
- if ((code == langcode && name != "chinese-traditional") ||
- (code == "zh_TW" && name == "chinese-traditional") ||
- (code.size() == 2 && langcode.size() > 2 &&
- code + '_' == langcode.substr(0, 3))) {
- if (firstlang)
- it->second.readLayoutTranslations(*firstlang);
- else {
- if (!it->second.readLayoutTranslations(lex)) {
- lex.printError("Could not read "
- "layout translations "
- "for language `" +
- code + "'");
- break;
- }
- firstlang = &(it->second);
- }
+ bool readit = false;
+ for (LanguageList::iterator lit = lbeg; lit != lend; ++lit) {
+ if (match(code, lit->second) != NoMatch) {
+ if (readTranslations(lex, trans[code]))
+ readit = true;
+ else
+ lex.printError("Could not read layout "
+ "translations for language "
+ "`" + code + "'");
+ break;
}
}
- if (!firstlang) {
+ if (!readit) {
lex.printError("Unknown 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 m = match(tit->first, lit->second);
+ if (m == NoMatch)
+ continue;
+ lit->second.readLayoutTranslations(tit->second,
+ m == ExactMatch);
+ }
+ }
+
}