1/*
2 SPDX-FileCopyrightText: 1999-2003 Hans Petter Bieker <bieker@kde.org>
3 SPDX-FileCopyrightText: 2007 David Jarvie <software@astrojar.org.uk>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "klanguagename.h"
9
10#include <KConfig>
11#include <KConfigGroup>
12
13#include <QDir>
14#include <QLocale>
15
16QString KLanguageName::nameForCode(const QString &code)
17{
18 const QStringList parts = QLocale().name().split(sep: QLatin1Char('_'));
19 return nameForCodeInLocale(code, outputLocale: parts.at(i: 0));
20}
21
22static std::tuple<QString, QString> namesFromEntryFile(const QString &realCode, const QString &realOutputCode)
23{
24 const QString entryFile = QStandardPaths::locate(type: QStandardPaths::GenericDataLocation,
25 QStringLiteral("locale") + QLatin1Char('/') + realCode + QStringLiteral("/kf6_entry.desktop"));
26
27 if (!entryFile.isEmpty()) {
28 KConfig entry(entryFile, KConfig::SimpleConfig);
29 entry.setLocale(realOutputCode);
30 const KConfigGroup group(&entry, QStringLiteral("KCM Locale"));
31 const QString name = group.readEntry(key: "Name");
32
33 entry.setLocale(QStringLiteral("en_US"));
34 const QString englishName = group.readEntry(key: "Name");
35 return std::make_tuple(args: name, args: englishName);
36 }
37 return {};
38}
39
40QString KLanguageName::nameForCodeInLocale(const QString &code, const QString &outputCode)
41{
42 const QString realCode = code == QLatin1String("en") ? QStringLiteral("en_US") : code;
43 const QString realOutputCode = outputCode == QLatin1String("en") ? QStringLiteral("en_US") : outputCode;
44
45 const std::tuple<QString, QString> nameAndEnglishName = namesFromEntryFile(realCode, realOutputCode);
46 const QString name = std::get<0>(t: nameAndEnglishName);
47 const QString englishName = std::get<1>(t: nameAndEnglishName);
48
49 if (!name.isEmpty()) {
50 // KConfig doesn't have a way to say it didn't find the entry in
51 // realOutputCode. When it doesn't find it in the locale you ask for, it just returns the english version
52 // so we compare the returned name against the english version, if they are different we return it, if they
53 // are equal we defer to QLocale (with a final fallback to name/englishName if QLocale doesn't know about it)
54 if (name != englishName || realOutputCode == QLatin1String("en_US")) {
55 return name;
56 }
57 }
58
59 const QLocale locale(realCode);
60 if (locale != QLocale::c()) {
61 if (realCode == realOutputCode) {
62 return locale.nativeLanguageName();
63 }
64 return QLocale::languageToString(language: locale.language());
65 }
66
67 // We get here if QLocale doesn't know about realCode (at the time of writing this happens for crh, csb, hne, mai) and name and englishName are the same.
68 // So what we do here is return name, which can be either empty if the KDE side doesn't know about the code, or otherwise will be the name/englishName
69 return name;
70}
71
72QStringList KLanguageName::allLanguageCodes()
73{
74 QStringList systemLangList;
75 const QStringList localeDirs = QStandardPaths::locateAll(type: QStandardPaths::GenericDataLocation, QStringLiteral("locale"), options: QStandardPaths::LocateDirectory);
76 for (const QString &localeDir : localeDirs) {
77 const QStringList entries = QDir(localeDir).entryList(filters: QDir::Dirs);
78 auto languageExists = [&localeDir](const QString &language) {
79 return QFile::exists(fileName: localeDir + QLatin1Char('/') + language + QLatin1String("/kf6_entry.desktop"));
80 };
81 std::copy_if(first: entries.begin(), last: entries.end(), result: std::back_inserter(x&: systemLangList), pred: languageExists);
82 }
83 if (localeDirs.count() > 1) {
84 systemLangList.removeDuplicates();
85 }
86 return systemLangList;
87}
88

source code of kconfigwidgets/src/klanguagename.cpp