*
* \author Lars Gullik Bjønnes
* \author Jean-Marc Lasgouttes
+ * \author Jürgen Spitzmüller
* \author Dekel Tsur
*
* Full author contact details are available in file CREDITS.
#include "support/debug.h"
#include "support/FileName.h"
+#include "support/filetools.h"
#include "support/lstrings.h"
+#include "support/Messages.h"
using namespace std;
using namespace lyx::support;
Language const * reset_language = 0;
+docstring const Language::translateLayout(string const & m) const
+{
+ if (m.empty())
+ return docstring();
+
+ if (!isAscii(m)) {
+ lyxerr << "Warning: not translating `" << m
+ << "' because it is not pure ASCII.\n";
+ return from_utf8(m);
+ }
+
+ TranslationMap::const_iterator it = layoutTranslations_.find(m);
+ if (it != layoutTranslations_.end())
+ return it->second;
+
+ return from_ascii(m);
+}
+
+
bool Language::readLanguage(Lexer & lex)
{
enum LanguageTags {
- LA_BABELNAME = 1,
+ LA_AS_BABELOPTS = 1,
+ LA_BABELNAME,
LA_ENCODING,
LA_END,
LA_GUINAME,
LA_INTERNAL_ENC,
LA_LANG_CODE,
LA_LANG_VARIETY,
+ LA_POLYGLOSSIANAME,
+ LA_POLYGLOSSIAOPTS,
LA_POSTBABELPREAMBLE,
+ LA_PREBABELPREAMBLE,
LA_RTL
};
// Keep these sorted alphabetically!
LexerKeyword languageTags[] = {
+ { "asbabeloptions", LA_AS_BABELOPTS },
{ "babelname", LA_BABELNAME },
{ "encoding", LA_ENCODING },
{ "end", LA_END },
{ "internalencoding", LA_INTERNAL_ENC },
{ "langcode", LA_LANG_CODE },
{ "langvariety", LA_LANG_VARIETY },
+ { "polyglossianame", LA_POLYGLOSSIANAME },
+ { "polyglossiaopts", LA_POLYGLOSSIAOPTS },
{ "postbabelpreamble", LA_POSTBABELPREAMBLE },
+ { "prebabelpreamble", LA_PREBABELPREAMBLE },
{ "rtl", LA_RTL }
};
case LA_END: // end of structure
finished = true;
break;
+ case LA_AS_BABELOPTS:
+ lex >> as_babel_options_;
+ break;
case LA_BABELNAME:
lex >> babel_;
break;
+ case LA_POLYGLOSSIANAME:
+ lex >> polyglossia_name_;
+ break;
+ case LA_POLYGLOSSIAOPTS:
+ lex >> polyglossia_opts_;
+ break;
case LA_ENCODING:
lex >> encodingStr_;
break;
babel_postsettings_ =
lex.getLongString("EndPostBabelPreamble");
break;
+ case LA_PREBABELPREAMBLE:
+ babel_presettings_ =
+ lex.getLongString("EndPreBabelPreamble");
+ break;
case LA_RTL:
lex >> rightToLeft_;
break;
bool Language::read(Lexer & lex)
{
+ as_babel_options_ = 0;
encoding_ = 0;
internal_enc_ = 0;
rightToLeft_ = 0;
encoding_ = encodings.fromLyXName("iso8859-1");
LYXERR0("Unknown encoding " << encodingStr_);
}
+ // cache translation status. Calling getMessages() directly in
+ // PrefLanguage::PrefLanguage() did only work if the gui language
+ // was set to auto (otherwise all languages would be marked as available).
+ translated_ = getMessages(code()).available();
return true;
}
+
+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 Language::readLayoutTranslations(Language::TranslationMap const & trans, bool replace)
+{
+ 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;
+}
+
+
void Languages::read(FileName const & filename)
{
Lexer lex;
default_language = &(*languagelist.begin()).second;
LYXERR0("Using \"" << default_language->lang() << "\" instead!");
}
+
+ // Read layout translations
+ FileName const path = libFileSearch(string(), "layouttranslations");
+ readLayoutTranslations(path);
+}
+
+
+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 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 (!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);
+ }
+ }
+
}