Skip to content

Commit 57a5ea0

Browse files
authored
Just use translated language name and country code for language name from iso639 and iso3166 (#93)
QLocale, or icu locale, no matter which, has only iso639-2 support. We may use code from iso639-3 or even more. Also, the native language, since we only use them for terriority, which means in real only zh_CN & zh_TW will be using such function. It doesn't really serve the purpose of always show language name in native language. In the end, the change is: 1. use iso639 to get langauge name, in English & Translated 2. Display with translated, but search with both English / Translated. Fix #92
1 parent 9dffa79 commit 57a5ea0

File tree

5 files changed

+152
-90
lines changed

5 files changed

+152
-90
lines changed

src/lib/configlib/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ set_target_properties(configlib PROPERTIES
1616
AUTOUIC_OPTIONS "-tr=fcitx::tr2fcitx;--include=fcitxqti18nhelper.h"
1717
)
1818
target_include_directories(configlib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
19-
target_link_libraries(configlib Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Gui Fcitx5Qt${QT_MAJOR_VERSION}::DBusAddons Fcitx5::Core Fcitx5::Utils)
19+
target_link_libraries(configlib
20+
Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Gui Fcitx5Qt${QT_MAJOR_VERSION}::DBusAddons
21+
Fcitx5::Core Fcitx5::Utils
22+
Fcitx5Qt${QT_MAJOR_VERSION}::WidgetsAddons KF${QT_MAJOR_VERSION}::I18n PkgConfig::XkbFile
23+
)
2024

src/lib/configlib/iso639.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,20 @@ QMap<QString, QString> readAlpha3ToNameMap(const char *name, const char *base) {
3737
continue;
3838
}
3939
auto alpha3 = item.toObject().value("alpha_3").toString();
40+
auto alpha2 = item.toObject().value("alpha_2").toString();
4041
auto bibliographic = item.toObject().value("bibliographic").toString();
4142
auto name = item.toObject().value("name").toString();
42-
if (alpha3.isEmpty() || name.isEmpty()) {
43+
if (name.isEmpty()) {
4344
continue;
4445
}
45-
map.insert(alpha3, name);
46-
if (!bibliographic.isEmpty()) {
47-
map.insert(bibliographic, name);
46+
if (!alpha2.isEmpty()) {
47+
map.insert(alpha2, name);
48+
}
49+
if (!alpha3.isEmpty()) {
50+
map.insert(alpha3, name);
51+
if (!bibliographic.isEmpty()) {
52+
map.insert(bibliographic, name);
53+
}
4854
}
4955
}
5056
return map;

src/lib/configlib/iso639.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ class Iso639 {
3333
return value;
3434
}
3535

36+
QString queryNative(const QString &code) const {
37+
auto value = iso639_2data_.value(code);
38+
if (!value.isEmpty()) {
39+
return value;
40+
}
41+
value = iso639_3data_.value(code);
42+
if (!value.isEmpty()) {
43+
return value;
44+
}
45+
value = iso639_5data_.value(code);
46+
if (!value.isEmpty()) {
47+
return value;
48+
}
49+
return value;
50+
}
51+
3652
private:
3753
QMap<QString, QString> iso639_2data_;
3854
QMap<QString, QString> iso639_3data_;

src/lib/configlib/model.cpp

Lines changed: 96 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,66 @@
55
*/
66

77
#include "model.h"
8+
#include <QAbstractItemModel>
89
#include <QCollator>
10+
#include <QHash>
911
#include <QLocale>
12+
#include <QObject>
13+
#include <QSet>
14+
#include <QSortFilterProxyModel>
15+
#include <QString>
16+
#include <QStringLiteral>
17+
#include <Qt>
18+
#include <QtTypes>
19+
#include <algorithm>
1020
#include <fcitx-utils/i18n.h>
11-
12-
namespace fcitx {
13-
namespace kcm {
21+
#include <fcitxqtdbustypes.h>
22+
#include <utility>
23+
24+
namespace fcitx::kcm {
25+
26+
const IMConfigModelInterface::LanguageNames &
27+
IMConfigModelInterface::languageNames(const QString &langCode) const {
28+
auto iter = languageNames_.find(langCode);
29+
if (iter == languageNames_.end()) {
30+
LanguageNames names;
31+
if (langCode.isEmpty()) {
32+
names.nativeName = names.localName = _("Unknown");
33+
} else if (langCode == "*" || langCode == "mul") {
34+
names.nativeName = names.localName = _("Multilingual");
35+
} else {
36+
QString lang = langCode;
37+
// The lang before _.
38+
QString territory;
39+
if (auto items = langCode.split('_'); !items.isEmpty()) {
40+
if (!items.first().isEmpty()) {
41+
lang = items.first();
42+
}
43+
if (items.size() > 1) {
44+
QLocale locale(langCode);
45+
if (locale.territory() != QLocale::AnyTerritory) {
46+
territory =
47+
QLocale::territoryToString(locale.territory());
48+
}
49+
if (!territory.isEmpty()) {
50+
territory =
51+
D_("iso_3166", territory.toUtf8().constData());
52+
}
53+
}
54+
}
55+
names.nativeName = iso639_.queryNative(lang);
56+
names.localName = iso639_.query(lang);
57+
if (!territory.isEmpty()) {
58+
names.localName =
59+
QString(C_("%1 is language name, %2 is country name",
60+
"%1 (%2)"))
61+
.arg(names.localName, territory);
62+
}
63+
}
64+
iter = languageNames_.insert(langCode, std::move(names));
65+
}
66+
return iter.value();
67+
}
1468

1569
CategorizedItemModel::CategorizedItemModel(QObject *parent)
1670
: QAbstractItemModel(parent) {}
@@ -31,7 +85,9 @@ int CategorizedItemModel::rowCount(const QModelIndex &parent) const {
3185
return subListSize(parent.row());
3286
}
3387

34-
int CategorizedItemModel::columnCount(const QModelIndex &) const { return 1; }
88+
int CategorizedItemModel::columnCount(const QModelIndex & /*parent*/) const {
89+
return 1;
90+
}
3591

3692
QModelIndex CategorizedItemModel::parent(const QModelIndex &child) const {
3793
if (!child.isValid()) {
@@ -52,9 +108,8 @@ QModelIndex CategorizedItemModel::index(int row, int column,
52108
if (!parent.isValid()) {
53109
if (column > 0 || row >= listSize()) {
54110
return QModelIndex();
55-
} else {
56-
return createIndex(row, column, static_cast<quintptr>(0));
57111
}
112+
return createIndex(row, column, static_cast<quintptr>(0));
58113
}
59114

60115
// return im index
@@ -90,62 +145,14 @@ QVariant CategorizedItemModel::data(const QModelIndex &index, int role) const {
90145
return dataForItem(index, role);
91146
}
92147

93-
static QString languageName(const QString &langCode) {
94-
if (langCode.isEmpty()) {
95-
return _("Unknown");
96-
} else if (langCode == "*")
97-
return _("Multilingual");
98-
else {
99-
QLocale locale(langCode);
100-
if (locale.language() == QLocale::C) {
101-
// return lang code seems to be a better solution other than
102-
// indistinguishable "unknown"
103-
return langCode;
104-
}
105-
106-
const bool hasTerritory = (langCode.indexOf("_") != -1 &&
107-
locale.territory() != QLocale::AnyTerritory);
108-
QString languageName;
109-
if (hasTerritory) {
110-
languageName = locale.nativeLanguageName();
111-
}
112-
if (languageName.isEmpty()) {
113-
languageName =
114-
D_("iso_639",
115-
QLocale::languageToString(locale.language()).toUtf8());
116-
}
117-
if (languageName.isEmpty()) {
118-
languageName = _("Other");
119-
}
120-
QString territoryName;
121-
// QLocale will always assign a default country for us, check if our
122-
// lang code
123-
124-
if (hasTerritory) {
125-
territoryName = locale.nativeTerritoryName();
126-
if (territoryName.isEmpty()) {
127-
territoryName = QLocale::territoryToString(locale.territory());
128-
}
129-
}
130-
131-
if (territoryName.isEmpty()) {
132-
return languageName;
133-
} else {
134-
return QString(
135-
C_("%1 is language name, %2 is country name", "%1 (%2)"))
136-
.arg(languageName, territoryName);
137-
}
138-
}
139-
}
140-
141148
AvailIMModel::AvailIMModel(QObject *parent) : CategorizedItemModel(parent) {}
142149

143150
QVariant AvailIMModel::dataForCategory(const QModelIndex &index,
144151
int role) const {
145152
switch (role) {
146153

147154
case Qt::DisplayRole:
148-
return languageName(filteredIMEntryList[index.row()].first);
155+
return languageNames(filteredIMEntryList[index.row()].first).localName;
149156

150157
case FcitxLanguageRole:
151158
return filteredIMEntryList[index.row()].first;
@@ -180,8 +187,11 @@ QVariant AvailIMModel::dataForItem(const QModelIndex &index, int role) const {
180187

181188
case FcitxLanguageRole:
182189
return imEntry.languageCode();
190+
191+
default:
192+
break;
183193
}
184-
return QVariant();
194+
return {};
185195
}
186196

187197
void AvailIMModel::filterIMEntryList(
@@ -292,24 +302,33 @@ bool IMProxyModel::filterIM(const QModelIndex &index) const {
292302
return true;
293303
}
294304

295-
bool flag = true;
296-
QString lang = langCode.left(2);
297-
bool showOnlyCurrentLanguage =
298-
filterText_.isEmpty() && showOnlyCurrentLanguage_;
299-
300-
flag =
301-
flag && (showOnlyCurrentLanguage
302-
? !lang.isEmpty() && (QLocale().name().startsWith(lang) ||
303-
languageSet_.contains(lang))
304-
: true);
305-
if (!filterText_.isEmpty()) {
306-
flag = flag && (name.contains(filterText_, Qt::CaseInsensitive) ||
307-
uniqueName.contains(filterText_, Qt::CaseInsensitive) ||
308-
langCode.contains(filterText_, Qt::CaseInsensitive) ||
309-
languageName(langCode).contains(filterText_,
310-
Qt::CaseInsensitive));
311-
}
312-
return flag;
305+
QString lang = langCode;
306+
// The lang before _.
307+
if (auto items = langCode.split('_');
308+
!items.isEmpty() && !items[0].isEmpty()) {
309+
lang = items.first();
310+
}
311+
312+
if (filterText_.isEmpty()) {
313+
if (showOnlyCurrentLanguage_) {
314+
return !lang.isEmpty() && (QLocale().name().startsWith(lang) ||
315+
languageSet_.contains(lang));
316+
}
317+
return true;
318+
}
319+
320+
if (name.contains(filterText_, Qt::CaseInsensitive) ||
321+
uniqueName.contains(filterText_, Qt::CaseInsensitive) ||
322+
langCode.contains(filterText_, Qt::CaseInsensitive)) {
323+
return true;
324+
}
325+
326+
const auto &langNames = languageNames(langCode);
327+
if (langNames.localName.contains(filterText_, Qt::CaseInsensitive) ||
328+
langNames.nativeName.contains(filterText_, Qt::CaseInsensitive)) {
329+
return true;
330+
}
331+
return false;
313332
}
314333

315334
bool IMProxyModel::lessThan(const QModelIndex &left,
@@ -378,7 +397,7 @@ QVariant FilteredIMModel::data(const QModelIndex &index, int role) const {
378397
return imEntry.configurable();
379398

380399
case FcitxLanguageNameRole:
381-
return languageName(imEntry.languageCode());
400+
return languageNames(imEntry.languageCode()).localName;
382401

383402
case FcitxIMLayoutRole: {
384403
auto iter = std::find_if(enabledIMList_.begin(), enabledIMList_.end(),
@@ -395,7 +414,7 @@ QVariant FilteredIMModel::data(const QModelIndex &index, int role) const {
395414
: QStringLiteral("inactive");
396415

397416
default:
398-
return QVariant();
417+
return {};
399418
}
400419
}
401420

@@ -477,5 +496,4 @@ void FilteredIMModel::remove(int idx) {
477496
Q_EMIT imListChanged(filteredIMEntryList_);
478497
}
479498

480-
} // namespace kcm
481-
} // namespace fcitx
499+
} // namespace fcitx::kcm

src/lib/configlib/model.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,19 @@
66
#ifndef _KCM_FCITX_MODEL_H_
77
#define _KCM_FCITX_MODEL_H_
88

9+
#include "iso639.h"
10+
#include <QAbstractItemModel>
11+
#include <QHash>
12+
#include <QList>
13+
#include <QObject>
914
#include <QSet>
1015
#include <QSortFilterProxyModel>
16+
#include <QVariant>
17+
#include <Qt>
1118
#include <fcitxqtdbustypes.h>
19+
#include <utility>
1220

13-
namespace fcitx {
14-
namespace kcm {
21+
namespace fcitx::kcm {
1522

1623
enum {
1724
FcitxRowTypeRole = 0x324da8fc,
@@ -31,6 +38,19 @@ class IMConfigModelInterface {
3138
virtual void
3239
filterIMEntryList(const FcitxQtInputMethodEntryList &imEntryList,
3340
const FcitxQtStringKeyValueList &enabledIMs) = 0;
41+
42+
protected:
43+
struct LanguageNames {
44+
// Language names in own locale
45+
QString nativeName;
46+
// Language names in system locale
47+
QString localName;
48+
};
49+
50+
const LanguageNames &languageNames(const QString &langCode) const;
51+
52+
mutable QHash<QString, LanguageNames> languageNames_;
53+
Iso639 iso639_;
3454
};
3555

3656
class CategorizedItemModel : public QAbstractItemModel {
@@ -60,7 +80,7 @@ class AvailIMModel : public CategorizedItemModel,
6080
AvailIMModel(QObject *parent = 0);
6181
void
6282
filterIMEntryList(const FcitxQtInputMethodEntryList &imEntryList,
63-
const FcitxQtStringKeyValueList &enabledIMs) override;
83+
const FcitxQtStringKeyValueList &enabledIMList) override;
6484

6585
protected:
6686
int listSize() const override { return filteredIMEntryList.size(); }
@@ -95,7 +115,7 @@ class IMProxyModel : public QSortFilterProxyModel,
95115
const QString &filterText() const { return filterText_; }
96116
void setFilterText(const QString &text);
97117
bool showOnlyCurrentLanguage() const { return showOnlyCurrentLanguage_; }
98-
void setShowOnlyCurrentLanguage(bool checked);
118+
void setShowOnlyCurrentLanguage(bool show);
99119

100120
void
101121
filterIMEntryList(const FcitxQtInputMethodEntryList &imEntryList,
@@ -153,8 +173,6 @@ public Q_SLOTS:
153173
FcitxQtStringKeyValueList enabledIMList_;
154174
};
155175

156-
} // namespace kcm
157-
158-
} // namespace fcitx
176+
} // namespace fcitx::kcm
159177

160178
#endif // _KCM_FCITX_MODEL_H_

0 commit comments

Comments
 (0)