diff --git a/lib/languages b/lib/languages index a5bcaeee6f..54be6912a4 100644 --- a/lib/languages +++ b/lib/languages @@ -39,7 +39,7 @@ finnish finnish "Finnish" false iso8859-15 fi_FI "" # We redefine \og and \fg (guillemets) for older french language definitions french french "French" false iso8859-15 fr_FR "\addto\extrasfrench{\providecommand{\og}{\leavevmode\flqq~}\providecommand{\fg}{\ifdim\lastskip>\z@\unskip\fi~\frqq}}" galician galician "Galician" false iso8859-15 gl_ES "" -german german "German (old spelling)" false iso8859-15 de_DE "" +german german "German (old spelling)" false iso8859-15 de-alt "" ngerman ngerman "German" false iso8859-15 de_DE "" german-ch ngerman "German (Switzerland)" false iso8859-15 de_CH "" greek greek "Greek" false iso8859-7 el_GR "" diff --git a/src/AspellChecker.cpp b/src/AspellChecker.cpp index 98506b88c4..55441516d7 100644 --- a/src/AspellChecker.cpp +++ b/src/AspellChecker.cpp @@ -45,11 +45,17 @@ struct AspellChecker::Private ~Private(); - /// add a speller of the given language - AspellSpeller * addSpeller(string const & lang); + /// add a speller of the given language and variety + AspellSpeller * addSpeller(string const & lang, + string const & variety = string()); /// - AspellSpeller * speller(string const & lang); + AspellSpeller * speller(string const & lang, + string const & variety); + + /// create a unique ID from lang code and variety + string const spellerID(string const & lang, + string const & variety); /// the spellers Spellers spellers_; @@ -77,11 +83,16 @@ AspellChecker::Private::~Private() } -AspellSpeller * AspellChecker::Private::addSpeller(string const & lang) +AspellSpeller * AspellChecker::Private::addSpeller(string const & lang, + string const & variety) { AspellConfig * config = new_aspell_config(); - // FIXME The aspell documentation says to use "lang" - aspell_config_replace(config, "language-tag", lang.c_str()); + // Aspell supports both languages and varieties (such as German + // old vs. new spelling). The respective naming convention is + // lang_REGION-variety (e.g. de_DE-alt). + aspell_config_replace(config, "lang", lang.c_str()); + if (!variety.empty()) + aspell_config_replace(config, "variety", variety.c_str()); // Set the encoding to utf-8. // aspell does also understand "ucs-4", so we would not need a // conversion in theory, but if this is used it expects all @@ -110,18 +121,28 @@ AspellSpeller * AspellChecker::Private::addSpeller(string const & lang) Speller m; m.speller = to_aspell_speller(err); m.config = config; - spellers_[lang] = m; + spellers_[spellerID(lang, variety)] = m; return m.speller; } -AspellSpeller * AspellChecker::Private::speller(string const & lang) +AspellSpeller * AspellChecker::Private::speller(string const & lang, + string const & variety) { - Spellers::iterator it = spellers_.find(lang); + Spellers::iterator it = spellers_.find(spellerID(lang, variety)); if (it != spellers_.end()) return it->second.speller; - return addSpeller(lang); + return addSpeller(lang, variety); +} + + +string const AspellChecker::Private::spellerID(string const & lang, + string const & variety) +{ + if (variety.empty()) + return lang; + return lang + "-" + variety; } @@ -138,7 +159,10 @@ AspellChecker::~AspellChecker() SpellChecker::Result AspellChecker::check(WordLangTuple const & word) { - AspellSpeller * m = d->speller(word.lang_code()); + + AspellSpeller * m = + d->speller(word.lang_code(), word.lang_variety()); + if (!m) return OK; @@ -155,7 +179,8 @@ SpellChecker::Result AspellChecker::check(WordLangTuple const & word) void AspellChecker::insert(WordLangTuple const & word) { - Spellers::iterator it = d->spellers_.find(word.lang_code()); + Spellers::iterator it = d->spellers_.find( + d->spellerID(word.lang_code(), word.lang_variety())); if (it != d->spellers_.end()) aspell_speller_add_to_personal(it->second.speller, to_utf8(word.word()).c_str(), -1); } @@ -163,7 +188,8 @@ void AspellChecker::insert(WordLangTuple const & word) void AspellChecker::accept(WordLangTuple const & word) { - Spellers::iterator it = d->spellers_.find(word.lang_code()); + Spellers::iterator it = d->spellers_.find( + d->spellerID(word.lang_code(), word.lang_variety())); if (it != d->spellers_.end()) aspell_speller_add_to_session(it->second.speller, to_utf8(word.word()).c_str(), -1); } @@ -173,7 +199,9 @@ void AspellChecker::suggest(WordLangTuple const & wl, docstring_list & suggestions) { suggestions.clear(); - AspellSpeller * m = d->speller(wl.lang_code()); + AspellSpeller * m = + d->speller(wl.lang_code(), wl.lang_variety()); + if (!m) return; diff --git a/src/Language.cpp b/src/Language.cpp index 2093bc373c..1ff2cf7189 100644 --- a/src/Language.cpp +++ b/src/Language.cpp @@ -20,6 +20,7 @@ #include "support/debug.h" #include "support/FileName.h" +#include "support/lstrings.h" using namespace std; using namespace lyx::support; @@ -44,11 +45,13 @@ bool Language::read(Lexer & lex) lex >> display_; lex >> rightToLeft_; lex >> encodingStr_; - lex >> code_; + lex >> codeStr_; lex >> latex_options_; if (!lex) return false; + variety_ = split(codeStr_, code_, '-'); + encoding_ = encodings.fromLyXName(encodingStr_); if (!encoding_ && !encodingStr_.empty()) { encoding_ = encodings.fromLyXName("iso8859-1"); diff --git a/src/Language.h b/src/Language.h index 14700710b7..9e89f367b6 100644 --- a/src/Language.h +++ b/src/Language.h @@ -46,6 +46,8 @@ public: /// std::string const & code() const { return code_; } /// + std::string const & variety() const { return variety_; } + /// std::string const & latex_options() const { return latex_options_; } /// bool internalFontEncoding() const; @@ -67,8 +69,12 @@ private: /// Encoding const * encoding_; /// + std::string codeStr_; + /// std::string code_; /// + std::string variety_; + /// std::string latex_options_; }; diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index abee04a727..c357fcda2b 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -3131,10 +3131,17 @@ bool Paragraph::spellCheck(pos_type & from, pos_type & to, WordLangTuple & wl, return false; docstring word = asString(from, to, AS_STR_INSETS); - string const lang_code = lyxrc.spellchecker_alt_lang.empty() - ? getFontSettings(d->inset_owner_->buffer().params(), from).language()->code() - : lyxrc.spellchecker_alt_lang; - wl = WordLangTuple(word, lang_code); + string lang_code; + string lang_variety; + if (!lyxrc.spellchecker_alt_lang.empty()) + lang_variety = split(lyxrc.spellchecker_alt_lang, lang_code, '-'); + else { + lang_code = getFontSettings( + d->inset_owner_->buffer().params(), from).language()->code(); + lang_variety = getFontSettings( + d->inset_owner_->buffer().params(), from).language()->variety(); + } + wl = WordLangTuple(word, lang_code, lang_variety); SpellChecker::Result res = speller->check(wl); // Just ignore any error that the spellchecker reports. // FIXME: we should through out an exception and catch it in the GUI to diff --git a/src/WordLangTuple.h b/src/WordLangTuple.h index b1a31bd90d..4802c2fb55 100644 --- a/src/WordLangTuple.h +++ b/src/WordLangTuple.h @@ -19,15 +19,17 @@ namespace lyx { /** - * A word and its given language code ("en_US"). + * A word and its given language code ("en_US") + * plus a variety if needed. * This is used for spellchecking. */ class WordLangTuple { public: WordLangTuple() {} - WordLangTuple(docstring const & w, std::string const & c) - : word_(w), code_(c) + WordLangTuple(docstring const & w, std::string const & c, + std::string const & v = std::string()) + : word_(w), code_(c), variety_(v) {} /// return the word @@ -40,11 +42,18 @@ public: return code_; } + /// return the language variety + std::string const & lang_variety() const { + return variety_; + } + private: /// the word docstring word_; /// language code of word std::string code_; + /// language variety of word + std::string variety_; };