File indexing completed on 2024-12-08 03:38:43

0001 /*
0002     SPDX-FileCopyrightText: 1999-2003 Hans Petter Bieker <bieker@kde.org>
0003     SPDX-FileCopyrightText: 2007 David Jarvie <software@astrojar.org.uk>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "klanguagename.h"
0009 
0010 #include <KConfig>
0011 #include <KConfigGroup>
0012 
0013 #include <QDir>
0014 #include <QLocale>
0015 
0016 QString KLanguageName::nameForCode(const QString &code)
0017 {
0018     const QStringList parts = QLocale().name().split(QLatin1Char('_'));
0019     return nameForCodeInLocale(code, parts.at(0));
0020 }
0021 
0022 static std::tuple<QString, QString> namesFromEntryFile(const QString &realCode, const QString &realOutputCode)
0023 {
0024     const QString entryFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0025                                                      QStringLiteral("locale") + QLatin1Char('/') + realCode + QStringLiteral("/kf6_entry.desktop"));
0026 
0027     if (!entryFile.isEmpty()) {
0028         KConfig entry(entryFile, KConfig::SimpleConfig);
0029         entry.setLocale(realOutputCode);
0030         const KConfigGroup group(&entry, QStringLiteral("KCM Locale"));
0031         const QString name = group.readEntry("Name");
0032 
0033         entry.setLocale(QStringLiteral("en_US"));
0034         const QString englishName = group.readEntry("Name");
0035         return std::make_tuple(name, englishName);
0036     }
0037     return {};
0038 }
0039 
0040 QString KLanguageName::nameForCodeInLocale(const QString &code, const QString &outputCode)
0041 {
0042     const QString realCode = code == QLatin1String("en") ? QStringLiteral("en_US") : code;
0043     const QString realOutputCode = outputCode == QLatin1String("en") ? QStringLiteral("en_US") : outputCode;
0044 
0045     const std::tuple<QString, QString> nameAndEnglishName = namesFromEntryFile(realCode, realOutputCode);
0046     const QString name = std::get<0>(nameAndEnglishName);
0047     const QString englishName = std::get<1>(nameAndEnglishName);
0048 
0049     if (!name.isEmpty()) {
0050         // KConfig doesn't have a way to say it didn't find the entry in
0051         // realOutputCode. When it doesn't find it in the locale you ask for, it just returns the english version
0052         // so we compare the returned name against the english version, if they are different we return it, if they
0053         // are equal we defer to QLocale (with a final fallback to name/englishName if QLocale doesn't know about it)
0054         if (name != englishName || realOutputCode == QLatin1String("en_US")) {
0055             return name;
0056         }
0057     }
0058 
0059     const QLocale locale(realCode);
0060     if (locale != QLocale::c()) {
0061         if (realCode == realOutputCode) {
0062             return locale.nativeLanguageName();
0063         }
0064         return QLocale::languageToString(locale.language());
0065     }
0066 
0067     // 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.
0068     // 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
0069     return name;
0070 }
0071 
0072 QStringList KLanguageName::allLanguageCodes()
0073 {
0074     QStringList systemLangList;
0075     const QStringList localeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("locale"), QStandardPaths::LocateDirectory);
0076     for (const QString &localeDir : localeDirs) {
0077         const QStringList entries = QDir(localeDir).entryList(QDir::Dirs);
0078         auto languageExists = [&localeDir](const QString &language) {
0079             return QFile::exists(localeDir + QLatin1Char('/') + language + QLatin1String("/kf6_entry.desktop"));
0080         };
0081         std::copy_if(entries.begin(), entries.end(), std::back_inserter(systemLangList), languageExists);
0082     }
0083     if (localeDirs.count() > 1) {
0084         systemLangList.removeDuplicates();
0085     }
0086     return systemLangList;
0087 }