diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml index 2b9d8cf69a..7d99bc2fa4 100644 --- a/.github/workflows/linters.yaml +++ b/.github/workflows/linters.yaml @@ -95,23 +95,3 @@ jobs: run: | conda info REPOSITORY_ROOT=$(pwd)/.. ./gradlew ktlint - - check-language-json: - name: Check if languages.json is valid - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v3 - with: - submodules: "true" - - - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: "npm" - - run: npm install - - - name: Run languagelocalizer - run: | - cd tools/languagelocalizer - node languageLocalizer.js --check diff --git a/scripts/cmake/generate_translations_target.cmake b/scripts/cmake/generate_translations_target.cmake index 9f25b4a11b..4dfa0ddf38 100644 --- a/scripts/cmake/generate_translations_target.cmake +++ b/scripts/cmake/generate_translations_target.cmake @@ -41,6 +41,7 @@ function(generate_translations_target TARGET_NAME ASSETS_DIRECTORY TRANSLATIONS_ target_include_directories(${TARGET_NAME} PUBLIC ${GENERATED_DIR}) target_sources(${TARGET_NAME} PRIVATE + ${GENERATED_DIR}/i18nlanguagenames.h ${GENERATED_DIR}/i18nstrings_p.cpp ${GENERATED_DIR}/i18nstrings.h ${GENERATED_DIR}/translations.qrc @@ -56,15 +57,26 @@ function(generate_translations_target TARGET_NAME ASSETS_DIRECTORY TRANSLATIONS_ OUTPUT ${GENERATED_DIR}/i18nstrings_p.cpp ${GENERATED_DIR}/i18nstrings.h DEPENDS ${ASSETS_DIRECTORY}/strings.yaml + ${ASSETS_DIRECTORY}/extras/extras.xliff ${MVPN_SCRIPT_DIR}/utils/generate_strings.py COMMAND ${PYTHON_EXECUTABLE} ${MVPN_SCRIPT_DIR}/utils/generate_strings.py -o ${GENERATED_DIR} ${ASSETS_DIRECTORY}/strings.yaml + ${ASSETS_DIRECTORY}/extras/extras.xliff + ) + + add_custom_command( + OUTPUT ${GENERATED_DIR}/i18nlanguagenames.h + DEPENDS + ${ASSETS_DIRECTORY}/extras/extras.xliff + ${MVPN_SCRIPT_DIR}/utils/generate_language_names_map.py + COMMAND ${PYTHON_EXECUTABLE} ${MVPN_SCRIPT_DIR}/utils/generate_language_names_map.py + ${TRANSLATIONS_DIRECTORY} + ${GENERATED_DIR}/i18nlanguagenames.h ) ## Build the list of supported locales and add rules to build them. file(GLOB I18N_LOCALES LIST_DIRECTORIES true RELATIVE ${TRANSLATIONS_DIRECTORY} ${TRANSLATIONS_DIRECTORY}/*) - message(${I18N_LOCALES}) list(FILTER I18N_LOCALES EXCLUDE REGEX "^\\..+") foreach(LOCALE ${I18N_LOCALES}) if(NOT EXISTS ${TRANSLATIONS_DIRECTORY}/${LOCALE}/mozillavpn.xliff) @@ -81,11 +93,13 @@ function(generate_translations_target TARGET_NAME ASSETS_DIRECTORY TRANSLATIONS_ add_custom_command( OUTPUT ${GENERATED_DIR}/mozillavpn_${LOCALE}.ts MAIN_DEPENDENCY ${TRANSLATIONS_DIRECTORY}/${LOCALE}/mozillavpn.xliff - DEPENDS ${GENERATED_DIR}/i18nstrings_p.cpp + DEPENDS + ${GENERATED_DIR}/i18nstrings_p.cpp + ${TRANSLATIONS_DIRECTORY}/${LOCALE}/extras.xliff COMMAND ${QT_LUPDATE_EXECUTABLE} -target-language ${LOCALE} ${GENERATED_DIR}/i18nstrings_p.cpp -ts ${GENERATED_DIR}/mozillavpn_${LOCALE}.ts COMMAND ${QT_LCONVERT_EXECUTABLE} -verbose -o ${GENERATED_DIR}/mozillavpn_${LOCALE}.ts -if ts -i ${GENERATED_DIR}/mozillavpn_${LOCALE}.ts ${INCLUDE_UNTRANSLATED} - -if xlf -i ${TRANSLATIONS_DIRECTORY}/${LOCALE}/mozillavpn.xliff + -if xlf -i ${TRANSLATIONS_DIRECTORY}/${LOCALE}/mozillavpn.xliff -i ${TRANSLATIONS_DIRECTORY}/${LOCALE}/extras.xliff ) add_custom_command( diff --git a/scripts/utils/generate_language_names_map.py b/scripts/utils/generate_language_names_map.py new file mode 100755 index 0000000000..ed4d380dac --- /dev/null +++ b/scripts/utils/generate_language_names_map.py @@ -0,0 +1,58 @@ +#! /usr/bin/env python3 +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import argparse +import xml.etree.ElementTree as etree + +def extract_strings_with_id(directory): + language_strings = {} + + for root, dirs, files in os.walk(directory): + if "extras.xliff" in files: + extras_xliff_path = os.path.join(root, "extras.xliff") + lang_code = os.path.basename(root) + if lang_code not in language_strings: + language_strings[lang_code] = {} + + tree = etree.parse(extras_xliff_path) + root = tree.getroot() + + for trans_unit in root.findall('.//{urn:oasis:names:tc:xliff:document:1.2}trans-unit'): + unit_id = trans_unit.get('id') + if unit_id.startswith('languages.'): + if lang_code == 'en': + value = trans_unit.find('.//{urn:oasis:names:tc:xliff:document:1.2}source') + else: + value = trans_unit.find('.//{urn:oasis:names:tc:xliff:document:1.2}target') + + if value is not None and value.text is not None: + source_text = value.text.strip() + language_strings[lang_code][unit_id.replace('languages.', '')] = source_text + + return language_strings + +def generate_cpp_header(language_strings, output_file): + with open(output_file, 'w', encoding="utf-8") as f: + f.write('#ifndef LANGUAGE_STRINGS_H\n') + f.write('#define LANGUAGE_STRINGS_H\n\n') + f.write('#include \n#include \n\n') + f.write('namespace LanguageStrings {\n') + f.write('const QMap NATIVE_LANGUAGE_NAMES = {\n') + for lang_code, strings in language_strings.items(): + f.write(' {"' + lang_code + '", "' + strings.get(lang_code, strings.get("en", "")) + '"},\n') + f.write('};\n}\n\n#endif\n') + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Extract language name strings from "extras.xliff" files.') + parser.add_argument('directory', type=str, help='Path to the i18n directory') + parser.add_argument('output_file', type=str, help='Output file name') + args = parser.parse_args() + + directory_path = args.directory + output_file = args.output_file + + language_strings = extract_strings_with_id(directory_path) + generate_cpp_header(language_strings, output_file) diff --git a/scripts/utils/generate_strings.py b/scripts/utils/generate_strings.py index e4913b59a8..4ae5c5ecc3 100755 --- a/scripts/utils/generate_strings.py +++ b/scripts/utils/generate_strings.py @@ -6,7 +6,8 @@ import os import yaml import argparse - +import xml.etree.ElementTree as etree +import re def stop(string_id): exit( @@ -36,7 +37,31 @@ def construct_mapping(self, node, deep=False): return super().construct_mapping(node, deep) -def parseTranslationStrings(yamlfile): +def parseXLIFFTranslationStrings(xliff_file): + if not os.path.isfile(xliff_file): + exit(f"Unable to find {xliff_file}") + + strings = {} + + tree = etree.parse(xliff_file) + root = tree.getroot() + + for node in root.findall('.//{urn:oasis:names:tc:xliff:document:1.2}trans-unit'): + # Remove any unexpected characters e.g. São Paulo -> SoPaulo + id = re.sub(r'[^a-zA-Z._]', '', node.get('id')) + cpp_id = pascalize(id.replace('.', '_')) + value = node.findall('.//{urn:oasis:names:tc:xliff:document:1.2}source')[0].text + + strings[cpp_id] = { + "string_id": id, + "value": [value], + "comments": [], + } + + return strings + + +def parseYAMLTranslationStrings(yamlfile): if not os.path.isfile(yamlfile): exit(f"Unable to find {yamlfile}") @@ -147,6 +172,10 @@ class I18nStrings final : public QQmlPropertyMap { """ __Last, }; + static String getString(const QString& s) { + return s_stringIdMap.value(s, I18nStrings::Empty); + } + static I18nStrings* instance(); static void initialize(); @@ -157,10 +186,20 @@ class I18nStrings final : public QQmlPropertyMap { const char* id(I18nStrings::String) const; - QString t(String) const; + QString t(I18nStrings::String) const; private: static const char* const _ids[]; + + static inline const QHash s_stringIdMap = { +""" + ) + + for i, key in enumerate(strings): + output.write(f" {{\"{key}\", I18nStrings::{key}}}, \n") + + output.write(""" + }; }; #endif // I18NSTRINGS_H @@ -218,15 +257,15 @@ def serialize(string): if __name__ == "__main__": # Parse arguments to locate the input and output files. parser = argparse.ArgumentParser( - description="Generate internationalization strings database from a YAML source" + description="Generate internationalization strings database from a YAML and/or XLIFF sources" ) parser.add_argument( - "source", + "sources", metavar="SOURCE", type=str, action="store", nargs='+', - help="YAML strings file to process", + help="Comma separated list of YAML and/or XLIFF sources to parse", ) parser.add_argument( "-o", @@ -238,18 +277,25 @@ def serialize(string): ) args = parser.parse_args() - if not args.source: + if not args.sources: exit("No source argument.") # If no output directory was provided, use the current directory. if args.output is None: args.output = os.getcwd() - # Parse the inputs for their sweet juicy strings. + # Parse the inputs strings = {} - for source in args.source: - substrings = parseTranslationStrings(source) - strings.update(substrings) + for source in args.sources: + _, ext = os.path.splitext(source) + if ext == '.yaml': + substrings = parseYAMLTranslationStrings(source) + strings.update(substrings) + elif ext == '.xliff': + substrings = parseXLIFFTranslationStrings(source) + strings.update(substrings) + else: + raise f'Unknown file format provided: {source}' # Render the strings into generated content. generateStrings(strings, args.output) diff --git a/src/cmake/shared-sources.cmake b/src/cmake/shared-sources.cmake index 1d47189513..112e09c00e 100644 --- a/src/cmake/shared-sources.cmake +++ b/src/cmake/shared-sources.cmake @@ -124,8 +124,6 @@ target_sources(shared-sources INTERFACE ${CMAKE_SOURCE_DIR}/src/ipaddress.h ${CMAKE_SOURCE_DIR}/src/itempicker.cpp ${CMAKE_SOURCE_DIR}/src/itempicker.h - ${CMAKE_SOURCE_DIR}/src/languagei18n.cpp - ${CMAKE_SOURCE_DIR}/src/languagei18n.h ${CMAKE_SOURCE_DIR}/src/leakdetector.cpp ${CMAKE_SOURCE_DIR}/src/leakdetector.h ${CMAKE_SOURCE_DIR}/src/localizer.cpp diff --git a/src/cmake/sources.cmake b/src/cmake/sources.cmake index 2acd48e697..c2aa278dc7 100644 --- a/src/cmake/sources.cmake +++ b/src/cmake/sources.cmake @@ -151,8 +151,6 @@ target_sources(mozillavpn-sources INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/purchasewebhandler.h ${CMAKE_CURRENT_SOURCE_DIR}/releasemonitor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/releasemonitor.h - ${CMAKE_CURRENT_SOURCE_DIR}/serveri18n.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/serveri18n.h ${CMAKE_CURRENT_SOURCE_DIR}/serverlatency.cpp ${CMAKE_CURRENT_SOURCE_DIR}/serverlatency.h ${CMAKE_CURRENT_SOURCE_DIR}/settingswatcher.cpp @@ -230,7 +228,7 @@ endif() # Creates Target (mozillavpn-sources_clang_tidy_report) mz_add_clang_tidy(mozillavpn-sources) -# we need to make sure those are up to date before we build. +# we need to make sure those are up to date before we build. # Those targets generate code we #include, therefore mz_optional_dependency(mozillavpn-sources_clang_tidy_report qtglean) diff --git a/src/controller.cpp b/src/controller.cpp index 739942e4a5..0af905e17d 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -28,7 +28,6 @@ #include "rfc/rfc1918.h" #include "rfc/rfc4193.h" #include "rfc/rfc4291.h" -#include "serveri18n.h" #include "serverlatency.h" #include "settingsholder.h" #include "tasks/controlleraction/taskcontrolleraction.h" diff --git a/src/languagei18n.cpp b/src/languagei18n.cpp deleted file mode 100644 index a996872fe8..0000000000 --- a/src/languagei18n.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "languagei18n.h" - -#include -#include -#include -#include -#include -#include - -#include "constants.h" -#include "leakdetector.h" -#include "localizer.h" -#include "logger.h" -#include "resourceloader.h" -#include "settingsholder.h" - -namespace { -Logger logger("LanguageI18N"); - -QString itemKey(const QString& translationCode, const QString& languageCode) { - return QString("%1^%2").arg(translationCode, languageCode); -} - -} // namespace - -// static -LanguageI18N* LanguageI18N::instance() { - static LanguageI18N* s_instance = nullptr; - if (!s_instance) { - s_instance = new LanguageI18N(qApp); - s_instance->initialize(); - } - - return s_instance; -} - -LanguageI18N::LanguageI18N(QObject* parent) : QObject(parent) { - MZ_COUNT_CTOR(LanguageI18N); - - connect(ResourceLoader::instance(), &ResourceLoader::cacheFlushNeeded, this, - [this]() { - m_languageList.clear(); - m_translations.clear(); - m_currencies.clear(); - initialize(); - }); -} - -LanguageI18N::~LanguageI18N() { MZ_COUNT_DTOR(LanguageI18N); } - -void LanguageI18N::initialize() { - QFile file(ResourceLoader::instance()->loadFile(":/i18n/languages.json")); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - logger.error() << "Failed to open the languages.json"; - return; - } - - QJsonDocument json = QJsonDocument::fromJson(file.readAll()); - if (!json.isArray()) { - logger.error() << "Invalid format (expected array)"; - return; - } - - QJsonArray array = json.array(); - for (const QJsonValue& language : array) { - addLanguage(language); - } -} - -void LanguageI18N::addLanguage(const QJsonValue& value) { - if (!value.isObject()) { - return; - } - - QJsonObject obj = value.toObject(); - - QString languageCode = obj["languageCode"].toString(); - if (languageCode.isEmpty()) { - logger.error() << "Empty languageCode string"; - return; - } - - QJsonValue translations = obj["languages"]; - if (!translations.isObject()) { - logger.error() << "Empty translation list"; - return; - } - - QJsonObject translationObj = translations.toObject(); - for (const QString& translationCode : translationObj.keys()) { - QString translation(translationObj[translationCode].toString()); - m_translations.insert(itemKey(languageCode, translationCode), - translationObj[translationCode].toString()); - } - - QJsonValue currencies = obj["currencies"]; - if (!currencies.isObject()) { - logger.error() << "Empty currency list"; - return; - } - - QJsonObject currencyObj = currencies.toObject(); - for (const QString& currencyIso4217 : currencyObj.keys()) { - m_currencies.insert(itemKey(currencyIso4217, languageCode), - currencyObj[currencyIso4217].toString()); - } - - m_languageList.append(languageCode); -} - -bool LanguageI18N::languageExists(const QString& languageCode) { - return m_languageList.contains(languageCode); -} - -QString LanguageI18N::translateLanguage(const QString& translationCode, - const QString& languageCode) { - return m_translations.value(itemKey(translationCode, languageCode)); -} - -int LanguageI18N::languageCompare(const QString& languageCodeA, - const QString& languageCodeB) { - qsizetype a = m_languageList.indexOf(languageCodeA); - qsizetype b = m_languageList.indexOf(languageCodeB); - -#ifndef UNIT_TEST - if (a < 0 || b < 0) { - // We do not have all the languages in unit-tests - QByteArray message; - { - QTextStream str(&message); - str << "Unable to find language " << languageCodeA << ":" << a << " or " - << languageCodeB << ":" << b; - } - Q_ASSERT_X(false, "LanguageI18N", message); - } -#endif - - if (a < b) { - return -1; - } - - if (a == b) { - return 0; - } - - return 1; -} - -QString LanguageI18N::currencySymbolForLanguage( - const QString& languageCode, const QString& currencyIso4217) { - return m_currencies.value(itemKey(currencyIso4217, languageCode)); -} diff --git a/src/languagei18n.h b/src/languagei18n.h deleted file mode 100644 index 7344166b7a..0000000000 --- a/src/languagei18n.h +++ /dev/null @@ -1,47 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef LANGUAGEI18N_H -#define LANGUAGEI18N_H - -#include -#include -#include -#include - -class QJsonValue; - -class LanguageI18N final : public QObject { - Q_OBJECT - Q_DISABLE_COPY_MOVE(LanguageI18N) - - public: - static LanguageI18N* instance(); - - ~LanguageI18N(); - - QString currencySymbolForLanguage(const QString& languageCode, - const QString& currencyIso4217); - - bool languageExists(const QString& languageCode); - - QString translateLanguage(const QString& translationCode, - const QString& languageCode); - - int languageCompare(const QString& languageCodeA, - const QString& languageCodeB); - - private: - explicit LanguageI18N(QObject* parent); - - void initialize(); - void addLanguage(const QJsonValue& value); - - private: - QList m_languageList; - QHash m_translations; - QHash m_currencies; -}; - -#endif // LANGUAGEI18N_H diff --git a/src/localizer.cpp b/src/localizer.cpp index ffb882df1d..9b2e7b481c 100644 --- a/src/localizer.cpp +++ b/src/localizer.cpp @@ -11,12 +11,14 @@ #include #include #include +#include #include #include "constants.h" #include "glean/generated/metrics.h" #include "glean/mzglean.h" -#include "languagei18n.h" +#include "i18nlanguagenames.h" +#include "i18nstrings.h" #include "leakdetector.h" #include "logger.h" #include "resourceloader.h" @@ -31,19 +33,36 @@ Logger logger("Localizer"); Localizer* s_instance = nullptr; bool s_forceRTL = false; -// Some languages do not have the right localized/non-localized names in the QT -// framework (and some are missing entirely). This static map is the fallback -// when this happens. -QMap s_languageMap{ - {"es_AR", "Español, Argentina"}, - {"es_CL", "Español, Chile"}, - {"es_MX", "Español, México"}, -}; +// Fallback map of supported currency symbols. +// The list of supported countries can be found at +// https://mozilla-hub.atlassian.net/wiki/spaces/PXI/pages/173539548/Supported+Markets+and+Currencies. +QMap s_currencyMap{ + {"USD", "$"}, {"GBP", "£"}, {"NZD", "NZ$"}, {"MYR", "RM"}, + {"SGD", "S$"}, {"CAD", "CA$"}, {"EUR", "€"}, {"CHF", "CHF"}, + {"SEK", "kr"}, {"PLN", "zł"}, {"DKK", "kr"}, {"CZK", "Kč"}, + {"HUF", "Ft"}, {"BGN", "лв"}, {"RON", "lei"}}; QString toUpper(const QLocale& locale, QString input) { + if (input.isEmpty()) { + return ""; + } + return input.replace(0, 1, locale.toUpper(QString(input[0]))); } +QString toPascalCase(const QString& s) { + QStringList words = s.split("_"); + + for (int i = 0; i < words.size(); i++) { + QString word = words.at(i); + if (!word.isEmpty()) { + words[i] = word.at(0).toUpper() + word.mid(1); + } + } + + return words.join(""); +} + } // namespace // static @@ -211,8 +230,7 @@ void Localizer::loadLanguagesFromI18n() { std::sort(m_languages.begin(), m_languages.end(), [&](const Language& a, const Language& b) -> bool { - return LanguageI18N::instance()->languageCompare(a.m_code, - b.m_code) < 0; + return a.m_code < b.m_code; }); endResetModel(); @@ -329,8 +347,6 @@ bool Localizer::loadLanguage(const QString& requestedLocalCode) { localeCode = systemLanguageCode(); } - logger.debug() << "Let's try to load another language as fallback for code" - << localeCode; maybeLoadLanguageFallback(localeCode); QLocale locale = QLocale(localeCode); @@ -381,8 +397,7 @@ void Localizer::maybeLoadLanguageFallbackData() { } } -QStringList Localizer::fallbackForLanguage(const QString& code) { - maybeLoadLanguageFallbackData(); +QStringList Localizer::fallbackForLanguage(const QString& code) const { return m_translationFallback.value(code, QStringList()); } @@ -397,7 +412,7 @@ void Localizer::maybeLoadLanguageFallback(const QString& code) { for (const QString& fallbackCode : m_translationFallback.value(code, QStringList())) { - logger.debug() << "Fallback language:" << fallbackCode; + logger.debug() << "Loading fallback locale:" << fallbackCode; if (!createTranslator(QLocale(fallbackCode))) { logger.warning() << "Loading the fallback locale failed - code:" @@ -409,34 +424,22 @@ void Localizer::maybeLoadLanguageFallback(const QString& code) { // static QString Localizer::nativeLanguageName(const QLocale& locale, const QString& code) { -#ifndef UNIT_TEST - if (!Constants::inProduction()) { - Q_ASSERT_X(LanguageI18N::instance()->languageExists(code), "localizer", - "Languages are out of sync with the translations"); - } -#endif - - // Let's see if we have the translation of this language in this language. We - // can use it as native language name. - QString name = LanguageI18N::instance()->translateLanguage(code, code); - if (!name.isEmpty()) { - return toUpper(locale, name); - } - - if (s_languageMap.contains(code)) { - return s_languageMap[code]; + QString localizedLanguageName = + LanguageStrings::NATIVE_LANGUAGE_NAMES.value(code); + if (!localizedLanguageName.isEmpty()) { + return toUpper(locale, localizedLanguageName); } if (locale.language() == QLocale::C) { return "English (US)"; } - name = locale.nativeLanguageName(); - if (name.isEmpty()) { + localizedLanguageName = locale.nativeLanguageName(); + if (localizedLanguageName.isEmpty()) { return locale.languageToString(locale.language()); } - return toUpper(locale, name); + return toUpper(locale, localizedLanguageName); } QHash Localizer::roleNames() const { @@ -452,36 +455,13 @@ int Localizer::rowCount(const QModelIndex&) const { return static_cast(m_languages.count()); } -QString Localizer::localizedLanguageName(const Language& language) const { - QString translationCode = SettingsHolder::instance()->languageCode(); - if (translationCode.isEmpty()) { - translationCode = Localizer::instance()->languageCodeOrSystem(); - } - - QString value = LanguageI18N::instance()->translateLanguage(translationCode, - language.m_code); - if (!value.isEmpty()) { - return toUpper(QLocale(translationCode), value); - } - - // If we don't have 'ab_BC', but we have 'ab' - if (translationCode.contains('_')) { - QStringList parts = translationCode.split('_'); +QString Localizer::localizedLanguageName(const QString& languageCode) const { + QString i18nLangId = QString("Languages%1").arg(toPascalCase(languageCode)); + QString value = getCapitalizedStringFromI18n(i18nLangId); - QString value = - LanguageI18N::instance()->translateLanguage(parts[0], language.m_code); - if (!value.isEmpty()) { - return toUpper(QLocale(translationCode), value); - } - } - - // Let's ask QT to localize the language. - QLocale locale(language.m_code); - if (language.m_code.isEmpty()) { - locale = QLocale::system(); - } - - return locale.languageToString(locale.language()); + // Value should never be empty, because the ultimate fallback locale is "en" + // and that locale has all strings. + return value; } QVariant Localizer::data(const QModelIndex& index, int role) const { @@ -493,7 +473,7 @@ QVariant Localizer::data(const QModelIndex& index, int role) const { switch (role) { case LocalizedLanguageNameRole: - return QVariant(localizedLanguageName(language)); + return QVariant(localizedLanguageName(language.m_code)); case NativeLanguageNameRole: return QVariant(language.m_nativeLanguageName); @@ -537,15 +517,12 @@ QString Localizer::localizeCurrency(double value, return locale.toCurrencyString(value, currencyIso4217); } - // Happy path if (locale.currencySymbol(QLocale::CurrencyIsoCode) == currencyIso4217) { return locale.toCurrencyString(value); } - QString symbol = LanguageI18N::instance()->currencySymbolForLanguage( - languageCode, currencyIso4217); - if (!symbol.isEmpty()) { - return locale.toCurrencyString(value, symbol); + if (s_currencyMap.contains(currencyIso4217)) { + return locale.toCurrencyString(value, s_currencyMap[currencyIso4217]); } return locale.toCurrencyString(value, currencyIso4217); @@ -593,5 +570,70 @@ QString Localizer::findLanguageCode(const QString& languageCode, return languageCodeWithoutCountry; } +QString Localizer::getTranslatedCountryName(const QString& countryCode, + const QString& countryName) const { + if (countryCode.isEmpty()) { + return ""; + } + + // Country name i18n id is: Servers + // e.g. ServersDe -> Germany + QString i18nCountryId = QString("Servers%1").arg(toPascalCase(countryCode)); + auto value = getCapitalizedStringFromI18n(i18nCountryId); + + // The server list is ever changing, so it is plausible that a translation + // doesn't exist yet for a given server. + if (value.isEmpty()) { + return countryName; + } + + return value; +} + +QString Localizer::getTranslatedCityName(const QString& cityName) const { + if (cityName.isEmpty()) { + return ""; + } + + // City name i18n id is: + // Servers e.g. + // Malmö -> ServersMalm, São Paulo, SP -> ServersSoPaulo, Berlin, BE -> + // ServersBerlin + + QRegularExpression acceptedChars("[^a-zA-Z]"); + QString parsedCityName = + cityName.split(u',')[0] + .replace(" ", "") // Remove state suffix + .replace(acceptedChars, ""); // Remove special characters + + QString i18nCityId = QString("Servers%1").arg(toPascalCase(parsedCityName)); + + auto value = getCapitalizedStringFromI18n(i18nCityId); + + // The server list is ever changing, so it is plausible that a translation + // doesn't exist yet for a given server. + if (value.isEmpty()) { + return cityName; + } + + return value; +} + +// static +QString Localizer::getTranslationCode() { + QString translationCode = SettingsHolder::instance()->languageCode(); + if (translationCode.isEmpty()) { + translationCode = Localizer::instance()->languageCodeOrSystem(); + } + + return translationCode; +} + +// static +QString Localizer::getCapitalizedStringFromI18n(const QString& id) { + QString str = I18nStrings::instance()->t(I18nStrings::getString(id)); + return toUpper(QLocale(getTranslationCode()), str); +} + // static void Localizer::forceRTL() { s_forceRTL = true; } diff --git a/src/localizer.h b/src/localizer.h index f4f48cbf60..d1c137e26a 100644 --- a/src/localizer.h +++ b/src/localizer.h @@ -74,11 +74,15 @@ class Localizer final : public QAbstractListModel { static QMap loadTranslationCompleteness( const QString& fileName); + QString getTranslatedCountryName(const QString& countryCode, + const QString& countryName) const; + QString getTranslatedCityName(const QString& cityName) const; + Q_INVOKABLE QString formatDate(const QDateTime& nowDateTime, const QDateTime& messageDateTime, const QString& yesterday); - QStringList fallbackForLanguage(const QString& code); + QStringList fallbackForLanguage(const QString& code) const; // QAbstractListModel methods @@ -92,7 +96,7 @@ class Localizer final : public QAbstractListModel { void localeChanged(); private: - QString localizedLanguageName(const Language& language) const; + QString localizedLanguageName(const QString& languageCode) const; static QString nativeLanguageName(const QLocale& locale, const QString& code); QString systemLanguageCode() const; @@ -110,6 +114,10 @@ class Localizer final : public QAbstractListModel { void maybeLoadLanguageFallbackData(); + static QString getTranslationCode(); + + static QString getCapitalizedStringFromI18n(const QString& id); + private: QList m_translators; @@ -120,6 +128,10 @@ class Localizer final : public QAbstractListModel { QList m_languages; QMap m_translationCompleteness; QMap m_translationFallback; + +#ifdef UNIT_TEST + friend class TestLocalizer; +#endif }; #endif // LOCALIZER_H diff --git a/src/models/recentconnections.cpp b/src/models/recentconnections.cpp index d382beaa8c..4a5a75facc 100644 --- a/src/models/recentconnections.cpp +++ b/src/models/recentconnections.cpp @@ -11,10 +11,10 @@ #include "constants.h" #include "leakdetector.h" +#include "localizer.h" #include "logger.h" #include "mozillavpn.h" #include "serverdata.h" -#include "serveri18n.h" #include "settingsholder.h" namespace { @@ -177,8 +177,8 @@ QVariant RecentConnectionModel::data(const QModelIndex& index, int role) const { case LocalizedExitCityNameRole: { const RecentConnection& rc = m_list.at(id); - return QVariant(ServerI18N::instance()->translateCityName( - rc.m_exitCountryCode, rc.m_exitCityName)); + return QVariant( + Localizer::instance()->getTranslatedCityName(rc.m_exitCityName)); } case IsMultiHopRole: { @@ -195,8 +195,8 @@ QVariant RecentConnectionModel::data(const QModelIndex& index, int role) const { case LocalizedEntryCityNameRole: { const RecentConnection& rc = m_list.at(id); - return QVariant(ServerI18N::instance()->translateCityName( - rc.m_entryCountryCode, rc.m_entryCityName)); + return QVariant( + Localizer::instance()->getTranslatedCityName(rc.m_entryCityName)); } default: diff --git a/src/models/servercity.cpp b/src/models/servercity.cpp index 2da070174d..dc33a47d41 100644 --- a/src/models/servercity.cpp +++ b/src/models/servercity.cpp @@ -11,10 +11,10 @@ #include "constants.h" #include "feature/feature.h" #include "leakdetector.h" +#include "localizer.h" #include "location.h" #include "mozillavpn.h" #include "servercountrymodel.h" -#include "serveri18n.h" #include "serverlatency.h" // Latency threshold for excellent connections, set intentionally very low. @@ -110,7 +110,7 @@ QString ServerCity::hashKey(const QString& country, const QString cityName) { } const QString ServerCity::localizedName() const { - return ServerI18N::instance()->translateCityName(m_country, m_name); + return Localizer::instance()->getTranslatedCityName(m_name); } qint64 ServerCity::latency() const { diff --git a/src/models/servercountry.cpp b/src/models/servercountry.cpp index ff359e13d1..2882a67102 100644 --- a/src/models/servercountry.cpp +++ b/src/models/servercountry.cpp @@ -11,8 +11,8 @@ #include "collator.h" #include "leakdetector.h" +#include "localizer.h" #include "serverdata.h" -#include "serveri18n.h" ServerCountry::ServerCountry() { MZ_COUNT_CTOR(ServerCountry); } @@ -73,14 +73,16 @@ bool ServerCountry::fromJson(const QJsonObject& countryObj) { return true; } +QString ServerCountry::localizedName() const { + return Localizer::instance()->getTranslatedCountryName(m_code, m_name); +} + namespace { -bool sortCityCallback(const QString& a, const QString& b, - const QString& countryCode, Collator* collator) { +bool sortCityCallback(const QString& a, const QString& b, Collator* collator) { Q_ASSERT(collator); - return collator->compare( - ServerI18N::instance()->translateCityName(countryCode, a), - ServerI18N::instance()->translateCityName(countryCode, b)) < 0; + return collator->compare(Localizer::instance()->getTranslatedCityName(a), + Localizer::instance()->getTranslatedCityName(b)) < 0; } } // anonymous namespace @@ -90,5 +92,5 @@ void ServerCountry::sortCities() { std::sort(m_cities.begin(), m_cities.end(), std::bind(sortCityCallback, std::placeholders::_1, - std::placeholders::_2, m_code, &collator)); + std::placeholders::_2, &collator)); } diff --git a/src/models/servercountry.h b/src/models/servercountry.h index 8547deff3f..2c064c00ee 100644 --- a/src/models/servercountry.h +++ b/src/models/servercountry.h @@ -25,6 +25,8 @@ class ServerCountry final { const QString& code() const { return m_code; } + QString localizedName() const; + const QList& cities() const { return m_cities; } void sortCities(); diff --git a/src/models/servercountrymodel.cpp b/src/models/servercountrymodel.cpp index 253c7d53bf..2544406cd7 100644 --- a/src/models/servercountrymodel.cpp +++ b/src/models/servercountrymodel.cpp @@ -13,12 +13,12 @@ #include "constants.h" #include "feature/feature.h" #include "leakdetector.h" +#include "localizer.h" #include "logger.h" #include "mozillavpn.h" #include "recommendedlocationmodel.h" #include "servercountry.h" #include "serverdata.h" -#include "serveri18n.h" #include "serverlatency.h" #include "settingsholder.h" @@ -161,8 +161,7 @@ QVariant ServerCountryModel::data(const QModelIndex& index, int role) const { case LocalizedNameRole: { const ServerCountry& country = m_countries.at(index.row()); - return QVariant(ServerI18N::instance()->translateCountryName( - country.code(), country.name())); + return QVariant(country.localizedName()); } case CodeRole: @@ -264,10 +263,7 @@ namespace { bool sortCountryCallback(const ServerCountry& a, const ServerCountry& b, Collator* collator) { Q_ASSERT(collator); - return collator->compare( - ServerI18N::instance()->translateCountryName(a.code(), a.name()), - ServerI18N::instance()->translateCountryName(b.code(), b.name())) < - 0; + return collator->compare(a.localizedName(), b.localizedName()) < 0; } } // anonymous namespace diff --git a/src/models/serverdata.cpp b/src/models/serverdata.cpp index 72a3c14ca2..4c042eb55b 100644 --- a/src/models/serverdata.cpp +++ b/src/models/serverdata.cpp @@ -9,10 +9,10 @@ #include "glean/generated/metrics.h" #include "leakdetector.h" +#include "localizer.h" #include "logger.h" #include "mozillavpn.h" #include "servercountrymodel.h" -#include "serveri18n.h" #include "serverlatency.h" #include "settingsholder.h" @@ -164,38 +164,35 @@ bool ServerData::settingsChanged() { QString ServerData::localizedExitCityName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCityName(m_exitCountryCode, - m_exitCityName); + return Localizer::instance()->getTranslatedCityName(m_exitCityName); } QString ServerData::localizedEntryCityName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCityName(m_entryCountryCode, - m_entryCityName); + return Localizer::instance()->getTranslatedCityName(m_entryCityName); } QString ServerData::localizedPreviousExitCountryName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCityName(m_previousExitCountryCode, - m_previousExitCountryName); + return Localizer::instance()->getTranslatedCityName( + m_previousExitCountryName); } QString ServerData::localizedPreviousExitCityName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCityName(m_previousExitCountryCode, - m_previousExitCityName); + return Localizer::instance()->getTranslatedCityName(m_previousExitCityName); } QString ServerData::localizedEntryCountryName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCountryName(m_entryCountryCode, - m_entryCountryName); + return Localizer::instance()->getTranslatedCountryName(m_entryCountryCode, + m_entryCountryName); } QString ServerData::localizedExitCountryName() const { Q_ASSERT(m_initialized); - return ServerI18N::instance()->translateCountryName(m_exitCountryCode, - m_exitCountryName); + return Localizer::instance()->getTranslatedCountryName(m_exitCountryCode, + m_exitCountryName); } void ServerData::changeServer(const QString& countryCode, diff --git a/src/mozillavpn.cpp b/src/mozillavpn.cpp index 221b983617..f8ad0d8d35 100644 --- a/src/mozillavpn.cpp +++ b/src/mozillavpn.cpp @@ -22,6 +22,7 @@ #include "i18nstrings.h" #include "inspector/inspectorhandler.h" #include "leakdetector.h" +#include "localizer.h" #include "logger.h" #include "loghandler.h" #include "logoutobserver.h" @@ -39,7 +40,6 @@ #include "purchasehandler.h" #include "qmlengineholder.h" #include "releasemonitor.h" -#include "serveri18n.h" #include "settings/settinggroup.h" #include "settings/settingsmanager.h" #include "settingsholder.h" @@ -2033,17 +2033,14 @@ void MozillaVPN::registerInspectorCommands() { QJsonObject cityObj; cityObj["name"] = city.name(); cityObj["localizedName"] = - ServerI18N::instance()->translateCityName(country.code(), - city.name()); + Localizer::instance()->getTranslatedCityName(city.name()); cityObj["code"] = city.code(); cityArray.append(cityObj); } QJsonObject countryObj; countryObj["name"] = country.name(); - countryObj["localizedName"] = - ServerI18N::instance()->translateCountryName(country.code(), - country.name()); + countryObj["localizedName"] = country.localizedName(); countryObj["code"] = country.code(); countryObj["cities"] = cityArray; diff --git a/src/serveri18n.cpp b/src/serveri18n.cpp deleted file mode 100644 index 7f7e4a8588..0000000000 --- a/src/serveri18n.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "serveri18n.h" - -#include -#include -#include -#include -#include - -#include "leakdetector.h" -#include "localizer.h" -#include "logger.h" -#include "resourceloader.h" -#include "settingsholder.h" - -namespace { -Logger logger("ServerI18N"); - -QString itemKey(const QString& languageCode, const QString& countryCode, - const QString& city = QString()) { - return QString("%1^%2^%3").arg(languageCode, countryCode, city); -} -} // namespace - -// static -ServerI18N* ServerI18N::instance() { - static ServerI18N* s_instance = nullptr; - if (!s_instance) { - s_instance = new ServerI18N(qApp); - } - return s_instance; -} - -ServerI18N::ServerI18N(QObject* parent) : QObject(parent) { - MZ_COUNT_CTOR(ServerI18N); - - initialize(); - - connect(ResourceLoader::instance(), &ResourceLoader::cacheFlushNeeded, this, - &ServerI18N::initialize); -} - -ServerI18N::~ServerI18N() { MZ_COUNT_DTOR(ServerI18N); } - -void ServerI18N::initialize() { - m_items.clear(); - - QFile file(ResourceLoader::instance()->loadFile(":/i18n/servers.json")); - if (!file.open(QFile::ReadOnly | QFile::Text)) { - logger.error() << "Failed to open the servers.json"; - return; - } - - QJsonDocument json = QJsonDocument::fromJson(file.readAll()); - if (!json.isArray()) { - logger.error() << "Invalid format (expected array)"; - return; - } - - QJsonArray array = json.array(); - for (const QJsonValue& country : array) { - addCountry(country); - } -} - -QString ServerI18N::translateCountryName(const QString& countryCode, - const QString& countryName) { - return translateItem(countryCode, "", countryName); -} - -QString ServerI18N::translateCityName(const QString& countryCode, - const QString& cityName) { - return translateItem(countryCode, cityName, cityName); -} - -QString ServerI18N::translateItem(const QString& countryCode, - const QString& cityName, - const QString& fallback) { - QString languageCode = SettingsHolder::instance()->languageCode(); - if (languageCode.isEmpty()) { - languageCode = Localizer::instance()->languageCodeOrSystem(); - } - - QString result = - translateItemWithLanguage(languageCode, countryCode, cityName); - if (!result.isEmpty()) { - return result; - } - - if (languageCode != "en") { - result = translateItemWithLanguage("en", countryCode, cityName); - if (!result.isEmpty()) { - return result; - } - } - - return fallback; -} - -QString ServerI18N::translateItemWithLanguage(const QString& languageCode, - const QString& countryCode, - const QString& cityName) { - QString languageCodeCopy(languageCode); - - QString result = m_items.value(itemKey(languageCode, countryCode, cityName)); - if (!result.isEmpty()) { - return result; - } - - // if the language code contains the 'region' part too, we check if we have - // translations for the whole 'primary language'. Ex: 'de-AT' vs 'de'. - bool trimmed = false; - qsizetype pos = languageCodeCopy.indexOf("-"); - if (pos > 0) { - languageCodeCopy = languageCodeCopy.left(pos); - trimmed = true; - } - - pos = languageCodeCopy.indexOf("_"); - if (pos > 0) { - languageCodeCopy = languageCodeCopy.left(pos); - trimmed = true; - } - - if (trimmed) { - result = m_items.value(itemKey(languageCodeCopy, countryCode, cityName)); - if (!result.isEmpty()) { - return result; - } - } else { - // If the language code is not trimmed e.g "es" and we did not have a match - // so far, lets try itself as region e.g es -> es_ES, de -> de_DE - QString concat_code = languageCodeCopy + "_" + languageCodeCopy.toUpper(); - result = m_items.value(itemKey(concat_code, countryCode, cityName)); - if (!result.isEmpty()) { - return result; - } - } - - // Let's use 'en' translation, which is still better than what we obtain from - // Guardian. - result = m_items.value(itemKey("en", countryCode, cityName)); - if (!result.isEmpty()) { - return result; - } - - return QString(); -} - -void ServerI18N::addCity(const QString& countryCode, const QJsonValue& value) { - if (!value.isObject()) { - return; - } - - QJsonObject obj = value.toObject(); - - QString cityName = obj["city"].toString(); - if (cityName.isEmpty()) { - logger.error() << "Empty city string"; - return; - } - - QJsonValue languages = obj["languages"]; - if (!languages.isObject()) { - logger.error() << "Empty language list"; - return; - } - - QJsonObject languageObj = languages.toObject(); - for (const QString& languageCode : languageObj.keys()) { - m_items.insert(itemKey(languageCode, countryCode, cityName), - languageObj[languageCode].toString()); - } -} - -void ServerI18N::addCountry(const QJsonValue& value) { - if (!value.isObject()) { - return; - } - - QJsonObject obj = value.toObject(); - - QString countryCode = obj["countryCode"].toString(); - if (countryCode.isEmpty()) { - logger.error() << "Empty countryCode string"; - return; - } - - QJsonValue languages = obj["languages"]; - if (!languages.isObject()) { - logger.error() << "Empty language list"; - return; - } - - QJsonObject languageObj = languages.toObject(); - for (const QString& languageCode : languageObj.keys()) { - m_items.insert(itemKey(languageCode, countryCode), - languageObj[languageCode].toString()); - } - - QJsonValue cities = obj["cities"]; - if (!cities.isArray()) { - logger.error() << "Empty city list"; - return; - } - - QJsonArray cityArray = cities.toArray(); - for (const QJsonValue& city : cityArray) { - addCity(countryCode, city); - } -} diff --git a/src/serveri18n.h b/src/serveri18n.h deleted file mode 100644 index 33f458770d..0000000000 --- a/src/serveri18n.h +++ /dev/null @@ -1,42 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef SERVERI18N_H -#define SERVERI18N_H - -#include -#include - -class ServerI18N final : public QObject { - public: - static ServerI18N* instance(); - - ~ServerI18N(); - - QString translateCountryName(const QString& countryCode, - const QString& countryName); - - QString translateCityName(const QString& countryCode, - const QString& cityName); - - private: - ServerI18N(QObject* parent); - - void initialize(); - - QString translateItem(const QString& countryCode, const QString& cityName, - const QString& fallback); - - QString translateItemWithLanguage(const QString& languageCode, - const QString& countryCode, - const QString& cityName); - - void addCity(const QString& countryCode, const QJsonValue& value); - void addCountry(const QJsonValue& value); - - private: - QHash m_items; -}; - -#endif // SERVERI18N_H diff --git a/src/translations/extras/languages.json b/src/translations/extras/languages.json deleted file mode 100644 index 2d77fd500f..0000000000 --- a/src/translations/extras/languages.json +++ /dev/null @@ -1,2748 +0,0 @@ -[ - { - "wikiDataID": "Q7918", - "languageCode": "bg", - "IETFcode": "bg", - "currencies": { - "BGN": "лв.", - "EUR": "€", - "USD": "щ.д.", - "XAF": "FCFA", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "български", - "co": "корсикански", - "cs": "чешки", - "cy": "уелски", - "da": "датски", - "de": "немски", - "dsb": "долнолужишки", - "el": "гръцки", - "en": "английски", - "en_CA": "канадски английски", - "en_GB": "британски английски", - "es_ES": "испански", - "es_MX": "испански (Мексико)", - "fa": "персийски", - "fi": "фински", - "fr": "френски", - "fy_NL": "западнофризийски", - "hsb": "горнолужишки", - "hu": "унгарски", - "ia": "интерлингва", - "id": "индонезийски", - "is": "исландски", - "it": "италиански", - "ja": "японски", - "lo": "лаоски", - "nl": "нидерландски", - "pa_IN": "пенджабски", - "pl": "полски", - "pt_BR": "португалски", - "pt_PT": "португалски (Португалия)", - "ru": "руски", - "sk": "словашки", - "sl": "словенски", - "sq": "албански", - "sv_SE": "шведски", - "tr": "турски", - "uk": "украински", - "zh_CN": "китайски (опростен)", - "zh_TW": "китайски (традиционен)" - } - }, - { - "wikiDataID": "Q33111", - "languageCode": "co", - "IETFcode": "co", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Lingua bulgara", - "co": "corsu", - "cs": "Cecu", - "cy": "Gallese", - "de": "Tedescu", - "en": "Inglese", - "en_CA": "Inglese canadianu", - "en_GB": "Inglese britannicu", - "es_CL": "Spagnolu", - "fa": "Lingua persiana", - "fi": "Finlandese", - "fr": "Francese", - "fy_NL": "Frisone occidentale", - "ia": "Interlingua", - "id": "Indunesianu", - "is": "Lingua islandesa", - "it": "Talianu", - "ja": "Giapponese", - "nl": "Neerlandese", - "oc": "Occitanu", - "pt_BR": "Portughese brasilianu", - "ru": "Russu", - "sk": "Lingua sluvacca", - "sq": "Lingua albanese", - "sv_SE": "Lingua svedese", - "uk": "Lingua ucraina" - } - }, - { - "wikiDataID": "Q9056", - "languageCode": "cs", - "IETFcode": "cs", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "CSK": "Kčs", - "CZK": "Kč", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "TWD": "NT$", - "USD": "US$", - "XAF": "FCFA", - "XCD": "EC$", - "XEU": "ECU", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "bulharština", - "co": "korsičtina", - "cs": "čeština", - "cy": "velština", - "da": "dánština", - "de": "němčina", - "dsb": "dolnolužická srbština", - "el": "řečtina", - "en": "angličtina", - "en_CA": "angličtina (Kanada)", - "en_GB": "angličtina (Velká Británie)", - "es_ES": "španělština", - "es_MX": "španělština (Mexiko)", - "fa": "perština", - "fi": "finština", - "fr": "francouzština", - "fy_NL": "fríština (západní)", - "hsb": "hornolužická srbština", - "hu": "maďarština", - "ia": "interlingua", - "id": "indonéština", - "is": "islandština", - "it": "italština", - "ja": "japonština", - "lo": "laoština", - "nl": "nizozemština", - "pa_IN": "paňdžábština", - "pl": "polština", - "pt_BR": "portugalština", - "pt_PT": "portugalština (Evropa)", - "ru": "ruština", - "sk": "slovenština", - "sl": "slovinština", - "sq": "albánština", - "sv_SE": "švédština", - "tr": "turečtina", - "uk": "ukrajinština", - "zh_CN": "čínština (zjednodušená)", - "zh_TW": "čínština (tradiční)" - } - }, - { - "wikiDataID": "Q9309", - "languageCode": "cy", - "IETFcode": "cy", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "Bwlgareg", - "co": "Corseg", - "cs": "Tsieceg", - "cy": "Cymraeg", - "da": "Daneg", - "de": "Almaeneg", - "dsb": "Sorbeg Isaf", - "el": "Groeg", - "en": "Saesneg", - "en_CA": "Saesneg Canada", - "en_GB": "Saesneg Prydain", - "es_ES": "Sbaeneg", - "es_MX": "Sbaeneg Mecsico", - "fa": "Perseg", - "fi": "Ffinneg", - "fr": "Ffrangeg", - "fy_NL": "Ffriseg y Gorllewin", - "hsb": "Sorbeg Uchaf", - "hu": "Hwngareg", - "ia": "Interlingua", - "id": "Indoneseg", - "is": "Islandeg", - "it": "Eidaleg", - "ja": "Japaneeg", - "lo": "Laoeg", - "nl": "Iseldireg", - "pa_IN": "Pwnjabeg", - "pl": "Pwyleg", - "pt_BR": "Portiwgaleg", - "pt_PT": "Portiwgaleg Ewrop", - "ru": "Rwseg", - "sk": "Slofaceg", - "sl": "Slofeneg", - "sq": "Albaneg", - "sv_SE": "Swedeg", - "tr": "Tyrceg", - "uk": "Wcreineg", - "zh_CN": "Tsieinëeg Symledig", - "zh_TW": "Tsieinëeg Traddodiadol" - } - }, - { - "wikiDataID": "Q9035", - "languageCode": "da", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "DKK": "kr.", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bulgarsk", - "co": "korsikansk", - "cs": "tjekkisk", - "cy": "walisisk", - "da": "dansk", - "de": "tysk", - "dsb": "nedersorbisk", - "el": "græsk", - "en": "engelsk", - "en_CA": "canadisk engelsk", - "en_GB": "britisk engelsk", - "es_ES": "spansk", - "es_MX": "mexicansk spansk", - "fa": "persisk", - "fi": "finsk", - "fr": "fransk", - "fy_NL": "vestfrisisk", - "hsb": "øvresorbisk", - "hu": "ungarsk", - "ia": "interlingua", - "id": "indonesisk", - "is": "islandsk", - "it": "italiensk", - "ja": "japansk", - "lo": "lao", - "nl": "nederlandsk", - "pa_IN": "punjabisk", - "pl": "polsk", - "pt_BR": "portugisisk", - "pt_PT": "europæisk portugisisk", - "ru": "russisk", - "sk": "slovakisk", - "sl": "slovensk", - "sq": "albansk", - "sv_SE": "svensk", - "tr": "tyrkisk", - "uk": "ukrainsk", - "zh_CN": "forenklet kinesisk", - "zh_TW": "traditionelt kinesisk" - }, - "IETFcode": "da" - }, - { - "wikiDataID": "Q188", - "languageCode": "de", - "IETFcode": "de", - "currencies": { - "ATS": "öS", - "AUD": "AU$", - "BGM": "BGK", - "BGO": "BGJ", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "DEM": "DM", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "Bulgarisch", - "co": "Korsisch", - "cs": "Tschechisch", - "cy": "Walisisch", - "da": "Dänisch", - "de": "Deutsch", - "dsb": "Niedersorbisch", - "el": "Griechisch", - "en": "Englisch", - "en_CA": "Englisch (Kanada)", - "en_GB": "Englisch (Vereinigtes Königreich)", - "es_ES": "Spanisch", - "es_MX": "Spanisch (Mexiko)", - "fa": "Persisch", - "fi": "Finnisch", - "fr": "Französisch", - "fy_NL": "Westfriesisch", - "hsb": "Obersorbisch", - "hu": "Ungarisch", - "ia": "Interlingua", - "id": "Indonesisch", - "is": "Isländisch", - "it": "Italienisch", - "ja": "Japanisch", - "lo": "Laotisch", - "nl": "Niederländisch", - "pa_IN": "Punjabi", - "pl": "Polnisch", - "pt_BR": "Portugiesisch", - "pt_PT": "Portugiesisch (Portugal)", - "ru": "Russisch", - "sk": "Slowakisch", - "sl": "Slowenisch", - "sq": "Albanisch", - "sv_SE": "Schwedisch", - "tr": "Türkisch", - "uk": "Ukrainisch", - "zh_CN": "Chinesisch (vereinfacht)", - "zh_TW": "Chinesisch (traditionell)" - } - }, - { - "wikiDataID": "Q13286", - "languageCode": "dsb", - "IETFcode": "dsb", - "currencies": { - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "PLN": "zł", - "THB": "฿", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bulgaršćina", - "co": "korsišćina", - "cs": "češćina", - "cy": "walizišćina", - "da": "danšćina", - "de": "nimšćina", - "dsb": "dolnoserbšćina", - "el": "grichišćina", - "en": "engelšćina", - "en_CA": "kanadiska engelšćina", - "en_GB": "britiska engelšćina", - "es_ES": "špańšćina", - "es_MX": "mexikańska špańšćina", - "fa": "persišćina", - "fi": "finšćina", - "fr": "francojšćina", - "fy_NL": "frizišćina", - "hsb": "górnoserbšćina", - "hu": "hungoršćina", - "ia": "interlingua", - "id": "indonešćina", - "is": "islandšćina", - "it": "italšćina", - "ja": "japańšćina", - "lo": "laošćina", - "nl": "nižozemšćina", - "pa_IN": "pandžabšćina", - "pl": "pólšćina", - "pt_BR": "portugalšćina", - "pt_PT": "europejska portugalšćina", - "ru": "rušćina", - "sk": "słowakšćina", - "sl": "słowjeńšćina", - "sq": "albanšćina", - "sv_SE": "šwedšćina", - "tr": "turkojšćina", - "uk": "ukrainšćina", - "zh_CN": "chinšćina (zjadnorjona)", - "zh_TW": "chinšćina (tradicionalna)" - } - }, - { - "wikiDataID": "Q9129", - "languageCode": "el", - "IETFcode": "el", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "GRD": "Δρχ", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Βουλγαρικά", - "co": "Κορσικανικά", - "cs": "Τσεχικά", - "cy": "Ουαλικά", - "da": "Δανικά", - "de": "Γερμανικά", - "dsb": "Κάτω Σορβικά", - "el": "Ελληνικά", - "en": "Αγγλικά", - "en_CA": "Αγγλικά Καναδά", - "en_GB": "Αγγλικά Βρετανίας", - "es_ES": "Ισπανικά", - "es_MX": "Ισπανικά Μεξικού", - "fa": "Περσικά", - "fi": "Φινλανδικά", - "fr": "Γαλλικά", - "fy_NL": "Δυτικά Φριζικά", - "hsb": "Άνω Σορβικά", - "hu": "Ουγγρικά", - "ia": "Ιντερλίνγκουα", - "id": "Ινδονησιακά", - "is": "Ισλανδικά", - "it": "Ιταλικά", - "ja": "Ιαπωνικά", - "lo": "Λαοτινά", - "nl": "Ολλανδικά", - "pa_IN": "Παντζαπικά", - "pl": "Πολωνικά", - "pt_BR": "Πορτογαλικά", - "pt_PT": "Πορτογαλικά Ευρώπης", - "ru": "Ρωσικά", - "sk": "Σλοβακικά", - "sl": "Σλοβενικά", - "sq": "Αλβανικά", - "sv_SE": "Σουηδικά", - "tr": "Τουρκικά", - "uk": "Ουκρανικά", - "zh_CN": "Απλοποιημένα Κινεζικά", - "zh_TW": "Παραδοσιακά Κινεζικά" - } - }, - { - "wikiDataID": "Q1860", - "languageCode": "en", - "IETFcode": "en", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Bulgarian", - "co": "Corsican", - "cs": "Czech", - "cy": "Welsh", - "da": "Danish", - "de": "German", - "dsb": "Lower Sorbian", - "el": "Greek", - "en": "English", - "en_CA": "Canadian English", - "en_GB": "British English", - "es_ES": "Spanish", - "es_MX": "Mexican Spanish", - "fa": "Persian", - "fi": "Finnish", - "fr": "French", - "fy_NL": "Western Frisian", - "hsb": "Upper Sorbian", - "hu": "Hungarian", - "ia": "Interlingua", - "id": "Indonesian", - "is": "Icelandic", - "it": "Italian", - "ja": "Japanese", - "lo": "Lao", - "nl": "Dutch", - "pa_IN": "Punjabi", - "pl": "Polish", - "pt_BR": "Portuguese", - "pt_PT": "European Portuguese", - "ru": "Russian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sv_SE": "Swedish", - "tr": "Turkish", - "uk": "Ukrainian", - "zh_CN": "Simplified Chinese", - "zh_TW": "Traditional Chinese" - } - }, - { - "wikiDataID": "Q44676", - "languageCode": "en_CA", - "IETFcode": "en-CA", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Bulgarian", - "co": "Corsican", - "cs": "Czech", - "cy": "Welsh", - "da": "Danish", - "de": "German", - "dsb": "Lower Sorbian", - "el": "Greek", - "en": "English", - "en_CA": "Canadian English", - "en_GB": "British English", - "es_ES": "Spanish", - "es_MX": "Mexican Spanish", - "fa": "Persian", - "fi": "Finnish", - "fr": "French", - "fy_NL": "Western Frisian", - "hsb": "Upper Sorbian", - "hu": "Hungarian", - "ia": "Interlingua", - "id": "Indonesian", - "is": "Icelandic", - "it": "Italian", - "ja": "Japanese", - "lo": "Lao", - "nl": "Dutch", - "pa_IN": "Punjabi", - "pl": "Polish", - "pt_BR": "Portuguese", - "pt_PT": "European Portuguese", - "ru": "Russian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sv_SE": "Swedish", - "tr": "Turkish", - "uk": "Ukrainian", - "zh_CN": "simplified Chinese", - "zh_TW": "traditional Chinese" - } - }, - { - "wikiDataID": "Q7979", - "languageCode": "en_GB", - "IETFcode": "en-GB", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Bulgarian", - "co": "Corsican", - "cs": "Czech", - "cy": "Welsh", - "da": "Danish", - "de": "German", - "dsb": "Lower Sorbian", - "el": "Greek", - "en": "English", - "en_CA": "Canadian English", - "en_GB": "British English", - "es_ES": "Spanish", - "es_MX": "Mexican Spanish", - "fa": "Persian", - "fi": "Finnish", - "fr": "French", - "fy_NL": "Western Frisian", - "hsb": "Upper Sorbian", - "hu": "Hungarian", - "ia": "Interlingua", - "id": "Indonesian", - "is": "Icelandic", - "it": "Italian", - "ja": "Japanese", - "lo": "Lao", - "nl": "Dutch", - "pa_IN": "Punjabi", - "pl": "Polish", - "pt_BR": "Portuguese", - "pt_PT": "European Portuguese", - "ru": "Russian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sv_SE": "Swedish", - "tr": "Turkish", - "uk": "Ukrainian", - "zh_CN": "Simplified Chinese", - "zh_TW": "Traditional Chinese" - } - }, - { - "wikiDataID": "Q85146618", - "languageCode": "es_AR", - "IETFcode": "es-AR", - "currencies": { - "ARS": "$", - "ESP": "₧", - "USD": "US$", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "búlgaro", - "co": "corso", - "cs": "checo", - "cy": "galés", - "da": "danés", - "de": "alemán", - "dsb": "bajo sorbio", - "el": "griego", - "en": "inglés", - "en_CA": "inglés canadiense", - "en_GB": "inglés británico", - "es_ES": "español", - "es_MX": "español de México", - "fa": "persa", - "fi": "finés", - "fr": "francés", - "fy_NL": "frisón occidental", - "hsb": "alto sorbio", - "hu": "húngaro", - "ia": "interlingua", - "id": "indonesio", - "is": "islandés", - "it": "italiano", - "ja": "japonés", - "lo": "lao", - "nl": "neerlandés", - "pa_IN": "punyabí", - "pl": "polaco", - "pt_BR": "portugués", - "pt_PT": "portugués de Portugal", - "ru": "ruso", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanés", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chino simplificado", - "zh_TW": "chino tradicional" - } - }, - { - "wikiDataID": "Q857295", - "languageCode": "es_CL", - "alternativeWikiDataID": "Q1321", - "currencies": { - "CLP": "$", - "ESP": "₧", - "USD": "US$", - "XPF": "CFPF", - "XXX": "¤" - }, - "IETFcode": "es-CL", - "languages": { - "bg": "búlgaro", - "co": "corso", - "cs": "checo", - "cy": "galés", - "da": "danés", - "de": "alemán", - "dsb": "bajo sorbio", - "el": "griego", - "en": "inglés", - "en_CA": "inglés canadiense", - "en_GB": "inglés británico", - "es_ES": "español", - "es_MX": "español de México", - "fa": "persa", - "fi": "finés", - "fr": "francés", - "fy_NL": "frisón occidental", - "hsb": "alto sorbio", - "hu": "húngaro", - "ia": "interlingua", - "id": "indonesio", - "is": "islandés", - "it": "italiano", - "ja": "japonés", - "lo": "lao", - "nl": "neerlandés", - "pa_IN": "punyabí", - "pl": "polaco", - "pt_BR": "portugués", - "pt_PT": "portugués de Portugal", - "ru": "ruso", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanés", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chino simplificado", - "zh_TW": "chino tradicional" - } - }, - { - "wikiDataID": "Q7162990", - "languageCode": "es_ES", - "IETFcode": "es", - "currencies": { - "ESP": "₧", - "EUR": "€", - "THB": "฿", - "USD": "US$", - "VND": "₫", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "búlgaro", - "co": "corso", - "cs": "checo", - "cy": "galés", - "da": "danés", - "de": "alemán", - "dsb": "bajo sorbio", - "el": "griego", - "en": "inglés", - "en_CA": "inglés canadiense", - "en_GB": "inglés británico", - "es_ES": "español", - "es_MX": "español de México", - "fa": "persa", - "fi": "finés", - "fr": "francés", - "fy_NL": "frisón occidental", - "hsb": "alto sorbio", - "hu": "húngaro", - "ia": "interlingua", - "id": "indonesio", - "is": "islandés", - "it": "italiano", - "ja": "japonés", - "lo": "lao", - "nl": "neerlandés", - "pa_IN": "punyabí", - "pl": "polaco", - "pt_BR": "portugués", - "pt_PT": "portugués de Portugal", - "ru": "ruso", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanés", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chino simplificado", - "zh_TW": "chino tradicional" - } - }, - { - "wikiDataID": "Q616620", - "languageCode": "es_MX", - "IETFcode": "es-MX", - "currencies": { - "ESP": "₧", - "MRO": "MRU", - "MRU": "UM", - "MXN": "$", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "búlgaro", - "co": "corso", - "cs": "checo", - "cy": "galés", - "da": "danés", - "de": "alemán", - "dsb": "bajo sorbio", - "el": "griego", - "en": "inglés", - "en_CA": "inglés canadiense", - "en_GB": "inglés británico", - "es_ES": "español", - "es_MX": "español de México", - "fa": "persa", - "fi": "finés", - "fr": "francés", - "fy_NL": "frisón occidental", - "hsb": "alto sorbio", - "hu": "húngaro", - "ia": "interlingua", - "id": "indonesio", - "is": "islandés", - "it": "italiano", - "ja": "japonés", - "lo": "lao", - "nl": "neerlandés", - "pa_IN": "punyabí", - "pl": "polaco", - "pt_BR": "portugués", - "pt_PT": "portugués de Portugal", - "ru": "ruso", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanés", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chino simplificado", - "zh_TW": "chino tradicional" - } - }, - { - "wikiDataID": "Q9168", - "languageCode": "fa", - "IETFcode": "fa", - "currencies": { - "AFN": "؋", - "AUD": "A$", - "BRL": "R$", - "CAD": "$CA", - "CNY": "¥CN", - "EUR": "€", - "GBP": "£", - "HKD": "$HK", - "ILS": "₪", - "INR": "₹", - "IRR": "ریال", - "JPY": "¥", - "KRW": "₩", - "MXN": "$MX", - "NZD": "$NZ", - "THB": "฿", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "$EC", - "XOF": "فرانک CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "بلغاری", - "co": "کورسی", - "cs": "چکی", - "cy": "ولزی", - "da": "دانمارکی", - "de": "آلمانی", - "dsb": "صُربی سفلی", - "el": "یونانی", - "en": "انگلیسی", - "en_CA": "انگلیسی کانادا", - "en_GB": "انگلیسی بریتانیا", - "es_ES": "اسپانیایی", - "es_MX": "اسپانیایی مکزیک", - "fa": "فارسی", - "fi": "فنلاندی", - "fr": "فرانسوی", - "fy_NL": "فریسی غربی", - "hsb": "صُربی علیا", - "hu": "مجاری", - "ia": "اینترلینگوا", - "id": "اندونزیایی", - "is": "ایسلندی", - "it": "ایتالیایی", - "ja": "ژاپنی", - "lo": "لائوسی", - "nl": "هلندی", - "pa_IN": "پنجابی", - "pl": "لهستانی", - "pt_BR": "پرتغالی", - "pt_PT": "پرتغالی اروپا", - "ru": "روسی", - "sk": "اسلواکی", - "sl": "اسلوونیایی", - "sq": "آلبانیایی", - "sv_SE": "سوئدی", - "tr": "ترکی استانبولی", - "uk": "اوکراینی", - "zh_CN": "چینی ساده‌شده", - "zh_TW": "چینی سنتی" - } - }, - { - "wikiDataID": "Q1412", - "languageCode": "fi", - "IETFcode": "fi", - "currencies": { - "EUR": "€", - "FIM": "mk", - "GBP": "£", - "JPY": "¥", - "USD": "$", - "XAF": "FCFA", - "XOF": "F CFA" - }, - "languages": { - "bg": "bulgaria", - "co": "korsika", - "cs": "tšekki", - "cy": "kymri", - "da": "tanska", - "de": "saksa", - "dsb": "alasorbi", - "el": "kreikka", - "en": "englanti", - "en_CA": "kanadanenglanti", - "en_GB": "britannianenglanti", - "es_ES": "espanja", - "es_MX": "meksikonespanja", - "fa": "persia", - "fi": "suomi", - "fr": "ranska", - "fy_NL": "länsifriisi", - "hsb": "yläsorbi", - "hu": "unkari", - "ia": "interlingua", - "id": "indonesia", - "is": "islanti", - "it": "italia", - "ja": "japani", - "lo": "lao", - "nl": "hollanti", - "pa_IN": "pandžabi", - "pl": "puola", - "pt_BR": "portugali", - "pt_PT": "euroopanportugali", - "ru": "venäjä", - "sk": "slovakki", - "sl": "sloveeni", - "sq": "albania", - "sv_SE": "ruotsi", - "tr": "turkki", - "uk": "ukraina", - "zh_CN": "kiina (yksinkertaistettu)", - "zh_TW": "kiina (perinteinen)" - } - }, - { - "wikiDataID": "Q150", - "languageCode": "fr", - "IETFcode": "fr", - "currencies": { - "ARS": "$AR", - "AUD": "$AU", - "BEF": "FB", - "BMD": "$BM", - "BND": "$BN", - "BRL": "R$", - "BZD": "$BZ", - "CAD": "$CA", - "CLP": "$CL", - "COP": "$CO", - "CYP": "£CY", - "EUR": "€", - "FJD": "$FJ", - "FKP": "£FK", - "FRF": "F", - "GBP": "£GB", - "GIP": "£GI", - "IEP": "£IE", - "ILP": "£IL", - "ILS": "₪", - "INR": "₹", - "ITL": "₤IT", - "KRW": "₩", - "LBP": "£LB", - "MTP": "£MT", - "MXN": "$MX", - "NAD": "$NA", - "NZD": "$NZ", - "RHD": "$RH", - "SBD": "$SB", - "SGD": "$SG", - "SRD": "$SR", - "TTD": "$TT", - "USD": "$US", - "UYU": "$UY", - "VND": "₫", - "WST": "$WS", - "XAF": "FCFA", - "XOF": "F CFA", - "XPF": "FCFP", - "XXX": "¤" - }, - "languages": { - "bg": "bulgare", - "co": "corse", - "cs": "tchèque", - "cy": "gallois", - "da": "danois", - "de": "allemand", - "dsb": "bas-sorabe", - "el": "grec", - "en": "anglais", - "en_CA": "anglais canadien", - "en_GB": "anglais britannique", - "es_ES": "espagnol", - "es_MX": "espagnol du Mexique", - "fa": "persan", - "fi": "finnois", - "fr": "français", - "fy_NL": "frison occidental", - "hsb": "haut-sorabe", - "hu": "hongrois", - "ia": "interlingua", - "id": "indonésien", - "is": "islandais", - "it": "italien", - "ja": "japonais", - "lo": "lao", - "nl": "néerlandais", - "pa_IN": "pendjabi", - "pl": "polonais", - "pt_BR": "portugais", - "pt_PT": "portugais européen", - "ru": "russe", - "sk": "slovaque", - "sl": "slovène", - "sq": "albanais", - "sv_SE": "suédois", - "tr": "turc", - "uk": "ukrainien", - "zh_CN": "chinois simplifié", - "zh_TW": "chinois traditionnel" - } - }, - { - "wikiDataID": "Q27175", - "languageCode": "fy_NL", - "alternativeWikiDataID": "Q27175", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "C$", - "CNY": "CN¥", - "EUR": "€", - "FJD": "FJ$", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "SBD": "SI$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XXX": "¤" - }, - "languages": { - "bg": "Bulgaarsk", - "co": "Korsikaansk", - "cs": "Tsjechysk", - "cy": "Welsk", - "da": "Deensk", - "de": "Dútsk", - "dsb": "Nedersorbysk", - "el": "Gryks", - "en": "Ingelsk", - "en_CA": "Kanadeesk Ingelsk", - "en_GB": "Britsk Ingelsk", - "es_ES": "Spaansk", - "es_MX": "Meksikaansk Spaansk", - "fa": "Perzysk", - "fi": "Finsk", - "fr": "Frânsk", - "fy_NL": "Frysk", - "hsb": "Oppersorbysk", - "hu": "Hongaarsk", - "ia": "Interlingua", - "id": "Yndonezysk", - "is": "Yslâns", - "it": "Italiaansk", - "ja": "Japans", - "lo": "Laotiaansk", - "nl": "Nederlânsk", - "pa_IN": "Punjabi", - "pl": "Poalsk", - "pt_BR": "Portugeesk", - "pt_PT": "Europees Portugees", - "ru": "Russysk", - "sk": "Slowaaks", - "sl": "Sloveensk", - "sq": "Albaneesk", - "sv_SE": "Zweeds", - "tr": "Turks", - "uk": "Oekraïens", - "zh_CN": "Ferienfâldich Sineesk", - "zh_TW": "Tradisjoneel Sineesk" - }, - "IETFcode": "fy" - }, - { - "wikiDataID": "Q13248", - "languageCode": "hsb", - "IETFcode": "hsb", - "currencies": { - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PHP": "₱", - "PLN": "zł", - "THB": "฿", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bołharšćina", - "co": "korsišćina", - "cs": "čěšćina", - "cy": "walizišćina", - "da": "danšćina", - "de": "němčina", - "dsb": "delnjoserbšćina", - "el": "grjekšćina", - "en": "jendźelšćina", - "en_CA": "kanadiska jendźelšćina", - "en_GB": "britiska jendźelšćina", - "es_ES": "španišćina", - "es_MX": "mexiska španišćina", - "fa": "persišćina", - "fi": "finšćina", - "fr": "francošćina", - "fy_NL": "frizišćina", - "hsb": "hornjoserbšćina", - "hu": "madźaršćina", - "ia": "interlingua", - "id": "indonešćina", - "is": "islandšćina", - "it": "italšćina", - "ja": "japanšćina", - "lo": "laošćina", - "nl": "nižozemšćina", - "pa_IN": "pandźabšćina", - "pl": "pólšćina", - "pt_BR": "portugalšćina", - "pt_PT": "europska portugalšćina", - "ru": "rušćina", - "sk": "słowakšćina", - "sl": "słowjenšćina", - "sq": "albanšćina", - "sv_SE": "šwedšćina", - "tr": "turkowšćina", - "uk": "ukrainšćina", - "zh_CN": "chinšćina (zjednorjena)", - "zh_TW": "chinšćina (tradicionalna)" - } - }, - { - "wikiDataID": "Q9067", - "languageCode": "hu", - "IETFcode": "hu", - "currencies": { - "HUF": "Ft", - "JPY": "¥", - "XAF": "FCFA", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bolgár", - "co": "korzikai", - "cs": "cseh", - "cy": "walesi", - "da": "dán", - "de": "német", - "dsb": "alsó-szorb", - "el": "görög", - "en": "angol", - "en_CA": "kanadai angol", - "en_GB": "brit angol", - "es_ES": "spanyol", - "es_MX": "spanyol (mexikói)", - "fa": "perzsa", - "fi": "finn", - "fr": "francia", - "fy_NL": "nyugati fríz", - "hsb": "felső-szorb", - "hu": "magyar", - "ia": "interlingva", - "id": "indonéz", - "is": "izlandi", - "it": "olasz", - "ja": "japán", - "lo": "lao", - "nl": "holland", - "pa_IN": "pandzsábi", - "pl": "lengyel", - "pt_BR": "portugál", - "pt_PT": "európai portugál", - "ru": "orosz", - "sk": "szlovák", - "sl": "szlovén", - "sq": "albán", - "sv_SE": "svéd", - "tr": "török", - "uk": "ukrán", - "zh_CN": "egyszerűsített kínai", - "zh_TW": "hagyományos kínai" - } - }, - { - "wikiDataID": "Q35934", - "languageCode": "ia", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NLG": "ƒ", - "NZD": "NZ$", - "PHP": "₱", - "RUB": "₽", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bulgaro", - "co": "corso", - "cs": "checo", - "cy": "gallese", - "da": "danese", - "de": "germano", - "dsb": "basse sorabo", - "el": "greco", - "en": "anglese", - "en_CA": "anglese canadian", - "en_GB": "anglese britannic", - "es_ES": "espaniol", - "es_MX": "espaniol mexican", - "fa": "persa", - "fi": "finnese", - "fr": "francese", - "fy_NL": "frison occidental", - "hsb": "alte sorabo", - "hu": "hungaro", - "ia": "interlingua", - "id": "indonesiano", - "is": "islandese", - "it": "italiano", - "ja": "japonese", - "lo": "laotiano", - "nl": "nederlandese", - "pa_IN": "punjabi", - "pl": "polonese", - "pt_BR": "portugese", - "pt_PT": "portugese de Portugal", - "ru": "russo", - "sk": "slovaco", - "sl": "sloveno", - "sq": "albanese", - "sv_SE": "svedese", - "tr": "turco", - "uk": "ukrainiano", - "zh_CN": "chinese simplificate", - "zh_TW": "chinese traditional" - }, - "IETFcode": "ia" - }, - { - "wikiDataID": "Q9240", - "languageCode": "id", - "IETFcode": "id", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "IDR": "Rp", - "ILS": "₪", - "INR": "Rs", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "Bulgaria", - "co": "Korsika", - "cs": "Cheska", - "cy": "Welsh", - "da": "Dansk", - "de": "Jerman", - "dsb": "Sorbia Hilir", - "el": "Yunani", - "en": "Inggris", - "en_CA": "Inggris (Kanada)", - "en_GB": "Inggris (Britania)", - "es_ES": "Spanyol", - "es_MX": "Spanyol (Meksiko)", - "fa": "Persia", - "fi": "Suomi", - "fr": "Prancis", - "fy_NL": "Frisia Barat", - "hsb": "Sorbia Hulu", - "hu": "Hungaria", - "ia": "Interlingua", - "id": "Indonesia", - "is": "Islandia", - "it": "Italia", - "ja": "Jepang", - "lo": "Lao", - "nl": "Belanda", - "pa_IN": "Punjabi", - "pl": "Polski", - "pt_BR": "Portugis", - "pt_PT": "Portugis (Eropa)", - "ru": "Rusia", - "sk": "Slovak", - "sl": "Sloven", - "sq": "Albania", - "sv_SE": "Swedia", - "tr": "Turki", - "uk": "Ukraina", - "zh_CN": "Tionghoa (Sederhana)", - "zh_TW": "Tionghoa (Tradisional)" - } - }, - { - "wikiDataID": "Q294", - "languageCode": "is", - "IETFcode": "is", - "currencies": { - "CNY": "CN¥", - "HKD": "HK$", - "ILS": "₪", - "ISK": "kr.", - "JPY": "JP¥", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "búlgarska", - "co": "korsíska", - "cs": "tékkneska", - "cy": "velska", - "da": "danska", - "de": "þýska", - "dsb": "lágsorbneska", - "el": "gríska", - "en": "enska", - "en_CA": "kanadísk enska", - "en_GB": "bresk enska", - "es_ES": "spænska", - "es_MX": "mexíkósk spænska", - "fa": "persneska", - "fi": "finnska", - "fr": "franska", - "fy_NL": "vesturfrísneska", - "hsb": "hásorbneska", - "hu": "ungverska", - "ia": "interlingua", - "id": "indónesíska", - "is": "íslenska", - "it": "ítalska", - "ja": "japanska", - "lo": "laó", - "nl": "hollenska", - "pa_IN": "púnjabí", - "pl": "pólska", - "pt_BR": "portúgalska", - "pt_PT": "evrópsk portúgalska", - "ru": "rússneska", - "sk": "slóvakíska", - "sl": "slóvenska", - "sq": "albanska", - "sv_SE": "sænska", - "tr": "tyrkneska", - "uk": "úkraínska", - "zh_CN": "kínverska (einfölduð)", - "zh_TW": "kínverska (hefðbundin)" - } - }, - { - "wikiDataID": "Q652", - "languageCode": "it", - "IETFcode": "it", - "currencies": { - "AUD": "A$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "ILS": "₪", - "NZD": "NZ$", - "PHP": "₱", - "THB": "฿", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bulgaro", - "co": "corso", - "cs": "ceco", - "cy": "gallese", - "da": "danese", - "de": "tedesco", - "dsb": "basso sorabo", - "el": "greco", - "en": "inglese", - "en_CA": "inglese canadese", - "en_GB": "inglese britannico", - "es_ES": "spagnolo", - "es_MX": "spagnolo messicano", - "fa": "persiano", - "fi": "finlandese", - "fr": "francese", - "fy_NL": "frisone occidentale", - "hsb": "alto sorabo", - "hu": "ungherese", - "ia": "interlingua", - "id": "indonesiano", - "is": "islandese", - "it": "italiano", - "ja": "giapponese", - "lo": "lao", - "nl": "olandese", - "pa_IN": "punjabi", - "pl": "polacco", - "pt_BR": "portoghese", - "pt_PT": "portoghese europeo", - "ru": "russo", - "sk": "slovacco", - "sl": "sloveno", - "sq": "albanese", - "sv_SE": "svedese", - "tr": "turco", - "uk": "ucraino", - "zh_CN": "cinese semplificato", - "zh_TW": "cinese tradizionale" - } - }, - { - "wikiDataID": "Q5287", - "languageCode": "ja", - "IETFcode": "ja", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "元", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "ブルガリア語", - "co": "コルシカ語", - "cs": "チェコ語", - "cy": "ウェールズ語", - "da": "デンマーク語", - "de": "ドイツ語", - "dsb": "低地ソルブ語", - "el": "ギリシャ語", - "en": "英語", - "en_CA": "カナダ英語", - "en_GB": "イギリス英語", - "es_ES": "スペイン語", - "es_MX": "スペイン語 (メキシコ)", - "fa": "ペルシア語", - "fi": "フィンランド語", - "fr": "フランス語", - "fy_NL": "西フリジア語", - "hsb": "高地ソルブ語", - "hu": "ハンガリー語", - "ia": "インターリングア", - "id": "インドネシア語", - "is": "アイスランド語", - "it": "イタリア語", - "ja": "日本語", - "lo": "ラオ語", - "nl": "オランダ語", - "pa_IN": "パンジャブ語", - "pl": "ポーランド語", - "pt_BR": "ポルトガル語", - "pt_PT": "ポルトガル語 (イベリア半島)", - "ru": "ロシア語", - "sk": "スロバキア語", - "sl": "スロベニア語", - "sq": "アルバニア語", - "sv_SE": "スウェーデン語", - "tr": "トルコ語", - "uk": "ウクライナ語", - "zh_CN": "簡体中国語", - "zh_TW": "繁体中国語" - } - }, - { - "wikiDataID": "Q9211", - "languageCode": "lo", - "IETFcode": "lo", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "LAK": "₭", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "ບັງກາຣຽນ", - "co": "ຄໍຊິກາ", - "cs": "ເຊກ", - "cy": "ເວວ", - "da": "ແດນິຊ", - "de": "ເຢຍລະມັນ", - "dsb": "ຊໍບຽນຕໍ່ກວ່າ", - "el": "ກຣີກ", - "en": "ອັງກິດ", - "en_GB": "ອັງກິດ (ບຣິດທິຊ)", - "es_ES": "ສະແປນນິຊ", - "es_MX": "ເມັກຊິກັນ ສະແປນນິຊ", - "fa": "ເປີຊຽນ", - "fi": "ຟິນນິຊ", - "fr": "ຝຣັ່ງ", - "fy_NL": "ຟຣິຊຽນ ຕາເວັນຕົກ", - "hsb": "ຊໍບຽນ ທາງຕອນເໜືອ", - "hu": "ຮັງກາຣຽນ", - "ia": "ອິນເຕີລິງລົວ", - "id": "ອິນໂດເນຊຽນ", - "is": "ໄອສແລນດິກ", - "it": "ອິຕາລຽນ", - "ja": "ຍີ່ປຸ່ນ", - "lo": "ລາວ", - "nl": "ດັຊ", - "pa_IN": "ປັນຈາບີ", - "pl": "ໂປລິຊ", - "pt_BR": "ປອກຕຸຍກິສ", - "pt_PT": "ປອກຕຸຍກິສ ຢຸໂຣບ", - "ru": "ລັດເຊຍ", - "sk": "ສະໂລແວັກ", - "sl": "ສະໂລເວນຽນ", - "sq": "ອານບານຽນ", - "sv_SE": "ສະວີດິຊ", - "tr": "ເທີຄິຊ", - "uk": "ຢູເຄຣນຽນ", - "zh_CN": "ຈີນແບບຮຽບງ່າຍ", - "zh_TW": "ຈີນແບບດັ້ງເດີມ" - } - }, - { - "wikiDataID": "Q7411", - "languageCode": "nl", - "IETFcode": "nl", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "C$", - "CNY": "CN¥", - "EUR": "€", - "FJD": "FJ$", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "SBD": "SI$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA" - }, - "languages": { - "bg": "Bulgaars", - "co": "Corsicaans", - "cs": "Tsjechisch", - "cy": "Welsh", - "da": "Deens", - "de": "Duits", - "dsb": "Nedersorbisch", - "el": "Grieks", - "en": "Engels", - "en_CA": "Engels (Canada)", - "en_GB": "Engels (Verenigd Koninkrijk)", - "es_ES": "Spaans", - "es_MX": "Spaans (Mexico)", - "fa": "Perzisch", - "fi": "Fins", - "fr": "Frans", - "fy_NL": "Fries", - "hsb": "Oppersorbisch", - "hu": "Hongaars", - "ia": "Interlingua", - "id": "Indonesisch", - "is": "IJslands", - "it": "Italiaans", - "ja": "Japans", - "lo": "Laotiaans", - "nl": "Nederlands", - "pa_IN": "Punjabi", - "pl": "Pools", - "pt_BR": "Portugees", - "pt_PT": "Portugees (Portugal)", - "ru": "Russisch", - "sk": "Slowaaks", - "sl": "Sloveens", - "sq": "Albanees", - "sv_SE": "Zweeds", - "tr": "Turks", - "uk": "Oekraïens", - "zh_CN": "Chinees (vereenvoudigd)", - "zh_TW": "Chinees (traditioneel)" - } - }, - { - "wikiDataID": "Q14185", - "languageCode": "oc", - "currencies": {}, - "languages": { - "bg": "Bulgar", - "co": "Còrs", - "cs": "Chèc", - "cy": "Galés", - "da": "Danés", - "de": "Alemand", - "dsb": "Bas sorab", - "el": "Grèc", - "en": "Anglés", - "es_CL": "Espanhòu", - "fa": "Persan", - "fi": "Finés", - "fr": "Francés", - "fy_NL": "Frison occidental", - "hsb": "Aut sorab", - "hu": "Ongrés", - "ia": "Interlingua", - "id": "Bahasa Indonesia", - "is": "Islandés", - "it": "Italian", - "ja": "Japonés", - "nl": "Neerlandés", - "oc": "Occitan", - "pa_IN": "Pendjabi", - "pl": "Polonés", - "ru": "Rus", - "sk": "Eslovac", - "sl": "Eslovèn", - "sq": "Albanés", - "sv_SE": "Suedés", - "tr": "Turc", - "uk": "Ucraïnian" - } - }, - { - "wikiDataID": "Q58635", - "languageCode": "pa_IN", - "IETFcode": "pa", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "ਬੁਲਗਾਰੀਆਈ", - "co": "ਕੋਰਸੀਕਨ", - "cs": "ਚੈੱਕ", - "cy": "ਵੈਲਸ਼", - "da": "ਡੈਨਿਸ਼", - "de": "ਜਰਮਨ", - "dsb": "ਲੋਅਰ ਸੋਰਬੀਅਨ", - "el": "ਯੂਨਾਨੀ", - "en": "ਅੰਗਰੇਜ਼ੀ", - "en_CA": "ਅੰਗਰੇਜ਼ੀ (ਕੈਨੇਡਾ)", - "en_GB": "ਅੰਗਰੇਜ਼ੀ (ਬਰਤਾਨਵੀ)", - "es_ES": "ਸਪੇਨੀ", - "es_MX": "ਸਪੇਨੀ (ਮੈਕਸੀਕੋ)", - "fa": "ਫ਼ਾਰਸੀ", - "fi": "ਫਿਨਿਸ਼", - "fr": "ਫਰਾਂਸੀਸੀ", - "fy_NL": "ਪੱਛਮੀ ਫ੍ਰਿਸੀਅਨ", - "hsb": "ਅੱਪਰ ਸੋਰਬੀਅਨ", - "hu": "ਹੰਗਰੀਆਈ", - "ia": "ਇੰਟਰਲਿੰਗੁਆ", - "id": "ਇੰਡੋਨੇਸ਼ੀਆਈ", - "is": "ਆਈਸਲੈਂਡਿਕ", - "it": "ਇਤਾਲਵੀ", - "ja": "ਜਪਾਨੀ", - "lo": "ਲਾਓ", - "nl": "ਡੱਚ", - "pa_IN": "ਪੰਜਾਬੀ", - "pl": "ਪੋਲੈਂਡੀ", - "pt_BR": "ਪੁਰਤਗਾਲੀ", - "pt_PT": "ਪੁਰਤਗਾਲੀ (ਯੂਰਪੀ)", - "ru": "ਰੂਸੀ", - "sk": "ਸਲੋਵਾਕ", - "sl": "ਸਲੋਵੇਨੀਆਈ", - "sq": "ਅਲਬਾਨੀਆਈ", - "sv_SE": "ਸਵੀਡਿਸ਼", - "tr": "ਤੁਰਕੀ", - "uk": "ਯੂਕਰੇਨੀਆਈ", - "zh_CN": "ਚੀਨੀ (ਸਰਲ)", - "zh_TW": "ਚੀਨੀ (ਰਵਾਇਤੀ)" - } - }, - { - "wikiDataID": "Q809", - "languageCode": "pl", - "currencies": { - "BRL": "R$", - "EUR": "€", - "PLN": "zł", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bułgarski", - "co": "korsykański", - "cs": "czeski", - "cy": "walijski", - "da": "duński", - "de": "niemiecki", - "dsb": "dolnołużycki", - "el": "grecki", - "en": "angielski", - "en_CA": "angielski kanadyjski", - "en_GB": "angielski brytyjski", - "es_ES": "hiszpański", - "es_MX": "meksykański hiszpański", - "fa": "perski", - "fi": "fiński", - "fr": "francuski", - "fy_NL": "zachodniofryzyjski", - "hsb": "górnołużycki", - "hu": "węgierski", - "ia": "interlingua", - "id": "indonezyjski", - "is": "islandzki", - "it": "włoski", - "ja": "japoński", - "lo": "laotański", - "nl": "niderlandzki", - "pa_IN": "pendżabski", - "pl": "polski", - "pt_BR": "portugalski", - "pt_PT": "europejski portugalski", - "ru": "rosyjski", - "sk": "słowacki", - "sl": "słoweński", - "sq": "albański", - "sv_SE": "szwedzki", - "tr": "turecki", - "uk": "ukraiński", - "zh_CN": "chiński uproszczony", - "zh_TW": "chiński tradycyjny" - }, - "IETFcode": "pl" - }, - { - "wikiDataID": "Q750553", - "languageCode": "pt_BR", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PTE": "Esc.", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "IETFcode": "pt", - "languages": { - "bg": "búlgaro", - "co": "corso", - "cs": "tcheco", - "cy": "galês", - "da": "dinamarquês", - "de": "alemão", - "dsb": "baixo sorábio", - "el": "grego", - "en": "inglês", - "en_CA": "inglês (Canadá)", - "en_GB": "inglês (Reino Unido)", - "es_ES": "espanhol", - "es_MX": "espanhol (México)", - "fa": "persa", - "fi": "finlandês", - "fr": "francês", - "fy_NL": "frísio ocidental", - "hsb": "alto sorábio", - "hu": "húngaro", - "ia": "interlíngua", - "id": "indonésio", - "is": "islandês", - "it": "italiano", - "ja": "japonês", - "lo": "laosiano", - "nl": "holandês", - "pa_IN": "panjabi", - "pl": "polonês", - "pt_BR": "português", - "pt_PT": "português (Portugal)", - "ru": "russo", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanês", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chinês simplificado", - "zh_TW": "chinês tradicional" - } - }, - { - "wikiDataID": "Q922399", - "languageCode": "pt_PT", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "PTE": "​", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "IETFcode": "pt-PT", - "languages": { - "bg": "búlgaro", - "co": "córsico", - "cs": "checo", - "cy": "galês", - "da": "dinamarquês", - "de": "alemão", - "dsb": "baixo sorábio", - "el": "grego", - "en": "inglês", - "en_CA": "inglês canadiano", - "en_GB": "inglês britânico", - "es_ES": "espanhol", - "es_MX": "espanhol mexicano", - "fa": "persa", - "fi": "finlandês", - "fr": "francês", - "fy_NL": "frísico ocidental", - "hsb": "alto sorábio", - "hu": "húngaro", - "ia": "interlíngua", - "id": "indonésio", - "is": "islandês", - "it": "italiano", - "ja": "japonês", - "lo": "laosiano", - "nl": "neerlandês", - "pa_IN": "panjabi", - "pl": "polaco", - "pt_BR": "português", - "pt_PT": "português europeu", - "ru": "russo", - "sk": "eslovaco", - "sl": "esloveno", - "sq": "albanês", - "sv_SE": "sueco", - "tr": "turco", - "uk": "ucraniano", - "zh_CN": "chinês simplificado", - "zh_TW": "chinês tradicional" - } - }, - { - "wikiDataID": "Q7737", - "languageCode": "ru", - "IETFcode": "ru", - "currencies": { - "AUD": "A$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "RUB": "₽", - "RUR": "р.", - "THB": "฿", - "TMT": "ТМТ", - "TWD": "NT$", - "UAH": "₴", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "XXXX" - }, - "languages": { - "bg": "болгарский", - "co": "корсиканский", - "cs": "чешский", - "cy": "валлийский", - "da": "датский", - "de": "немецкий", - "dsb": "нижнелужицкий", - "el": "греческий", - "en": "английский", - "en_CA": "канадский английский", - "en_GB": "британский английский", - "es_ES": "испанский", - "es_MX": "мексиканский испанский", - "fa": "персидский", - "fi": "финский", - "fr": "французский", - "fy_NL": "западнофризский", - "hsb": "верхнелужицкий", - "hu": "венгерский", - "ia": "интерлингва", - "id": "индонезийский", - "is": "исландский", - "it": "итальянский", - "ja": "японский", - "lo": "лаосский", - "nl": "нидерландский", - "pa_IN": "панджаби", - "pl": "польский", - "pt_BR": "португальский", - "pt_PT": "европейский португальский", - "ru": "русский", - "sk": "словацкий", - "sl": "словенский", - "sq": "албанский", - "sv_SE": "шведский", - "tr": "турецкий", - "uk": "украинский", - "zh_CN": "китайский, упрощенное письмо", - "zh_TW": "китайский, традиционное письмо" - } - }, - { - "wikiDataID": "Q9058", - "languageCode": "sk", - "IETFcode": "sk", - "currencies": { - "EUR": "€", - "ILS": "NIS", - "MXN": "MX$", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "bulharčina", - "co": "korzičtina", - "cs": "čeština", - "cy": "waleština", - "da": "dánčina", - "de": "nemčina", - "dsb": "dolnolužická srbčina", - "el": "gréčtina", - "en": "angličtina", - "en_CA": "angličtina (kanadská)", - "en_GB": "angličtina (britská)", - "es_ES": "španielčina", - "es_MX": "španielčina (mexická)", - "fa": "perzština", - "fi": "fínčina", - "fr": "francúzština", - "fy_NL": "západná frízština", - "hsb": "hornolužická srbčina", - "hu": "maďarčina", - "ia": "interlingua", - "id": "indonézština", - "is": "islandčina", - "it": "taliančina", - "ja": "japončina", - "lo": "laoština", - "nl": "holandčina", - "pa_IN": "pandžábčina", - "pl": "poľština", - "pt_BR": "portugalčina", - "pt_PT": "portugalčina (európska)", - "ru": "ruština", - "sk": "slovenčina", - "sl": "slovinčina", - "sq": "albánčina", - "sv_SE": "švédčina", - "tr": "turečtina", - "uk": "ukrajinčina", - "zh_CN": "čínština (zjednodušená)", - "zh_TW": "čínština (tradičná)" - } - }, - { - "wikiDataID": "Q9063", - "languageCode": "sl", - "IETFcode": "sl", - "currencies": { - "CNY": "CN¥", - "EUR": "€", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bolgarščina", - "co": "korziščina", - "cs": "češčina", - "cy": "valižanščina", - "da": "danščina", - "de": "nemščina", - "dsb": "dolnja lužiška srbščina", - "el": "grščina", - "en": "angleščina", - "en_CA": "kanadska angleščina", - "en_GB": "britanska angleščina", - "es_ES": "španščina", - "es_MX": "mehiška španščina", - "fa": "perzijščina", - "fi": "finščina", - "fr": "francoščina", - "fy_NL": "zahodna frizijščina", - "hsb": "gornja lužiška srbščina", - "hu": "madžarščina", - "ia": "interlingva", - "id": "indonezijščina", - "is": "islandščina", - "it": "italijanščina", - "ja": "japonščina", - "lo": "laoščina", - "nl": "nizozemščina", - "pa_IN": "pandžabščina", - "pl": "poljščina", - "pt_BR": "portugalščina", - "pt_PT": "evropska portugalščina", - "ru": "ruščina", - "sk": "slovaščina", - "sl": "slovenščina", - "sq": "albanščina", - "sv_SE": "švedščina", - "tr": "turščina", - "uk": "ukrajinščina", - "zh_CN": "poenostavljena kitajščina", - "zh_TW": "tradicionalna kitajščina" - }, - "alternativeWikiDataID": "Q9063" - }, - { - "wikiDataID": "Q8748", - "languageCode": "sq", - "IETFcode": "sq", - "currencies": { - "ALL": "Lekë", - "AUD": "A$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bullgarisht", - "co": "korsikisht", - "cs": "çekisht", - "cy": "uellsisht", - "da": "danisht", - "de": "gjermanisht", - "dsb": "sorbishte e poshtme", - "el": "greqisht", - "en": "anglisht", - "en_CA": "anglishte kanadeze", - "en_GB": "anglishte britanike", - "es_ES": "spanjisht", - "es_MX": "spanjishte meksikane", - "fa": "persisht", - "fi": "finlandisht", - "fr": "frëngjisht", - "fy_NL": "frizianishte perëndimore", - "hsb": "sorbishte e sipërme", - "hu": "hungarisht", - "ia": "interlingua", - "id": "indonezisht", - "is": "islandisht", - "it": "italisht", - "ja": "japonisht", - "lo": "laosisht", - "nl": "holandisht", - "pa_IN": "punxhabisht", - "pl": "polonisht", - "pt_BR": "portugalisht", - "pt_PT": "portugalishte evropiane", - "ru": "rusisht", - "sk": "sllovakisht", - "sl": "sllovenisht", - "sq": "shqip", - "sv_SE": "suedisht", - "tr": "turqisht", - "uk": "ukrainisht", - "zh_CN": "kinezishte e thjeshtuar", - "zh_TW": "kinezishte tradicionale" - } - }, - { - "wikiDataID": "Q9027", - "languageCode": "sv_SE", - "IETFcode": "sv", - "currencies": { - "BBD": "Bds$", - "BMD": "BM$", - "BRL": "BR$", - "BSD": "BS$", - "BZD": "BZ$", - "CAD": "CA$", - "DKK": "Dkr", - "DOP": "RD$", - "EEK": "Ekr", - "EGP": "EG£", - "EUR": "€", - "IEP": "IE£", - "ILS": "₪", - "ISK": "Ikr", - "JMD": "JM$", - "MXN": "MX$", - "NOK": "Nkr", - "SEK": "kr", - "USD": "US$", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "bulgariska", - "co": "korsikanska", - "cs": "tjeckiska", - "cy": "walesiska", - "da": "danska", - "de": "tyska", - "dsb": "lågsorbiska", - "el": "grekiska", - "en": "engelska", - "en_CA": "kanadensisk engelska", - "en_GB": "brittisk engelska", - "es_ES": "spanska", - "es_MX": "mexikansk spanska", - "fa": "persiska", - "fi": "finska", - "fr": "franska", - "fy_NL": "västfrisiska", - "hsb": "högsorbiska", - "hu": "ungerska", - "ia": "interlingua", - "id": "indonesiska", - "is": "isländska", - "it": "italienska", - "ja": "japanska", - "lo": "laotiska", - "nl": "nederländska", - "pa_IN": "punjabi", - "pl": "polska", - "pt_BR": "portugisiska", - "pt_PT": "europeisk portugisiska", - "ru": "ryska", - "sk": "slovakiska", - "sl": "slovenska", - "sq": "albanska", - "sv_SE": "svenska", - "tr": "turkiska", - "uk": "ukrainska", - "zh_CN": "förenklad kinesiska", - "zh_TW": "traditionell kinesiska" - } - }, - { - "wikiDataID": "Q256", - "languageCode": "tr", - "IETFcode": "tr", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "THB": "฿", - "TRY": "₺", - "TWD": "NT$", - "USD": "$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "Bulgarca", - "co": "Korsikaca", - "cs": "Çekçe", - "cy": "Galce", - "da": "Danca", - "de": "Almanca", - "dsb": "Aşağı Sorbça", - "el": "Yunanca", - "en": "İngilizce", - "en_CA": "Kanada İngilizcesi", - "en_GB": "İngiliz İngilizcesi", - "es_ES": "İspanyolca", - "es_MX": "Meksika İspanyolcası", - "fa": "Farsça", - "fi": "Fince", - "fr": "Fransızca", - "fy_NL": "Batı Frizcesi", - "hsb": "Yukarı Sorbça", - "hu": "Macarca", - "ia": "İnterlingua", - "id": "Endonezce", - "is": "İzlandaca", - "it": "İtalyanca", - "ja": "Japonca", - "lo": "Lao dili", - "nl": "Felemenkçe", - "pa_IN": "Pencapça", - "pl": "Lehçe", - "pt_BR": "Portekizce", - "pt_PT": "Avrupa Portekizcesi", - "ru": "Rusça", - "sk": "Slovakça", - "sl": "Slovence", - "sq": "Arnavutça", - "sv_SE": "İsveççe", - "tr": "Türkçe", - "uk": "Ukraynaca", - "zh_CN": "Basitleştirilmiş Çince", - "zh_TW": "Geleneksel Çince" - } - }, - { - "wikiDataID": "Q8798", - "languageCode": "uk", - "IETFcode": "uk", - "currencies": { - "JPY": "¥", - "UAH": "₴", - "UAK": "крб.", - "XAF": "FCFA", - "XOF": "F CFA", - "XPF": "CFPF", - "XXX": "¤" - }, - "languages": { - "bg": "болгарська", - "co": "корсиканська", - "cs": "чеська", - "cy": "валлійська", - "da": "данська", - "de": "німецька", - "dsb": "нижньолужицька", - "el": "грецька", - "en": "англійська", - "en_CA": "англійська (Канада)", - "en_GB": "англійська (Велика Британія)", - "es_ES": "іспанська", - "es_MX": "мексиканська іспанська", - "fa": "перська", - "fi": "фінська", - "fr": "французька", - "fy_NL": "західнофризька", - "hsb": "верхньолужицька", - "hu": "угорська", - "ia": "інтерлінгва", - "id": "індонезійська", - "is": "ісландська", - "it": "італійська", - "ja": "японська", - "lo": "лаоська", - "nl": "нідерландська", - "pa_IN": "панджабі", - "pl": "польська", - "pt_BR": "португальська", - "pt_PT": "європейська португальська", - "ru": "російська", - "sk": "словацька", - "sl": "словенська", - "sq": "албанська", - "sv_SE": "шведська", - "tr": "турецька", - "uk": "українська", - "zh_CN": "китайська (спрощене письмо)", - "zh_TW": "китайська (традиційне письмо)" - } - }, - { - "wikiDataID": "Q13414913", - "languageCode": "zh_CN", - "IETFcode": "zh-Hans", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILR": "ILS", - "ILS": "₪", - "INR": "₹", - "JPY": "JP¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "TWD": "NT$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "保加利亚语", - "co": "科西嘉语", - "cs": "捷克语", - "cy": "威尔士语", - "da": "丹麦语", - "de": "德语", - "dsb": "下索布语", - "el": "希腊语", - "en": "英语", - "en_CA": "加拿大英语", - "en_GB": "英国英语", - "es_ES": "西班牙语", - "es_MX": "墨西哥西班牙语", - "fa": "波斯语", - "fi": "芬兰语", - "fr": "法语", - "fy_NL": "西弗里西亚语", - "hsb": "上索布语", - "hu": "匈牙利语", - "ia": "国际语", - "id": "印度尼西亚语", - "is": "冰岛语", - "it": "意大利语", - "ja": "日语", - "lo": "老挝语", - "nl": "荷兰语", - "pa_IN": "旁遮普语", - "pl": "波兰语", - "pt_BR": "葡萄牙语", - "pt_PT": "欧洲葡萄牙语", - "ru": "俄语", - "sk": "斯洛伐克语", - "sl": "斯洛文尼亚语", - "sq": "阿尔巴尼亚语", - "sv_SE": "瑞典语", - "tr": "土耳其语", - "uk": "乌克兰语", - "zh_CN": "简体中文", - "zh_TW": "繁体中文" - } - }, - { - "wikiDataID": "Q18130932", - "languageCode": "zh_TW", - "IETFcode": "zh-Hant", - "currencies": { - "AUD": "AU$", - "BRL": "R$", - "CAD": "CA$", - "CNY": "CN¥", - "EUR": "€", - "GBP": "£", - "HKD": "HK$", - "ILS": "₪", - "INR": "₹", - "JPY": "¥", - "KRW": "₩", - "MXN": "MX$", - "NZD": "NZ$", - "TWD": "$", - "USD": "US$", - "VND": "₫", - "XAF": "FCFA", - "XCD": "EC$", - "XOF": "F CFA", - "XPF": "CFPF" - }, - "languages": { - "bg": "保加利亞文", - "co": "科西嘉文", - "cs": "捷克文", - "cy": "威爾斯文", - "da": "丹麥文", - "de": "德文", - "dsb": "下索布文", - "el": "希臘文", - "en": "英文", - "en_CA": "英文(加拿大)", - "en_GB": "英文(英國)", - "es_ES": "西班牙文", - "es_MX": "西班牙文(墨西哥)", - "fa": "波斯文", - "fi": "芬蘭文", - "fr": "法文", - "fy_NL": "西弗里西亞文", - "hsb": "上索布文", - "hu": "匈牙利文", - "ia": "國際文", - "id": "印尼文", - "is": "冰島文", - "it": "義大利文", - "ja": "日文", - "lo": "寮文", - "nl": "荷蘭文", - "pa_IN": "旁遮普文", - "pl": "波蘭文", - "pt_BR": "葡萄牙文", - "pt_PT": "葡萄牙文(葡萄牙)", - "ru": "俄文", - "sk": "斯洛伐克文", - "sl": "斯洛維尼亞文", - "sq": "阿爾巴尼亞文", - "sv_SE": "瑞典文", - "tr": "土耳其文", - "uk": "烏克蘭文", - "zh_CN": "簡體中文", - "zh_TW": "繁體中文" - } - } -] diff --git a/src/translations/extras/servers.json b/src/translations/extras/servers.json deleted file mode 100644 index 7e9bc9808e..0000000000 --- a/src/translations/extras/servers.json +++ /dev/null @@ -1,4339 +0,0 @@ -[ - { - "wikiDataID": "Q222", - "countryCode": "al", - "languages": { - "bg": "Албания", - "co": "Albania", - "cs": "Albánie", - "cy": "Albania", - "da": "Albanien", - "de": "Albanien", - "dsb": "Albańska", - "el": "Αλβανία", - "en": "Albania", - "en_CA": "Albania", - "en_GB": "Albania", - "es_AR": "Albania", - "es_CL": "Albania", - "es_ES": "Albania", - "es_MX": "Albania", - "fa": "آلبانی", - "fi": "Albania", - "fr": "Albanie", - "fy_NL": "Albaanje", - "hsb": "Albanska", - "hu": "Albánia", - "ia": "Albania", - "id": "Albania", - "is": "Albanía", - "it": "Albania", - "ja": "アルバニア", - "lo": "ປະເທດອານບານີ", - "nl": "Albanië", - "oc": "Albania", - "pa_IN": "ਅਲਬਾਨੀਆ", - "pl": "Albania", - "pt_BR": "Albânia", - "pt_PT": "Albânia", - "ru": "Албания", - "sk": "Albánsko", - "sl": "Albanija", - "sq": "Shqipëri", - "sv_SE": "Albanien", - "tr": "Arnavutluk", - "uk": "Албанія", - "zh_CN": "阿尔巴尼亚", - "zh_TW": "阿爾巴尼亞" - }, - "cities": [ - { - "wikiDataID": "Q19689", - "city": "Tirana", - "languages": { - "bg": "Тирана", - "el": "Τίρανα", - "fa": "تیرانا", - "is": "Tírana", - "ja": "ティラナ", - "lo": "ທິຣານາ", - "pa_IN": "ਤਿਰਾਨਾ", - "ru": "Тирана", - "sq": "Tiranë", - "tr": "Tiran", - "uk": "Тирана", - "zh_CN": "地拉那", - "zh_TW": "地拉那" - } - } - ] - }, - { - "countryCode": "au", - "languages": { - "bg": "Австралия", - "co": "Australia", - "cs": "Austrálie", - "cy": "Awstralia", - "da": "Australien", - "de": "Australien", - "dsb": "Awstralska", - "el": "Αυστραλία", - "en": "Australia", - "en_CA": "Australia", - "en_GB": "Australia", - "es_AR": "Australia", - "es_CL": "Australia", - "es_ES": "Australia", - "es_MX": "Australia", - "fa": "استرالیا", - "fi": "Australia", - "fr": "Australie", - "fy_NL": "Austraalje", - "hsb": "Awstralska", - "hu": "Ausztrália", - "ia": "Australia", - "id": "Australia", - "is": "Ástralía", - "it": "Australia", - "ja": "オーストラリア", - "lo": "ປະເທດອົດສະຕຣາລີ", - "nl": "Australië", - "oc": "Austràlia", - "pa_IN": "ਆਸਟ੍ਰੇਲੀਆ", - "pl": "Australia", - "pt_BR": "Austrália", - "pt_PT": "Austrália", - "ru": "Австралия", - "sk": "Austrália", - "sl": "Avstralija", - "sq": "Australia", - "sv_SE": "Australien", - "tr": "Avustralya", - "uk": "Австралія", - "zh_CN": "澳大利亚", - "zh_TW": "澳大利亞" - }, - "cities": [ - { - "wikiDataID": "Q5112", - "city": "Adelaide", - "languages": { - "bg": "Аделаида", - "el": "Αδελαΐδα", - "es_AR": "Adelaida", - "es_CL": "Adelaida", - "es_ES": "Adelaida", - "es_MX": "Adelaida", - "fa": "آدلاید", - "fr": "Adélaïde", - "id": "Adelaide, Australia Selatan", - "ja": "アデレード", - "oc": "Adelaïda", - "pa_IN": "ਐਡਲੇਡ", - "ru": "Аделаида", - "uk": "Аделаїда", - "zh_CN": "阿德莱德", - "zh_TW": "阿得雷德" - } - }, - { - "wikiDataID": "Q34932", - "city": "Brisbane", - "languages": { - "bg": "Бризбън", - "el": "Μπρίσμπεϊν", - "fa": "بریزبن", - "ja": "ブリスベン", - "pa_IN": "ਬ੍ਰਿਜ਼ਬਨ", - "ru": "Брисбен", - "sq": "Brisbejn", - "uk": "Брисбен", - "zh_CN": "布里斯班", - "zh_TW": "布里斯本" - } - }, - { - "city": "Melbourne", - "languages": { - "bg": "Мелбърн", - "el": "Μελβούρνη", - "fa": "ملبورن", - "ja": "メルボルン", - "lo": "ເມລເບີນ", - "pa_IN": "ਮੈਲਬਰਨ", - "ru": "Мельбурн", - "sq": "Melburni", - "uk": "Мельбурн", - "zh_CN": "墨尔本", - "zh_TW": "墨爾本" - }, - "wikiDataID": "Q3141" - }, - { - "wikiDataID": "Q3183", - "city": "Perth", - "languages": { - "bg": "Пърт", - "cy": "Perth, Gorllewin Awstralia", - "el": "Περθ", - "fa": "پرث", - "ja": "パース", - "oc": "Boorloo", - "pa_IN": "ਪਰਥ", - "ru": "Перт", - "tr": "Perth, Batı Avustralya", - "uk": "Перт", - "zh_CN": "珀斯", - "zh_TW": "伯斯" - } - }, - { - "city": "Sydney", - "languages": { - "bg": "Сидни", - "el": "Σίδνεϊ", - "es_AR": "Sídney", - "es_CL": "Sídney", - "es_ES": "Sídney", - "es_MX": "Sídney", - "fa": "سیدنی", - "ja": "シドニー", - "pa_IN": "ਸਿਡਨੀ", - "ru": "Сидней", - "tr": "Sidney", - "uk": "Сідней", - "zh_CN": "悉尼", - "zh_TW": "雪梨" - }, - "wikiDataID": "Q3130" - } - ], - "wikiDataID": "Q408" - }, - { - "countryCode": "be", - "languages": { - "bg": "Белгия", - "co": "Belgiu", - "cs": "Belgie", - "cy": "Gwlad Belg", - "da": "Belgien", - "de": "Belgien", - "dsb": "Belgiska", - "el": "Βέλγιο", - "en": "Belgium", - "en_CA": "Belgium", - "en_GB": "Belgium", - "es_AR": "Bélgica", - "es_CL": "Bélgica", - "es_ES": "Bélgica", - "es_MX": "Bélgica", - "fa": "بلژیک", - "fi": "Belgia", - "fr": "Belgique", - "fy_NL": "Belgje", - "hsb": "Belgiska", - "hu": "Belgium", - "ia": "Belgica", - "id": "Belgia", - "is": "Belgía", - "it": "Belgio", - "ja": "ベルギー", - "lo": "ປະເທດແບນຊິກ", - "nl": "België", - "oc": "Belgica", - "pa_IN": "ਬੈਲਜੀਅਮ", - "pl": "Belgia", - "pt_BR": "Bélgica", - "pt_PT": "Bélgica", - "ru": "Бельгия", - "sk": "Belgicko", - "sl": "Belgija", - "sq": "Belgjika", - "sv_SE": "Belgien", - "tr": "Belçika", - "uk": "Бельгія", - "zh_CN": "比利时", - "zh_TW": "比利時" - }, - "cities": [ - { - "city": "Brussels", - "languages": { - "bg": "Брюксел", - "co": "Bruxelles", - "cs": "Brusel", - "cy": "Dinas Brwsel", - "da": "Bruxelles", - "de": "Stadt Brüssel", - "el": "Βρυξέλλες", - "en": "City of Brussels", - "en_CA": "City of Brussels", - "en_GB": "City of Brussels", - "es_AR": "Ciudad de Bruselas", - "es_CL": "Ciudad de Bruselas", - "es_ES": "Ciudad de Bruselas", - "es_MX": "Ciudad de Bruselas", - "fa": "شهر بروکسل", - "fi": "Bryssel", - "fr": "Ville de Bruxelles", - "fy_NL": "Brussel", - "hsb": "Brüssel", - "hu": "Brüsszel", - "ia": "Brussel", - "id": "Kota Brussel", - "is": "Brussel", - "it": "Bruxelles", - "ja": "ブリュッセル市", - "nl": "Stad Brussel", - "oc": "Brussèlas", - "pl": "Bruksela", - "pt_BR": "Cidade de Bruxelas", - "pt_PT": "Bruxelas", - "ru": "Брюссель", - "sk": "Brusel", - "sl": "Bruselj", - "sq": "Brukseli", - "sv_SE": "Bryssel", - "tr": "Brüksel Şehri", - "uk": "Брюссель", - "zh_CN": "布鲁塞尔", - "zh_TW": "布魯塞爾" - }, - "wikiDataID": "Q239" - } - ], - "wikiDataID": "Q31" - }, - { - "countryCode": "bg", - "languages": { - "bg": "България", - "co": "Bulgaria", - "cs": "Bulharsko", - "cy": "Bwlgaria", - "da": "Bulgarien", - "de": "Bulgarien", - "dsb": "Bulgaŕska", - "el": "Βουλγαρία", - "en": "Bulgaria", - "en_CA": "Bulgaria", - "en_GB": "Bulgaria", - "es_AR": "Bulgaria", - "es_CL": "Bulgaria", - "es_ES": "Bulgaria", - "es_MX": "Bulgaria", - "fa": "بلغارستان", - "fi": "Bulgaria", - "fr": "Bulgarie", - "fy_NL": "Bulgarije", - "hsb": "Bołharska", - "hu": "Bulgária", - "ia": "Bulgaria", - "id": "Bulgaria", - "is": "Búlgaría", - "it": "Bulgaria", - "ja": "ブルガリア", - "lo": "ປະເທດບູນກາລີ", - "nl": "Bulgarije", - "oc": "Bulgaria", - "pa_IN": "ਬਲਜੈਰੀਆ", - "pl": "Bułgaria", - "pt_BR": "Bulgária", - "pt_PT": "Bulgária", - "ru": "Болгария", - "sk": "Bulharsko", - "sl": "Bolgarija", - "sq": "Bullgaria", - "sv_SE": "Bulgarien", - "tr": "Bulgaristan", - "uk": "Болгарія", - "zh_CN": "保加利亚", - "zh_TW": "保加利亞" - }, - "cities": [ - { - "city": "Sofia", - "languages": { - "bg": "София", - "cs": "Sofie", - "dsb": "Sofija", - "el": "Σόφια", - "es_AR": "Sofía", - "es_CL": "Sofía", - "es_ES": "Sofía", - "es_MX": "Sofía", - "fa": "صوفیه", - "hsb": "Sofija", - "hu": "Szófia", - "is": "Sófía", - "ja": "ソフィア", - "oc": "Sòfia", - "pa_IN": "ਸੋਫ਼ੀਆ", - "pt_BR": "Sófia", - "pt_PT": "Sófia", - "ru": "София", - "sl": "Sofija", - "sq": "Sofja", - "tr": "Sofya", - "uk": "Софія", - "zh_CN": "索非亚", - "zh_TW": "索菲亞" - }, - "wikiDataID": "Q472" - } - ], - "wikiDataID": "Q219" - }, - { - "countryCode": "br", - "languages": { - "bg": "Бразилия", - "co": "Brasile", - "cs": "Brazílie", - "cy": "Brasil", - "da": "Brasilien", - "de": "Brasilien", - "dsb": "Brazilska", - "el": "Βραζιλία", - "en": "Brazil", - "en_CA": "Brazil", - "en_GB": "Brazil", - "es_AR": "Brasil", - "es_CL": "Brasil", - "es_ES": "Brasil", - "es_MX": "Brasil", - "fa": "برزیل", - "fi": "Brasilia", - "fr": "Brésil", - "fy_NL": "Brazylje", - "hsb": "Brazilska", - "hu": "Brazília", - "ia": "Brasil", - "id": "Brasil", - "is": "Brasilía", - "it": "Brasile", - "ja": "ブラジル", - "lo": "ປະເທດບຣາຊິນ", - "nl": "Brazilië", - "oc": "Brasil", - "pa_IN": "ਬ੍ਰਾਜ਼ੀਲ", - "pl": "Brazylia", - "pt_BR": "Brasil", - "pt_PT": "Brasil", - "ru": "Бразилия", - "sk": "Brazília", - "sl": "Brazilija", - "sq": "Brazili", - "sv_SE": "Brasilien", - "tr": "Brezilya", - "uk": "Бразилія", - "zh_CN": "巴西", - "zh_TW": "巴西" - }, - "cities": [ - { - "city": "Sao Paulo", - "languages": { - "bg": "Сао Пауло", - "co": "São Paulo", - "cs": "São Paulo", - "cy": "São Paulo", - "da": "São Paulo", - "de": "São Paulo", - "dsb": "São Paulo", - "el": "Σάο Πάολο", - "en": "São Paulo", - "en_CA": "São Paulo", - "en_GB": "São Paulo", - "es_AR": "São Paulo", - "es_CL": "São Paulo", - "es_ES": "São Paulo", - "es_MX": "São Paulo", - "fa": "سائوپائولو", - "fi": "São Paulo", - "fr": "São Paulo", - "fy_NL": "São Paulo", - "hsb": "São Paulo", - "hu": "São Paulo", - "ia": "São Paulo", - "id": "São Paulo", - "is": "São Paulo", - "it": "San Paolo", - "ja": "サンパウロ", - "lo": "ຊາວເປົາໂລ", - "nl": "São Paulo", - "oc": "São Paulo", - "pa_IN": "ਸਾਓ ਪਾਓਲੋ", - "pl": "São Paulo", - "pt_BR": "São Paulo", - "pt_PT": "São Paulo", - "ru": "Сан-Паулу", - "sk": "São Paulo", - "sl": "São Paulo", - "sq": "São Paulo", - "sv_SE": "São Paulo", - "tr": "São Paulo", - "uk": "Сан-Паулу", - "zh_CN": "圣保罗", - "zh_TW": "聖保羅" - }, - "wikiDataID": "Q174" - } - ], - "wikiDataID": "Q155" - }, - { - "countryCode": "ca", - "languages": { - "bg": "Канада", - "co": "Canadà", - "cs": "Kanada", - "cy": "Canada", - "da": "Canada", - "de": "Kanada", - "dsb": "Kanada", - "el": "Καναδάς", - "en": "Canada", - "en_CA": "Canada", - "en_GB": "Canada", - "es_AR": "Canadá", - "es_CL": "Canadá", - "es_ES": "Canadá", - "es_MX": "Canadá", - "fa": "کانادا", - "fi": "Kanada", - "fr": "Canada", - "fy_NL": "Kanada", - "hsb": "Kanada", - "hu": "Kanada", - "ia": "Canada", - "id": "Kanada", - "is": "Kanada", - "it": "Canada", - "ja": "カナダ", - "lo": "ປະເທດການາດາ", - "nl": "Canada", - "oc": "Canadà", - "pa_IN": "ਕੈਨੇਡਾ", - "pl": "Kanada", - "pt_BR": "Canadá", - "pt_PT": "Canadá", - "ru": "Канада", - "sk": "Kanada", - "sl": "Kanada", - "sq": "Kanadaja", - "sv_SE": "Kanada", - "tr": "Kanada", - "uk": "Канада", - "zh_CN": "加拿大", - "zh_TW": "加拿大" - }, - "cities": [ - { - "wikiDataID": "Q36312", - "city": "Calgary", - "languages": { - "bg": "Калгари", - "el": "Κάλγκαρι", - "fa": "کالگری", - "fy_NL": "Kelgery", - "ja": "カルガリー", - "pa_IN": "ਕੈਲਗਰੀ", - "ru": "Калгари", - "uk": "Калгарі", - "zh_CN": "卡尔加里", - "zh_TW": "卡加利" - } - }, - { - "city": "Montreal", - "languages": { - "bg": "Монреал", - "co": "Montréal", - "cs": "Montréal", - "cy": "Montréal", - "el": "Μόντρεαλ", - "fa": "مونترآل", - "fr": "Montréal", - "hu": "Montréal", - "is": "Montréal", - "it": "Montréal", - "ja": "モントリオール", - "lo": "ມົງເລອານ", - "pa_IN": "ਮੋਨਟਰਿਆਲ", - "ru": "Монреаль", - "sl": "Montréal", - "sq": "Montreali", - "sv_SE": "Montréal", - "uk": "Монреаль", - "zh_CN": "蒙特利尔", - "zh_TW": "蒙特婁" - }, - "wikiDataID": "Q340" - }, - { - "city": "Toronto", - "languages": { - "bg": "Торонто", - "el": "Τορόντο", - "fa": "تورنتو", - "is": "Torontó", - "ja": "トロント", - "pa_IN": "ਟੋਰਾਂਟੋ", - "ru": "Торонто", - "uk": "Торонто", - "zh_CN": "多伦多", - "zh_TW": "多倫多" - }, - "wikiDataID": "Q172" - }, - { - "wikiDataID": "Q24639", - "city": "Vancouver", - "languages": { - "bg": "Ванкувър", - "el": "Βανκούβερ", - "fa": "ونکوور", - "fy_NL": "Fankoever", - "ja": "バンクーバー", - "pa_IN": "ਵੈਨਕੂਵਰ", - "ru": "Ванкувер", - "uk": "Ванкувер", - "zh_CN": "温哥华", - "zh_TW": "溫哥華" - } - } - ], - "wikiDataID": "Q16" - }, - { - "countryCode": "ch", - "languages": { - "bg": "Швейцария", - "co": "Svizzera", - "cs": "Švýcarsko", - "cy": "Y Swistir", - "da": "Schweiz", - "de": "Schweiz", - "dsb": "Šwicaŕska", - "el": "Ελβετία", - "en": "Switzerland", - "en_CA": "Switzerland", - "en_GB": "Switzerland", - "es_AR": "Suiza", - "es_CL": "Suiza", - "es_ES": "Suiza", - "es_MX": "Suiza", - "fa": "سوئیس", - "fi": "Sveitsi", - "fr": "Suisse", - "fy_NL": "Switserlân", - "hsb": "Šwicarska", - "hu": "Svájc", - "ia": "Switza", - "id": "Swiss", - "is": "Sviss", - "it": "Svizzera", - "ja": "スイス", - "lo": "ປະເທດສະວິດ", - "nl": "Zwitserland", - "oc": "Soïssa", - "pa_IN": "ਸਵਿਟਜ਼ਰਲੈਂਡ", - "pl": "Szwajcaria", - "pt_BR": "Suíça", - "pt_PT": "Suíça", - "ru": "Швейцария", - "sk": "Švajčiarsko", - "sl": "Švica", - "sq": "Zvicër", - "sv_SE": "Schweiz", - "tr": "İsviçre", - "uk": "Швейцарія", - "zh_CN": "瑞士", - "zh_TW": "瑞士" - }, - "cities": [ - { - "city": "Zurich", - "languages": { - "bg": "Цюрих", - "cs": "Curych", - "cy": "Zürich", - "da": "Zürich", - "de": "Zürich", - "dsb": "Zürich", - "el": "Ζυρίχη", - "en": "Zürich", - "en_CA": "Zürich", - "en_GB": "Zürich", - "es_AR": "Zúrich", - "es_CL": "Zúrich", - "es_ES": "Zúrich", - "es_MX": "Zúrich", - "fa": "زوریخ", - "fi": "Zürich", - "fy_NL": "Zürich", - "hsb": "Zürich", - "hu": "Zürich", - "ia": "Zurico", - "id": "Zürich", - "is": "Zürich", - "it": "Zurigo", - "ja": "チューリッヒ", - "nl": "Zürich", - "oc": "Zuric", - "pa_IN": "ਜਿਊਰਿਖ", - "pl": "Zurych", - "pt_BR": "Zurique", - "pt_PT": "Zurique", - "ru": "Цюрих", - "sk": "Zürich", - "sl": "Zürich", - "sq": "Cyrih", - "sv_SE": "Zürich", - "tr": "Zürih", - "uk": "Цюрих", - "zh_CN": "苏黎世", - "zh_TW": "蘇黎世" - }, - "wikiDataID": "Q72" - } - ], - "wikiDataID": "Q39" - }, - { - "wikiDataID": "Q739", - "countryCode": "co", - "languages": { - "bg": "Колумбия", - "co": "Colombia", - "cs": "Kolumbie", - "cy": "Colombia", - "da": "Colombia", - "de": "Kolumbien", - "dsb": "Kolumbiska", - "el": "Κολομβία", - "en": "Colombia", - "en_CA": "Colombia", - "en_GB": "Colombia", - "es_AR": "Colombia", - "es_CL": "Colombia", - "es_ES": "Colombia", - "es_MX": "Colombia", - "fa": "کلمبیا", - "fi": "Kolumbia", - "fr": "Colombie", - "fy_NL": "Kolombia", - "hsb": "Kolumbiska", - "hu": "Kolumbia", - "ia": "Colombia", - "id": "Kolombia", - "is": "Kólumbía", - "it": "Colombia", - "ja": "コロンビア", - "lo": "ປະເທດໂກໂລມບີ", - "nl": "Colombia", - "oc": "Colómbia", - "pa_IN": "ਕੋਲੰਬੀਆ", - "pl": "Kolumbia", - "pt_BR": "Colômbia", - "pt_PT": "Colômbia", - "ru": "Колумбия", - "sk": "Kolumbia", - "sl": "Kolumbija", - "sq": "Kolumbia", - "sv_SE": "Colombia", - "tr": "Kolombiya", - "uk": "Колумбія", - "zh_CN": "哥伦比亚", - "zh_TW": "哥倫比亞" - }, - "cities": [ - { - "wikiDataID": "Q2841", - "city": "Bogota", - "languages": { - "bg": "Богота", - "co": "Bogotà", - "cy": "Bogotá", - "da": "Bogotá", - "de": "Bogotá", - "dsb": "Bogotá", - "el": "Μπογκοτά", - "en": "Bogotá", - "en_CA": "Bogotá", - "en_GB": "Bogotá", - "es_AR": "Bogotá", - "es_CL": "Bogotá", - "es_ES": "Bogotá", - "es_MX": "Bogotá", - "fa": "بوگوتا", - "fi": "Bogotá", - "hu": "Bogotá", - "ia": "Bogotá", - "id": "Bogotá", - "is": "Bógóta", - "it": "Bogotà", - "ja": "ボゴタ", - "oc": "Bogotà", - "pa_IN": "ਬੋਗੋਤਾ", - "pt_BR": "Bogotá", - "pt_PT": "Bogotá", - "ru": "Богота", - "sq": "Bogotá", - "sv_SE": "Bogotá", - "tr": "Bogotá", - "uk": "Богота", - "zh_CN": "波哥大", - "zh_TW": "波哥大" - } - } - ] - }, - { - "countryCode": "cz", - "languages": { - "bg": "Чехия", - "co": "Cechia", - "cs": "Česko", - "cy": "y Weriniaeth Tsiec", - "da": "Tjekkiet", - "de": "Tschechien", - "dsb": "Česka", - "el": "Τσεχία", - "en": "Czech Republic", - "en_CA": "Czech Republic", - "en_GB": "Czech Republic", - "es_AR": "República Checa", - "es_CL": "República Checa", - "es_ES": "República Checa", - "es_MX": "República Checa", - "fa": "جمهوری چک", - "fi": "Tšekki", - "fr": "Tchéquie", - "fy_NL": "Tsjechje", - "hsb": "Čěska", - "hu": "Csehország", - "ia": "Republica Chec", - "id": "Republik Ceko", - "is": "Tékkland", - "it": "Repubblica Ceca", - "ja": "チェコ", - "lo": "ປະເທດເຊັກກີ", - "nl": "Tsjechië", - "oc": "Republica Chèca", - "pa_IN": "ਚੈੱਕ ਗਣਰਾਜ", - "pl": "Czechy", - "pt_BR": "Tchéquia", - "pt_PT": "Chéquia", - "ru": "Чехия", - "sk": "Česko", - "sl": "Češka", - "sq": "Republika Çeke", - "sv_SE": "Tjeckien", - "tr": "Çekya", - "uk": "Чехія", - "zh_CN": "捷克", - "zh_TW": "捷克" - }, - "cities": [ - { - "city": "Prague", - "languages": { - "bg": "Прага", - "co": "Praga", - "cs": "Praha", - "cy": "Prag", - "da": "Prag", - "de": "Prag", - "dsb": "Praha", - "el": "Πράγα", - "es_AR": "Praga", - "es_CL": "Praga", - "es_ES": "Praga", - "es_MX": "Praga", - "fa": "پراگ", - "fi": "Praha", - "fy_NL": "Praach", - "hsb": "Praha", - "hu": "Prága", - "ia": "Praga", - "id": "Praha", - "is": "Prag", - "it": "Praga", - "ja": "プラハ", - "lo": "ປຣາກ", - "nl": "Praag", - "oc": "Praga", - "pa_IN": "ਪ੍ਰਾਗ", - "pl": "Praga", - "pt_BR": "Praga", - "pt_PT": "Praga", - "ru": "Прага", - "sk": "Praha", - "sl": "Praga", - "sq": "Praga", - "sv_SE": "Prag", - "tr": "Prag", - "uk": "Прага", - "zh_CN": "布拉格", - "zh_TW": "布拉格" - }, - "wikiDataID": "Q1085" - } - ], - "wikiDataID": "Q213" - }, - { - "countryCode": "de", - "languages": { - "bg": "Германия", - "co": "Germania", - "cs": "Německo", - "cy": "yr Almaen", - "da": "Tyskland", - "de": "Deutschland", - "dsb": "Nimska", - "el": "Γερμανία", - "en": "Germany", - "en_CA": "Germany", - "en_GB": "Germany", - "es_AR": "Alemania", - "es_CL": "Alemania", - "es_ES": "Alemania", - "es_MX": "Alemania", - "fa": "آلمان", - "fi": "Saksa", - "fr": "Allemagne", - "fy_NL": "Dútslân", - "hsb": "Němska", - "hu": "Németország", - "ia": "Germania", - "id": "Jerman", - "is": "Þýskaland", - "it": "Germania", - "ja": "ドイツ", - "lo": "ປະເທດເຢຍລະມັນ", - "nl": "Duitsland", - "oc": "Alemanha", - "pa_IN": "ਜਰਮਨੀ", - "pl": "Niemcy", - "pt_BR": "Alemanha", - "pt_PT": "Alemanha", - "ru": "Германия", - "sk": "Nemecko", - "sl": "Nemčija", - "sq": "Gjermania", - "sv_SE": "Tyskland", - "tr": "Almanya", - "uk": "Німеччина", - "zh_CN": "德国", - "zh_TW": "德國" - }, - "cities": [ - { - "wikiDataID": "Q64", - "city": "Berlin", - "languages": { - "bg": "Берлин", - "co": "Berlinu", - "cs": "Berlín", - "dsb": "Barliń", - "el": "Βερολίνο", - "es_AR": "Berlín", - "es_CL": "Berlín", - "es_ES": "Berlín", - "es_MX": "Berlín", - "fa": "برلین", - "fi": "Berliini", - "fy_NL": "Berlyn", - "is": "Berlín", - "it": "Berlino", - "ja": "ベルリン", - "lo": "ເບີລິນ", - "nl": "Berlijn", - "pa_IN": "ਬਰਲਿਨ", - "pt_BR": "Berlim", - "pt_PT": "Berlim", - "ru": "Берлин", - "sk": "Berlín", - "uk": "Берлін", - "zh_CN": "柏林", - "zh_TW": "柏林" - } - }, - { - "city": "Dusseldorf", - "languages": { - "bg": "Дюселдорф", - "co": "Düsseldorf", - "cs": "Düsseldorf", - "cy": "Düsseldorf", - "da": "Düsseldorf", - "de": "Düsseldorf", - "dsb": "Düsseldorf", - "el": "Ντύσσελντορφ", - "en": "Düsseldorf", - "en_CA": "Düsseldorf", - "en_GB": "Düsseldorf", - "es_AR": "Düsseldorf", - "es_CL": "Düsseldorf", - "es_ES": "Düsseldorf", - "es_MX": "Düsseldorf", - "fa": "دوسلدورف", - "fi": "Düsseldorf", - "fr": "Düsseldorf", - "fy_NL": "Düsseldorf", - "hsb": "Düsseldorf", - "hu": "Düsseldorf", - "ia": "Düsseldorf", - "id": "Düsseldorf", - "is": "Düsseldorf", - "it": "Düsseldorf", - "ja": "デュッセルドルフ", - "nl": "Düsseldorf", - "oc": "Düsseldorf", - "pl": "Düsseldorf", - "pt_BR": "Düsseldorf", - "pt_PT": "Düsseldorf", - "ru": "Дюссельдорф", - "sk": "Düsseldorf", - "sl": "Düsseldorf", - "sq": "Dyzeldorfi", - "sv_SE": "Düsseldorf", - "tr": "Düsseldorf", - "uk": "Дюссельдорф", - "zh_CN": "杜塞爾多夫", - "zh_TW": "杜塞道夫" - }, - "wikiDataID": "Q1718" - }, - { - "city": "Frankfurt", - "languages": { - "bg": "Франкфурт на Майн", - "co": "Francuforte nant'à u Menu", - "cs": "Frankfurt nad Mohanem", - "cy": "Frankfurt am Main", - "da": "Frankfurt am Main", - "de": "Frankfurt am Main", - "dsb": "Frankfurt nad Mainom", - "el": "Φραγκφούρτη", - "es_AR": "Fráncfort del Meno", - "es_CL": "Fráncfort del Meno", - "es_ES": "Fráncfort del Meno", - "es_MX": "Fráncfort del Meno", - "fa": "فرانکفورت آم ماین", - "fi": "Frankfurt am Main", - "fr": "Francfort-sur-le-Main", - "fy_NL": "Frankfurt am Main", - "hsb": "Frankobrod nad Mohanom", - "hu": "Frankfurt am Main", - "ia": "Frankfurt am Main", - "id": "Frankfurt am Main", - "is": "Frankfurt am Main", - "it": "Francoforte sul Meno", - "ja": "フランクフルト・アム・マイン", - "nl": "Frankfurt am Main", - "oc": "Francfòrt de Men", - "pa_IN": "ਫ਼ਰਾਂਕਫ਼ੁਰਟ", - "pl": "Frankfurt nad Menem", - "pt_BR": "Frankfurt am Main", - "pt_PT": "Frankfurt am Main", - "ru": "Франкфурт-на-Майне", - "sk": "Frankfurt nad Mohanom", - "sl": "Frankfurt ob Majni", - "sq": "Frankfurti mbi Main", - "sv_SE": "Frankfurt am Main", - "uk": "Франкфурт-на-Майні", - "zh_CN": "美因河畔法兰克福", - "zh_TW": "美茵河畔法蘭克福" - }, - "wikiDataID": "Q1794" - } - ], - "wikiDataID": "Q183" - }, - { - "countryCode": "dk", - "languages": { - "bg": "Дания", - "co": "Danimarca", - "cs": "Dánsko", - "cy": "Denmarc", - "da": "Danmark", - "de": "Dänemark", - "dsb": "Dańska", - "el": "Δανία", - "en": "Denmark", - "en_CA": "Denmark", - "en_GB": "Denmark", - "es_AR": "Dinamarca", - "es_CL": "Dinamarca", - "es_ES": "Dinamarca", - "es_MX": "Dinamarca", - "fa": "دانمارک", - "fi": "Tanska", - "fr": "Danemark", - "fy_NL": "Denemark", - "hsb": "Danska", - "hu": "Dánia", - "ia": "Danmark", - "id": "Denmark", - "is": "Danmörk", - "it": "Danimarca", - "ja": "デンマーク", - "lo": "ປະເທດດານມາກ", - "nl": "Denemarken", - "oc": "Danemarc", - "pa_IN": "ਡੈੱਨਮਾਰਕ", - "pl": "Dania", - "pt_BR": "Dinamarca", - "pt_PT": "Dinamarca", - "ru": "Дания", - "sk": "Dánsko", - "sl": "Danska", - "sq": "Danimarka", - "sv_SE": "Danmark", - "tr": "Danimarka", - "uk": "Данія", - "zh_CN": "丹麦", - "zh_TW": "丹麥" - }, - "cities": [ - { - "city": "Copenhagen", - "languages": { - "bg": "Копенхаген", - "co": "Copenaghen", - "cs": "Kodaň", - "da": "København", - "de": "Kopenhagen", - "dsb": "Kopenhagen", - "el": "Κοπεγχάγη", - "es_AR": "Copenhague", - "es_CL": "Copenhague", - "es_ES": "Copenhague", - "es_MX": "Copenhague", - "fa": "کپنهاگ", - "fi": "Kööpenhamina", - "fr": "Copenhague", - "fy_NL": "Kopenhagen", - "hsb": "Kopenhagen", - "hu": "Koppenhága", - "id": "Kopenhagen", - "is": "Kaupmannahöfn", - "it": "Copenaghen", - "ja": "コペンハーゲン", - "nl": "Kopenhagen", - "oc": "Copenaga", - "pa_IN": "ਕੋਪਨਹੈਗਨ", - "pl": "Kopenhaga", - "pt_BR": "Copenhague", - "pt_PT": "Copenhaga", - "ru": "Копенгаген", - "sk": "Kodaň", - "sl": "København", - "sq": "Kopenhagen", - "sv_SE": "Köpenhamn", - "tr": "Kopenhag", - "uk": "Копенгаген", - "zh_CN": "哥本哈根", - "zh_TW": "哥本哈根" - }, - "wikiDataID": "Q1748" - } - ], - "wikiDataID": "Q35" - }, - { - "countryCode": "ee", - "languages": { - "bg": "Естония", - "co": "Estonia", - "cs": "Estonsko", - "cy": "Estonia", - "da": "Estland", - "de": "Estland", - "dsb": "Estniska", - "el": "Εσθονία", - "en": "Estonia", - "en_CA": "Estonia", - "en_GB": "Estonia", - "es_AR": "Estonia", - "es_CL": "Estonia", - "es_ES": "Estonia", - "es_MX": "Estonia", - "fa": "استونی", - "fi": "Viro", - "fr": "Estonie", - "fy_NL": "Estlân", - "hsb": "Estiska", - "hu": "Észtország", - "ia": "Estonia", - "id": "Estonia", - "is": "Eistland", - "it": "Estonia", - "ja": "エストニア", - "lo": "ປະເທດແອັດສະໂຕນີ", - "nl": "Estland", - "oc": "Estònia", - "pa_IN": "ਏਸਟੋਨੀਆ", - "pl": "Estonia", - "pt_BR": "Estônia", - "pt_PT": "Estónia", - "ru": "Эстония", - "sk": "Estónsko", - "sl": "Estonija", - "sq": "Estonia", - "sv_SE": "Estland", - "tr": "Estonya", - "uk": "Естонія", - "zh_CN": "爱沙尼亚", - "zh_TW": "愛沙尼亞" - }, - "cities": [ - { - "city": "Tallinn", - "languages": { - "bg": "Талин", - "el": "Τάλιν", - "es_AR": "Tallin", - "es_CL": "Tallin", - "es_ES": "Tallin", - "es_MX": "Tallin", - "fa": "تالین", - "fi": "Tallinna", - "fy_NL": "Tallin", - "ja": "タリン", - "pa_IN": "ਤਾਲਿਨ", - "ru": "Таллин", - "sl": "Talin", - "sq": "Talini", - "uk": "Таллінн", - "zh_CN": "塔林", - "zh_TW": "塔林" - }, - "wikiDataID": "Q1770" - } - ], - "wikiDataID": "Q191" - }, - { - "countryCode": "es", - "languages": { - "bg": "Испания", - "co": "Spagna", - "cs": "Španělsko", - "cy": "Sbaen", - "da": "Spanien", - "de": "Spanien", - "dsb": "Špańska", - "el": "Ισπανία", - "en": "Spain", - "en_CA": "Spain", - "en_GB": "Spain", - "es_AR": "España", - "es_CL": "España", - "es_ES": "España", - "es_MX": "España", - "fa": "اسپانیا", - "fi": "Espanja", - "fr": "Espagne", - "fy_NL": "Spanje", - "hsb": "Španiska", - "hu": "Spanyolország", - "ia": "Espania", - "id": "Spanyol", - "is": "Spánn", - "it": "Spagna", - "ja": "スペイン", - "lo": "ປະເທດແອັດສະປາຍ", - "nl": "Spanje", - "oc": "Espanha", - "pa_IN": "ਸਪੇਨ", - "pl": "Hiszpania", - "pt_BR": "Espanha", - "pt_PT": "Espanha", - "ru": "Испания", - "sk": "Španielsko", - "sl": "Španija", - "sq": "Spanja", - "sv_SE": "Spanien", - "tr": "İspanya", - "uk": "Іспанія", - "zh_CN": "西班牙", - "zh_TW": "西班牙" - }, - "cities": [ - { - "city": "Madrid", - "languages": { - "bg": "Мадрид", - "el": "Μαδρίτη", - "fa": "مادرید", - "ja": "マドリード", - "pa_IN": "ਮਾਦਰਿਦ", - "pl": "Madryt", - "pt_BR": "Madri", - "pt_PT": "Madri", - "ru": "Мадрид", - "uk": "Мадрид", - "zh_CN": "马德里", - "zh_TW": "馬德里" - }, - "wikiDataID": "Q2807" - } - ], - "wikiDataID": "Q29" - }, - { - "countryCode": "fi", - "languages": { - "bg": "Финландия", - "co": "Finlandia", - "cs": "Finsko", - "cy": "y Ffindir", - "da": "Finland", - "de": "Finnland", - "dsb": "Finska", - "el": "Φινλανδία", - "en": "Finland", - "en_CA": "Finland", - "en_GB": "Finland", - "es_AR": "Finlandia", - "es_CL": "Finlandia", - "es_ES": "Finlandia", - "es_MX": "Finlandia", - "fa": "فنلاند", - "fi": "Suomi", - "fr": "Finlande", - "fy_NL": "Finlân", - "hsb": "Finska", - "hu": "Finnország", - "ia": "Finlandia", - "id": "Finlandia", - "is": "Finnland", - "it": "Finlandia", - "ja": "フィンランド", - "lo": "ປະເທດແຟງລັງ", - "nl": "Finland", - "oc": "Finlàndia", - "pa_IN": "ਫ਼ਿਨਲੈਂਡ", - "pl": "Finlandia", - "pt_BR": "Finlândia", - "pt_PT": "Finlândia", - "ru": "Финляндия", - "sk": "Fínsko", - "sl": "Finska", - "sq": "Finlanda", - "sv_SE": "Finland", - "tr": "Finlandiya", - "uk": "Фінляндія", - "zh_CN": "芬兰", - "zh_TW": "芬蘭" - }, - "cities": [ - { - "city": "Helsinki", - "languages": { - "bg": "Хелзинки", - "cs": "Helsinky", - "el": "Ελσίνκι", - "fa": "هلسینکی", - "fy_NL": "Helsinky", - "ja": "ヘルシンキ", - "pa_IN": "ਹੈਲਸਿੰਕੀ", - "pt_BR": "Helsinque", - "pt_PT": "Helsínquia", - "ru": "Хельсинки", - "sv_SE": "Helsingfors", - "uk": "Гельсінкі", - "zh_CN": "赫尔辛基", - "zh_TW": "赫爾辛基" - }, - "wikiDataID": "Q1757" - } - ], - "wikiDataID": "Q33" - }, - { - "countryCode": "fr", - "languages": { - "bg": "Франция", - "co": "Francia", - "cs": "Francie", - "cy": "Ffrainc", - "da": "Frankrig", - "de": "Frankreich", - "dsb": "Francojska", - "el": "Γαλλία", - "en": "France", - "en_CA": "France", - "en_GB": "France", - "es_AR": "Francia", - "es_CL": "Francia", - "es_ES": "Francia", - "es_MX": "Francia", - "fa": "فرانسه", - "fi": "Ranska", - "fr": "France", - "fy_NL": "Frankryk", - "hsb": "Francoska", - "hu": "Franciaország", - "ia": "Francia", - "id": "Prancis", - "is": "Frakkland", - "it": "Francia", - "ja": "フランス", - "lo": "ປະເທດຝຣັ່ງ", - "nl": "Frankrijk", - "oc": "França", - "pa_IN": "ਫ਼ਰਾਂਸ", - "pl": "Francja", - "pt_BR": "França", - "pt_PT": "França", - "ru": "Франция", - "sk": "Francúzsko", - "sl": "Francija", - "sq": "Francë", - "sv_SE": "Frankrike", - "tr": "Fransa", - "uk": "Франція", - "zh_CN": "法国", - "zh_TW": "法國" - }, - "cities": [ - { - "city": "Marseille", - "languages": { - "bg": "Марсилия", - "co": "Marseglia", - "el": "Μασσαλία", - "es_AR": "Marsella", - "es_CL": "Marsella", - "es_ES": "Marsella", - "es_MX": "Marsella", - "fa": "مارسی", - "it": "Marsiglia", - "ja": "マルセイユ", - "oc": "Marselha", - "pa_IN": "ਮਾਰਸੇਈ", - "pl": "Marsylia", - "pt_BR": "Marselha", - "pt_PT": "Marselha", - "ru": "Марсель", - "tr": "Marsilya", - "uk": "Марсель", - "zh_CN": "马赛", - "zh_TW": "馬賽" - }, - "wikiDataID": "Q23482" - }, - { - "city": "Paris", - "languages": { - "bg": "Париж", - "co": "Parighji", - "cs": "Paříž", - "el": "Παρίσι", - "es_AR": "París", - "es_CL": "París", - "es_ES": "París", - "es_MX": "París", - "fa": "پاریس", - "fi": "Pariisi", - "fy_NL": "Parys", - "hu": "Párizs", - "is": "París", - "it": "Parigi", - "ja": "パリ", - "lo": "ປາຣີ", - "nl": "Parijs", - "oc": "París", - "pa_IN": "ਪੈਰਿਸ", - "pl": "Paryż", - "ru": "Париж", - "sk": "Paríž", - "sl": "Pariz", - "uk": "Париж", - "zh_CN": "巴黎", - "zh_TW": "巴黎" - }, - "wikiDataID": "Q90" - } - ], - "wikiDataID": "Q142" - }, - { - "countryCode": "gb", - "languages": { - "bg": "Великобритания", - "co": "Regnu Unitu", - "cs": "Spojené království", - "cy": "y Deyrnas Gyfunol", - "da": "Storbritannien", - "de": "Vereinigtes Königreich", - "dsb": "Zjadnośone kralojstwo", - "el": "Ηνωμένο Βασίλειο", - "en": "United Kingdom", - "en_CA": "United Kingdom", - "en_GB": "United Kingdom", - "es_AR": "Reino Unido", - "es_CL": "Reino Unido", - "es_ES": "Reino Unido", - "es_MX": "Reino Unido", - "fa": "بریتانیا", - "fi": "Yhdistynyt kuningaskunta", - "fr": "Royaume-Uni", - "fy_NL": "Feriene Keninkryk", - "hsb": "Zjednoćene kralestwo", - "hu": "Egyesült Királyság", - "ia": "Regno Unite", - "id": "Britania Raya", - "is": "Bretland", - "it": "Regno Unito", - "ja": "イギリス", - "lo": "ສະຫະລາຊະອານາຈັກ", - "nl": "Verenigd Koninkrijk", - "oc": "Reialme Unit", - "pa_IN": "ਯੂਨਾਈਟਡ ਕਿੰਗਡਮ", - "pl": "Wielka Brytania", - "pt_BR": "Reino Unido", - "pt_PT": "Reino Unido", - "ru": "Великобритания", - "sk": "Spojené kráľovstvo", - "sl": "Združeno kraljestvo", - "sq": "Britania e Madhe", - "sv_SE": "Storbritannien", - "tr": "Birleşik Krallık", - "uk": "Велика Британія", - "zh_CN": "英国", - "zh_TW": "英國" - }, - "cities": [ - { - "wikiDataID": "Q4093", - "city": "Glasgow", - "languages": { - "bg": "Глазгоу", - "el": "Γλασκώβη", - "fa": "گلاسگو", - "ja": "グラスゴー", - "pa_IN": "ਗਲਾਸਗੋ", - "ru": "Глазго", - "uk": "Глазго", - "zh_CN": "格拉斯哥", - "zh_TW": "格拉斯哥" - } - }, - { - "city": "London", - "languages": { - "bg": "Лондон", - "co": "Londra", - "cs": "Londýn", - "cy": "Llundain", - "el": "Λονδίνο", - "es_AR": "Londres", - "es_CL": "Londres", - "es_ES": "Londres", - "es_MX": "Londres", - "fa": "لندن", - "fi": "Lontoo", - "fr": "Londres", - "fy_NL": "Londen", - "it": "Londra", - "ja": "ロンドン", - "lo": "ລອນດອນ", - "nl": "Londen", - "oc": "Londres", - "pa_IN": "ਲੰਦਨ", - "pl": "Londyn", - "pt_BR": "Londres", - "pt_PT": "Londres", - "ru": "Лондон", - "sk": "Londýn", - "sq": "Londër", - "tr": "Londra", - "uk": "Лондон", - "zh_CN": "伦敦", - "zh_TW": "倫敦" - }, - "wikiDataID": "Q84" - }, - { - "city": "Manchester", - "languages": { - "bg": "Манчестър", - "cy": "Manceinion", - "el": "Μάντσεστερ", - "es_AR": "Mánchester", - "es_CL": "Mánchester", - "es_ES": "Mánchester", - "es_MX": "Mánchester", - "fa": "منچستر", - "ia": "Manchester (Anglaterra)", - "ja": "マンチェスター", - "pa_IN": "ਮਾਨਚੈਸਟਰ", - "ru": "Манчестер", - "uk": "Манчестер", - "zh_CN": "曼彻斯特", - "zh_TW": "曼徹斯特" - }, - "wikiDataID": "Q18125" - } - ], - "wikiDataID": "Q145" - }, - { - "wikiDataID": "Q41", - "countryCode": "gr", - "languages": { - "bg": "Гърция", - "co": "Grecia", - "cs": "Řecko", - "cy": "Gwlad Groeg", - "da": "Grækenland", - "de": "Griechenland", - "dsb": "Grichiska", - "el": "Ελλάδα", - "en": "Greece", - "en_CA": "Greece", - "en_GB": "Greece", - "es_AR": "Grecia", - "es_CL": "Grecia", - "es_ES": "Grecia", - "es_MX": "Grecia", - "fa": "یونان", - "fi": "Kreikka", - "fr": "Grèce", - "fy_NL": "Grikelân", - "hsb": "Grjekska", - "hu": "Görögország", - "ia": "Grecia", - "id": "Yunani", - "is": "Grikkland", - "it": "Grecia", - "ja": "ギリシャ", - "lo": "ປະເທດເກຣັກ", - "nl": "Griekenland", - "oc": "Grècia", - "pa_IN": "ਯੂਨਾਨ", - "pl": "Grecja", - "pt_BR": "Grécia", - "pt_PT": "Grécia", - "ru": "Греция", - "sk": "Grécko", - "sl": "Grčija", - "sq": "Greqia", - "sv_SE": "Grekland", - "tr": "Yunanistan", - "uk": "Греція", - "zh_CN": "希腊", - "zh_TW": "希臘" - }, - "cities": [ - { - "wikiDataID": "Q1524", - "city": "Athens", - "languages": { - "bg": "Атина", - "co": "Atene", - "cs": "Athény", - "cy": "Athen", - "da": "Athen", - "de": "Athen", - "dsb": "Atheny", - "el": "Αθήνα", - "es_AR": "Atenas", - "es_CL": "Atenas", - "es_ES": "Atenas", - "es_MX": "Atenas", - "fa": "آتن", - "fi": "Ateena", - "fr": "Athènes", - "fy_NL": "Atene", - "hsb": "Athen", - "hu": "Athén", - "ia": "Athenas", - "id": "Athena", - "is": "Aþena", - "it": "Atene", - "ja": "アテネ", - "lo": "ເອເທນ", - "nl": "Athene", - "oc": "Atenas", - "pa_IN": "ਐਥਨਜ਼", - "pl": "Ateny", - "pt_BR": "Atenas", - "pt_PT": "Atenas", - "ru": "Афины", - "sk": "Atény", - "sl": "Atene", - "sq": "Athina", - "sv_SE": "Aten", - "tr": "Atina", - "uk": "Афіни", - "zh_CN": "雅典", - "zh_TW": "雅典" - } - } - ] - }, - { - "countryCode": "hk", - "languages": { - "bg": "Хонконг", - "co": "Hong Kong", - "cs": "Hongkong", - "cy": "Hong Cong", - "da": "Hongkong", - "de": "Hongkong", - "el": "Χονγκ Κονγκ", - "en": "Hong Kong", - "en_CA": "Hong Kong", - "en_GB": "Hong Kong", - "es_AR": "Hong Kong", - "es_CL": "Hong Kong", - "es_ES": "Hong Kong", - "es_MX": "Hong Kong", - "fa": "هنگ کنگ", - "fi": "Hongkong", - "fr": "Hong Kong", - "fy_NL": "Hongkong", - "hu": "Hongkong", - "ia": "Hong Kong", - "id": "Hong Kong", - "is": "Hong Kong", - "it": "Hong Kong", - "ja": "香港", - "lo": "ຮົງກົງ", - "nl": "Hongkong", - "oc": "Hong Kong", - "pa_IN": "ਹਾਂਗ ਕਾਂਗ", - "pl": "Hongkong", - "pt_BR": "Hong Kong", - "pt_PT": "Hong Kong", - "ru": "Гонконг", - "sk": "Hongkong", - "sl": "Hongkong", - "sq": "Hong Kong", - "sv_SE": "Hongkong", - "tr": "Hong Kong", - "uk": "Гонконг", - "zh_CN": "香港", - "zh_TW": "香港" - }, - "cities": [ - { - "wikiDataID": "Q8646", - "city": "Hong Kong", - "languages": { - "bg": "Хонконг", - "cs": "Hongkong", - "cy": "Hong Cong", - "da": "Hongkong", - "de": "Hongkong", - "el": "Χονγκ Κονγκ", - "fa": "هنگ کنگ", - "fi": "Hongkong", - "fy_NL": "Hongkong", - "hu": "Hongkong", - "ja": "香港", - "lo": "ຮົງກົງ", - "nl": "Hongkong", - "pa_IN": "ਹਾਂਗ ਕਾਂਗ", - "pl": "Hongkong", - "ru": "Гонконг", - "sk": "Hongkong", - "sl": "Hongkong", - "sv_SE": "Hongkong", - "uk": "Гонконг", - "zh_CN": "香港", - "zh_TW": "香港" - } - } - ], - "wikiDataID": "Q8646" - }, - { - "wikiDataID": "Q224", - "countryCode": "hr", - "languages": { - "bg": "Хърватия", - "co": "Croazia", - "cs": "Chorvatsko", - "cy": "Croatia", - "da": "Kroatien", - "de": "Kroatien", - "dsb": "Chorwatska", - "el": "Κροατία", - "en": "Croatia", - "en_CA": "Croatia", - "en_GB": "Croatia", - "es_AR": "Croacia", - "es_CL": "Croacia", - "es_ES": "Croacia", - "es_MX": "Croacia", - "fa": "کرواسی", - "fi": "Kroatia", - "fr": "Croatie", - "fy_NL": "Kroaasje", - "hsb": "Chorwatska", - "hu": "Horvátország", - "ia": "Croatia", - "id": "Kroasia", - "is": "Króatía", - "it": "Croazia", - "ja": "クロアチア", - "lo": "ປະເທດກຣົວຊີ", - "nl": "Kroatië", - "oc": "Croàcia", - "pa_IN": "ਕ੍ਰੋਏਸ਼ੀਆ", - "pl": "Chorwacja", - "pt_BR": "Croácia", - "pt_PT": "Croácia", - "ru": "Хорватия", - "sk": "Chorvátsko", - "sl": "Hrvaška", - "sq": "Kroacia", - "sv_SE": "Kroatien", - "tr": "Hırvatistan", - "uk": "Хорватія", - "zh_CN": "克罗地亚", - "zh_TW": "克羅埃西亞" - }, - "cities": [ - { - "wikiDataID": "Q1435", - "city": "Zagreb", - "languages": { - "bg": "Загреб", - "co": "Zagabria", - "cs": "Záhřeb", - "el": "Ζάγκρεμπ", - "fa": "زاگرب", - "hu": "Zágráb", - "it": "Zagabria", - "ja": "ザグレブ", - "lo": "ຊາເກຣບ", - "oc": "Zagrèb", - "pa_IN": "ਜ਼ਾਗਰਬ", - "pl": "Zagrzeb", - "ru": "Загреб", - "sk": "Záhreb", - "sq": "Zagrebi", - "tr": "Zagrep", - "uk": "Загреб", - "zh_CN": "萨格勒布", - "zh_TW": "札格雷布" - } - } - ] - }, - { - "countryCode": "hu", - "languages": { - "bg": "Унгария", - "co": "Ungheria", - "cs": "Maďarsko", - "cy": "Hwngari", - "da": "Ungarn", - "de": "Ungarn", - "dsb": "Hungorska", - "el": "Ουγγαρία", - "en": "Hungary", - "en_CA": "Hungary", - "en_GB": "Hungary", - "es_AR": "Hungría", - "es_CL": "Hungría", - "es_ES": "Hungría", - "es_MX": "Hungría", - "fa": "مجارستان", - "fi": "Unkari", - "fr": "Hongrie", - "fy_NL": "Hongarije", - "hsb": "Madźarska", - "hu": "Magyarország", - "ia": "Hungaria", - "id": "Hungaria", - "is": "Ungverjaland", - "it": "Ungheria", - "ja": "ハンガリー", - "lo": "ປະເທດຮົງກະລີ", - "nl": "Hongarije", - "oc": "Ongria", - "pa_IN": "ਹੰਗਰੀ", - "pl": "Węgry", - "pt_BR": "Hungria", - "pt_PT": "Hungria", - "ru": "Венгрия", - "sk": "Maďarsko", - "sl": "Madžarska", - "sq": "Hungaria", - "sv_SE": "Ungern", - "tr": "Macaristan", - "uk": "Угорщина", - "zh_CN": "匈牙利", - "zh_TW": "匈牙利" - }, - "cities": [ - { - "city": "Budapest", - "languages": { - "bg": "Будапеща", - "cs": "Budapešť", - "el": "Βουδαπέστη", - "fa": "بوداپست", - "fy_NL": "Bûdapest", - "is": "Búdapest", - "ja": "ブダペスト", - "nl": "Boedapest", - "oc": "Budapèst", - "pa_IN": "ਬੁਦਾਪੈਸਤ", - "pl": "Budapeszt", - "pt_BR": "Budapeste", - "pt_PT": "Budapeste", - "ru": "Будапешт", - "sk": "Budapešť", - "sl": "Budimpešta", - "tr": "Budapeşte", - "uk": "Будапешт", - "zh_CN": "布达佩斯", - "zh_TW": "布達佩斯" - }, - "wikiDataID": "Q1781" - } - ], - "wikiDataID": "Q28" - }, - { - "countryCode": "ie", - "languages": { - "bg": "Ирландия", - "co": "Irlanda", - "cs": "Irsko", - "cy": "Gweriniaeth Iwerddon", - "da": "Irland", - "de": "Irland", - "dsb": "Irska", - "el": "Δημοκρατία της Ιρλανδίας", - "en": "Republic of Ireland", - "en_CA": "Republic of Ireland", - "en_GB": "Ireland", - "es_AR": "Irlanda", - "es_CL": "Irlanda", - "es_ES": "Irlanda", - "es_MX": "Irlanda", - "fa": "ایرلند", - "fi": "Irlanti", - "fr": "Irlande", - "fy_NL": "Ierlân", - "hsb": "Irska", - "hu": "Írország", - "ia": "Republica de Irlanda", - "id": "Republik Irlandia", - "is": "Írska lýðveldið", - "it": "Irlanda", - "ja": "アイルランド", - "lo": "ປະເທດອຽກລັງ", - "nl": "Ierland", - "oc": "Irlanda", - "pa_IN": "ਆਇਰਲੈਂਡ", - "pl": "Irlandia", - "pt_BR": "República da Irlanda", - "pt_PT": "República da Irlanda", - "ru": "Ирландия", - "sk": "Írsko", - "sl": "Irska", - "sq": "Republika e Irlandës", - "sv_SE": "Irland", - "tr": "İrlanda", - "uk": "Ірландія", - "zh_CN": "爱尔兰", - "zh_TW": "愛爾蘭" - }, - "cities": [ - { - "city": "Dublin", - "languages": { - "bg": "Дъблин", - "co": "Dublinu", - "cy": "Dulyn", - "el": "Δουβλίνο", - "es_AR": "Dublín", - "es_CL": "Dublín", - "es_ES": "Dublín", - "es_MX": "Dublín", - "fa": "دوبلین", - "is": "Dyflinn", - "it": "Dublino", - "ja": "ダブリン", - "pa_IN": "ਡਬਲਿਨ", - "ru": "Дублин", - "sq": "Dublini", - "uk": "Дублін", - "zh_CN": "都柏林", - "zh_TW": "都柏林" - }, - "wikiDataID": "Q1761" - } - ], - "wikiDataID": "Q27" - }, - { - "wikiDataID": "Q801", - "countryCode": "il", - "languages": { - "bg": "Израел", - "co": "Israele", - "cs": "Izrael", - "cy": "Israel", - "da": "Israel", - "de": "Israel", - "dsb": "Israel", - "el": "Ισραήλ", - "en": "Israel", - "en_CA": "Israel", - "en_GB": "Israel", - "es_AR": "Israel", - "es_CL": "Israel", - "es_ES": "Israel", - "es_MX": "Israel", - "fa": "اسرائیل", - "fi": "Israel", - "fr": "Israël", - "fy_NL": "Israel", - "hsb": "Israel", - "hu": "Izrael", - "ia": "Israel", - "id": "Israel", - "is": "Ísrael", - "it": "Israele", - "ja": "イスラエル", - "lo": "ປະເທດອິດສະຣາເອນ", - "nl": "Israël", - "oc": "Israèl", - "pa_IN": "ਇਜ਼ਰਾਈਲ", - "pl": "Izrael", - "pt_BR": "Israel", - "pt_PT": "Israel", - "ru": "Израиль", - "sk": "Izrael", - "sl": "Izrael", - "sq": "Izraeli", - "sv_SE": "Israel", - "tr": "İsrail", - "uk": "Ізраїль", - "zh_CN": "以色列", - "zh_TW": "以色列" - }, - "cities": [ - { - "wikiDataID": "Q33935", - "city": "Tel Aviv", - "languages": { - "bg": "Тел Авив", - "de": "Tel Aviv-Jaffa", - "el": "Τελ Αβίβ", - "fa": "تلآویو", - "hu": "Tel-Aviv", - "is": "Tel Avív", - "ja": "テルアビブ", - "pa_IN": "ਤਲ ਅਵੀਵ", - "pl": "Tel Awiw-Jafa", - "ru": "Тель-Авив", - "sk": "Tel Aviv - Jafo", - "uk": "Тель-Авів-Яфо", - "zh_CN": "特拉维夫", - "zh_TW": "臺拉維夫" - } - } - ] - }, - { - "countryCode": "it", - "languages": { - "bg": "Италия", - "co": "Italia", - "cs": "Itálie", - "cy": "yr Eidal", - "da": "Italien", - "de": "Italien", - "dsb": "Italska", - "el": "Ιταλία", - "en": "Italy", - "en_CA": "Italy", - "en_GB": "Italy", - "es_AR": "Italia", - "es_CL": "Italia", - "es_ES": "Italia", - "es_MX": "Italia", - "fa": "ایتالیا", - "fi": "Italia", - "fr": "Italie", - "fy_NL": "Itaalje", - "hsb": "Italska", - "hu": "Olaszország", - "ia": "Italia", - "id": "Italia", - "is": "Ítalía", - "it": "Italia", - "ja": "イタリア", - "lo": "ອິຕາລີ", - "nl": "Italië", - "oc": "Itàlia", - "pa_IN": "ਇਟਲੀ", - "pl": "Włochy", - "pt_BR": "Itália", - "pt_PT": "Itália", - "ru": "Италия", - "sk": "Taliansko", - "sl": "Italija", - "sq": "Italia", - "sv_SE": "Italien", - "tr": "İtalya", - "uk": "Італія", - "zh_CN": "意大利", - "zh_TW": "義大利" - }, - "cities": [ - { - "city": "Milan", - "languages": { - "bg": "Милано", - "co": "Milanu", - "cs": "Milán", - "da": "Milano", - "de": "Mailand", - "el": "Μιλάνο", - "es_AR": "Milán", - "es_CL": "Milán", - "es_ES": "Milán", - "es_MX": "Milán", - "fa": "میلان", - "fi": "Milano", - "fy_NL": "Milaan", - "hsb": "Mailand", - "hu": "Milánó", - "ia": "Milano", - "is": "Mílanó", - "it": "Milano", - "ja": "ミラノ", - "nl": "Milaan", - "pa_IN": "ਮਿਲਾਨ", - "pl": "Mediolan", - "pt_BR": "Milão", - "pt_PT": "Milão", - "ru": "Милан", - "sk": "Miláno", - "sl": "Milano", - "sq": "Milano", - "sv_SE": "Milano", - "tr": "Milano", - "uk": "Мілан", - "zh_CN": "米兰", - "zh_TW": "米蘭" - }, - "wikiDataID": "Q490" - } - ], - "wikiDataID": "Q38" - }, - { - "countryCode": "jp", - "languages": { - "bg": "Япония", - "co": "Giappone", - "cs": "Japonsko", - "cy": "Japan", - "da": "Japan", - "de": "Japan", - "dsb": "Japańska", - "el": "Ιαπωνία", - "en": "Japan", - "en_CA": "Japan", - "en_GB": "Japan", - "es_AR": "Japón", - "es_CL": "Japón", - "es_ES": "Japón", - "es_MX": "Japón", - "fa": "ژاپن", - "fi": "Japani", - "fr": "Japon", - "fy_NL": "Japan", - "hsb": "Japanska", - "hu": "Japán", - "ia": "Japon", - "id": "Jepang", - "is": "Japan", - "it": "Giappone", - "ja": "日本", - "lo": "ປະເທດຍີ່ປຸ່ນ", - "nl": "Japan", - "oc": "Japon", - "pa_IN": "ਜਪਾਨ", - "pl": "Japonia", - "pt_BR": "Japão", - "pt_PT": "Japão", - "ru": "Япония", - "sk": "Japonsko", - "sl": "Japonska", - "sq": "Japonia", - "sv_SE": "Japan", - "tr": "Japonya", - "uk": "Японія", - "zh_CN": "日本", - "zh_TW": "日本" - }, - "cities": [ - { - "city": "Osaka", - "languages": { - "en": "Ōsaka", - "en_CA": "Ōsaka", - "en_GB": "Ōsaka", - "ja": "大阪", - "nl": "Ōsaka", - "zh_CN": "大阪", - "zh_TW": "大阪" - }, - "wikiDataID": "Q11439906" - }, - { - "city": "Tokyo", - "languages": { - "bg": "Токио", - "co": "Tokiu", - "cs": "Tokio", - "de": "Tokio", - "dsb": "Tokio", - "el": "Τόκιο", - "es_AR": "Tokio", - "es_CL": "Tokio", - "es_ES": "Tokio", - "es_MX": "Tokio", - "fa": "توکیو", - "fi": "Tokio", - "fy_NL": "Tokio", - "hsb": "Tokio", - "hu": "Tokió", - "id": "Prefektur Tokyo", - "is": "Tókýó", - "ja": "東京都", - "lo": "ໂຕກຽວ", - "nl": "Tokio", - "oc": "prefectura de Tòquio", - "pa_IN": "ਟੋਕੀਓ", - "pl": "Tokio", - "pt_BR": "Tóquio", - "pt_PT": "Tóquio", - "ru": "Токио", - "sk": "Tokio", - "sl": "Tokio", - "sq": "Tokjo", - "sv_SE": "Tokyo prefektur", - "uk": "Токіо", - "zh_CN": "东京都", - "zh_TW": "東京都" - }, - "wikiDataID": "Q1490" - } - ], - "wikiDataID": "Q17" - }, - { - "countryCode": "lv", - "languages": { - "bg": "Латвия", - "co": "Lettonia", - "cs": "Lotyšsko", - "cy": "Latfia", - "da": "Letland", - "de": "Lettland", - "dsb": "Letiska", - "el": "Λετονία", - "en": "Latvia", - "en_CA": "Latvia", - "en_GB": "Latvia", - "es_AR": "Letonia", - "es_CL": "Letonia", - "es_ES": "Letonia", - "es_MX": "Letonia", - "fa": "لتونی", - "fi": "Latvia", - "fr": "Lettonie", - "fy_NL": "Letlân", - "hsb": "Letiska", - "hu": "Lettország", - "ia": "Lettonia", - "id": "Latvia", - "is": "Lettland", - "it": "Lettonia", - "ja": "ラトビア", - "lo": "ປະເທດແລດໂຕນີ", - "nl": "Letland", - "oc": "Letònia", - "pa_IN": "ਲਾਤਵੀਆ", - "pl": "Łotwa", - "pt_BR": "Letônia", - "pt_PT": "Letónia", - "ru": "Латвия", - "sk": "Lotyšsko", - "sl": "Latvija", - "sq": "Letonia", - "sv_SE": "Lettland", - "tr": "Letonya", - "uk": "Латвія", - "zh_CN": "拉脱维亚", - "zh_TW": "拉脫維亞" - }, - "cities": [ - { - "city": "Riga", - "languages": { - "bg": "Рига", - "el": "Ρίγα", - "fa": "ریگا", - "fi": "Riika", - "is": "Ríga", - "ja": "リーガ", - "pa_IN": "ਰੀਗਾ", - "pl": "Ryga", - "ru": "Рига", - "uk": "Рига", - "zh_CN": "里加", - "zh_TW": "里加" - }, - "wikiDataID": "Q1773" - } - ], - "wikiDataID": "Q211" - }, - { - "wikiDataID": "Q96", - "countryCode": "mx", - "languages": { - "bg": "Мексико", - "co": "Messicu", - "cs": "Mexiko", - "cy": "Mecsico", - "da": "Mexico", - "de": "Mexiko", - "dsb": "Mexiko", - "el": "Μεξικό", - "en": "Mexico", - "en_CA": "Mexico", - "en_GB": "Mexico", - "es_AR": "México", - "es_CL": "México", - "es_ES": "México", - "es_MX": "México", - "fa": "مکزیک", - "fi": "Meksiko", - "fr": "Mexique", - "fy_NL": "Meksiko", - "hsb": "Mexiko", - "hu": "Mexikó", - "ia": "Mexico", - "id": "Meksiko", - "is": "Mexíkó", - "it": "Messico", - "ja": "メキシコ", - "lo": "ປະເທດເມັກຊິກ", - "nl": "Mexico", - "oc": "Mexic", - "pa_IN": "ਮੈਕਸੀਕੋ", - "pl": "Meksyk", - "pt_BR": "México", - "pt_PT": "México", - "ru": "Мексика", - "sk": "Mexiko", - "sl": "Mehika", - "sq": "Meksika", - "sv_SE": "Mexiko", - "tr": "Meksika", - "uk": "Мексика", - "zh_CN": "墨西哥", - "zh_TW": "墨西哥" - }, - "cities": [ - { - "wikiDataID": "Q79754", - "city": "Queretaro", - "languages": { - "bg": "Керетаро", - "cs": "Querétaro", - "cy": "Querétaro", - "da": "Querétaro", - "de": "Querétaro", - "el": "Κερέταρο", - "en": "Querétaro", - "en_CA": "Querétaro", - "en_GB": "Querétaro", - "es_AR": "Querétaro", - "es_CL": "Querétaro", - "es_ES": "Querétaro", - "es_MX": "Querétaro", - "fa": "کرتارو", - "fi": "Querétaro", - "fr": "Querétaro", - "hu": "Querétaro", - "id": "Querétaro", - "is": "Querétaro (fylki)", - "it": "Querétaro", - "ja": "ケレタロ州", - "nl": "Querétaro", - "oc": "Querétaro", - "pl": "Querétaro", - "pt_BR": "Querétaro (estado)", - "pt_PT": "Querétaro", - "ru": "Керетаро", - "sk": "Querétaro", - "sv_SE": "Querétaro Arteaga", - "tr": "Querétaro", - "uk": "Керетаро", - "zh_CN": "克雷塔羅州", - "zh_TW": "克雷塔羅州" - } - } - ] - }, - { - "countryCode": "nl", - "languages": { - "bg": "Нидерландия", - "co": "Paesi Bassi", - "cs": "Nizozemsko", - "cy": "Yr Iseldiroedd", - "da": "Holland", - "de": "Niederlande", - "dsb": "Nižozemska", - "el": "Ολλανδία", - "en": "Netherlands", - "en_CA": "Netherlands", - "en_GB": "Netherlands", - "es_AR": "Países Bajos", - "es_CL": "Países Bajos", - "es_ES": "Países Bajos", - "es_MX": "Países Bajos", - "fa": "هلند", - "fi": "Alankomaat", - "fr": "Pays-Bas", - "fy_NL": "Nederlân", - "hsb": "Nižozemska", - "hu": "Hollandia", - "ia": "Paises Basse", - "id": "Belanda", - "is": "Holland", - "it": "Paesi Bassi", - "ja": "オランダ", - "lo": "ປະເທດໂຮນລັງ", - "nl": "Nederland", - "oc": "Païses Basses", - "pa_IN": "ਨੀਦਰਲੈਂਡ", - "pl": "Holandia", - "pt_BR": "Países Baixos", - "pt_PT": "Países Baixos", - "ru": "Нидерланды", - "sk": "Holandsko", - "sl": "Nizozemska", - "sq": "Holanda", - "sv_SE": "Nederländerna", - "tr": "Hollanda", - "uk": "Нідерланди", - "zh_CN": "荷兰", - "zh_TW": "荷蘭" - }, - "cities": [ - { - "city": "Amsterdam", - "languages": { - "bg": "Амстердам", - "el": "Άμστερνταμ", - "es_AR": "Ámsterdam", - "es_CL": "Ámsterdam", - "es_ES": "Ámsterdam", - "es_MX": "Ámsterdam", - "fa": "آمستردام", - "hu": "Amszterdam", - "ja": "アムステルダム", - "lo": "ອຳສະເຕີດຳ", - "pa_IN": "ਅਮਸਤਰਦਮ", - "pt_BR": "Amsterdã", - "pt_PT": "Amesterdão", - "ru": "Амстердам", - "sq": "Amsterdami", - "uk": "Амстердам", - "zh_CN": "阿姆斯特丹", - "zh_TW": "阿姆斯特丹" - }, - "wikiDataID": "Q727" - } - ], - "wikiDataID": "Q55" - }, - { - "countryCode": "no", - "languages": { - "bg": "Норвегия", - "co": "Nurvegia", - "cs": "Norsko", - "cy": "Norwy", - "da": "Norge", - "de": "Norwegen", - "dsb": "Norwegska", - "el": "Νορβηγία", - "en": "Norway", - "en_CA": "Norway", - "en_GB": "Norway", - "es_AR": "Noruega", - "es_CL": "Noruega", - "es_ES": "Noruega", - "es_MX": "Noruega", - "fa": "نروژ", - "fi": "Norja", - "fr": "Norvège", - "fy_NL": "Noarwegen", - "hsb": "Norwegska", - "hu": "Norvégia", - "ia": "Norvegia", - "id": "Norwegia", - "is": "Noregur", - "it": "Norvegia", - "ja": "ノルウェー", - "lo": "ປະເທດນອກແວດ", - "nl": "Noorwegen", - "oc": "Norvègia", - "pa_IN": "ਨੌਰਵੇ", - "pl": "Norwegia", - "pt_BR": "Noruega", - "pt_PT": "Noruega", - "ru": "Норвегия", - "sk": "Nórsko", - "sl": "Norveška", - "sq": "Norvegjia", - "sv_SE": "Norge", - "tr": "Norveç", - "uk": "Норвегія", - "zh_CN": "挪威", - "zh_TW": "挪威" - }, - "cities": [ - { - "city": "Oslo", - "languages": { - "bg": "Осло", - "co": "Oslu", - "el": "Όσλο", - "fa": "اسلو", - "is": "Ósló", - "ja": "オスロ", - "oc": "Òslo", - "pa_IN": "ਓਸਲੋ", - "ru": "Осло", - "uk": "Осло", - "zh_CN": "奥斯陆", - "zh_TW": "奧斯陸" - }, - "wikiDataID": "Q585" - }, - { - "wikiDataID": "Q25416", - "city": "Stavanger", - "languages": { - "bg": "Ставангер", - "el": "Σταβάνγκερ", - "en": "Stavanger Municipality", - "en_CA": "Stavanger Municipality", - "en_GB": "Stavanger Municipality", - "fa": "استاوانگر", - "is": "Stafangur", - "ja": "スタヴァンゲル", - "ru": "Ставангер", - "sv_SE": "Stavangers kommun", - "uk": "Ставанґер", - "zh_CN": "斯塔万格", - "zh_TW": "斯塔万格" - } - } - ], - "wikiDataID": "Q20" - }, - { - "countryCode": "nz", - "languages": { - "bg": "Нова Зеландия", - "co": "Nova Zilanda", - "cs": "Nový Zéland", - "cy": "Seland Newydd", - "da": "New Zealand", - "de": "Neuseeland", - "dsb": "Nowoseelandska", - "el": "Νέα Ζηλανδία", - "en": "New Zealand", - "en_CA": "New Zealand", - "en_GB": "New Zealand", - "es_AR": "Nueva Zelanda", - "es_CL": "Nueva Zelanda", - "es_ES": "Nueva Zelanda", - "es_MX": "Nueva Zelanda", - "fa": "نیوزیلند", - "fi": "Uusi-Seelanti", - "fr": "Nouvelle-Zélande", - "fy_NL": "Nij-Seelân", - "hsb": "Nowoseelandska", - "hu": "Új-Zéland", - "ia": "Nove Zelanda", - "id": "Selandia Baru", - "is": "Nýja-Sjáland", - "it": "Nuova Zelanda", - "ja": "ニュージーランド", - "lo": "ປະເທດນູແວນ ເຊລັງ", - "nl": "Nieuw-Zeeland", - "oc": "Aotearoa", - "pa_IN": "ਨਿਊਜ਼ੀਲੈਂਡ", - "pl": "Nowa Zelandia", - "pt_BR": "Nova Zelândia", - "pt_PT": "Nova Zelândia", - "ru": "Новая Зеландия", - "sk": "Nový Zéland", - "sl": "Nova Zelandija", - "sq": "Zelanda e Re", - "sv_SE": "Nya Zeeland", - "tr": "Yeni Zelanda", - "uk": "Нова Зеландія", - "zh_CN": "新西兰", - "zh_TW": "紐西蘭" - }, - "cities": [ - { - "city": "Auckland", - "languages": { - "bg": "Окланд", - "el": "Όκλαντ", - "fa": "آوکلند", - "ja": "オークランド", - "pa_IN": "ਆਕਲੈਂਡ", - "ru": "Окленд", - "sq": "Okland", - "uk": "Окленд", - "zh_CN": "奧克蘭", - "zh_TW": "奧克蘭" - }, - "wikiDataID": "Q37100" - } - ], - "wikiDataID": "Q664" - }, - { - "countryCode": "pl", - "languages": { - "bg": "Полша", - "co": "Polonia", - "cs": "Polsko", - "cy": "Gwlad Pwyl", - "da": "Polen", - "de": "Polen", - "dsb": "Pólska", - "el": "Πολωνία", - "en": "Poland", - "en_CA": "Poland", - "en_GB": "Poland", - "es_AR": "Polonia", - "es_CL": "Polonia", - "es_ES": "Polonia", - "es_MX": "Polonia", - "fa": "لهستان", - "fi": "Puola", - "fr": "Pologne", - "fy_NL": "Poalen", - "hsb": "Pólska", - "hu": "Lengyelország", - "ia": "Polonia", - "id": "Polandia", - "is": "Pólland", - "it": "Polonia", - "ja": "ポーランド", - "lo": "ປະເທດໂປໂລຍ", - "nl": "Polen", - "oc": "Polonha", - "pa_IN": "ਪੋਲੈਂਡ", - "pl": "Polska", - "pt_BR": "Polônia", - "pt_PT": "Polónia", - "ru": "Польша", - "sk": "Poľsko", - "sl": "Poljska", - "sq": "Polonia", - "sv_SE": "Polen", - "tr": "Polonya", - "uk": "Польща", - "zh_CN": "波兰", - "zh_TW": "波蘭" - }, - "cities": [ - { - "city": "Warsaw", - "languages": { - "bg": "Варшава", - "co": "Varsavia", - "cs": "Varšava", - "da": "Warszawa", - "de": "Warschau", - "dsb": "Waršawa", - "el": "Βαρσοβία", - "es_AR": "Varsovia", - "es_CL": "Varsovia", - "es_ES": "Varsovia", - "es_MX": "Varsovia", - "fa": "ورشو", - "fi": "Varsova", - "fr": "Varsovie", - "fy_NL": "Warsjau", - "hsb": "Waršawa", - "hu": "Varsó", - "ia": "Varsovia", - "id": "Warsawa", - "is": "Varsjá", - "it": "Varsavia", - "ja": "ワルシャワ", - "nl": "Warschau", - "oc": "Varsòvia", - "pa_IN": "ਵਾਰਸਾ", - "pl": "Warszawa", - "pt_BR": "Varsóvia", - "pt_PT": "Varsóvia", - "ru": "Варшава", - "sk": "Varšava", - "sl": "Varšava", - "sq": "Varshava", - "sv_SE": "Warszawa", - "tr": "Varşova", - "uk": "Варшава", - "zh_CN": "华沙", - "zh_TW": "華沙" - }, - "wikiDataID": "Q270" - } - ], - "wikiDataID": "Q36" - }, - { - "countryCode": "pt", - "languages": { - "bg": "Португалия", - "co": "Portugallu", - "cs": "Portugalsko", - "cy": "Portiwgal", - "da": "Portugal", - "de": "Portugal", - "dsb": "Portugalska", - "el": "Πορτογαλία", - "en": "Portugal", - "en_CA": "Portugal", - "en_GB": "Portugal", - "es_AR": "Portugal", - "es_CL": "Portugal", - "es_ES": "Portugal", - "es_MX": "Portugal", - "fa": "پرتغال", - "fi": "Portugali", - "fr": "Portugal", - "fy_NL": "Portegal", - "hsb": "Portugalska", - "hu": "Portugália", - "ia": "Portugal", - "id": "Portugal", - "is": "Portúgal", - "it": "Portogallo", - "ja": "ポルトガル", - "lo": "ປະເທດປອກຕຸຍການ", - "nl": "Portugal", - "oc": "Portugal", - "pa_IN": "ਪੁਰਤਗਾਲ", - "pl": "Portugalia", - "pt_BR": "Portugal", - "pt_PT": "Portugal", - "ru": "Португалия", - "sk": "Portugalsko", - "sl": "Portugalska", - "sq": "Portugalia", - "sv_SE": "Portugal", - "tr": "Portekiz", - "uk": "Португалія", - "zh_CN": "葡萄牙", - "zh_TW": "葡萄牙" - }, - "cities": [ - { - "city": "Lisbon", - "languages": { - "bg": "Лисабон", - "co": "Lisbona", - "cs": "Lisabon", - "da": "Lissabon", - "de": "Lissabon", - "dsb": "Lisabon", - "el": "Λισαβόνα", - "es_AR": "Lisboa", - "es_CL": "Lisboa", - "es_ES": "Lisboa", - "es_MX": "Lisboa", - "fa": "لیسبون", - "fi": "Lissabon", - "fr": "Lisbonne", - "fy_NL": "Lissabon", - "hsb": "Lisabon", - "hu": "Lisszabon", - "ia": "Lisbona", - "id": "Lisboa", - "is": "Lissabon", - "it": "Lisbona", - "ja": "リスボン", - "lo": "ລີຊະບົນ", - "nl": "Lissabon", - "oc": "Lisbona", - "pa_IN": "ਲਿਸਬਨ", - "pl": "Lizbona", - "pt_BR": "Lisboa", - "pt_PT": "Lisboa", - "ru": "Лиссабон", - "sk": "Lisabon", - "sl": "Lizbona", - "sq": "Lisbona", - "sv_SE": "Lissabon", - "uk": "Лісабон", - "zh_CN": "里斯本", - "zh_TW": "里斯本" - }, - "wikiDataID": "Q597" - } - ], - "wikiDataID": "Q45" - }, - { - "countryCode": "ro", - "languages": { - "bg": "Румъния", - "co": "Romania", - "cs": "Rumunsko", - "cy": "Rwmania", - "da": "Rumænien", - "de": "Rumänien", - "dsb": "Rumuńska", - "el": "Ρουμανία", - "en": "Romania", - "en_CA": "Romania", - "en_GB": "Romania", - "es_AR": "Rumania", - "es_CL": "Rumania", - "es_ES": "Rumania", - "es_MX": "Rumania", - "fa": "رومانی", - "fi": "Romania", - "fr": "Roumanie", - "fy_NL": "Roemeenje", - "hsb": "Rumunska", - "hu": "Románia", - "ia": "Romania", - "id": "Rumania", - "is": "Rúmenía", - "it": "Romania", - "ja": "ルーマニア", - "lo": "ປະເທດຣູມານີ", - "nl": "Roemenië", - "oc": "Romania", - "pa_IN": "ਰੋਮਾਨੀਆ", - "pl": "Rumunia", - "pt_BR": "Romênia", - "pt_PT": "Roménia", - "ru": "Румыния", - "sk": "Rumunsko", - "sl": "Romunija", - "sq": "Rumania", - "sv_SE": "Rumänien", - "tr": "Romanya", - "uk": "Румунія", - "zh_CN": "罗马尼亚", - "zh_TW": "羅馬尼亞" - }, - "cities": [ - { - "city": "Bucharest", - "languages": { - "bg": "Букурещ", - "co": "Bucarest", - "cs": "Bukurešť", - "cy": "Bwcarést", - "da": "Bukarest", - "de": "Bukarest", - "dsb": "Bukarest", - "el": "Βουκουρέστι", - "es_AR": "Bucarest", - "es_CL": "Bucarest", - "es_ES": "Bucarest", - "es_MX": "Bucarest", - "fa": "بخارست", - "fi": "Bukarest", - "fr": "Bucarest", - "fy_NL": "Bûkarest", - "hsb": "Bukarest", - "hu": "Bukarest", - "ia": "Bucarest", - "id": "Bukares", - "is": "Búkarest", - "it": "Bucarest", - "ja": "ブカレスト", - "nl": "Boekarest", - "oc": "Bucarèst", - "pa_IN": "ਬੁਖ਼ਾਰੈਸਟ", - "pl": "Bukareszt", - "pt_BR": "Bucareste", - "pt_PT": "Bucareste", - "ru": "Бухарест", - "sk": "Bukurešť", - "sl": "Bukarešta", - "sq": "Bukureshti", - "sv_SE": "Bukarest", - "tr": "Bükreş", - "uk": "Бухарест", - "zh_CN": "布加勒斯特", - "zh_TW": "布加勒斯特" - }, - "wikiDataID": "Q19660" - } - ], - "wikiDataID": "Q218" - }, - { - "countryCode": "rs", - "languages": { - "bg": "Сърбия", - "co": "Serbia", - "cs": "Srbsko", - "cy": "Serbia", - "da": "Serbien", - "de": "Serbien", - "dsb": "Serbiska", - "el": "Σερβία", - "en": "Serbia", - "en_CA": "Serbia", - "en_GB": "Serbia", - "es_AR": "Serbia", - "es_CL": "Serbia", - "es_ES": "Serbia", - "es_MX": "Serbia", - "fa": "صربستان", - "fi": "Serbia", - "fr": "Serbie", - "fy_NL": "Servje", - "hsb": "Serbiska", - "hu": "Szerbia", - "ia": "Serbia", - "id": "Serbia", - "is": "Serbía", - "it": "Serbia", - "ja": "セルビア", - "lo": "ປະເທດແຊກບີ", - "nl": "Servië", - "oc": "Serbia", - "pa_IN": "ਸਰਬੀਆ", - "pl": "Serbia", - "pt_BR": "Sérvia", - "pt_PT": "Sérvia", - "ru": "Сербия", - "sk": "Srbsko", - "sl": "Srbija", - "sq": "Serbia", - "sv_SE": "Serbien", - "tr": "Sırbistan", - "uk": "Сербія", - "zh_CN": "塞尔维亚", - "zh_TW": "塞爾維亞" - }, - "cities": [ - { - "city": "Belgrade", - "languages": { - "bg": "Белград", - "co": "Belgradu", - "cs": "Bělehrad", - "cy": "Beograd", - "da": "Beograd", - "de": "Belgrad", - "dsb": "Běłogrod", - "el": "Βελιγράδι", - "es_AR": "Belgrado", - "es_CL": "Belgrado", - "es_ES": "Belgrado", - "es_MX": "Belgrado", - "fa": "بلگراد", - "fi": "Belgrad", - "fy_NL": "Belgrado", - "hsb": "Běłohród", - "hu": "Belgrád", - "ia": "Belgrad", - "id": "Beograd", - "is": "Belgrad", - "it": "Belgrado", - "ja": "ベオグラード", - "nl": "Belgrado", - "oc": "Belgrad", - "pa_IN": "ਬੈਲਗ੍ਰਾਦ", - "pl": "Belgrad", - "pt_BR": "Belgrado", - "pt_PT": "Belgrado", - "ru": "Белград", - "sk": "Belehrad", - "sl": "Beograd", - "sq": "Beogradi", - "sv_SE": "Belgrad", - "tr": "Belgrad", - "uk": "Белград", - "zh_CN": "贝尔格莱德", - "zh_TW": "貝爾格勒" - }, - "wikiDataID": "Q3711" - } - ], - "wikiDataID": "Q403" - }, - { - "countryCode": "se", - "languages": { - "bg": "Швеция", - "co": "Svezia", - "cs": "Švédsko", - "cy": "Sweden", - "da": "Sverige", - "de": "Schweden", - "dsb": "Šwedska", - "el": "Σουηδία", - "en": "Sweden", - "en_CA": "Sweden", - "en_GB": "Sweden", - "es_AR": "Suecia", - "es_CL": "Suecia", - "es_ES": "Suecia", - "es_MX": "Suecia", - "fa": "سوئد", - "fi": "Ruotsi", - "fr": "Suède", - "fy_NL": "Sweden", - "hsb": "Šwedska", - "hu": "Svédország", - "ia": "Svedia", - "id": "Swedia", - "is": "Svíþjóð", - "it": "Svezia", - "ja": "スウェーデン", - "lo": "ປະເທດຊູແອດ", - "nl": "Zweden", - "oc": "Suècia", - "pa_IN": "ਸਵੀਡਨ", - "pl": "Szwecja", - "pt_BR": "Suécia", - "pt_PT": "Suécia", - "ru": "Швеция", - "sk": "Švédsko", - "sl": "Švedska", - "sq": "Suedia", - "sv_SE": "Sverige", - "tr": "İsveç", - "uk": "Швеція", - "zh_CN": "瑞典", - "zh_TW": "瑞典" - }, - "cities": [ - { - "city": "Gothenburg", - "languages": { - "bg": "Гьотеборг", - "co": "Göteborg", - "cs": "Göteborg", - "cy": "Göteborg", - "da": "Göteborg", - "de": "Göteborg", - "dsb": "Göteborg", - "el": "Γκέτεμποργκ", - "es_AR": "Gotemburgo", - "es_CL": "Gotemburgo", - "es_ES": "Gotemburgo", - "es_MX": "Gotemburgo", - "fa": "یوتبری", - "fi": "Göteborg", - "fr": "Göteborg", - "fy_NL": "Goateboarch", - "hsb": "Göteborg", - "hu": "Göteborg", - "ia": "Göteborg", - "id": "Göteborg", - "is": "Gautaborg", - "it": "Göteborg", - "ja": "イェーテボリ", - "nl": "Göteborg", - "oc": "Göteborg", - "pl": "Göteborg", - "pt_BR": "Gotemburgo", - "pt_PT": "Gotemburgo", - "ru": "Гётеборг", - "sk": "Göteborg", - "sl": "Göteborg", - "sq": "Göteborg", - "sv_SE": "Göteborg", - "tr": "Göteborg", - "uk": "Гетеборг", - "zh_CN": "哥德堡", - "zh_TW": "哥特堡" - }, - "wikiDataID": "Q25287" - }, - { - "city": "Malmö", - "languages": { - "bg": "Малмьо", - "da": "Malmø", - "el": "Μάλμε", - "fa": "مالمو", - "ja": "マルメ", - "ru": "Мальмё", - "uk": "Мальме", - "zh_CN": "马尔默", - "zh_TW": "馬爾摩" - }, - "wikiDataID": "Q2211" - }, - { - "city": "Stockholm", - "languages": { - "bg": "Стокхолм", - "co": "Stoccolma", - "el": "Στοκχόλμη", - "es_AR": "Estocolmo", - "es_CL": "Estocolmo", - "es_ES": "Estocolmo", - "es_MX": "Estocolmo", - "fa": "استکهلم", - "fi": "Tukholma", - "is": "Stokkhólmur", - "it": "Stoccolma", - "ja": "ストックホルム", - "oc": "Estocòlme", - "pa_IN": "ਸਟਾਕਹੋਮ", - "pl": "Sztokholm", - "pt_BR": "Estocolmo", - "pt_PT": "Estocolmo", - "ru": "Стокгольм", - "sk": "Štokholm", - "sq": "Stokholmi", - "uk": "Стокгольм", - "zh_CN": "斯德哥尔摩", - "zh_TW": "斯德哥爾摩" - }, - "wikiDataID": "Q1754" - } - ], - "wikiDataID": "Q34" - }, - { - "countryCode": "sg", - "languages": { - "bg": "Сингапур", - "co": "Singapore", - "cs": "Singapur", - "cy": "Singapôr", - "da": "Singapore", - "de": "Singapur", - "dsb": "Singapur", - "el": "Σιγκαπούρη", - "en": "Singapore", - "en_CA": "Singapore", - "en_GB": "Singapore", - "es_AR": "Singapur", - "es_CL": "Singapur", - "es_ES": "Singapur", - "es_MX": "Singapur", - "fa": "سنگاپور", - "fi": "Singapore", - "fr": "Singapour", - "fy_NL": "Singapore", - "hsb": "Singapur", - "hu": "Szingapúr", - "ia": "Singapur", - "id": "Singapura", - "is": "Singapúr", - "it": "Singapore", - "ja": "シンガポール", - "lo": "ປະເທດສິງກະໂປ", - "nl": "Singapore", - "oc": "Singapor", - "pa_IN": "ਸਿੰਘਾਪੁਰ", - "pl": "Singapur", - "pt_BR": "Singapura", - "pt_PT": "Singapura", - "ru": "Сингапур", - "sk": "Singapur", - "sl": "Singapur", - "sq": "Singapori", - "sv_SE": "Singapore", - "tr": "Singapur", - "uk": "Сінгапур", - "zh_CN": "新加坡", - "zh_TW": "新加坡" - }, - "cities": [ - { - "wikiDataID": "Q334", - "city": "Singapore", - "languages": { - "bg": "Сингапур", - "cs": "Singapur", - "cy": "Singapôr", - "de": "Singapur", - "dsb": "Singapur", - "el": "Σιγκαπούρη", - "es_AR": "Singapur", - "es_CL": "Singapur", - "es_ES": "Singapur", - "es_MX": "Singapur", - "fa": "سنگاپور", - "fr": "Singapour", - "hsb": "Singapur", - "hu": "Szingapúr", - "ia": "Singapur", - "id": "Singapura", - "is": "Singapúr", - "ja": "シンガポール", - "lo": "ປະເທດສິງກະໂປ", - "oc": "Singapor", - "pa_IN": "ਸਿੰਘਾਪੁਰ", - "pl": "Singapur", - "pt_BR": "Singapura", - "pt_PT": "Singapura", - "ru": "Сингапур", - "sk": "Singapur", - "sl": "Singapur", - "sq": "Singapori", - "tr": "Singapur", - "uk": "Сінгапур", - "zh_CN": "新加坡", - "zh_TW": "新加坡" - } - } - ], - "wikiDataID": "Q334" - }, - { - "wikiDataID": "Q215", - "countryCode": "si", - "languages": { - "bg": "Словения", - "co": "Sluvenia", - "cs": "Slovinsko", - "cy": "Slofenia", - "da": "Slovenien", - "de": "Slowenien", - "dsb": "Słowjeńska", - "el": "Σλοβενία", - "en": "Slovenia", - "en_CA": "Slovenia", - "en_GB": "Slovenia", - "es_AR": "Eslovenia", - "es_CL": "Eslovenia", - "es_ES": "Eslovenia", - "es_MX": "Eslovenia", - "fa": "اسلوونی", - "fi": "Slovenia", - "fr": "Slovénie", - "fy_NL": "Sloveenje", - "hsb": "Słowjenska", - "hu": "Szlovénia", - "ia": "Slovenia", - "id": "Slovenia", - "is": "Slóvenía", - "it": "Slovenia", - "ja": "スロベニア", - "lo": "ປະເທດສະໂລເວນີ", - "nl": "Slovenië", - "oc": "Eslovènia", - "pa_IN": "ਸਲੋਵੇਨੀਆ", - "pl": "Słowenia", - "pt_BR": "Eslovênia", - "pt_PT": "Eslovénia", - "ru": "Словения", - "sk": "Slovinsko", - "sl": "Slovenija", - "sq": "Sllovenia", - "sv_SE": "Slovenien", - "tr": "Slovenya", - "uk": "Словенія", - "zh_CN": "斯洛文尼亚", - "zh_TW": "斯洛維尼亞" - }, - "cities": [ - { - "wikiDataID": "Q437", - "city": "Ljubljana", - "languages": { - "bg": "Любляна", - "cs": "Lublaň", - "el": "Λιουμπλιάνα", - "es_AR": "Liubliana", - "es_CL": "Liubliana", - "es_ES": "Liubliana", - "es_MX": "Liubliana", - "fa": "لیوبلیانا", - "it": "Lubiana", - "ja": "リュブリャナ", - "pa_IN": "ਲਿਊਬਲਿਆਨਾ", - "pl": "Lublana", - "pt_BR": "Liubliana", - "pt_PT": "Liubliana", - "ru": "Любляна", - "sk": "Ľubľana", - "sq": "Lubjana", - "uk": "Любляна", - "zh_CN": "卢布尔雅那", - "zh_TW": "盧比安納" - } - } - ] - }, - { - "wikiDataID": "Q214", - "countryCode": "sk", - "languages": { - "bg": "Словакия", - "co": "Sluvacchia", - "cs": "Slovensko", - "cy": "Slofacia", - "da": "Slovakiet", - "de": "Slowakei", - "dsb": "Słowakska", - "el": "Σλοβακία", - "en": "Slovakia", - "en_CA": "Slovakia", - "en_GB": "Slovakia", - "es_AR": "Eslovaquia", - "es_CL": "Eslovaquia", - "es_ES": "Eslovaquia", - "es_MX": "Eslovaquia", - "fa": "اسلواکی", - "fi": "Slovakia", - "fr": "Slovaquie", - "fy_NL": "Slowakije", - "hsb": "Słowakska", - "hu": "Szlovákia", - "ia": "Slovachia", - "id": "Slowakia", - "is": "Slóvakía", - "it": "Slovacchia", - "ja": "スロバキア", - "lo": "ປະເທດສະໂລວາກີ", - "nl": "Slowakije", - "oc": "Eslovaquia", - "pa_IN": "ਸਲੋਵਾਕੀਆ", - "pl": "Słowacja", - "pt_BR": "Eslováquia", - "pt_PT": "Eslováquia", - "ru": "Словакия", - "sk": "Slovensko", - "sl": "Slovaška", - "sq": "Sllovakia", - "sv_SE": "Slovakien", - "tr": "Slovakya", - "uk": "Словаччина", - "zh_CN": "斯洛伐克", - "zh_TW": "斯洛伐克" - }, - "cities": [ - { - "wikiDataID": "Q1780", - "city": "Bratislava", - "languages": { - "bg": "Братислава", - "el": "Μπρατισλάβα", - "fa": "براتیسلاوا", - "hsb": "Bratisława", - "hu": "Pozsony", - "ja": "ブラチスラヴァ", - "pa_IN": "ਬ੍ਰਾਤਿਸਲਾਵਾ", - "pl": "Bratysława", - "ru": "Братислава", - "sq": "Bratisllava", - "uk": "Братислава", - "zh_CN": "布拉迪斯拉发", - "zh_TW": "布拉提斯拉瓦" - } - } - ] - }, - { - "wikiDataID": "Q212", - "countryCode": "ua", - "languages": { - "bg": "Украйна", - "co": "Ucraina", - "cs": "Ukrajina", - "cy": "Wcráin", - "da": "Ukraine", - "de": "Ukraine", - "dsb": "Ukraina", - "el": "Ουκρανία", - "en": "Ukraine", - "en_CA": "Ukraine", - "en_GB": "Ukraine", - "es_AR": "Ucrania", - "es_CL": "Ucrania", - "es_ES": "Ucrania", - "es_MX": "Ucrania", - "fa": "اوکراین", - "fi": "Ukraina", - "fr": "Ukraine", - "fy_NL": "Oekraïne", - "hsb": "Ukraina", - "hu": "Ukrajna", - "ia": "Ukraina", - "id": "Ukraina", - "is": "Úkraína", - "it": "Ucraina", - "ja": "ウクライナ", - "lo": "ປະເທດອູແກຣນ", - "nl": "Oekraïne", - "oc": "Ucraïna", - "pa_IN": "ਯੂਕ੍ਰੇਨ", - "pl": "Ukraina", - "pt_BR": "Ucrânia", - "pt_PT": "Ucrânia", - "ru": "Украина", - "sk": "Ukrajina", - "sl": "Ukrajina", - "sq": "Ukraina", - "sv_SE": "Ukraina", - "tr": "Ukrayna", - "uk": "Україна", - "zh_CN": "乌克兰", - "zh_TW": "烏克蘭" - }, - "cities": [ - { - "wikiDataID": "Q1899", - "city": "Kyiv", - "languages": { - "bg": "Киев", - "co": "Kiev", - "cs": "Kyjev", - "da": "Kijev", - "de": "Kiew", - "dsb": "Kijew", - "el": "Κίεβο", - "es_AR": "Kiev", - "es_CL": "Kiev", - "es_ES": "Kiev", - "es_MX": "Kiev", - "fa": "کییف", - "fi": "Kiova", - "fr": "Kiev", - "fy_NL": "Kiev", - "hsb": "Kijew", - "hu": "Kijev", - "ia": "Kiev", - "is": "Kænugarður", - "it": "Kiev", - "ja": "キーウ", - "lo": "ຄີຟ", - "nl": "Kiev", - "oc": "Kyiiv", - "pa_IN": "ਕੀਵ", - "pl": "Kijów", - "pt_BR": "Kiev", - "pt_PT": "Kiev", - "ru": "Киев", - "sk": "Kyjev", - "sl": "Kijev", - "sq": "Kievi", - "sv_SE": "Kiev", - "tr": "Kiev", - "uk": "Київ", - "zh_CN": "基辅", - "zh_TW": "基輔" - } - } - ] - }, - { - "countryCode": "us", - "languages": { - "bg": "САЩ", - "co": "Stati Uniti d'America", - "cs": "Spojené státy americké", - "cy": "Unol Daleithiau America", - "da": "USA", - "de": "Vereinigte Staaten", - "dsb": "Zjadnośone staty Ameriki", - "el": "Ηνωμένες Πολιτείες Αμερικής", - "en": "United States of America", - "en_CA": "United States of America", - "en_GB": "United States of America", - "es_AR": "Estados Unidos", - "es_CL": "Estados Unidos", - "es_ES": "Estados Unidos", - "es_MX": "Estados Unidos", - "fa": "ایالات متحده آمریکا", - "fi": "Yhdysvallat", - "fr": "États-Unis", - "fy_NL": "Feriene Steaten fan Amearika", - "hsb": "Zjednoćene staty Ameriki", - "hu": "Amerikai Egyesült Államok", - "ia": "Statos Unite de America", - "id": "Amerika Serikat", - "is": "Bandaríkin", - "it": "Stati Uniti d'America", - "ja": "アメリカ合衆国", - "lo": "ສະຫະລັດ", - "nl": "Verenigde Staten van Amerika", - "oc": "Estats Units d'America", - "pa_IN": "ਸੰਯੁਕਤ ਰਾਜ ਅਮਰੀਕਾ", - "pl": "Stany Zjednoczone", - "pt_BR": "Estados Unidos", - "pt_PT": "Estados Unidos", - "ru": "США", - "sk": "Spojené štáty americké", - "sl": "Združene države Amerike", - "sq": "Shtetet e Bashkuara të Amerikës", - "sv_SE": "USA", - "tr": "Amerika Birleşik Devletleri", - "uk": "Сполучені Штати Америки", - "zh_CN": "美国", - "zh_TW": "美國" - }, - "cities": [ - { - "city": "Ashburn, VA", - "languages": { - "bg": "Ашбърн", - "cs": "Ashburn", - "cy": "Ashburn, Virginia", - "da": "Ashburn", - "de": "Ashburn", - "en": "Ashburn", - "en_CA": "Ashburn", - "en_GB": "Ashburn", - "es_AR": "Ashburn", - "es_CL": "Ashburn", - "es_ES": "Ashburn", - "es_MX": "Ashburn", - "fa": "اشبرن، ویرجینیا", - "fr": "Ashburn", - "id": "Ashburn", - "it": "Ashburn", - "ja": "アッシュバーン (バージニア州)", - "nl": "Ashburn (Virginia)", - "oc": "Ashburn", - "pl": "Ashburn (Wirginia)", - "pt_BR": "Ashburn (Virgínia)", - "pt_PT": "Ashburn (Virgínia)", - "ru": "Ашберн", - "sk": "Ashburn", - "sl": "Ashburn", - "sv_SE": "Ashburn", - "uk": "Ешберн", - "zh_CN": "阿什本", - "zh_TW": "阿什本" - }, - "wikiDataID": "Q724884" - }, - { - "city": "Atlanta, GA", - "languages": { - "bg": "Атланта", - "co": "Atlanta", - "cs": "Atlanta", - "cy": "Atlanta", - "da": "Atlanta", - "de": "Atlanta", - "el": "Ατλάντα", - "en": "Atlanta", - "en_CA": "Atlanta", - "en_GB": "Atlanta", - "es_AR": "Atlanta", - "es_CL": "Atlanta", - "es_ES": "Atlanta", - "es_MX": "Atlanta", - "fa": "آتلانتا", - "fi": "Atlanta", - "fr": "Atlanta", - "fy_NL": "Atlanta", - "hu": "Atlanta", - "ia": "Atlanta", - "id": "Atlanta", - "is": "Atlanta", - "it": "Atlanta", - "ja": "アトランタ", - "nl": "Atlanta", - "oc": "Atlanta", - "pa_IN": "ਅਟਲਾਂਟਾ", - "pl": "Atlanta", - "pt_BR": "Atlanta", - "pt_PT": "Atlanta", - "ru": "Атланта", - "sk": "Atlanta", - "sl": "Atlanta", - "sq": "Atlanta", - "sv_SE": "Atlanta", - "tr": "Atlanta", - "uk": "Атланта", - "zh_CN": "亚特兰大", - "zh_TW": "亞特蘭大" - }, - "wikiDataID": "Q23556" - }, - { - "wikiDataID": "Q100", - "city": "Boston, MA", - "languages": { - "bg": "Бостън", - "co": "Boston", - "cs": "Boston", - "cy": "Boston", - "da": "Boston", - "de": "Boston", - "dsb": "Boston", - "el": "Βοστώνη", - "en": "Boston", - "en_CA": "Boston", - "en_GB": "Boston", - "es_AR": "Boston", - "es_CL": "Boston", - "es_ES": "Boston", - "es_MX": "Boston", - "fa": "بوستون", - "fi": "Boston", - "fr": "Boston", - "fy_NL": "Boston", - "hsb": "Boston", - "hu": "Boston", - "ia": "Boston", - "id": "Boston", - "is": "Boston", - "it": "Boston", - "ja": "ボストン", - "nl": "Boston", - "oc": "Boston", - "pa_IN": "ਬੌਸਟਨ", - "pl": "Boston", - "pt_BR": "Boston", - "pt_PT": "Boston", - "ru": "Бостон", - "sk": "Boston", - "sl": "Boston", - "sq": "Boston", - "sv_SE": "Boston", - "tr": "Boston", - "uk": "Бостон", - "zh_CN": "波士顿", - "zh_TW": "波士頓" - } - }, - { - "city": "Chicago, IL", - "languages": { - "bg": "Чикаго", - "co": "Chicago", - "cs": "Chicago", - "cy": "Chicago", - "da": "Chicago", - "de": "Chicago", - "dsb": "Chicago", - "el": "Σικάγο", - "en": "Chicago", - "en_CA": "Chicago", - "en_GB": "Chicago", - "es_AR": "Chicago", - "es_CL": "Chicago", - "es_ES": "Chicago", - "es_MX": "Chicago", - "fa": "شیکاگو", - "fi": "Chicago", - "fr": "Chicago", - "fy_NL": "Chicago", - "hsb": "Chicago", - "hu": "Chicago", - "ia": "Chicago", - "id": "Chicago", - "is": "Chicago", - "it": "Chicago", - "ja": "シカゴ", - "nl": "Chicago", - "oc": "Chicago", - "pa_IN": "ਸ਼ਿਕਾਗੋ", - "pl": "Chicago", - "pt_BR": "Chicago", - "pt_PT": "Chicago", - "ru": "Чикаго", - "sk": "Chicago", - "sl": "Chicago", - "sq": "Chicago", - "sv_SE": "Chicago", - "tr": "Şikago", - "uk": "Чикаго", - "zh_CN": "芝加哥", - "zh_TW": "芝加哥" - }, - "wikiDataID": "Q1297" - }, - { - "city": "Dallas, TX", - "languages": { - "bg": "Далас", - "co": "Dallas", - "cs": "Dallas", - "cy": "Dallas, Texas", - "da": "Dallas", - "de": "Dallas", - "el": "Ντάλας", - "en": "Dallas", - "en_CA": "Dallas", - "en_GB": "Dallas", - "es_AR": "Dallas", - "es_CL": "Dallas", - "es_ES": "Dallas", - "es_MX": "Dallas", - "fa": "دالاس", - "fi": "Dallas", - "fr": "Dallas", - "fy_NL": "Dallas", - "hsb": "Dallas", - "hu": "Dallas", - "ia": "Dallas", - "id": "Dallas", - "is": "Dallas", - "it": "Dallas", - "ja": "ダラス", - "nl": "Dallas", - "oc": "Dallas", - "pa_IN": "ਡਾਲਸ", - "pl": "Dallas", - "pt_BR": "Dallas", - "pt_PT": "Dallas", - "ru": "Даллас", - "sk": "Dallas", - "sl": "Dallas", - "sq": "Dallas", - "sv_SE": "Dallas", - "tr": "Dallas", - "uk": "Даллас", - "zh_CN": "达拉斯", - "zh_TW": "達拉斯" - }, - "wikiDataID": "Q16557" - }, - { - "city": "Denver, CO", - "languages": { - "bg": "Денвър", - "co": "Denver", - "cs": "Denver", - "cy": "Denver, Colorado", - "da": "Denver", - "de": "Denver", - "el": "Ντένβερ", - "en": "Denver", - "en_CA": "Denver", - "en_GB": "Denver", - "es_AR": "Denver", - "es_CL": "Denver", - "es_ES": "Denver", - "es_MX": "Denver", - "fa": "دنور", - "fi": "Denver", - "fr": "Denver", - "fy_NL": "Denver", - "hu": "Denver", - "ia": "Denver", - "id": "Denver", - "is": "Denver", - "it": "Denver", - "ja": "デンバー", - "nl": "Denver", - "oc": "Denver", - "pa_IN": "ਡੈਨਵਰ", - "pl": "Denver", - "pt_BR": "Denver", - "pt_PT": "Denver", - "ru": "Денвер", - "sk": "Denver", - "sl": "Denver", - "sq": "Denver", - "sv_SE": "Denver", - "tr": "Denver", - "uk": "Денвер", - "zh_CN": "丹佛", - "zh_TW": "丹佛" - }, - "wikiDataID": "Q16554" - }, - { - "wikiDataID": "Q12439", - "city": "Detroit, MI", - "languages": { - "bg": "Детройт", - "co": "Detroit", - "cs": "Detroit", - "cy": "Detroit", - "da": "Detroit", - "de": "Detroit", - "el": "Ντιτρόιτ", - "en": "Detroit", - "en_CA": "Detroit", - "en_GB": "Detroit", - "es_AR": "Detroit", - "es_CL": "Detroit", - "es_ES": "Detroit", - "es_MX": "Detroit", - "fa": "میشیگان، میشیگان", - "fi": "Detroit", - "fr": "Détroit", - "fy_NL": "Detroit", - "hsb": "Detroit", - "hu": "Detroit", - "ia": "Detroit", - "id": "Detroit", - "is": "Detroit", - "it": "Detroit", - "ja": "デトロイト", - "nl": "Detroit", - "oc": "Detroit", - "pa_IN": "ਡਿਟਰਾਇਟ", - "pl": "Detroit", - "pt_BR": "Detroit", - "pt_PT": "Detroit", - "ru": "Детройт", - "sk": "Detroit", - "sl": "Detroit", - "sq": "Detroit", - "sv_SE": "Detroit", - "tr": "Detroit", - "uk": "Детройт", - "zh_CN": "底特律", - "zh_TW": "底特律" - } - }, - { - "wikiDataID": "Q16555", - "city": "Houston, TX", - "languages": { - "bg": "Хюстън", - "cs": "Houston", - "cy": "Houston, Texas", - "da": "Houston", - "de": "Houston", - "el": "Χιούστον", - "en": "Houston", - "en_CA": "Houston", - "en_GB": "Houston", - "es_AR": "Houston", - "es_CL": "Houston", - "es_ES": "Houston", - "es_MX": "Houston", - "fa": "هیوستون", - "fi": "Houston", - "fr": "Houston", - "fy_NL": "Houston", - "hu": "Houston", - "ia": "Houston, Texas", - "id": "Houston", - "is": "Houston", - "it": "Houston", - "ja": "ヒューストン", - "nl": "Houston", - "oc": "Houston", - "pa_IN": "ਹੂਸਟਨ", - "pl": "Houston", - "pt_BR": "Houston", - "pt_PT": "Houston", - "ru": "Хьюстон", - "sk": "Houston", - "sl": "Houston", - "sq": "Houston", - "sv_SE": "Houston", - "tr": "Houston", - "uk": "Х'юстон", - "zh_CN": "休斯敦", - "zh_TW": "休士頓" - } - }, - { - "city": "Los Angeles, CA", - "languages": { - "bg": "Лос Анджелис", - "co": "Los Angeles", - "cs": "Los Angeles", - "cy": "Los Angeles", - "da": "Los Angeles", - "de": "Los Angeles", - "dsb": "Los Angeles", - "el": "Λος Άντζελες", - "en": "Los Angeles", - "en_CA": "Los Angeles", - "en_GB": "Los Angeles", - "es_AR": "Los Ángeles", - "es_CL": "Los Ángeles", - "es_ES": "Los Ángeles", - "es_MX": "Los Ángeles", - "fa": "لس آنجلس", - "fi": "Los Angeles", - "fr": "Los Angeles", - "fy_NL": "Los Angeles", - "hsb": "Los Angeles", - "hu": "Los Angeles", - "ia": "Los Angeles", - "id": "Los Angeles", - "is": "Los Angeles", - "it": "Los Angeles", - "ja": "ロサンゼルス", - "nl": "Los Angeles", - "oc": "Los Angeles", - "pa_IN": "ਲਾਸ ਐਂਜਲਸ", - "pl": "Los Angeles", - "pt_BR": "Los Angeles", - "pt_PT": "Los Angeles", - "ru": "Лос-Анджелес", - "sk": "Los Angeles", - "sl": "Los Angeles", - "sq": "Los Axhelos", - "sv_SE": "Los Angeles", - "tr": "Los Angeles", - "uk": "Лос-Анджелес", - "zh_CN": "洛杉矶", - "zh_TW": "洛杉磯" - }, - "wikiDataID": "Q65" - }, - { - "city": "Miami, FL", - "languages": { - "bg": "Маями", - "co": "Miami", - "cs": "Miami", - "cy": "Miami", - "da": "Miami", - "de": "Miami", - "el": "Μαϊάμι", - "en": "Miami", - "en_CA": "Miami", - "en_GB": "Miami", - "es_AR": "Miami", - "es_CL": "Miami", - "es_ES": "Miami", - "es_MX": "Miami", - "fa": "میامی", - "fi": "Miami", - "fr": "Miami", - "fy_NL": "Miami", - "hu": "Miami", - "ia": "Miami, Florida", - "id": "Miami", - "is": "Miami", - "it": "Miami", - "ja": "マイアミ", - "nl": "Miami", - "oc": "Miami", - "pl": "Miami", - "pt_BR": "Miami", - "pt_PT": "Miami", - "ru": "Майами", - "sk": "Miami", - "sl": "Miami", - "sq": "Miami", - "sv_SE": "Miami", - "tr": "Miami", - "uk": "Маямі", - "zh_CN": "迈阿密", - "zh_TW": "邁阿密" - }, - "wikiDataID": "Q8652" - }, - { - "city": "New York, NY", - "languages": { - "bg": "Ню Йорк", - "co": "New York", - "cs": "New York", - "cy": "Dinas Efrog Newydd", - "da": "New York City", - "de": "New York City", - "dsb": "New York City", - "el": "Νέα Υόρκη", - "en": "New York City", - "en_CA": "New York City", - "en_GB": "New York City", - "es_AR": "Nueva York", - "es_CL": "Nueva York", - "es_ES": "Nueva York", - "es_MX": "Nueva York", - "fa": "نیویورک", - "fi": "New York", - "fr": "New York", - "fy_NL": "New York City", - "hsb": "New York City", - "hu": "New York", - "ia": "New York", - "id": "Kota New York", - "is": "New York-borg", - "it": "New York", - "ja": "ニューヨーク", - "lo": "ນະຄອນນິວຢອກ", - "nl": "New York", - "oc": "Nòva York", - "pa_IN": "ਨਿਊਯਾਰਕ ਸ਼ਹਿਰ", - "pl": "Nowy Jork", - "pt_BR": "Nova Iorque", - "pt_PT": "Nova Iorque", - "ru": "Нью-Йорк", - "sk": "New York", - "sl": "New York", - "sq": "New York City", - "sv_SE": "New York", - "tr": "New York", - "uk": "Нью-Йорк", - "zh_CN": "纽约", - "zh_TW": "紐約" - }, - "wikiDataID": "Q60" - }, - { - "city": "Phoenix, AZ", - "languages": { - "bg": "Финикс", - "co": "Phoenix", - "cs": "Phoenix", - "cy": "Phoenix", - "da": "Phoenix", - "de": "Phoenix", - "el": "Φοίνιξ", - "en": "Phoenix", - "en_CA": "Phoenix", - "en_GB": "Phoenix", - "es_AR": "Phoenix", - "es_CL": "Phoenix", - "es_ES": "Phoenix", - "es_MX": "Phoenix", - "fa": "فینیکس", - "fi": "Phoenix", - "fr": "Phoenix", - "fy_NL": "Phoenix", - "hu": "Phoenix", - "ia": "Phoenix", - "id": "Phoenix", - "is": "Phoenix", - "it": "Phoenix", - "ja": "フェニックス", - "nl": "Phoenix", - "oc": "Phoenix", - "pa_IN": "ਫ਼ੀਨਿਕਸ", - "pl": "Phoenix", - "pt_BR": "Phoenix", - "pt_PT": "Phoenix", - "ru": "Финикс", - "sk": "Phoenix", - "sl": "Phoenix", - "sq": "Phoenix", - "sv_SE": "Phoenix", - "tr": "Phoenix", - "uk": "Фінікс", - "zh_CN": "菲尼克斯", - "zh_TW": "鳳凰城" - }, - "wikiDataID": "Q16556" - }, - { - "city": "Raleigh, NC", - "languages": { - "bg": "Роли", - "cs": "Raleigh", - "cy": "Raleigh, Gogledd Carolina", - "da": "Raleigh", - "de": "Raleigh", - "el": "Ράλεϊ", - "en": "Raleigh", - "en_CA": "Raleigh, North Carolina", - "en_GB": "Raleigh", - "es_AR": "Raleigh", - "es_CL": "Raleigh", - "es_ES": "Raleigh", - "es_MX": "Raleigh", - "fa": "رالی، کارولینای شمالی", - "fi": "Raleigh", - "fr": "Raleigh", - "fy_NL": "Raleigh", - "hu": "Raleigh", - "ia": "Raleigh", - "id": "Raleigh, Carolina Utara", - "is": "Raleigh", - "it": "Raleigh", - "ja": "ローリー", - "nl": "Raleigh", - "oc": "Raleigh", - "pl": "Raleigh", - "pt_BR": "Raleigh", - "pt_PT": "Raleigh", - "ru": "Роли", - "sk": "Raleigh", - "sl": "Raleigh", - "sq": "Raleigh", - "sv_SE": "Raleigh", - "tr": "Raleigh, Kuzey Karolina", - "uk": "Ролі", - "zh_CN": "罗利", - "zh_TW": "羅利" - }, - "wikiDataID": "Q41087" - }, - { - "city": "Salt Lake City, UT", - "languages": { - "bg": "Солт Лейк Сити", - "co": "Salt Lake City", - "cs": "Salt Lake City", - "cy": "Salt Lake City", - "da": "Salt Lake City", - "de": "Salt Lake City", - "el": "Σολτ Λέικ Σίτι", - "en": "Salt Lake City", - "en_CA": "Salt Lake City", - "en_GB": "Salt Lake City", - "es_AR": "Salt Lake City", - "es_CL": "Salt Lake City", - "es_ES": "Salt Lake City", - "es_MX": "Salt Lake City", - "fa": "سالتلیکسیتی", - "fi": "Salt Lake City", - "fr": "Salt Lake City", - "fy_NL": "Salt Lake City", - "hu": "Salt Lake City", - "ia": "Salt Lake City", - "id": "Salt Lake City", - "is": "Salt Lake City", - "it": "Salt Lake City", - "ja": "ソルトレイクシティ", - "nl": "Salt Lake City", - "oc": "Salt Lake City", - "pa_IN": "ਸਾਲਟ ਲੇਕ ਸਿਟੀ", - "pl": "Salt Lake City", - "pt_BR": "Salt Lake City", - "pt_PT": "Salt Lake City", - "ru": "Солт-Лейк-Сити", - "sk": "Salt Lake City", - "sl": "Salt Lake City", - "sq": "Salt Lake City", - "sv_SE": "Salt Lake City", - "tr": "Salt Lake City", - "uk": "Солт-Лейк-Сіті", - "zh_CN": "盐湖城", - "zh_TW": "鹽湖城" - }, - "wikiDataID": "Q23337" - }, - { - "city": "San Jose, CA", - "languages": { - "bg": "Сан Хосе", - "cs": "San José", - "cy": "San Jose, Califfornia", - "da": "San Jose", - "de": "San José", - "el": "Σαν Χοσέ", - "en": "San Jose", - "en_CA": "San Jose, California", - "en_GB": "San Jose", - "es_AR": "San José", - "es_CL": "San José", - "es_ES": "San José", - "es_MX": "San José", - "fa": "سان خوزه٬ کالیفرنیا", - "fi": "San José", - "fr": "San José", - "fy_NL": "San Jose", - "hu": "San José", - "ia": "San Jose", - "id": "San Jose, California", - "is": "San Jose", - "it": "San Jose", - "ja": "サンノゼ", - "nl": "San Jose", - "oc": "San José", - "pa_IN": "ਸਾਨ ਹੋਜ਼ੇ", - "pl": "San Jose", - "pt_BR": "São José", - "pt_PT": "São José", - "ru": "Сан-Хосе", - "sk": "San José", - "sl": "San Jose", - "sq": "San Hose", - "sv_SE": "San Jose", - "tr": "San Jose", - "uk": "Сан-Хосе", - "zh_CN": "圣何塞", - "zh_TW": "聖荷西" - }, - "wikiDataID": "Q16553" - }, - { - "city": "Seattle, WA", - "languages": { - "bg": "Сиатъл", - "co": "Seattle", - "cs": "Seattle", - "cy": "Seattle", - "da": "Seattle", - "de": "Seattle", - "el": "Σιάτλ", - "en": "Seattle", - "en_CA": "Seattle", - "en_GB": "Seattle", - "es_AR": "Seattle", - "es_CL": "Seattle", - "es_ES": "Seattle", - "es_MX": "Seattle", - "fa": "سیاتل", - "fi": "Seattle", - "fr": "Seattle", - "fy_NL": "Seattle", - "hu": "Seattle", - "ia": "Seattle", - "id": "Seattle", - "is": "Seattle", - "it": "Seattle", - "ja": "シアトル", - "nl": "Seattle", - "oc": "Seattle", - "pa_IN": "ਸੀਐਟਲ", - "pl": "Seattle", - "pt_BR": "Seattle", - "pt_PT": "Seattle", - "ru": "Сиэтл", - "sk": "Seattle", - "sl": "Seattle", - "sq": "Seattle", - "sv_SE": "Seattle", - "tr": "Seattle", - "uk": "Сіетл", - "zh_CN": "西雅图", - "zh_TW": "西雅圖" - }, - "wikiDataID": "Q5083" - }, - { - "city": "Secaucus, NJ", - "languages": { - "cy": "Secaucus, New Jersey", - "da": "Secaucus", - "de": "Secaucus", - "en": "Secaucus", - "en_CA": "Secaucus", - "en_GB": "Secaucus", - "es_AR": "Secaucus", - "es_CL": "Secaucus", - "es_ES": "Secaucus", - "es_MX": "Secaucus", - "fa": "سیکوکس، نیوجرسی", - "fr": "Secaucus", - "it": "Secaucus", - "ja": "セコーカス", - "nl": "Secaucus", - "pl": "Secaucus", - "pt_BR": "Secaucus", - "pt_PT": "Secaucus", - "ru": "Секокус (Нью-Джерси)", - "sv_SE": "Secaucus", - "tr": "Secaucus", - "uk": "Сікокес", - "zh_CN": "锡考克斯", - "zh_TW": "西考克斯市,新泽西州" - }, - "wikiDataID": "Q1013249" - } - ], - "wikiDataID": "Q30" - }, - { - "wikiDataID": "Q258", - "countryCode": "za", - "languages": { - "bg": "ЮАР", - "co": "Sudafrica", - "cs": "Jihoafrická republika", - "cy": "De Affrica", - "da": "Sydafrika", - "de": "Südafrika", - "dsb": "Pódpołdnjowa Afrika", - "el": "Νότια Αφρική", - "en": "South Africa", - "en_CA": "South Africa", - "en_GB": "South Africa", - "es_AR": "Sudáfrica", - "es_CL": "Sudáfrica", - "es_ES": "Sudáfrica", - "es_MX": "Sudáfrica", - "fa": "آفریقای جنوبی", - "fi": "Etelä-Afrikka", - "fr": "Afrique du Sud", - "fy_NL": "Súd-Afrika", - "hsb": "Južna Afrika", - "hu": "Dél-afrikai Köztársaság", - "ia": "Africa del Sud", - "id": "Afrika Selatan", - "is": "Suður-Afríka", - "it": "Sudafrica", - "ja": "南アフリカ共和国", - "lo": "ປະເທດອາຟຣິກາໃຕ້", - "nl": "Zuid-Afrika", - "oc": "Sud-Africa", - "pa_IN": "ਦੱਖਣ ਅਫ਼ਰੀਕਾ", - "pl": "Południowa Afryka", - "pt_BR": "África do Sul", - "pt_PT": "África do Sul", - "ru": "ЮАР", - "sk": "Juhoafrická republika", - "sl": "Južna Afrika", - "sq": "Republika Jugafrikane", - "sv_SE": "Sydafrika", - "tr": "Güney Afrika Cumhuriyeti", - "uk": "Південно-Африканська Республіка", - "zh_CN": "南非", - "zh_TW": "南非" - }, - "cities": [ - { - "wikiDataID": "Q34647", - "city": "Johannesburg", - "languages": { - "bg": "Йоханесбург", - "co": "Johannesburgu", - "el": "Γιοχάνεσμπουργκ", - "es_AR": "Johannesburgo", - "es_CL": "Johannesburgo", - "es_ES": "Johannesburgo", - "es_MX": "Johannesburgo", - "fa": "ژوهانسبورگ", - "fr": "Johannesbourg", - "fy_NL": "Jehannesburch", - "is": "Jóhannesarborg", - "ja": "ヨハネスブルグ", - "pa_IN": "ਜੋਹਾਨਿਸਬਰਗ", - "pt_BR": "Joanesburgo", - "pt_PT": "Joanesburgo", - "ru": "Йоханнесбург", - "uk": "Йоганнесбург", - "zh_CN": "约翰内斯堡", - "zh_TW": "約翰尼斯堡" - } - } - ] - } -] diff --git a/tests/functional/addons/07_replacer/replacer_01/fs/home.qml b/tests/functional/addons/07_replacer/replacer_01/fs/home.qml deleted file mode 100644 index c83f61b254..0000000000 --- a/tests/functional/addons/07_replacer/replacer_01/fs/home.qml +++ /dev/null @@ -1,10 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import components 0.1 - -MZLoader { - objectName: "replacedHome" - headlineText: MZI18n.InAppAuthWaitingForSignIn -} diff --git a/tests/functional/addons/07_replacer/replacer_01/manifest.json b/tests/functional/addons/07_replacer/replacer_01/manifest.json deleted file mode 100644 index 8916e000a0..0000000000 --- a/tests/functional/addons/07_replacer/replacer_01/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "api_version": "0.1", - "id": "replacer_01", - "name": "Replacer test", - "type": "replacer", - "conditions": { - "locales": [ "en" ], - "translation_threshold": 0 - }, - "replacer": { - "urls": [ - { "request": "qrc:/Mozilla/VPN/screens/home/ViewHome.qml", "response": "fs/home.qml" } - ] - } -} diff --git a/tests/functional/addons/07_replacer/replacer_02/fs/servers.json b/tests/functional/addons/07_replacer/replacer_02/fs/servers.json deleted file mode 100644 index f27e4c47ce..0000000000 --- a/tests/functional/addons/07_replacer/replacer_02/fs/servers.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "countryCode": "au", - "languages": { - "en": "4ustr4l14" - }, - "cities": [ - { - "city": "Melbourne", - "languages": { - "en": "М4lb0urn3" - }, - "wikiDataID": "Q3141" - }, - { - "city": "Sydney", - "languages": { - "en": "S1dn3y" - }, - "wikiDataID": "Q3130" - } - ], - "wikiDataID": "Q408" - }, - { - "countryCode": "at", - "languages": { - "en": "4ustr14" - }, - "cities": [ - { - "city": "Vienna", - "languages": { - "en": "V13nn4" - }, - "wikiDataID": "Q1741" - } - ], - "wikiDataID": "Q40" - }, - { - "countryCode": "be", - "languages": { - "en": "B3lg1um" - }, - "cities": [ - { - "city": "Brussels", - "languages": { - "en": "C1ty 0f Bruss3ls" - }, - "wikiDataID": "Q239" - } - ], - "wikiDataID": "Q31" - } -] diff --git a/tests/functional/addons/07_replacer/replacer_02/manifest.json b/tests/functional/addons/07_replacer/replacer_02/manifest.json deleted file mode 100644 index 069ad1d8cd..0000000000 --- a/tests/functional/addons/07_replacer/replacer_02/manifest.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "api_version": "0.1", - "id": "replacer_02", - "name": "Replacer test", - "type": "replacer", - "conditions": { - "translation_threshold": 0 - }, - "replacer": { - "urls": [ - { "request": "qrc:/i18n/servers.json", "response": "fs/servers.json" } - ] - } -} diff --git a/tests/functional/addons/CMakeLists.txt b/tests/functional/addons/CMakeLists.txt index 26236ffee9..2ba647c046 100644 --- a/tests/functional/addons/CMakeLists.txt +++ b/tests/functional/addons/CMakeLists.txt @@ -42,12 +42,6 @@ add_addon_target(test_03_single_addon ) set_target_properties(test_03_single_addon PROPERTIES EXCLUDE_FROM_ALL FALSE) -add_addon_target(test_07_replacer - OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/07_replacer/ - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/07_replacer/ -) -set_target_properties(test_07_replacer PROPERTIES EXCLUDE_FROM_ALL FALSE) - add_addon_target(test_08_message_disabled OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/08_message_disabled/ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/08_message_disabled/ diff --git a/tests/functional/testReplacer.js b/tests/functional/testReplacer.js deleted file mode 100644 index 2d6deb3d14..0000000000 --- a/tests/functional/testReplacer.js +++ /dev/null @@ -1,69 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const assert = require('assert'); -const vpn = require('./helper.js'); -const queries = require('./queries.js'); - -describe('Addon content replacer', function() { - this.timeout(60000); - - beforeEach(async () => { - await vpn.flipFeatureOn('replacerAddon'); - }); - - afterEach(async () => { - await vpn.flipFeatureOff('replacerAddon'); - }); - - describe('Addon replacer', function() { - beforeEach(async () => { - await vpn.resetAddons('07_replacer'); - }); - - it('Replace the country/city names', async () => { - // In this way we disable the 'home-replacement' addon. - await vpn.setSetting('languageCode', 'it'); - await vpn.authenticateInApp(); - - await vpn.waitForQueryAndClick( - queries.screenHome.SERVER_LIST_BUTTON.visible()); - await vpn.waitForQuery(queries.screenHome.STACKVIEW.ready()); - await vpn.waitForQueryAndClick( - queries.screenHome.serverListView.ALL_SERVERS_TAB.visible()); - - const servers = await vpn.servers(); - - for (let server of servers) { - const countryId = - queries.screenHome.serverListView.generateCountryId(server.code); - await vpn.waitForQuery(countryId.visible()); - - await vpn.scrollToQuery( - queries.screenHome.serverListView.COUNTRY_VIEW, countryId); - - if (await vpn.getQueryProperty(countryId, 'cityListVisible') === - 'false') { - await vpn.clickOnQuery(countryId); - } - - for (let city of server.cities) { - const cityId = queries.screenHome.serverListView.generateCityId( - countryId, city.name); - await vpn.waitForQuery(cityId.visible()); - const cityName = - await vpn.getQueryProperty(cityId, 'radioButtonLabelText'); - assert( - cityName.length > 0 && !cityName.includes('a') && - !cityName.includes('A') && !cityName.includes('e') && - !cityName.includes('E') && !cityName.includes('i') && - !cityName.includes('I') && !cityName.includes('o') && - !cityName.includes('O')) - } - } - - await vpn.setSetting('languageCode', ''); - }); - }); -}); diff --git a/tests/qml/CMakeLists.txt b/tests/qml/CMakeLists.txt index 97ee948ca0..1003f9bb2f 100644 --- a/tests/qml/CMakeLists.txt +++ b/tests/qml/CMakeLists.txt @@ -68,8 +68,6 @@ target_sources(qml_tests PRIVATE ${MZ_SOURCE_DIR}/pingsenderfactory.h ${MZ_SOURCE_DIR}/platforms/dummy/dummypingsender.cpp ${MZ_SOURCE_DIR}/platforms/dummy/dummypingsender.h - ${MZ_SOURCE_DIR}/serveri18n.cpp - ${MZ_SOURCE_DIR}/serveri18n.h ${MZ_SOURCE_DIR}/serverlatency.cpp ${MZ_SOURCE_DIR}/serverlatency.h ${MZ_SOURCE_DIR}/tasks/controlleraction/taskcontrolleraction.cpp @@ -176,8 +174,6 @@ target_sources(qml_tests PRIVATE ${MZ_SOURCE_DIR}/ipaddress.h ${MZ_SOURCE_DIR}/itempicker.cpp ${MZ_SOURCE_DIR}/itempicker.h - ${MZ_SOURCE_DIR}/languagei18n.cpp - ${MZ_SOURCE_DIR}/languagei18n.h ${MZ_SOURCE_DIR}/leakdetector.cpp ${MZ_SOURCE_DIR}/leakdetector.h ${MZ_SOURCE_DIR}/localizer.cpp diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 8daad09220..d7514dbcc9 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -104,8 +104,6 @@ target_sources(unit_tests PRIVATE ${MZ_SOURCE_DIR}/platforms/dummy/dummypingsender.h ${MZ_SOURCE_DIR}/releasemonitor.cpp ${MZ_SOURCE_DIR}/releasemonitor.h - ${MZ_SOURCE_DIR}/serveri18n.cpp - ${MZ_SOURCE_DIR}/serveri18n.h ${MZ_SOURCE_DIR}/serverlatency.cpp ${MZ_SOURCE_DIR}/serverlatency.h ${MZ_SOURCE_DIR}/statusicon.cpp @@ -225,8 +223,6 @@ target_sources(unit_tests PRIVATE ${MZ_SOURCE_DIR}/ipaddress.h ${MZ_SOURCE_DIR}/itempicker.cpp ${MZ_SOURCE_DIR}/itempicker.h - ${MZ_SOURCE_DIR}/languagei18n.cpp - ${MZ_SOURCE_DIR}/languagei18n.h ${MZ_SOURCE_DIR}/leakdetector.cpp ${MZ_SOURCE_DIR}/leakdetector.h ${MZ_SOURCE_DIR}/localizer.cpp @@ -339,8 +335,6 @@ target_sources(unit_tests PRIVATE testmodels.h testreleasemonitor.cpp testreleasemonitor.h - testserveri18n.cpp - testserveri18n.h testserverlatency.cpp testserverlatency.h teststatusicon.cpp @@ -353,7 +347,6 @@ configure_file(${MZ_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version # Unit test mock resources target_sources(unit_tests PRIVATE addons/addons.qrc - servers/servers.qrc ) ## Add the tests to be run, one for each test class. diff --git a/tests/unit/servers/servers.json b/tests/unit/servers/servers.json deleted file mode 100644 index 9d87854332..0000000000 --- a/tests/unit/servers/servers.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - { - "countryCode": "au", - "languages": { - "sk": "au_SK", - "en": "au_EN" - }, - "cities": [ - { - "city": "Melbourne", - "languages": { - "sk": "Melbourne_SK" - } - }, - { - "city": "Sydney", - "languages": { - "sk": "Sydney_SK", - "en": "Sydney_EN" - } - } - ] - } -] diff --git a/tests/unit/servers/servers.qrc b/tests/unit/servers/servers.qrc deleted file mode 100644 index 407ecb32a4..0000000000 --- a/tests/unit/servers/servers.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - servers.json - - diff --git a/tests/unit/testserveri18n.cpp b/tests/unit/testserveri18n.cpp deleted file mode 100644 index 99c900b222..0000000000 --- a/tests/unit/testserveri18n.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "testserveri18n.h" - -#include "localizer.h" -#include "serveri18n.h" -#include "settingsholder.h" - -void TestServerI18n::basic() { - SettingsHolder settingsHolder; - Localizer l; - - // Non existing countries/cities - QCOMPARE(ServerI18N::instance()->translateCountryName("FOO", "FOO"), "FOO"); - QCOMPARE(ServerI18N::instance()->translateCityName("FOO", "FOO"), "FOO"); - QCOMPARE(ServerI18N::instance()->translateCityName("au", "FOO"), "FOO"); - - // Existing language - settingsHolder.setLanguageCode("sk"); - QCOMPARE(ServerI18N::instance()->translateCountryName("au", "FOO"), "au_SK"); - QCOMPARE(ServerI18N::instance()->translateCityName("au", "Melbourne"), - "Melbourne_SK"); - QCOMPARE(ServerI18N::instance()->translateCityName("au", "Sydney"), - "Sydney_SK"); - - // Non-existing language with fallback to en - settingsHolder.setLanguageCode("fr"); - QCOMPARE(ServerI18N::instance()->translateCountryName("au", "FOO"), "au_EN"); - QCOMPARE(ServerI18N::instance()->translateCityName("au", "Melbourne"), - "Melbourne"); - QCOMPARE(ServerI18N::instance()->translateCityName("au", "Sydney"), - "Sydney_EN"); -} - -static TestServerI18n s_testServerI18n; diff --git a/tests/unit/testserveri18n.h b/tests/unit/testserveri18n.h deleted file mode 100644 index 86637997f0..0000000000 --- a/tests/unit/testserveri18n.h +++ /dev/null @@ -1,12 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "helper.h" - -class TestServerI18n : public TestHelper { - Q_OBJECT - - private slots: - void basic(); -}; diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 16482fbae4..6e1403ee58 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -95,8 +95,6 @@ target_sources(app_unit_tests PRIVATE testenv.h testipaddress.cpp testipaddress.h - testlanguagei18n.cpp - testlanguagei18n.h testlicense.cpp testlicense.h testlocalizer.cpp diff --git a/tests/unit_tests/resourceloader/resourceloader.qrc b/tests/unit_tests/resourceloader/resourceloader.qrc index 02d326094d..6245126f76 100644 --- a/tests/unit_tests/resourceloader/resourceloader.qrc +++ b/tests/unit_tests/resourceloader/resourceloader.qrc @@ -2,7 +2,6 @@ encodedPassword.txt ../../../src/resources/encodedPassword.txt - languages.json LICENSE.md diff --git a/tests/unit_tests/testlanguagei18n.cpp b/tests/unit_tests/testlanguagei18n.cpp deleted file mode 100644 index 6356b85368..0000000000 --- a/tests/unit_tests/testlanguagei18n.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "testlanguagei18n.h" - -#include "languagei18n.h" -#include "localizer.h" -#include "settingsholder.h" - -void TestLanguageI18n::translations() { - QVERIFY(LanguageI18N::instance()->languageExists("tlh")); - QVERIFY(!LanguageI18N::instance()->languageExists("FOO")); - - // Non existing language - QVERIFY(LanguageI18N::instance()->translateLanguage("FOO", "FOO").isEmpty()); - - // Self-translation - QCOMPARE(LanguageI18N::instance()->translateLanguage("tlh", "tlh"), - " "); - - // Other language - QCOMPARE(LanguageI18N::instance()->translateLanguage("fr", "tlh"), "klingon"); - - // Non existing translation - QVERIFY(LanguageI18N::instance()->translateLanguage("fi", "tlh").isEmpty()); -} - -void TestLanguageI18n::currencies() { - // Non existing language - QVERIFY(LanguageI18N::instance() - ->currencySymbolForLanguage("FOO", "FOO") - .isEmpty()); - - // Not existing currency - QVERIFY(LanguageI18N::instance() - ->currencySymbolForLanguage("tlh", "FOO") - .isEmpty()); - - // OK - QCOMPARE(LanguageI18N::instance()->currencySymbolForLanguage("tlh", "EUR"), - "€"); -} - -static TestLanguageI18n s_testLanguageI18n; diff --git a/tests/unit_tests/testlanguagei18n.h b/tests/unit_tests/testlanguagei18n.h deleted file mode 100644 index 6133d0825a..0000000000 --- a/tests/unit_tests/testlanguagei18n.h +++ /dev/null @@ -1,13 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "helper.h" - -class TestLanguageI18n : public TestHelper { - Q_OBJECT - - private slots: - void translations(); - void currencies(); -}; diff --git a/tests/unit_tests/testlocalizer.cpp b/tests/unit_tests/testlocalizer.cpp index d5af01ff7b..fcf161f4b4 100644 --- a/tests/unit_tests/testlocalizer.cpp +++ b/tests/unit_tests/testlocalizer.cpp @@ -40,7 +40,7 @@ void TestLocalizer::basic() { QCOMPARE(rn[Localizer::CodeRole], "code"); QCOMPARE(rn[Localizer::RTLRole], "isRightToLeft"); - QVERIFY(l.rowCount(QModelIndex()) == 4); + QVERIFY(l.rowCount(QModelIndex()) == 5); QCOMPARE(l.data(QModelIndex(), Localizer::LocalizedLanguageNameRole), QVariant()); } @@ -97,12 +97,11 @@ void TestLocalizer::localizeCurrency() { // Happy path QCOMPARE(l.localizeCurrency(123.123, "GBP"), "£123.12"); + QCOMPARE(l.localizeCurrency(123.123, "USD"), "$123.12"); + QCOMPARE(l.localizeCurrency(123.123, "BGN"), "лв123.12"); // Let's guess - invalid currency QCOMPARE(l.localizeCurrency(123.123, "AAA"), "AAA123.12"); - - // Let's guess - valid currency for CLDR - QCOMPARE(l.localizeCurrency(123.123, "BBB"), "WOW123.12"); } void TestLocalizer::majorLanguageCode() { @@ -253,7 +252,8 @@ void TestLocalizer::fallback() { QCOMPARE(l.languages(), QStringList() << "en" << "es_CL" << "es_ES" - << "es_MX"); + << "es_MX" + << "pt_BR"); // MX contains translations for "foo.1" QCOMPARE(qtTrId("foo.1"), "hello world 1 es_MX"); @@ -368,4 +368,129 @@ void TestLocalizer::formattedDate() { QCOMPARE(Localizer::instance()->formatDate(now, date, "Yesterday"), result); } +void TestLocalizer::nativeLanguageName_data() { + QTest::addColumn("locale"); + QTest::addColumn("code"); + QTest::addColumn("output"); + + // Happy path + QTest::addRow("existing transation") << QLocale(QLocale::C) << "en" + << "English"; + + // Happy path + QTest::addRow("existing transation") << QLocale(QLocale::Spanish) << "es_ES" + << "Español de españa"; + + // There is a key for this locale in NATIVE_LANGUAGE_NAMES, + // but there is no translation. This is going to use Qt's translation + // (which in this case is a terrible translation). + QTest::addRow("missing transation") << QLocale(QLocale::Spanish) << "es_CL" + << "Español de España"; + + // When the locale code provided is not in the map, + // but the QLocale provided is QLocale::C we will fallback to en_US. + QTest::addRow("english fallback") << QLocale(QLocale::C) << "Unknown" + << "English (US)"; + + // When all else fails, we just trust Qt again. + QTest::addRow("qt fallback") << QLocale(QLocale::Portuguese) << "Unknown" + << "Português"; +} + +void TestLocalizer::nativeLanguageName() { + QFETCH(QLocale, locale); + QFETCH(QString, code); + QFETCH(QString, output); + + QCOMPARE(Localizer::nativeLanguageName(locale, code), output); +} + +void TestLocalizer::localizedLanguageName() { + Localizer localizer; + + // Happy path + QCOMPARE(localizer.localizedLanguageName("en"), "English"); + + m_settingsHolder->setLanguageCode("es_ES"); + QCOMPARE(localizer.localizedLanguageName("en"), "Inglés"); + + // This language doesn't have a translations for "es_MX". + // It does have fallback into es_MX and then es_ES. + // It should get the translation from the first fallback language: es_MX. + m_settingsHolder->setLanguageCode("es_CL"); + QCOMPARE(localizer.localizedLanguageName("es_MX"), "Español"); + + // This language doesn't have a translations for "es_ES", + // and neither does the first fallback language: es_MX. + // It should still get the translation from the second fallback language + QCOMPARE(localizer.localizedLanguageName("es_ES"), "Español de españa"); + + // This language doesn't have a translations for "es_ES" + // and it also doesn't have fallbacks. "en" is the default fallback locale. + m_settingsHolder->setLanguageCode("pt_BR"); + QCOMPARE(localizer.localizedLanguageName("es_ES"), "Spanish"); +} + +void TestLocalizer::getTranslatedCountryName() { + Localizer localizer; + + // Make sure we don't crash on an empty input. + QCOMPARE(localizer.getTranslatedCountryName("", ""), ""); + + // If the country name provided doesn't match any translation, + // just return what was provided. + QCOMPARE(localizer.getTranslatedCountryName("Middle Earth", "Middle Earth"), + "Middle Earth"); + + // Happy path + QCOMPARE(localizer.getTranslatedCountryName("us", ""), + "United States of America"); + + m_settingsHolder->setLanguageCode("es_ES"); + QCOMPARE(localizer.getTranslatedCountryName("us", ""), + "Estados Unidos de América"); + + // This language doesn't have a translations for "us", + // but it should not fallback to English. It should fallback to Spanish. + m_settingsHolder->setLanguageCode("es_CL"); + QCOMPARE(localizer.getTranslatedCountryName("us", ""), + "Estados Unidos de América"); + + // This language doesn't have a translations for "en" + // and it also doesn't have fallbacks. It should fallback to English. + m_settingsHolder->setLanguageCode("pt_BR"); + QCOMPARE(localizer.getTranslatedCountryName("us", ""), + "United States of America"); +} + +void TestLocalizer::getTranslatedCityName() { + Localizer localizer; + + // Make sure we don't crash on an empty input. + QCOMPARE(localizer.getTranslatedCityName(""), ""); + + // If the city name provided doesn't match any translation, + // just return what was provided. + QCOMPARE(localizer.getTranslatedCityName("Hogsmead"), "Hogsmead"); + + // Make sure special characters and state suffixes don't trip us up. + QCOMPARE(localizer.getTranslatedCityName("Salt Lake City, UT"), + "Salt Lake City"); + QCOMPARE(localizer.getTranslatedCityName("São Paulo, SP"), "São Paulo"); + + // Happy path + m_settingsHolder->setLanguageCode("es_ES"); + QCOMPARE(localizer.getTranslatedCityName("Mexico City"), "Ciudad de México"); + + // This language doesn't have a translations for "Mexico City", + // but it should not fallback to English. It should fallback to Spanish. + m_settingsHolder->setLanguageCode("es_CL"); + QCOMPARE(localizer.getTranslatedCityName("Mexico City"), "Ciudad de México"); + + // This language doesn't have a translations for "en" + // and it also doesn't have fallbacks. It should fallback to English. + m_settingsHolder->setLanguageCode("pt_BR"); + QCOMPARE(localizer.getTranslatedCityName("Mexico City"), "Mexico City"); +} + static TestLocalizer s_testLocalizer; diff --git a/tests/unit_tests/testlocalizer.h b/tests/unit_tests/testlocalizer.h index 047cff0750..615989add6 100644 --- a/tests/unit_tests/testlocalizer.h +++ b/tests/unit_tests/testlocalizer.h @@ -35,6 +35,15 @@ class TestLocalizer final : public TestHelper { void formattedDate_data(); void formattedDate(); + void nativeLanguageName_data(); + void nativeLanguageName(); + + void localizedLanguageName(); + + void getTranslatedCountryName(); + + void getTranslatedCityName(); + private: SettingsHolder* m_settingsHolder = nullptr; }; diff --git a/tests/unit_tests/testresourceloader.cpp b/tests/unit_tests/testresourceloader.cpp index 3d702f18bb..cf54e7cff7 100644 --- a/tests/unit_tests/testresourceloader.cpp +++ b/tests/unit_tests/testresourceloader.cpp @@ -12,7 +12,6 @@ #include "authenticationinapp/authenticationinapp.h" #include "feature/feature.h" #include "helper.h" -#include "languagei18n.h" #include "localizer.h" #include "models/licensemodel.h" #include "qmlengineholder.h" @@ -102,31 +101,6 @@ void TestResourceLoader::commonPasswords() { QCOMPARE(aia->validatePasswordCommons("12345678"), false); } -void TestResourceLoader::languageI18N() { - SettingsHolder settingsHolder; - Localizer l; - - QQmlApplicationEngine engine; - QmlEngineHolder qml(&engine); - - QCOMPARE(LanguageI18N::instance()->translateLanguage("fr", "tlh"), "klingon"); - QVERIFY(LanguageI18N::instance()->translateLanguage("gr", "tlh").isEmpty()); - - Interceptor i(QUrl("qrc:/i18n/languages.json"), - QUrl("qrc:/replace/languages.json")); - - ResourceLoader* rl = ResourceLoader::instance(); - - rl->addUrlInterceptor(&i); - QVERIFY(LanguageI18N::instance()->translateLanguage("fr", "tlh").isEmpty()); - QCOMPARE(LanguageI18N::instance()->translateLanguage("gr", "tlh"), - "Κλίνγκον γλώσσα"); - - rl->removeUrlInterceptor(&i); - QCOMPARE(LanguageI18N::instance()->translateLanguage("fr", "tlh"), "klingon"); - QVERIFY(LanguageI18N::instance()->translateLanguage("gr", "tlh").isEmpty()); -} - void TestResourceLoader::licenseModel() { SettingsHolder settingsHolder; Localizer l; diff --git a/tests/unit_tests/testresourceloader.h b/tests/unit_tests/testresourceloader.h index 4a2062ed18..fc1079395b 100644 --- a/tests/unit_tests/testresourceloader.h +++ b/tests/unit_tests/testresourceloader.h @@ -12,7 +12,6 @@ class TestResourceLoader final : public TestHelper { void loadDir(); void commonPasswords(); - void languageI18N(); void licenseModel(); void addon(); diff --git a/tests/unit_tests/translations/extras/extras.xliff b/tests/unit_tests/translations/extras/extras.xliff new file mode 100644 index 0000000000..cb83959ed4 --- /dev/null +++ b/tests/unit_tests/translations/extras/extras.xliff @@ -0,0 +1,41 @@ + + + + + + English + + + Spanish + + + Mexican Spanish + + + + + + + United States of America + + + Mexico + + + Spain + + + Salt Lake City + + + Mexico City + + + Barcelona + + + São Paulo + + + + diff --git a/tests/unit_tests/translations/extras/languages.json b/tests/unit_tests/translations/extras/languages.json deleted file mode 100644 index 272d346546..0000000000 --- a/tests/unit_tests/translations/extras/languages.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "wikiDataID": "Q10134", - "languageCode": "tlh", - "languages": { - "tlh": " " - }, - "currencies": { - "EUR": "€" - } - }, - { - "wikiDataID": "Q1860", - "languageCode": "en", - "languages": { - "tlh": "Klingon" - } - }, - { - "wikiDataID": "Q652", - "languageCode": "it", - "languages": { - "tlh": "lingua klingon" - } - }, - { - "wikiDataID": "Q150", - "languageCode": "fr", - "languages": { - "tlh": "klingon" - } - }, - { - "wikiDataID": "Q7979", - "languageCode": "en_GB", - "languages": {}, - "currencies": { - "BBB": "WOW" - } - } -] diff --git a/tests/unit_tests/translations/extras/translations.completeness b/tests/unit_tests/translations/extras/translations.completeness index a203d4e5a8..21ca4fc6eb 100644 --- a/tests/unit_tests/translations/extras/translations.completeness +++ b/tests/unit_tests/translations/extras/translations.completeness @@ -2,3 +2,4 @@ en:1 es_ES:1 es_MX:0.666 es_CL:0.666 +pt_BR:0.666 diff --git a/tests/unit_tests/translations/extras/translations_fallback.json b/tests/unit_tests/translations/extras/translations_fallback.json index 71e25c8d17..2060cb0710 100644 --- a/tests/unit_tests/translations/extras/translations_fallback.json +++ b/tests/unit_tests/translations/extras/translations_fallback.json @@ -1,3 +1,4 @@ { - "es_MX": ["es_CL", "es_ES"] + "es_MX": ["es_CL", "es_ES"], + "es_CL": ["es_MX", "es_ES"] } diff --git a/tests/unit_tests/translations/i18n/en/extras.xliff b/tests/unit_tests/translations/i18n/en/extras.xliff new file mode 100644 index 0000000000..cb83959ed4 --- /dev/null +++ b/tests/unit_tests/translations/i18n/en/extras.xliff @@ -0,0 +1,41 @@ + + + + + + English + + + Spanish + + + Mexican Spanish + + + + + + + United States of America + + + Mexico + + + Spain + + + Salt Lake City + + + Mexico City + + + Barcelona + + + São Paulo + + + + diff --git a/tests/unit_tests/translations/i18n/es_CL/extras.xliff b/tests/unit_tests/translations/i18n/es_CL/extras.xliff new file mode 100644 index 0000000000..5fb6f1f5f4 --- /dev/null +++ b/tests/unit_tests/translations/i18n/es_CL/extras.xliff @@ -0,0 +1,51 @@ + + + + + + English + + + + Spanish + + + + Mexican Spanish + + + + + + + + United States of America + + + + Mexico + + + + Spain + + + + Salt Lake City + + + + Mexico City + + + + Barcelona + + + + São Paulo + + + + + diff --git a/tests/unit_tests/translations/i18n/es_ES/extras.xliff b/tests/unit_tests/translations/i18n/es_ES/extras.xliff new file mode 100644 index 0000000000..e874aea971 --- /dev/null +++ b/tests/unit_tests/translations/i18n/es_ES/extras.xliff @@ -0,0 +1,51 @@ + + + + + + English + Inglés + + + Spanish + Español de españa + + + Mexican Spanish + Español mexicano + + + + + + + United States of America + Estados Unidos de América + + + Mexico + México + + + Spain + España + + + Salt Lake City + Salt Lake City + + + Mexico City + Ciudad de México + + + Barcelona + Barcelona + + + São Paulo + + + + + diff --git a/tests/unit_tests/translations/i18n/es_MX/extras.xliff b/tests/unit_tests/translations/i18n/es_MX/extras.xliff new file mode 100644 index 0000000000..e82ad1024c --- /dev/null +++ b/tests/unit_tests/translations/i18n/es_MX/extras.xliff @@ -0,0 +1,51 @@ + + + + + + English + Inglés + + + Spanish + + + + Mexican Spanish + Español + + + + + + + United States of America + Estados Unidos de América + + + Mexico + México + + + Spain + España + + + Salt Lake City + Salt Lake City + + + Mexico City + Ciudad de México + + + Barcelona + Barcelona + + + São Paulo + + + + + diff --git a/tests/unit_tests/translations/i18n/pt_BR/extras.xliff b/tests/unit_tests/translations/i18n/pt_BR/extras.xliff new file mode 100644 index 0000000000..d017b41e16 --- /dev/null +++ b/tests/unit_tests/translations/i18n/pt_BR/extras.xliff @@ -0,0 +1,51 @@ + + + + + + English + + + + Spanish + + + + Mexican Spanish + Espanhol do México + + + + + + + United States of America + + + + Mexico + México + + + Spain + Espanha + + + Salt Lake City + Salt Lake City + + + Mexico City + + + + Barcelona + Barcelona + + + São Paulo + + + + + diff --git a/tests/unit_tests/translations/i18n/pt_BR/mozillavpn.xliff b/tests/unit_tests/translations/i18n/pt_BR/mozillavpn.xliff new file mode 100644 index 0000000000..72b5a54700 --- /dev/null +++ b/tests/unit_tests/translations/i18n/pt_BR/mozillavpn.xliff @@ -0,0 +1,11 @@ + + + + + + Hello world 1 + hello world 1 pt_BR + + + + diff --git a/tools/languagelocalizer/README.md b/tools/languagelocalizer/README.md deleted file mode 100644 index f0fb7bd378..0000000000 --- a/tools/languagelocalizer/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Language string mapping tool - -This tool retrieves the native language and the localized language names for -all the available locales. - -## How to interact with this tool - -During the execution, this tool uses `translations/languages.json` to retrieve -the WikiData resource code for all the available languages. If there is a new -language on Pontoon, it will ask for the code. You can write the code or an -alternative one if wiki data does not have a page about that new language. - -For instance, while I write this README, `es_CL` is an unknown language on wiki -data, and we use the `es` as an alternative code. - -## How to find the code on WikiData - -Search for the language code (fa - Persian), for instance. Open the page and -see the URL: https://www.wikidata.org/wiki/Q9168. The code is Q9168. diff --git a/tools/languagelocalizer/languageLocalizer.js b/tools/languagelocalizer/languageLocalizer.js deleted file mode 100644 index de6426c8fa..0000000000 --- a/tools/languagelocalizer/languageLocalizer.js +++ /dev/null @@ -1,336 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import chalk from 'chalk'; -import {program} from 'commander'; -import fs from 'fs'; -import { fileURLToPath } from 'node:url'; -import path from 'path'; -import inquirer from 'inquirer'; -import fetch from 'node-fetch'; -import WBK from 'wikibase-sdk'; - -const I18N_SUBMODULE_PATH = '../../3rdparty/i18n'; -const LANGUAGES_OUTPUT_FILE = - '../../src/translations/extras/languages.json'; - -const LanguageLocalizer = { - - quit() { - - process.exit(); - }, - - - retrieveJson(url) { - return fetch(url, { - headers: { - 'User-Agent': - 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0', - 'Accept': - 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', - } - }) - .then(r => r.json()); - }, - - async init() { - program.version('0.0.1') - program.option("-c, --check", ` - Check only, will fail if user input would be required to generate - the file. - `); - - program.action(async () => await this.run(program.opts())); - - program.parseAsync(process.argv); - }, - - async run(options) { - this.options = options; - if(options.check){ - console.log("Running Checks Only"); - } - this.wbk = WBK({ - instance: 'https://www.wikidata.org', - sparqlEndpoint: 'https://query.wikidata.org/sparql', - }) - const __filename = fileURLToPath(import.meta.url); - const __dirname = path.dirname(__filename); - const submodule_path = path.resolve(__dirname, I18N_SUBMODULE_PATH) - const dir_entries = fs.readdirSync(submodule_path, {withFileTypes: true}); - const language_folders = dir_entries - .filter(f => f.isDirectory()) - .map(f=>f.name) - .filter(f=>!f.startsWith(".")); - - this.languages = language_folders; - - - this.oldData = - JSON.parse(fs.readFileSync(LANGUAGES_OUTPUT_FILE).toString()) || []; - - for (const language of this.languages) { - await this.localizeLanguage(language); - } - - // `localizeLanguage` creates a `translations` object with all the language - // translations in language X using Wikidata as a data source (via SPARQL - // queries). Now we use CLDR which will give us X translated in all the - // languages in an object called `languages`. We need to normalize these 2 - // objects and then drop the `translations`. Wikidata is used fallback. - for (let language of this.newData) { - await this.cldrLanguage(language); - } - - this.writeData(); - console.log(chalk.green('Languages known file written.')); - - this.quit(); - }, - - writeData() { - if(this.options.check){ - console.log(chalk.green('In check mode, skipping write')); - return; - } - console.log(chalk.yellow('Sorting data...')); - - for (let language of this.newData) { - delete language.translations; - const old_entry = this.oldData.find(e => e.languageCode === language.languageCode) - - if ('currencies' in language) { - language.currencies = - Object.keys(language.currencies).sort().reduce((obj, key) => { - obj[key] = language.currencies[key]; - return obj; - }, {}); - } - - if ('languages' in language) { - if( old_entry && 'languages' in old_entry){ - // Check if we the new languages object lost language data, if so - // put it back. - const old_languages = Object.keys(old_entry.languages); - const new_languages = Object.keys(language.languages); - // List of keys we no longer have in the new lang obj i.e ["bg","cy"] - const lost_languages = old_languages.filter( l => !new_languages.includes(l)); - lost_languages.forEach(lost_language_code =>{ - language.languages[lost_language_code] = old_entry.languages[lost_language_code]; - }); - } - language.languages = - Object.keys(language.languages).sort().reduce((obj, key) => { - obj[key] = language.languages[key]; - return obj; - }, {}); - } - } - - this.newData.sort((a, b) => a.languageCode < b.languageCode ? -1 : 1); - - fs.writeFileSync( - LANGUAGES_OUTPUT_FILE, JSON.stringify(this.newData, null, ' ')); - }, - - async localizeLanguage(language) { - console.log(` - Localizing language ${chalk.yellow(language)}...`); - const language_old_Data = this.oldData.find(s => s.languageCode === language); - // Create a copy, otherwise we modify our old state - let languageData = structuredClone(language_old_Data); - if (!languageData) { - if(this.options.check){ - console.error(`Unknown language ${language} - cannot continue`); - console.error(`Check out this branch and run "npm run languages:update" to update languages.json`); - process.exit(1); - } - console.log(' Unknown language!'); - languageData = { - wikiDataID: null, - languageCode: language, - currencies: {}, - languages: {}, - } - } else if (!languageData.wikiDataID) { - console.log( - ' Language found but we do not have a valid wikiDataID. Please update the file!'); - if(this.options.check){ - console.log(JSON.stringify(languageData)) - console.error(`${ languageData.languageCode } - No Wikidata ID found.`) - console.error(`This is likely a new language. Check this branch out and run this`) - console.error(`tool locally again!`) - process.exit(1); - } - languageData.wikiDataID = null; - languageData.currencies = {}; - languageData.languages = {}; - } - - // This is a temporary object to unify Wikidata and CLDR values - languageData.translations = {}; - - if (!languageData.wikiDataID) { - while (true) { - let answer = await inquirer.prompt([{ - type: 'confirm', - name: 'value', - message: `${ languageData.languageCode } - No Wikidata ID found. Do you know it?`, - }]); - - if (answer.value) { - answer = await inquirer.prompt([{ - name: 'value', - message: 'Wikidata ID:', - }]); - - if (answer.value != '') { - languageData.wikiDataID = answer.value; - break; - } - - continue; - } - - answer = await inquirer.prompt([{ - name: 'value', - message: `Alternative Wikidata ID: ${ - languageData.alternativeWikiDataID ? - '(' + languageData.alternativeWikiDataID + ')' : - ''}:` - }]); - - if (answer.value != '') { - languageData.alternativeWikiDataID = answer.value; - break; - } - } - } - - if (!languageData.IETFcode && !this.options?.check) { - while (true) { - let answer = await inquirer.prompt([{ - type: 'confirm', - name: 'value', - message: `${ languageData.languageCode } - No IETF ID found. Do you know it?`, - }]); - - if (!answer.value) { - break; - } - - answer = await inquirer.prompt([{ - name: 'value', - message: 'IETF language code:', - }]); - - if (answer.value != '') { - languageData.IETFcode = answer.value; - break; - } - - continue; - } - } - - const sparql = `SELECT ?languageName (lang(?languageName) as ?lang) - WHERE { rdfs:label ?languageName . }`; - const url = this.wbk.sparqlQuery(sparql) - const result = await this.retrieveJson(url); - - if (!('head' in result)) throw new Error('Invalid SPARQL result (no head)'); - if (!('results' in result)) - throw new Error('Invalid SPARQL result (no results)'); - if (!('bindings' in result.results)) - throw new Error('Invalid SPARQL result (no results/bindings)'); - - if (result.results.bindings.length === 0) { - console.log(sparql); - throw new Error('No results'); - } - - const translations = {}; - for (let lang of result.results.bindings) { - const langCode = lang.languageName['xml:lang']; - let value = lang.languageName['value']; - value = value.charAt(0).toUpperCase() + value.slice(1); - - if (this.languages.includes(langCode)) { - translations[langCode] = value; - } - - for (let lang of this.languages) { - if (lang.toLowerCase().replace('_', '-') === langCode) { - translations[lang] = value; - } - if (lang.toLowerCase().split('_')[0] === langCode && - !translations[langCode]) { - translations[langCode] = value; - } - } - } - - const currencies = {}; - if (languageData.IETFcode) { - const currencyData = await this.retrieveJson( - `https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/cldr-numbers-full/main/${ - languageData.IETFcode}/currencies.json`); - Object.keys(currencyData.main[languageData.IETFcode].numbers.currencies) - .map(c => ({ - c, - s: currencyData.main[languageData.IETFcode] - .numbers.currencies[c] - .symbol - })) - .filter(a => a.c != a.s) - .forEach(a => currencies[a.c] = a.s); - } - - languageData.translations = translations; - languageData.currencies = currencies; - this.newData.push(languageData); - }, - - async cldrLanguage(languageData) { - console.log(` - Fetching CLDR language values for language ${ - chalk.yellow(languageData.languageCode)}...`); - const languages = {}; - - if (languageData.IETFcode) { - const ietfToCode = - this.newData.filter(a => 'IETFcode' in a) - .map(a => ({languageCode: a.languageCode, IETFcode: a.IETFcode})); - - const cldrLanguages = - (await this.retrieveJson( - `https://raw.githubusercontent.com/unicode-org/cldr-json/main/cldr-json/cldr-localenames-full/main/${ - languageData.IETFcode}/languages.json`)) - .main[languageData.IETFcode] - .localeDisplayNames.languages; - - Object.keys(cldrLanguages) - .filter(l => !!ietfToCode.find(ietf => ietf.IETFcode === l)) - .forEach( - code => languages[ietfToCode.find(ietf => ietf.IETFcode === code) - .languageCode] = cldrLanguages[code]); - } - - // Let's add languages from Wikidata if CLDR does not have them yet. - this.newData.filter(l => languageData.languageCode in l.translations) - .filter(l => !(languageData.languageCode in languages)) - .forEach( - l => languages[l.languageCode] = - l.translations[languageData.languageCode]); - - languageData.languages = languages; - }, - - languages: new Map(), - newData: [], - oldData: [], -}; - -LanguageLocalizer.init(); diff --git a/tools/languagelocalizer/package.json b/tools/languagelocalizer/package.json deleted file mode 100644 index c1cafc7d84..0000000000 --- a/tools/languagelocalizer/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "languagelocalizer", - "version": "1.0.0", - "description": "The localizator of languages", - "main": "languagelocalizer.js", - "type": "module", - "license": "Mozilla Public License 2.0", - "dependencies": { - "chalk": "^5.2.0", - "commander": "^11.1.0", - "inquirer": "^9.2.13", - "node-fetch": "^3.2.3", - "wikibase-sdk": "^9.2.4" - }, - "scripts": { - "build": "exit 0" - } -} diff --git a/tools/serverlocalizer/package.json b/tools/serverlocalizer/package.json deleted file mode 100644 index 359fffd076..0000000000 --- a/tools/serverlocalizer/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "serverlocalizer", - "version": "1.0.0", - "description": "The localizator of countries and cities", - "main": "serverlocalizer.js", - "type": "module", - "license": "Mozilla Public License 2.0", - "dependencies": { - "chalk": "^5.2.0", - "commander": "^10.0.0", - "inquirer": "^9.1.4", - "node-fetch": "^3.2.3", - "websocket": "^1.0.34", - "wikibase-sdk": "^9.0.3" - } -} diff --git a/tools/serverlocalizer/serverlocalizer.js b/tools/serverlocalizer/serverlocalizer.js deleted file mode 100644 index 3b32e10d12..0000000000 --- a/tools/serverlocalizer/serverlocalizer.js +++ /dev/null @@ -1,367 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -import chalk from 'chalk'; -import child_process from 'child_process'; -import {program} from 'commander'; -import fs from 'fs'; -import inquirer from 'inquirer'; -import fetch from 'node-fetch'; -import websocket from 'websocket'; -import WBK from 'wikibase-sdk'; - -const DEFAULT_MOZILLAVPN = '../../build/src/mozillavpn'; -const SERVERS_OUTPUT_FILE = - '../../src/translations/extras/servers.json'; - -const ServerLocalizer = { - get vpn() { - return this._vpn; - }, - get client() { - return this._client; - }, - - quit() { - if (this.vpn) { - this.vpn.kill(); - } - - process.exit(); - }, - - async sendMessageToClient(cmd, params = '', reportError = false) { - let answer = await new Promise(resolve => { - this._waitReadCallback = resolve; - this.client.send(`${cmd} ${params}`.trim()); - }); - - if (answer.type !== cmd) { - console.log(chalk.red('Something wrong is happening.')); - this.quit(); - } - - if (!reportError) { - if (answer.error) { - console.log(chalk.red(`Something wrong is happening: ${answer.error}`)); - this.quit(); - } - } - - return answer; - }, - - execClient(path) { - const vpn = child_process.spawn(path, ['ui', '--testing']); - - console.log(chalk.yellow('Running the client...')); - vpn.stderr.on('data', data => {}); - vpn.stdout.on('data', data => {}); - vpn.on('close', code => { - console.log(chalk.red( - 'The client has been closed. I hope this is what you wanted.')); - this.quit(); - }); - - this._vpn = vpn; - }, - - async connectToClient() { - // Let's wait 1 sec for the activation of the websocket. - await new Promise(r => setTimeout(r, 1000)); - - const client = await new Promise(resolve => { - const client = new websocket.w3cwebsocket('ws://localhost:8765/', ''); - - client.onopen = async () => resolve(client); - - client.onclose = () => { - console.log( - chalk.yellow('The client has closed the websocket connection.')); - this.quit(); - }; - - client.onerror = () => resolve(null); - - client.onmessage = data => { - const json = JSON.parse(data.data); - - // Ignoring logs. - if (json.type === 'log') return; - - // Ignore notifications. - if (json.type === 'notification' || - json.type === 'addon_load_completed') - return; - - if (!this._waitReadCallback) { - console.log('Internal error?!?'); - return; - } - - const wr = this._waitReadCallback; - this._waitReadCallback = null; - wr(json); - }; - }); - - if (!client) { - console.log('Failed to connect.'); - process.exit(); - } - - this._client = client; - }, - - retrieveJson(url) { - return fetch(url, { - headers: { - 'User-Agent': - 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0', - 'Accept': - 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', - } - }) - .then(r => r.json()); - }, - - async init() { - program.version('0.0.1') - - program.option( - '-p, --path ', - `config file. Default: ${DEFAULT_MOZILLAVPN}`, DEFAULT_MOZILLAVPN); - program.action(async () => await this.run(program.opts())); - - program.parseAsync(process.argv); - }, - - async run(options) { - this.execClient(options.path); - await this.connectToClient(); - - this.wbk = WBK({ - instance: 'https://www.wikidata.org', - sparqlEndpoint: 'https://query.wikidata.org/sparql', - }) - - const languages = await this.sendMessageToClient('languages'); - if (!Array.isArray(languages.value) || languages.value.length === 0) { - console.log('No languages! Are you authenticated already?'); - this.quit(); - } - - for (let language of languages.value) { - this.languages.set(language.toLowerCase().replace('_', '-'), language); - } - - const servers = await this.sendMessageToClient('servers'); - if (!Array.isArray(servers.value) || servers.value.length === 0) { - console.log('No servers! Are you authenticated already?'); - this.quit(); - } - - this.oldData = - JSON.parse(fs.readFileSync(SERVERS_OUTPUT_FILE).toString()) || []; - - for (const server of servers.value) { - await this.localizeServer(server); - } - - this.writeData(); - console.log(chalk.green('Servers known file written.')); - - this.quit(); - }, - - writeData() { - console.log(chalk.yellow('Sorting data...')); - - for (let country of this.newData) { - if ('languages' in country) { - country.languages = - Object.keys(country.languages).sort().reduce((obj, key) => { - obj[key] = country.languages[key]; - return obj; - }, {}); - } - - if (Array.isArray(country.cities)) { - for (let city of country.cities) { - if ('languages' in city) { - city.languages = - Object.keys(city.languages).sort().reduce((obj, key) => { - obj[key] = city.languages[key]; - return obj; - }, {}); - } - } - } - } - - this.newData.sort((a, b) => a.countryCode < b.countryCode ? -1 : 1); - - fs.writeFileSync( - SERVERS_OUTPUT_FILE, JSON.stringify(this.newData, null, ' ')); - }, - - async localizeServer(server) { - console.log(` - Localizing country ${chalk.yellow(server.name)}...`); - let serverData = this.oldData.find(s => s.countryCode === server.code); - if (!serverData) { - console.log(' Unknown country!'); - serverData = { - wikiDataID: null, - countryCode: server.code, - languages: {}, - cities: [], - } - } else if (!serverData.wikiDataID) { - console.log( - ' Server found but we do not have a valid wikiDataID. Please update the file!'); - serverData.wikiDataID = null; - serverData.languages = {}; - } - - if (!serverData.wikiDataID) { - while (true) { - const answer = await inquirer.prompt([{ - name: 'value', - message: 'WikiData ID:', - }]); - - if (answer.value != '') { - serverData.wikiDataID = answer.value; - break; - } - } - } - - const sparql = `SELECT ?countryName (lang(?countryName) as ?lang) - WHERE { rdfs:label ?countryName . }`; - const url = this.wbk.sparqlQuery(sparql) - const result = await this.retrieveJson(url); - - if (!('head' in result)) throw new Error('Invalid SPARQL result (no head)'); - if (!('results' in result)) - throw new Error('Invalid SPARQL result (no results)'); - if (!('bindings' in result.results)) - throw new Error('Invalid SPARQL result (no results/bindings)'); - - if (result.results.bindings.length === 0) { - console.log(sparql); - throw new Error('No results'); - } - - const translations = {}; - for (let lang of result.results.bindings) { - const langCode = lang.countryName['xml:lang']; - const value = lang.countryName['value']; - - if (this.languages.has(langCode)) { - translations[this.languages.get(langCode)] = value; - } - - for (let language of this.languages) { - if (langCode === language[0]) continue; - if (translations[language[1]]) continue; - if (!language[0].startsWith(langCode + '-')) continue; - translations[language[1]] = value; - } - } - - serverData.languages = translations; - - serverData.cities = await this.localizeCities(server, serverData); - this.newData.push(serverData); - }, - - async localizeCities(server, serverData) { - const cities = []; - for (const city of server.cities) { - cities.push(await this.localizeCity(city.name, serverData)); - } - return cities; - }, - - async localizeCity(name, serverData) { - console.log(` - Localizing city ${chalk.yellow(name)}...`); - let cityData = serverData.cities.find(c => c.city === name); - if (!cityData) { - console.log(' Unknown country!'); - cityData = { - wikiDataID: null, - city: name, - languages: {}, - } - } else if (!cityData.wikiDataID) { - console.log( - ' City found but we do not have a valid wikiDataID. Please update the file!'); - cityData.wikiDataID = null; - cityData.languages = {}; - } - - if (!cityData.wikiDataID) { - while (true) { - const answer = await inquirer.prompt([{ - name: 'value', - message: 'WikiData ID:', - }]); - - if (answer.value != '') { - cityData.wikiDataID = answer.value; - break; - } - } - } - - const translations = {}; - - const sparql = `SELECT ?cityName (lang(?cityName) as ?lang) - WHERE { rdfs:label ?cityName . }`; - - const url = this.wbk.sparqlQuery(sparql) - const result = await this.retrieveJson(url); - - if (!('head' in result)) throw new Error('Invalid SPARQL result (no head)'); - if (!('results' in result)) - throw new Error('Invalid SPARQL result (no results)'); - if (!('bindings' in result.results)) - throw new Error('Invalid SPARQL result (no results/bindings)'); - - if (result.results.bindings.length === 0) { - console.log(sparql); - throw new Error('No results'); - } - - for (let lang of result.results.bindings) { - const langCode = lang.cityName['xml:lang']; - const value = lang.cityName['value']; - - if (name === value) continue; - - if (this.languages.has(langCode)) { - translations[this.languages.get(langCode)] = value; - } - - for (let language of this.languages) { - if (langCode === language[0]) continue; - if (translations[language[1]]) continue; - if (!language[0].startsWith(langCode + '-')) continue; - translations[language[1]] = value; - } - } - - cityData.languages = translations; - return cityData; - }, - - languages: new Map(), - newData: [], - oldData: [], -}; - -ServerLocalizer.init(); diff --git a/tools/translationsreport/app/src/LanguageDropdown.js b/tools/translationsreport/app/src/LanguageDropdown.js index c3600f7248..186071c7fc 100644 --- a/tools/translationsreport/app/src/LanguageDropdown.js +++ b/tools/translationsreport/app/src/LanguageDropdown.js @@ -2,7 +2,7 @@ import { useState } from 'react' import { Dropdown } from 'semantic-ui-react' -// Language names from src/translations/languages.json +// Language names from src/translations/extras.xliff export const LANGUAGES = [ { value: "bg", text: "Bulgarian" }, { value: "co", text: "Corsican" },