// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "i18nImpl.hpp" #include "Metadata.hpp" #include #include #include #include namespace utils { namespace { auto returnNonEmptyString(const std::string &str, const std::string &ret) -> const std::string & { return str.empty() ? ret : str; } class i18nPrivateInterface : public i18n { public: const std::string &get(const std::string &str); const std::vector get_array(const std::string &str); }; const std::string &i18nPrivateInterface::get(const std::string &str) { // if language pack returned nothing then try default language if (getDisplayLanguageJSON()[str].string_value().empty()) { return returnNonEmptyString(getFallbackLanguageJSON()[str].string_value(), str); } return returnNonEmptyString(getDisplayLanguageJSON()[str].string_value(), str); } const std::vector i18nPrivateInterface::get_array(const std::string &str) { std::vector out; auto object = getDisplayLanguageJSON()[str]; // if language pack returned nothing then try default language if (not object.is_array()) { object = getFallbackLanguageJSON()[str]; } if (object.is_array()) { out.reserve(object.array_items().size()); std::for_each(object.array_items().begin(), object.array_items().end(), [&out](const auto &o) { out.emplace_back(o.string_value()); }); } return out; } i18nPrivateInterface localize; } // namespace void i18n::resetAssetsPath(const std::filesystem::path &assets) { displayLanguageDirPath = assets / "lang"; inputLanguageDirPath = assets / "profiles"; } bool i18n::setInputLanguage(const Language &lang) { cpp_freertos::LockGuard lock(mutex); if (lang.empty() || lang == inputLanguage) { return false; } inputLanguage = lang; return true; } const std::string &i18n::getInputLanguageFilename(const std::string &inputMode) { // if language pack returned nothing then try default language if (inputLanguage.empty()) { inputLanguageFilename = fallbackLanguageName + utils::files::breakSign + inputMode; } else { inputLanguageFilename = inputLanguage + utils::files::breakSign + inputMode; } return inputLanguageFilename; } bool i18n::setDisplayLanguage(const Language &lang) { cpp_freertos::LockGuard lock(mutex); if (fallbackLanguage.is_null()) { loadFallbackLanguage(); loadMetadata(); } if ((lang.empty() || lang == currentDisplayLanguage) && !currentDisplayLanguage.empty()) { return false; } else if (const auto result = getMetadata(lang)) { currentDisplayLanguage = lang; displayLanguage = loader(result->path).value(); return true; } return false; } void i18n::loadFallbackLanguage() { currentDisplayLanguage = fallbackLanguageName; fallbackLanguage = loader(localize.getDisplayLanguagePath() / (fallbackLanguageName + utils::files::jsonExtension)).value(); } void i18n::loadMetadata() { for (const auto &entry : std::filesystem::directory_iterator(getDisplayLanguagePath())) { if (const auto data = fetchMetadata(entry.path())) { metadata.push_back(*data); } } } const std::string &translate(const std::string &text) { return utils::localize.get(text); } const std::vector translate_array(const std::string &text) { return utils::localize.get_array(text); } const std::string &getDisplayLanguage() { return utils::localize.getDisplayLanguage(); } const std::string &getInputLanguage() { return utils::localize.getInputLanguage(); } const std::string &getInputLanguageFilename(const std::string &inputMode) { return localize.getInputLanguageFilename(inputMode); } bool setInputLanguage(const Language &lang) { return localize.setInputLanguage(lang); } bool setDisplayLanguage(const Language &lang) { return localize.setDisplayLanguage(lang); } const std::filesystem::path getInputLanguagePath() { return localize.getInputLanguagePath(); } const std::filesystem::path getDisplayLanguagePath() { return localize.getDisplayLanguagePath(); } void i18n::resetDisplayLanguages() { currentDisplayLanguage.clear(); displayLanguage = json11::Json(); fallbackLanguage = json11::Json(); } std::optional i18n::getMetadata(const Language &lang) const { const auto result = std::find_if(metadata.begin(), metadata.end(), [&lang](const auto &e) { return e.displayName == lang; }); if (result != metadata.end()) { return *result; } return {}; } std::optional i18n::fetchMetadata(const std::filesystem::path &path) const { if (const auto jsonData = loader(path)) { return LanguageMetadata::get(path, jsonData.value()); } return {}; } std::vector i18n::getAvailableDisplayLanguages() const { std::vector languages{metadata.size()}; std::transform( metadata.cbegin(), metadata.cend(), languages.begin(), [](const auto &meta) { return meta.displayName; }); std::sort(languages.begin(), languages.end()); return languages; } void resetDisplayLanguages() { return localize.resetDisplayLanguages(); } void resetAssetsPath(const std::filesystem::path &p) { return localize.resetAssetsPath(p); } std::vector getAvailableDisplayLanguages() { return localize.getAvailableDisplayLanguages(); } } // namespace utils