Hi,
I have been annoyed for a long time by the combox for choosing UI
language: it shows English (UK), English (UK)... where as only one en.po
exists. This patch solves this problem. The way it is implemented is to
decide that the first language that corresponds to a given .po file is
the one that gets displayed. The languages file is therefore reorganized
in order to be sorted by GuiName, which works weird.
I wanted to avoid having to create a new list of UI languages that would
have to be kept in sync when adding new languages. The only remaining
glitch is for Arabic, where the choice is between displaying "Arabic
(Arabi)" and "Arabic (ArabTeX)".
Thoughts?
JMarc
>From 7f5c652c743f5a69ce12b8de84a1c3eb234d2596 Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Thu, 7 May 2015 17:20:23 +0200
Subject: [PATCH] Improve list of available languages for UI l10n.
Expose realCode in Messages.h; get rid of available().
When reading languages, build a list of GUI languages. This avoids duplicates (like "English" and "English (UK)") and languages for which no translation exists. Note that the removal of duplicates takes in account the order of languages.
Sort languages by GUINames in lib/languages file.
Add in GuiApplication a function guiLanguageModel() that creates a model for the Prefs dialog. Use it in GuiPrefs.
---
lib/languages | 297 +++++++++++++++++-----------------
src/Language.cpp | 24 ++-
src/Language.h | 10 +-
src/frontends/qt4/GuiApplication.cpp | 36 ++++-
src/frontends/qt4/GuiApplication.h | 2 +
src/frontends/qt4/GuiPrefs.cpp | 27 +---
src/support/Messages.cpp | 16 +-
src/support/Messages.h | 7 +-
8 files changed, 224 insertions(+), 195 deletions(-)
diff --git a/lib/languages b/lib/languages
index 1661699..ca7526c 100644
--- a/lib/languages
+++ b/lib/languages
@@ -91,6 +91,9 @@ End
#
# Real languages
#
+# The languages are sorted by GUIName. WARNING: if several languages
+# correspond to the same .po file, it is the name of the first one
+# that will appear in the Preference GUI language picker.
# not yet supported by polyglossia
Language afrikaans
@@ -110,33 +113,6 @@ Language albanian
LangCode sq_AL
End
-Language american
- GuiName "English (USA)"
- BabelName american
- PolyglossiaName english
- PolyglossiaOpts "variant=american"
- QuoteStyle english
- Encoding iso8859-15
- LangCode en_US
-End
-
-# In Babel, this is supported since v. 1.8a of babel-greek (2013-12-03)
-# We introduce it with LyX 2.2 to give the support time to settle.
-Language ancientgreek
- GuiName "Greek (ancient)"
- BabelName greek
- PostBabelPreamble
- \languageattribute{greek}{ancient}
- EndPostBabelPreamble
- PolyglossiaName greek
- PolyglossiaOpts variant=ancient
- QuoteStyle french
- Encoding iso8859-7
- InternalEncoding true
- FontEncoding LGR
- LangCode grc_GR
-End
-
# FIXME: dummy babel language for arabic_arabtex to be able
# to switch the language the way of the ArabTeX-package
Language arabic_arabtex
@@ -170,58 +146,6 @@ Language armenian
LangCode hy_AM
End
-Language australian
- GuiName "English (Australia)"
- BabelName australian
- PolyglossiaName english
- PolyglossiaOpts "variant=australian"
- Encoding iso8859-15
- QuoteStyle english
- LangCode en_AU
-End
-
-# In polyglossia, this is supported since release 1.33.4 (May 2014)
-# We introduce it with LyX 2.2 to give the support time to settle.
-Language austrian
- GuiName "German (Austria, old spelling)"
- BabelName austrian
- PolyglossiaName german
- PolyglossiaOpts "variant=austrian,spelling=old,babelshorthands=true"
- QuoteStyle german
- Encoding iso8859-15
- LangCode de_AT
-End
-
-# In polyglossia, this is supported since release 1.33.4 (May 2014)
-# We introduce it with LyX 2.2 to give the support time to settle.
-Language naustrian
- GuiName "German (Austria)"
- BabelName naustrian
- PolyglossiaName german
- PolyglossiaOpts "variant=austrian,babelshorthands=true"
- QuoteStyle german
- Encoding iso8859-15
- LangCode de_AT
-End
-
-Language bahasa
- GuiName "Indonesian"
- BabelName bahasa
- PolyglossiaName bahasai
- QuoteStyle english
- Encoding iso8859-15
- LangCode id_ID
-End
-
-Language bahasam
- GuiName "Malay"
- BabelName bahasam
- PolyglossiaName bahasam
- QuoteStyle english
- Encoding iso8859-15
- LangCode ms_MY
-End
-
Language basque
GuiName "Basque"
BabelName basque
@@ -244,15 +168,6 @@ Language belarusian
AsBabelOptions true
End
-Language brazilian
- GuiName "Portuguese (Brazil)"
- BabelName brazil
- PolyglossiaName brazil
- QuoteStyle english
- Encoding iso8859-15
- LangCode pt_BR
-End
-
Language breton
GuiName "Breton"
BabelName breton
@@ -262,16 +177,6 @@ Language breton
LangCode br_FR
End
-Language british
- GuiName "English (UK)"
- BabelName british
- PolyglossiaName english
- PolyglossiaOpts "variant=british"
- QuoteStyle english
- Encoding iso8859-15
- LangCode en_GB
-End
-
Language bulgarian
GuiName "Bulgarian"
BabelName bulgarian
@@ -281,28 +186,6 @@ Language bulgarian
LangCode bg_BG
End
-# not yet supported by polyglossia
-Language canadian
- GuiName "English (Canada)"
- BabelName canadian
-# PolyglossiaName english
-# PolyglossiaOpts "variant=canadian"
- QuoteStyle english
- Encoding iso8859-15
- LangCode en_CA
-End
-
-# not yet supported by polyglossia
-Language canadien
- GuiName "French (Canada)"
- BabelName canadien
-# PolyglossiaName french
-# PolyglossiaOpts "variant=canadien"
- QuoteStyle french
- Encoding iso8859-15
- LangCode fr_CA
-End
-
Language catalan
GuiName "Catalan"
BabelName catalan
@@ -326,8 +209,8 @@ End
Language chinese-traditional
GuiName "Chinese (traditional)"
QuoteStyle english
- Encoding utf8-cjk
- LangCode zh_TW
+ Encoding utf8-cjk
+ LangCode zh_TW
Requires CJK
End
@@ -393,6 +276,57 @@ Language english
LangCode en_US
End
+Language australian
+ GuiName "English (Australia)"
+ BabelName australian
+ PolyglossiaName english
+ PolyglossiaOpts "variant=australian"
+ Encoding iso8859-15
+ QuoteStyle english
+ LangCode en_AU
+End
+
+# not yet supported by polyglossia
+Language canadian
+ GuiName "English (Canada)"
+ BabelName canadian
+# PolyglossiaName english
+# PolyglossiaOpts "variant=canadian"
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode en_CA
+End
+
+Language newzealand
+ GuiName "English (New Zealand)"
+ BabelName newzealand
+ PolyglossiaName english
+ PolyglossiaOpts "variant=newzealand"
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode en_NZ
+End
+
+Language british
+ GuiName "English (UK)"
+ BabelName british
+ PolyglossiaName english
+ PolyglossiaOpts "variant=british"
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode en_GB
+End
+
+Language american
+ GuiName "English (USA)"
+ BabelName american
+ PolyglossiaName english
+ PolyglossiaOpts "variant=american"
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode en_US
+End
+
# Esperanto has no country code because it is an auxiliary language.
# We therefore the name of its hunspell dictionary.
Language esperanto
@@ -457,6 +391,17 @@ Language french
EndPostBabelPreamble
End
+# not yet supported by polyglossia
+Language canadien
+ GuiName "French (Canada)"
+ BabelName canadien
+# PolyglossiaName french
+# PolyglossiaOpts "variant=canadien"
+ QuoteStyle french
+ Encoding iso8859-15
+ LangCode fr_CA
+End
+
Language galician
GuiName "Galician"
BabelName galician
@@ -479,6 +424,16 @@ Language georgian
LangCode ka_GE
End
+Language ngerman
+ GuiName "German"
+ BabelName ngerman
+ PolyglossiaName german
+ PolyglossiaOpts "babelshorthands=true"
+ QuoteStyle german
+ Encoding iso8859-15
+ LangCode de_DE
+End
+
# german does not use a country code (due to the variety)
Language german
GuiName "German (old spelling)"
@@ -491,14 +446,28 @@ Language german
LangVariety alt
End
-Language ngerman
- GuiName "German"
- BabelName ngerman
+# In polyglossia, this is supported since release 1.33.4 (May 2014)
+# We introduce it with LyX 2.2 to give the support time to settle.
+Language austrian
+ GuiName "German (Austria, old spelling)"
+ BabelName austrian
PolyglossiaName german
- PolyglossiaOpts "babelshorthands=true"
+ PolyglossiaOpts "variant=austrian,spelling=old,babelshorthands=true"
QuoteStyle german
Encoding iso8859-15
- LangCode de_DE
+ LangCode de_AT
+End
+
+# In polyglossia, this is supported since release 1.33.4 (May 2014)
+# We introduce it with LyX 2.2 to give the support time to settle.
+Language naustrian
+ GuiName "German (Austria)"
+ BabelName naustrian
+ PolyglossiaName german
+ PolyglossiaOpts "variant=austrian,babelshorthands=true"
+ QuoteStyle german
+ Encoding iso8859-15
+ LangCode de_AT
End
# In Babel, this is supported since release 2.7 of babel-german (Dec 2013)
@@ -539,6 +508,23 @@ Language greek
LangCode el_GR
End
+# In Babel, this is supported since v. 1.8a of babel-greek (2013-12-03)
+# We introduce it with LyX 2.2 to give the support time to settle.
+Language ancientgreek
+ GuiName "Greek (ancient)"
+ BabelName greek
+ PostBabelPreamble
+ \languageattribute{greek}{ancient}
+ EndPostBabelPreamble
+ PolyglossiaName greek
+ PolyglossiaOpts variant=ancient
+ QuoteStyle french
+ Encoding iso8859-7
+ InternalEncoding true
+ FontEncoding LGR
+ LangCode grc_GR
+End
+
Language polutonikogreek
GuiName "Greek (polytonic)"
BabelName polutonikogreek
@@ -593,6 +579,15 @@ Language icelandic
LangCode is_IS
End
+Language bahasa
+ GuiName "Indonesian"
+ BabelName bahasa
+ PolyglossiaName bahasai
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode id_ID
+End
+
# Interlingua has no official country code because it is an auxiliary
# language. We therefore the name of its hunspell dictionary.
Language interlingua
@@ -734,6 +729,15 @@ Language magyar
LangCode hu_HU
End
+Language bahasam
+ GuiName "Malay"
+ BabelName bahasam
+ PolyglossiaName bahasam
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode ms_MY
+End
+
# not supported by babel
Language marathi
GuiName "Marathi"
@@ -753,16 +757,6 @@ Language mongolian
AsBabelOptions true
End
-Language newzealand
- GuiName "English (New Zealand)"
- BabelName newzealand
- PolyglossiaName english
- PolyglossiaOpts "variant=newzealand"
- QuoteStyle english
- Encoding iso8859-15
- LangCode en_NZ
-End
-
Language norsk
GuiName "Norwegian (Bokmaal)"
BabelName norsk
@@ -790,16 +784,6 @@ Language occitan
LangCode oc_FR
End
-# Currently not supported (file format change!)
-# Russian orthography from the Petrine orthographic reforms of
-# 1708 to the 1917 orthographic reform
-# Language oldrussian
-# GuiName "Russian (Petrine orthography)"
-# PolyglossiaName russian
-# PolyglossiaOpts spelling=old
-# LangCode ru_petr1708
-# End
-
Language polish
GuiName "Polish"
BabelName polish
@@ -818,6 +802,15 @@ Language portuguese
LangCode pt_PT
End
+Language brazilian
+ GuiName "Portuguese (Brazil)"
+ BabelName brazil
+ PolyglossiaName brazil
+ QuoteStyle english
+ Encoding iso8859-15
+ LangCode pt_BR
+End
+
Language romanian
GuiName "Romanian"
BabelName romanian
@@ -838,6 +831,16 @@ Language russian
LangCode ru_RU
End
+# Currently not supported (file format change!)
+# Russian orthography from the Petrine orthographic reforms of
+# 1708 to the 1917 orthographic reform
+# Language oldrussian
+# GuiName "Russian (Petrine orthography)"
+# PolyglossiaName russian
+# PolyglossiaOpts spelling=old
+# LangCode ru_petr1708
+# End
+
Language samin
GuiName "North Sami"
BabelName samin
diff --git a/src/Language.cpp b/src/Language.cpp
index 28ce4e2..b6ddd75 100644
--- a/src/Language.cpp
+++ b/src/Language.cpp
@@ -224,6 +224,10 @@ void Language::readLayoutTranslations(Language::TranslationMap const & trans, bo
void Languages::read(FileName const & filename)
{
+ // This is used to populate the list of GUI languages
+ gui_vector_.clear();
+ set<string> real_codes;
+
Lexer lex;
lex.setFile(filename);
lex.setContext("Languages::read");
@@ -254,8 +258,26 @@ void Languages::read(FileName const & filename)
LASSERT(ignore_language == 0, continue);
static const Language ignore_lang = l;
ignore_language = &ignore_lang;
- } else
+ } else {
languagelist[l.lang()] = l;
+ /** also populate the list of GUI translations. Discard
+ * (1) the languages without translation and () the
+ * languages for which the translation is alsready
+ * claimed. The algorithm relies on the fact that entries
+ * in the "languages" file are sorted to have the
+ * reference language first. (e.g. "french" before
+ * "canadien").
+ */
+ string const real_code = Messages::realCode(l.code());
+ if ((!real_code.empty() // only when translation is available
+ // don't add twice the same language
+ && real_codes.find(real_code) == real_codes.end())
+ // never skip the currently selected language
+ || l.lang() == lyxrc.gui_language) {
+ real_codes.insert(real_code);
+ gui_vector_.push_back(make_pair(l.lang(), l.display()));
+ }
+ }
}
default_language = getLanguage("english");
diff --git a/src/Language.h b/src/Language.h
index b532d9c..9958778 100644
--- a/src/Language.h
+++ b/src/Language.h
@@ -19,6 +19,7 @@
#include "support/trivstring.h"
#include <map>
+#include <vector>
namespace lyx {
@@ -147,6 +148,8 @@ public:
///
typedef LanguageList::size_type size_type;
///
+ typedef std::vector< std::pair<trivstring, std::string> > DescVector;
+ ///
void read(support::FileName const & filename);
///
void readLayoutTranslations(support::FileName const & filename);
@@ -158,11 +161,16 @@ public:
const_iterator begin() const { return languagelist.begin(); }
///
const_iterator end() const { return languagelist.end(); }
- ///
+ /// Return a vector of pairs (name, display) of languages that
+ /// correspond to available UI translations.
+ DescVector const & getGuiLanguages() const { return gui_vector_; }
+
private:
///
LanguageList languagelist;
+ ///
+ DescVector gui_vector_;
};
/// Global singleton instance.
diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp
index 160df4a..450a1d8 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -895,8 +895,8 @@ public:
struct GuiApplication::Private
{
- Private(): language_model_(0), meta_fake_bit(NoModifier),
- global_menubar_(0)
+ Private(): language_model_(0), gui_language_model_(0),
+ meta_fake_bit(NoModifier), global_menubar_(0)
{
#if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
#if defined(Q_OS_WIN) || defined(Q_CYGWIN_WIN)
@@ -914,7 +914,9 @@ struct GuiApplication::Private
}
///
- QSortFilterProxyModel * language_model_;
+ QAbstractItemModel * language_model_;
+ ///
+ QAbstractItemModel * gui_language_model_;
///
GuiClipboard clipboard_;
///
@@ -2455,6 +2457,34 @@ QAbstractItemModel * GuiApplication::languageModel()
}
+QAbstractItemModel * GuiApplication::guiLanguageModel()
+{
+ if (d->gui_language_model_)
+ return d->gui_language_model_;
+
+ QAbstractItemModel * lang_model = new QStandardItemModel(this);
+ lang_model->insertColumn(0);
+
+ Languages::DescVector const & guivec = lyx::languages.getGuiLanguages();
+ Languages::DescVector::const_iterator it = guivec.begin();
+ Languages::DescVector::const_iterator end = guivec.end();
+ for (; it != end; ++it) {
+ int const current_row = lang_model->rowCount();
+ lang_model->insertRow(current_row);
+ QModelIndex item = lang_model->index(current_row, 0);
+ lang_model->setData(item, qt_(it->second), Qt::DisplayRole);
+ lang_model->setData(item, toqstr(it->first), Qt::UserRole);
+ }
+ lang_model->sort(0);
+ lang_model->insertRow(0);
+ QModelIndex item = lang_model->index(0, 0);
+ lang_model->setData(item, qt_("Default"), Qt::DisplayRole);
+ lang_model->setData(item, toqstr("auto"), Qt::UserRole);
+ d->gui_language_model_ = lang_model;
+ return d->gui_language_model_;
+}
+
+
void GuiApplication::restoreGuiSession()
{
if (!lyxrc.load_session)
diff --git a/src/frontends/qt4/GuiApplication.h b/src/frontends/qt4/GuiApplication.h
index c6258ea..81fd883 100644
--- a/src/frontends/qt4/GuiApplication.h
+++ b/src/frontends/qt4/GuiApplication.h
@@ -135,6 +135,8 @@ public:
ColorCache & colorCache();
///
QAbstractItemModel * languageModel();
+ ///
+ QAbstractItemModel * guiLanguageModel();
/// return a suitable serif font name.
QString const romanFontName();
diff --git a/src/frontends/qt4/GuiPrefs.cpp b/src/frontends/qt4/GuiPrefs.cpp
index 995f8fa..a696c46 100644
--- a/src/frontends/qt4/GuiPrefs.cpp
+++ b/src/frontends/qt4/GuiPrefs.cpp
@@ -2296,38 +2296,15 @@ PrefLanguage::PrefLanguage(GuiPreferences * form)
startCommandED->setValidator(new NoNewLineValidator(startCommandED));
endCommandED->setValidator(new NoNewLineValidator(endCommandED));
- uiLanguageCO->clear();
-
- QAbstractItemModel * language_model = guiApp->languageModel();
- // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
- language_model->sort(0);
defaultDecimalPointLE->setInputMask("X; ");
defaultDecimalPointLE->setMaxLength(1);
defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::CM]), Length::CM);
defaultLengthUnitCO->addItem(lyx::qt_(unit_name_gui[Length::IN]), Length::IN);
- set<string> added;
+ QAbstractItemModel * gui_language_model = guiApp->guiLanguageModel();
uiLanguageCO->blockSignals(true);
- uiLanguageCO->addItem(qt_("Default"), toqstr("auto"));
- for (int i = 0; i != language_model->rowCount(); ++i) {
- QModelIndex index = language_model->index(i, 0);
- // Filter the list based on the available translation and add
- // each language code only once
- string const name = fromqstr(index.data(Qt::UserRole).toString());
- Language const * lang = languages.getLanguage(name);
- if (!lang)
- continue;
- // never remove the currently selected language
- if (name != form->rc().gui_language
- && name != lyxrc.gui_language
- && (!Messages::available(lang->code())
- || added.find(lang->code()) != added.end()))
- continue;
- added.insert(lang->code());
- uiLanguageCO->addItem(index.data(Qt::DisplayRole).toString(),
- index.data(Qt::UserRole).toString());
- }
+ uiLanguageCO->setModel(gui_language_model);
uiLanguageCO->blockSignals(false);
}
diff --git a/src/support/Messages.cpp b/src/support/Messages.cpp
index fd5d228..6b9e49f 100644
--- a/src/support/Messages.cpp
+++ b/src/support/Messages.cpp
@@ -151,10 +151,8 @@ Messages::Messages(string const & l)
}
-namespace {
-
// Find the code we have for a given language code. Return empty if not found.
-string realCode(string code)
+string Messages::realCode(string code)
{
// this loops at most twice
while (true) {
@@ -167,19 +165,7 @@ string realCode(string code)
}
return string();
}
-}
-
-
-bool Messages::available(string const & c)
-{
- return !realCode(c).empty();
-}
-
-string Messages::language() const
-{
- return realCode(lang_);
-}
namespace {
diff --git a/src/support/Messages.h b/src/support/Messages.h
index dd24e1c..4a03fb8 100644
--- a/src/support/Messages.h
+++ b/src/support/Messages.h
@@ -28,9 +28,10 @@ public:
///
docstring const get(std::string const & msg) const;
/// What is the language associated with this translation?
- std::string language() const;
- /// Is an (at least partial) translation of language with code \p c available?
- static bool available(std::string const & c);
+ std::string language() const { return realCode(lang_); }
+
+ /// Find the code we have for a given language code. Return empty if not found.
+ static std::string realCode(std::string code);
///
static void guiLanguage(std::string const & l) { gui_lang_ = l; }
///
--
1.7.9.5