From 9119d224aedc31c74e67da5c0841b52eb1a2b7fa Mon Sep 17 00:00:00 2001 From: sunyaozu Date: Tue, 7 Nov 2023 17:21:44 +0800 Subject: [PATCH] provide set and get app language interfaces Signed-off-by: sunyaozu --- bundle.json | 1 + frameworks/intl/BUILD.gn | 2 + frameworks/intl/src/preferred_language.cpp | 140 ++++++------------ interfaces/js/kits/BUILD.gn | 4 + interfaces/js/kits/src/i18n_system_addon.cpp | 8 +- .../include/preferred_language.h | 25 +++- 6 files changed, 82 insertions(+), 98 deletions(-) diff --git a/bundle.json b/bundle.json index 0f7b99c8..a0b720cf 100644 --- a/bundle.json +++ b/bundle.json @@ -61,6 +61,7 @@ "init", "ipc", "napi", + "preferences", "resource_management", "samgr" ], diff --git a/frameworks/intl/BUILD.gn b/frameworks/intl/BUILD.gn index 7e15a03a..d302c21d 100644 --- a/frameworks/intl/BUILD.gn +++ b/frameworks/intl/BUILD.gn @@ -48,11 +48,13 @@ ohos_shared_library("preferred_language") { "//foundation/systemabilitymgr/samgr/interfaces/innerkits/samgr_proxy/include/", ] external_deps += [ + "ability_runtime:app_context", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "preferences:native_preferences", "resource_management:global_resmgr", "samgr:samgr_proxy", ] diff --git a/frameworks/intl/src/preferred_language.cpp b/frameworks/intl/src/preferred_language.cpp index 68f8c97f..4baf1622 100644 --- a/frameworks/intl/src/preferred_language.cpp +++ b/frameworks/intl/src/preferred_language.cpp @@ -14,6 +14,7 @@ */ #ifdef SUPPORT_APP_PREFERRED_LANGUAGE #include +#include "application_context.h" #include "bundle_info.h" #include "bundle_mgr_interface.h" #include "hap_resource.h" @@ -36,6 +37,8 @@ const char *PreferredLanguage::RESOURCE_PATH_HEAD = "/data/accounts/account_0/ap const char *PreferredLanguage::RESOURCE_PATH_TAILOR = "/assets/entry/resources.index"; const char *PreferredLanguage::RESOURCE_PATH_SPLITOR = "/"; const char *PreferredLanguage::PREFERRED_LANGUAGES = "persist.sys.preferredLanguages"; +const char *PreferredLanguage::APP_LANGUAGE_KEY = "app_language"; +const char *PreferredLanguage::I18N_PREFERENCES_FILE_NAME = "/i18n"; bool PreferredLanguage::AddPreferredLanguageExist(std::vector &preferredLanguageList, int languageIdx, int index, const std::string& language) @@ -200,108 +203,57 @@ std::string PreferredLanguage::GetFirstPreferredLanguage() } #ifdef SUPPORT_APP_PREFERRED_LANGUAGE -std::string PreferredLanguage::GetBundleName() +std::shared_ptr PreferredLanguage::GetI18nAppPreferences() { - auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (systemAbilityManager == nullptr) { - HiLog::Error(LABEL, "Failed to create system ability manager."); - return ""; + std::shared_ptr appContext = AbilityRuntime::ApplicationContext::GetInstance(); + std::string preferencesDirPath = appContext->GetPreferencesDir(); + std::string i18nPreferencesFilePath = preferencesDirPath + I18N_PREFERENCES_FILE_NAME; + int status; + NativePreferences::Options options(i18nPreferencesFilePath); + std::shared_ptr preferences = + NativePreferences::PreferencesHelper::GetPreferences(options, status); + if (status != 0) { + HiLog::Error(LABEL, "PreferredLanguage::GetAppPreferredLanguage get i18n app preferences failed."); + return nullptr; } - auto bundleMgrSa = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); - if (bundleMgrSa == nullptr) { - HiLog::Error(LABEL, "Failed to create bundle manager SA."); - return ""; - } - auto bundleMgr = OHOS::iface_cast(bundleMgrSa); - if (bundleMgr == nullptr) { - HiLog::Error(LABEL, "Failed to create bundle manager."); - return ""; - } - AppExecFwk::BundleInfo bundleInfo; - bundleMgr->GetBundleInfoForSelf(0, bundleInfo); - return bundleInfo.name; -} - -std::set PreferredLanguage::GetResources() -{ - std::string bundleName = GetBundleName(); - const std::string resourcePath = RESOURCE_PATH_HEAD + bundleName + RESOURCE_PATH_SPLITOR + bundleName + - RESOURCE_PATH_TAILOR; - const OHOS::Global::Resource::HapResource *resource = - OHOS::Global::Resource::HapResource::LoadFromIndex(resourcePath.c_str(), nullptr); - const std::vector qualifiers = resource->GetQualifiers(); - std::set result; - std::regex languagePattern("type:0.*str:([a-z]{2})"); - std::regex countryPattern("type:1.*str:([A-Z]{2})"); - for (size_t i = 0; i < qualifiers.size(); i++) { - std::smatch match; - bool found = regex_search(qualifiers[i], match, languagePattern); - if (!found) { - continue; - } - std::string locale = match.str(1); - found = regex_search(qualifiers[i], match, countryPattern); - if (found) { - locale += "-"; - locale += match.str(1); - } - result.insert(locale); - } - return result; -} - -bool PreferredLanguage::IsMatched(const std::string& preferred, const std::string& resource) -{ - LocaleInfo preferredLocaleInfo(preferred); - LocaleInfo resourceLocaleInfo(resource); - if (preferred == resource) { - return true; - } - if (preferredLocaleInfo.GetLanguage() != resourceLocaleInfo.GetLanguage()) { - return false; - } - LocaleInfo maximizedResourceLocale(resourceLocaleInfo.Maximize()); - std::string resourceScript = maximizedResourceLocale.GetScript(); - if (resourceScript == "") { - std::string resourceCountry = maximizedResourceLocale.GetRegion(); - if (resourceCountry == "") { - return true; - } - std::string preferredCountry = preferredLocaleInfo.GetRegion(); - if (resourceCountry == preferredCountry) { - return true; - } - return false; - } - LocaleInfo maximizedPreferredLocale(preferredLocaleInfo.Maximize()); - std::string preferredScript = maximizedResourceLocale.GetScript(); - if (resourceScript == preferredScript) { - return true; - } - return false; + return preferences; } std::string PreferredLanguage::GetAppPreferredLanguage() { - std::vector preferredLanguageList = GetPreferredLanguageList(); - std::set resources = GetResources(); - int minmumMatchedIdx = -1; - for (size_t i = 0; i < preferredLanguageList.size(); i++) { - for (std::set::iterator it = resources.begin(); it != resources.end(); ++it) { - std::string preferredLanguage = preferredLanguageList[i]; - if (preferredLanguage == "en-Qaag") { - preferredLanguage = "en-Latn"; - } - if (IsMatched(preferredLanguage, *it)) { - minmumMatchedIdx = (int)i; - break; - } - } + std::shared_ptr preferences = GetI18nAppPreferences(); + if (preferences == nullptr) { + HiLog::Error(LABEL, + "PreferredLanguage::GetAppPreferredLanguage get i18n preferences failed, return system language."); + return LocaleConfig::GetSystemLanguage(); } - if (minmumMatchedIdx != -1) { - return preferredLanguageList[minmumMatchedIdx]; + std::string res = preferences->GetString(PreferredLanguage::APP_LANGUAGE_KEY, ""); + if (res.length() == 0) { + HiLog::Info(LABEL, + "PreferredLanguage::GetAppPreferredLanguage app language is empty, return system language."); + return LocaleConfig::GetSystemLanguage(); } - return preferredLanguageList[0]; + return res; +} + +void PreferredLanguage::SetAppPreferredLanguage(const std::string &language, I18nErrorCode &errCode) +{ + std::shared_ptr appContext = AbilityRuntime::ApplicationContext::GetInstance(); + appContext->SetLanguage(language); + std::shared_ptr preferences = GetI18nAppPreferences(); + if (preferences == nullptr) { + errCode = I18nErrorCode::FAILED; + HiLog::Error(LABEL, "PreferredLanguage::SetAppPreferredLanguage get i18n preferences failed."); + return; + } + int32_t status = preferences->PutString(PreferredLanguage::APP_LANGUAGE_KEY, language); + if (status != 0) { + errCode = I18nErrorCode::FAILED; + HiLog::Error(LABEL, + "PreferredLanguage::SetAppPreferredLanguage set app language to i18n preferences failed."); + return; + } + preferences->Flush(); } #endif diff --git a/interfaces/js/kits/BUILD.gn b/interfaces/js/kits/BUILD.gn index ef50707e..33e6e5b8 100644 --- a/interfaces/js/kits/BUILD.gn +++ b/interfaces/js/kits/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//base/global/i18n/i18n.gni") import("//build/ohos.gni") group("build_module") { @@ -92,6 +93,9 @@ ohos_shared_library("i18n") { "hilog:libhilog", "napi:ace_napi", ] + if (i18n_support_app_preferred_language) { + defines = [ "SUPPORT_APP_PREFERRED_LANGUAGE" ] + } relative_install_dir = "module" subsystem_name = "global" part_name = "i18n" diff --git a/interfaces/js/kits/src/i18n_system_addon.cpp b/interfaces/js/kits/src/i18n_system_addon.cpp index 5ff9c9fc..c4149307 100644 --- a/interfaces/js/kits/src/i18n_system_addon.cpp +++ b/interfaces/js/kits/src/i18n_system_addon.cpp @@ -324,7 +324,13 @@ napi_value I18nSystemAddon::SetAppPreferredLanguage(napi_env env, napi_callback_ ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true); return nullptr; } - // Do something next +#ifdef SUPPORT_APP_PREFERRED_LANGUAGE + I18nErrorCode errCode = I18nErrorCode::SUCCESS; + PreferredLanguage::SetAppPreferredLanguage(localeTag, errCode); + if (errCode != I18nErrorCode::SUCCESS) { + HiLog::Error(LABEL, "SetAppPreferredLanguage: set app language to i18n app preferences failed."); + } +#endif return nullptr; } diff --git a/interfaces/native/inner_api/preferred_language/include/preferred_language.h b/interfaces/native/inner_api/preferred_language/include/preferred_language.h index e03b157f..2e138f52 100644 --- a/interfaces/native/inner_api/preferred_language/include/preferred_language.h +++ b/interfaces/native/inner_api/preferred_language/include/preferred_language.h @@ -19,6 +19,9 @@ #include #include #include "i18n_types.h" +#ifdef SUPPORT_APP_PREFERRED_LANGUAGE +#include "preferences_helper.h" +#endif namespace OHOS { namespace Global { @@ -30,7 +33,23 @@ public: static std::vector GetPreferredLanguageList(); static std::string GetFirstPreferredLanguage(); #ifdef SUPPORT_APP_PREFERRED_LANGUAGE + /** + * @brief Get App Language. + * Get the app language from app preferences data which saved by SetAppPreferredLanguage method. + * + * @return std::string return current app language. + */ static std::string GetAppPreferredLanguage(); + + /** + * @brief Set App Language. + * The application interface will be refreshed in real time after call this method. And the language will be saved + * to app preferences data which will be used the next time the application starts. + * + * @param language language to be set. + * @param errCode Indicates whether the setting was successful; errCode == I18nErrorCode::SUCCESS means successful. + */ + static void SetAppPreferredLanguage(const std::string &language, I18nErrorCode &errCode); #endif static std::string GetPreferredLocale(); @@ -43,14 +62,14 @@ private: static bool IsValidTag(const std::string &tag); static void Split(const std::string &src, const std::string &sep, std::vector &dest); #ifdef SUPPORT_APP_PREFERRED_LANGUAGE - static std::string GetBundleName(); - static std::set GetResources(); - static bool IsMatched(const std::string& preferred, const std::string& resource); + static std::shared_ptr GetI18nAppPreferences(); #endif static const char *RESOURCE_PATH_HEAD; static const char *RESOURCE_PATH_TAILOR; static const char *RESOURCE_PATH_SPLITOR; static const char *PREFERRED_LANGUAGES; + static const char *APP_LANGUAGE_KEY; + static const char *I18N_PREFERENCES_FILE_NAME; static constexpr int CONFIG_LEN = 128; static constexpr uint32_t LANGUAGE_LEN = 2; };