mirror of
https://gitee.com/openharmony/global_i18n
synced 2024-11-22 22:49:54 +00:00
支持多用户
Signed-off-by: LY <liuyong235@huawei.com>
This commit is contained in:
parent
09b1dceee4
commit
85d5e10585
@ -69,6 +69,7 @@
|
||||
"memmgr",
|
||||
"napi",
|
||||
"openssl",
|
||||
"os_account",
|
||||
"preferences",
|
||||
"resource_management",
|
||||
"safwk",
|
||||
|
@ -108,6 +108,7 @@ ohos_shared_library("intl_util") {
|
||||
"src/locale_matcher.cpp",
|
||||
"src/locale_util.cpp",
|
||||
"src/measure_data.cpp",
|
||||
"src/multi_users.cpp",
|
||||
"src/number_format.cpp",
|
||||
"src/phone_number_format.cpp",
|
||||
"src/plural_rules.cpp",
|
||||
@ -168,6 +169,7 @@ ohos_shared_library("intl_util") {
|
||||
"libxml2:libxml2",
|
||||
"openssl:libcrypto_shared",
|
||||
"openssl:libssl_shared",
|
||||
"os_account:os_account_innerkits",
|
||||
"preferences:native_preferences",
|
||||
]
|
||||
public_external_deps = []
|
||||
|
@ -12,7 +12,7 @@
|
||||
# limitations under the License.
|
||||
persist.global.language=zh-Hans
|
||||
persist.global.locale=zh-Hans-CN
|
||||
persist.global.is24Hour=
|
||||
persist.global.is24Hour=default
|
||||
persist.global.preferredLanguages=
|
||||
const.global.language=zh-Hans
|
||||
const.global.locale=zh-Hans-CN
|
||||
|
@ -105,6 +105,9 @@ public:
|
||||
static bool IsValidRegion(const std::string ®ion);
|
||||
static bool IsValidTag(const std::string &tag);
|
||||
static bool IsValid24HourClockValue(const std::string &tag);
|
||||
static std::string GetLanguageKey();
|
||||
static std::string GetLocaleKey();
|
||||
static std::string GetHourKey();
|
||||
|
||||
private:
|
||||
static void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);
|
||||
|
61
frameworks/intl/include/multi_users.h
Normal file
61
frameworks/intl/include/multi_users.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef OHOS_GLOBAL_I18N_MULTI_USERS_H
|
||||
#define OHOS_GLOBAL_I18N_MULTI_USERS_H
|
||||
|
||||
#include <string>
|
||||
#include "i18n_types.h"
|
||||
#include "preferences.h"
|
||||
#include "preferences_helper.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
class MultiUsers {
|
||||
public:
|
||||
static void InitMultiUser();
|
||||
static void SwitchUser(const std::string& curLocalId);
|
||||
static void AddUser(const std::string& localId);
|
||||
static void RemoveUser(const std::string& localId);
|
||||
static I18nErrorCode SaveLanguage(const std::string& localId, const std::string& language);
|
||||
static I18nErrorCode SaveLocale(const std::string& localId, const std::string& locale);
|
||||
static I18nErrorCode SaveIs24Hour(const std::string& localId, const std::string& is24Hour);
|
||||
|
||||
private:
|
||||
static I18nErrorCode SaveGlobalParam(const std::string& localId);
|
||||
static I18nErrorCode LoadGlobalParam(const std::string& localId);
|
||||
static I18nErrorCode GetForegroundLocalId(std::string& localId);
|
||||
static I18nErrorCode RemoveGlobalParam(const std::string& localId);
|
||||
static std::string ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId);
|
||||
static I18nErrorCode WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
|
||||
const std::string& localId, bool isDel);
|
||||
static bool IsValidLocalId(const std::string& localId);
|
||||
static void InitPreferences();
|
||||
static std::string GetParamFromPreferences(const std::string& paramKey);
|
||||
static I18nErrorCode SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue);
|
||||
|
||||
static const std::string MULTI_USERS_LANGUAGE_KEY;
|
||||
static const std::string MULTI_USERS_LOCALE_KEY;
|
||||
static const std::string MULTI_USERS_HOUR_KEY;
|
||||
static const std::string INIT_KEY;
|
||||
static const std::string PREFERENCE_PATH;
|
||||
static const int32_t DEFAULT_LOCAL_ID;
|
||||
static const int CONFIG_LEN;
|
||||
static std::shared_ptr<NativePreferences::Preferences> preferences;
|
||||
};
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
||||
#endif
|
@ -32,6 +32,7 @@ static const uint32_t BYTE_ARRAY_INDEX_THIRD = 3;
|
||||
static std::set<std::string> availableIDs;
|
||||
|
||||
void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);
|
||||
void Merge(const std::vector<std::string>& src, const std::string& sep, std::string& dest);
|
||||
std::string ReadSystemParameter(const char *paramKey, const int paramLength);
|
||||
int32_t ConvertString2Int(const std::string &numberStr, int32_t& status);
|
||||
bool IsValidLocaleTag(icu::Locale &locale);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "ipc_skeleton.h"
|
||||
#include "libxml/parser.h"
|
||||
#include "locale_info.h"
|
||||
#include "multi_users.h"
|
||||
#include "unicode/localebuilder.h"
|
||||
#include "unicode/locdspnm.h"
|
||||
#include "unicode/locid.h"
|
||||
@ -1076,7 +1077,7 @@ bool LocaleConfig::IsEmpty24HourClock()
|
||||
bool LocaleConfig::Is24HourClock()
|
||||
{
|
||||
std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
|
||||
if (is24Hour.empty()) {
|
||||
if (is24Hour.compare("default") == 0) {
|
||||
std::string systemLocale = GetSystemLocale();
|
||||
return Is24HourLocale(systemLocale);
|
||||
}
|
||||
@ -1188,6 +1189,7 @@ I18nErrorCode LocaleConfig::SetSystemLanguage(const std::string &languageTag)
|
||||
}
|
||||
std::string newLocaleTag = UpdateLanguageOfLocale(languageTag);
|
||||
if (SetSystemLocale(newLocaleTag) == I18nErrorCode::SUCCESS) {
|
||||
MultiUsers::SaveLanguage("", languageTag);
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
// reset system language to old language in case that system language is inconsist with system locale's lanuage.
|
||||
@ -1214,6 +1216,7 @@ I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
|
||||
if (SetParameter(LOCALE_KEY, localeTag.data()) != 0) {
|
||||
return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED;
|
||||
}
|
||||
MultiUsers::SaveLocale("", localeTag);
|
||||
#ifdef SUPPORT_GRAPHICS
|
||||
UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, localeTag);
|
||||
return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
|
||||
@ -1224,7 +1227,7 @@ I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
|
||||
|
||||
bool LocaleConfig::IsValid24HourClockValue(const std::string &tag)
|
||||
{
|
||||
if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.length() == 0) {
|
||||
if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.compare("default") == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1241,6 +1244,7 @@ I18nErrorCode LocaleConfig::Set24HourClock(const std::string &option)
|
||||
option.c_str());
|
||||
return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED;
|
||||
}
|
||||
MultiUsers::SaveIs24Hour("", option);
|
||||
#ifdef SUPPORT_GRAPHICS
|
||||
UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, option);
|
||||
return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
|
||||
@ -1425,6 +1429,21 @@ std::string LocaleConfig::CreateLocaleFromRegion(const std::string ®ionTag)
|
||||
}
|
||||
return localeTag;
|
||||
}
|
||||
|
||||
std::string LocaleConfig::GetLanguageKey()
|
||||
{
|
||||
return LANGUAGE_KEY;
|
||||
}
|
||||
|
||||
std::string LocaleConfig::GetLocaleKey()
|
||||
{
|
||||
return LOCALE_KEY;
|
||||
}
|
||||
|
||||
std::string LocaleConfig::GetHourKey()
|
||||
{
|
||||
return HOUR_KEY;
|
||||
}
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
||||
|
349
frameworks/intl/src/multi_users.cpp
Normal file
349
frameworks/intl/src/multi_users.cpp
Normal file
@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "i18n_hilog.h"
|
||||
#include "locale_config.h"
|
||||
#include "os_account_manager.h"
|
||||
#include "parameter.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "multi_users.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
const std::string MultiUsers::MULTI_USERS_LANGUAGE_KEY = "languageData";
|
||||
const std::string MultiUsers::MULTI_USERS_LOCALE_KEY = "localeData";
|
||||
const std::string MultiUsers::MULTI_USERS_HOUR_KEY = "is24HourData";
|
||||
const std::string MultiUsers::INIT_KEY = "init";
|
||||
const std::string MultiUsers::PREFERENCE_PATH = "/data/service/el1/public/i18n/global/GlobalParamData";
|
||||
const int32_t MultiUsers::DEFAULT_LOCAL_ID = 100;
|
||||
const int MultiUsers::CONFIG_LEN = 128;
|
||||
std::shared_ptr<NativePreferences::Preferences> MultiUsers::preferences = nullptr;
|
||||
|
||||
void MultiUsers::InitMultiUser()
|
||||
{
|
||||
InitPreferences();
|
||||
if (preferences == nullptr) {
|
||||
HILOG_ERROR_I18N("InitMultiUser: InitPreferences failed");
|
||||
return;
|
||||
}
|
||||
bool init = preferences->GetBool(INIT_KEY, false);
|
||||
std::string localId;
|
||||
I18nErrorCode errCode = GetForegroundLocalId(localId);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("InitMultiUser: get foreground local id failed");
|
||||
return;
|
||||
}
|
||||
if (!init) {
|
||||
AddUser(localId);
|
||||
preferences->PutBool(INIT_KEY, true);
|
||||
preferences->Flush();
|
||||
HILOG_ERROR_I18N("InitMultiUser: init multi user data success");
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUsers::SwitchUser(const std::string& curLocalId)
|
||||
{
|
||||
if (!IsValidLocalId(curLocalId)) {
|
||||
HILOG_ERROR_I18N("SwitchUser: curLocalId is an invalid LocalId");
|
||||
return;
|
||||
}
|
||||
I18nErrorCode errCode = LoadGlobalParam(curLocalId);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SwitchUser: load global params failed");
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUsers::AddUser(const std::string& localId)
|
||||
{
|
||||
if (!IsValidLocalId(localId)) {
|
||||
HILOG_ERROR_I18N("AddUser: %{public}s is invalid local id", localId.c_str());
|
||||
return;
|
||||
}
|
||||
I18nErrorCode errCode = SaveGlobalParam(localId);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("AddUser: add global param failed");
|
||||
}
|
||||
}
|
||||
|
||||
void MultiUsers::RemoveUser(const std::string& localId)
|
||||
{
|
||||
if (!IsValidLocalId(localId)) {
|
||||
HILOG_ERROR_I18N("RemoveUser: %{public}s is invalid local id", localId.c_str());
|
||||
return;
|
||||
}
|
||||
I18nErrorCode errCode = RemoveGlobalParam(localId);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("RemoveUser: remove global param failed");
|
||||
}
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::GetForegroundLocalId(std::string& localId)
|
||||
{
|
||||
int id = 0;
|
||||
int errCode = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(id);
|
||||
if (errCode != 0) {
|
||||
HILOG_ERROR_I18N("GetForegroundLocalId: get foreground locale Id failed, errCode is %{public}d", errCode);
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
localId = std::to_string(id);
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::SaveLanguage(const std::string& localId, const std::string& language)
|
||||
{
|
||||
std::string foregroundLocalId = localId;
|
||||
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
|
||||
if (localId.empty()) {
|
||||
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
|
||||
}
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
errCode =
|
||||
WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, language, foregroundLocalId, false);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveLanguage: save language of user %{public}s failed", foregroundLocalId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::SaveLocale(const std::string& localId, const std::string& locale)
|
||||
{
|
||||
std::string foregroundLocalId = localId;
|
||||
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
|
||||
if (localId.empty()) {
|
||||
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
|
||||
}
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveLocale: get foreground locale Id failed");
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
errCode =
|
||||
WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, locale, foregroundLocalId, false);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveLocale: save locale of user %{public}s failed", foregroundLocalId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::SaveIs24Hour(const std::string& localId, const std::string& is24Hour)
|
||||
{
|
||||
HILOG_ERROR_I18N("TestLog: SaveIs24Hour start");
|
||||
std::string foregroundLocalId = localId;
|
||||
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
|
||||
if (localId.empty()) {
|
||||
HILOG_ERROR_I18N("TestLog: localId");
|
||||
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
|
||||
}
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("TestLog: get foreground locale Id failed");
|
||||
HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
HILOG_ERROR_I18N("TestLog: foregroundLocalId is %{public}s", foregroundLocalId.c_str());
|
||||
errCode =
|
||||
WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, is24Hour, foregroundLocalId, false);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveIs24Hour: save is24Hour of user %{public}s failed", foregroundLocalId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::SaveGlobalParam(const std::string& localId)
|
||||
{
|
||||
std::string language = ReadSystemParameter(LocaleConfig::GetLanguageKey().data(), CONFIG_LEN);
|
||||
std::string locale = ReadSystemParameter(LocaleConfig::GetLocaleKey().data(), CONFIG_LEN);
|
||||
std::string is24Hour = ReadSystemParameter(LocaleConfig::GetHourKey().data(), CONFIG_LEN);
|
||||
I18nErrorCode errCode = SaveLanguage(localId, language);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveGlobalParam: save language of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
errCode = SaveLocale(localId, locale);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveGlobalParam: save locale of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
errCode = SaveIs24Hour(localId, is24Hour);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("SaveGlobalParam: save is24Hour of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::LoadGlobalParam(const std::string& localId)
|
||||
{
|
||||
std::string newLocale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
|
||||
if (!newLocale.empty() && SetParameter(LocaleConfig::GetLocaleKey().data(), newLocale.data()) != 0) {
|
||||
HILOG_ERROR_I18N("LoadGlobalParam: set locale %{public}s failed", newLocale.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
std::string newLanguage = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
|
||||
if (!newLanguage.empty() && LocaleConfig::SetSystemLanguage(newLanguage) != 0) {
|
||||
HILOG_ERROR_I18N("LoadGlobalParam: set language %{public}s failed", newLanguage.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
std::string newIs24Hour = ReadMultiUsersParameter(MULTI_USERS_HOUR_KEY, localId);
|
||||
if (!newIs24Hour.empty() && LocaleConfig::Set24HourClock(newIs24Hour) != 0) {
|
||||
HILOG_ERROR_I18N("LoadGlobalParam: set is24Hour %{public}s failed", newIs24Hour.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::RemoveGlobalParam(const std::string& localId)
|
||||
{
|
||||
I18nErrorCode errCode = WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, "", localId, true);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("RemoveGlobalParam: remove language of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
errCode = WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, "", localId, true);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("RemoveGlobalParam: remove locale of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
|
||||
errCode = WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, "", localId, true);
|
||||
if (errCode != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("RemoveGlobalParam: remove is24Hour of user %{public}s failed", localId.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
std::string MultiUsers::ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId)
|
||||
{
|
||||
std::string param = GetParamFromPreferences(paramKey);
|
||||
if (param.empty()) {
|
||||
return "";
|
||||
}
|
||||
std::vector<std::string> multiUsersParam;
|
||||
Split(param, ";", multiUsersParam);
|
||||
for (auto& userParam : multiUsersParam) {
|
||||
std::vector<std::string> content;
|
||||
Split(userParam, ":", content);
|
||||
// 2 is number of param
|
||||
if (content.size() != 2) {
|
||||
continue;
|
||||
}
|
||||
if (content[0] == localId) {
|
||||
return content[1];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
|
||||
const std::string& localId, bool isDel)
|
||||
{
|
||||
std::string param = GetParamFromPreferences(paramKey);
|
||||
std::vector<std::string> multiUsersParam;
|
||||
Split(param, ";", multiUsersParam);
|
||||
std::vector<std::string> newMultiUsersParam;
|
||||
bool userIsExist = false;
|
||||
for (auto& userParam : multiUsersParam) {
|
||||
std::vector<std::string> content;
|
||||
Split(userParam, ":", content);
|
||||
// 2 is number of param
|
||||
if (content.size() != 2) {
|
||||
continue;
|
||||
}
|
||||
std::string userLocalId = content[0];
|
||||
if (!isDel && userLocalId == localId) {
|
||||
content[1] = paramValue;
|
||||
Merge(content, ":", userParam);
|
||||
userIsExist = true;
|
||||
}
|
||||
newMultiUsersParam.emplace_back(userParam);
|
||||
if (isDel && userLocalId == localId) {
|
||||
newMultiUsersParam.pop_back();
|
||||
}
|
||||
}
|
||||
if (!isDel && !userIsExist) {
|
||||
newMultiUsersParam.push_back(localId + ":" + paramValue);
|
||||
}
|
||||
std::string newParam;
|
||||
Merge(newMultiUsersParam, ";", newParam);
|
||||
if (SetParamFromPreferences(paramKey, newParam) != I18nErrorCode::SUCCESS) {
|
||||
HILOG_ERROR_I18N("WriteMultiUsersParameter: set param %{public}s failed", paramKey.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
bool MultiUsers::IsValidLocalId(const std::string& localId)
|
||||
{
|
||||
if (std::atoi(localId.c_str()) < DEFAULT_LOCAL_ID) {
|
||||
HILOG_ERROR_I18N("IsValidLocalId: %{public}s is an invalid local ID", localId.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiUsers::InitPreferences()
|
||||
{
|
||||
if (preferences == nullptr) {
|
||||
HILOG_ERROR_I18N("InitPreferences: preferences Init");
|
||||
OHOS::NativePreferences::Options opt(PREFERENCE_PATH);
|
||||
int status;
|
||||
preferences = NativePreferences::PreferencesHelper::GetPreferences(opt, status);
|
||||
if (status != 0) {
|
||||
HILOG_ERROR_I18N("InitPreferences: get preferences failed");
|
||||
preferences = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string MultiUsers::GetParamFromPreferences(const std::string& paramKey)
|
||||
{
|
||||
InitPreferences();
|
||||
if (preferences == nullptr) {
|
||||
HILOG_ERROR_I18N("GetParamFromPreferences: preferences is nullptr");
|
||||
return "";
|
||||
}
|
||||
return preferences->GetString(paramKey, "");
|
||||
}
|
||||
|
||||
I18nErrorCode MultiUsers::SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue)
|
||||
{
|
||||
InitPreferences();
|
||||
if (preferences == nullptr) {
|
||||
HILOG_ERROR_I18N("SetParamFromPreferences: preferences is nullptr");
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
int status = preferences->PutString(paramKey, paramValue);
|
||||
if (status != 0) {
|
||||
HILOG_ERROR_I18N("SetParamFromPreferences: put param %{public}s failed", paramKey.c_str());
|
||||
return I18nErrorCode::FAILED;
|
||||
}
|
||||
preferences->Flush();
|
||||
return I18nErrorCode::SUCCESS;
|
||||
}
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
@ -13,8 +13,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <climits>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <dirent.h>
|
||||
@ -58,6 +58,19 @@ void Split(const string &src, const string &sep, vector<string> &dest)
|
||||
}
|
||||
}
|
||||
|
||||
void Merge(const std::vector<std::string>& src, const std::string& sep, std::string& dest)
|
||||
{
|
||||
if (src.size() == 0) {
|
||||
dest = "";
|
||||
return;
|
||||
}
|
||||
dest = src[0];
|
||||
for (size_t i = 1; i < src.size(); ++i) {
|
||||
dest += sep;
|
||||
dest += src[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string ReadSystemParameter(const char *paramKey, const int paramLength)
|
||||
{
|
||||
char param[paramLength];
|
||||
|
@ -52,6 +52,7 @@ ohos_unittest("intl_test") {
|
||||
"libphonenumber:phonenumber_standard",
|
||||
"libpng:libpng",
|
||||
"openssl:libssl_shared",
|
||||
"preferences:native_preferences",
|
||||
]
|
||||
if (i18n_support_app_preferred_language) {
|
||||
defines = [ "SUPPORT_APP_PREFERRED_LANGUAGE" ]
|
||||
|
@ -127,6 +127,12 @@ int IntlFuncTest0094(void);
|
||||
int IntlFuncTest0095(void);
|
||||
int IntlFuncTest0096(void);
|
||||
int IntlFuncTest0097(void);
|
||||
int IntlFuncTest0098(void);
|
||||
int IntlFuncTest0099(void);
|
||||
int IntlFuncTest00100(void);
|
||||
int IntlFuncTest00101(void);
|
||||
int IntlFuncTest00102(void);
|
||||
int IntlFuncTest00103(void);
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "locale_info.h"
|
||||
#include "locale_matcher.h"
|
||||
#include "measure_data.h"
|
||||
#include "multi_users.h"
|
||||
#include "number_format.h"
|
||||
#include "parameter.h"
|
||||
#include "phone_number_format.h"
|
||||
@ -1827,6 +1828,40 @@ HWTEST_F(IntlTest, IntlFuncTest0097, TestSize.Level1)
|
||||
bool isWeekend = calendarMock->IsWeekend();
|
||||
EXPECT_FALSE(isWeekend);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: IntlFuncTest00103
|
||||
* @tc.desc: Test Intl multi users
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(IntlTest, IntlFuncTest00103, TestSize.Level1)
|
||||
{
|
||||
std::string path = "/data/service/el1/public/i18n/global/GlobalParamData";
|
||||
OHOS::NativePreferences::Options opt(path);
|
||||
int status;
|
||||
std::shared_ptr<NativePreferences::Preferences> preferences =
|
||||
NativePreferences::PreferencesHelper::GetPreferences(opt, status);
|
||||
MultiUsers::AddUser("101");
|
||||
MultiUsers::SwitchUser("101");
|
||||
MultiUsers::RemoveUser("100");
|
||||
if (preferences != nullptr) {
|
||||
std::string language = preferences->GetString("languageData", "");
|
||||
std::string locale = preferences->GetString("localeData", "");
|
||||
std::string is24Hour = preferences->GetString("is24HourData", "");
|
||||
EXPECT_EQ(language, "101:zh-Hans");
|
||||
EXPECT_EQ(locale, "101:zh-Hans-CN");
|
||||
EXPECT_EQ(is24Hour, "101:false");
|
||||
}
|
||||
MultiUsers::RemoveUser("101");
|
||||
if (preferences != nullptr) {
|
||||
std::string language = preferences->GetString("languageData", "");
|
||||
std::string locale = preferences->GetString("localeData", "");
|
||||
std::string is24Hour = preferences->GetString("is24HourData", "");
|
||||
EXPECT_EQ(language, "");
|
||||
EXPECT_EQ(locale, "");
|
||||
EXPECT_EQ(is24Hour, "");
|
||||
}
|
||||
}
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
@ -6,7 +6,21 @@
|
||||
"libpath": "libi18n_sa.z.so",
|
||||
"run-on-create": false,
|
||||
"distributed": false,
|
||||
"dump_level": 1
|
||||
"dump_level": 1,
|
||||
"start-on-demand": {
|
||||
"allow-update":false,
|
||||
"commonevent":[
|
||||
{
|
||||
"name":"usual.event.USER_SWITCHED"
|
||||
},
|
||||
{
|
||||
"name":"usual.event.USER_ADDED"
|
||||
},
|
||||
{
|
||||
"name":"usual.event.USER_REMOVED"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -67,6 +67,7 @@ ohos_shared_library("i18n_sa") {
|
||||
sources = [
|
||||
"./src/i18n_service_ability.cpp",
|
||||
"./src/i18n_service_ability_stub.cpp",
|
||||
"./src/i18n_service_event.cpp",
|
||||
]
|
||||
include_dirs = [
|
||||
"./include",
|
||||
@ -79,6 +80,7 @@ ohos_shared_library("i18n_sa") {
|
||||
"../frameworks/intl:preferred_language",
|
||||
]
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"ability_runtime:ability_manager",
|
||||
"access_token:libaccesstoken_sdk",
|
||||
"access_token:libtokenid_sdk",
|
||||
|
@ -3,9 +3,10 @@
|
||||
{
|
||||
"name": "boot",
|
||||
"cmds": [
|
||||
"mkdir /data/service/el1/public/i18n/ 0744 i18n_service i18n_service",
|
||||
"mkdir /data/service/el1/public/i18n/ 0755 i18n_service i18n_service",
|
||||
"mkdir /data/service/el1/public/i18n/timezone/ 0755 i18n_service i18n_service",
|
||||
"mkdir /data/service/el1/public/i18n/libphonenumber/ 0755 i18n_service i18n_service",
|
||||
"mkdir /data/service/el1/public/i18n/global/ 0777 i18n_service i18n_service",
|
||||
"exec /system/bin/hmos_cust_timezone_mount",
|
||||
"exec /system/bin/hmos_cust_libphonenumber_mount"
|
||||
]
|
||||
@ -19,7 +20,8 @@
|
||||
"gid": ["i18n", "shell"],
|
||||
"permission": [
|
||||
"ohos.permission.UPDATE_CONFIGURATION",
|
||||
"ohos.permission.MANAGE_SECURE_SETTINGS"
|
||||
"ohos.permission.MANAGE_SECURE_SETTINGS",
|
||||
"ohos.permission.MANAGE_LOCAL_ACCOUNTS"
|
||||
],
|
||||
"ondemand": true,
|
||||
"secon": "u:r:i18n_service:s0"
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "event_handler.h"
|
||||
#include "i18n_service_ability_stub.h"
|
||||
#include "i18n_service_event.h"
|
||||
#include "system_ability.h"
|
||||
|
||||
namespace OHOS {
|
||||
@ -48,7 +49,7 @@ protected:
|
||||
/**
|
||||
* @brief Called when i18n service start.
|
||||
*/
|
||||
void OnStart() override;
|
||||
void OnStart(const SystemAbilityOnDemandReason& startReason) override;
|
||||
|
||||
/**
|
||||
* @brief Called when i18n service stop.
|
||||
@ -58,6 +59,7 @@ protected:
|
||||
private:
|
||||
// i18n service unload event handler.
|
||||
std::shared_ptr<AppExecFwk::EventHandler> handler;
|
||||
I18nServiceEvent* i18nServiceEvent = nullptr;
|
||||
};
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
|
77
services/include/i18n_service_event.h
Normal file
77
services/include/i18n_service_event.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H
|
||||
#define OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <singleton.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "common_event_subscriber.h"
|
||||
#include "system_ability.h"
|
||||
#include "want.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
class I18nServiceEvent {
|
||||
public:
|
||||
I18nServiceEvent();
|
||||
~I18nServiceEvent();
|
||||
|
||||
void CheckStartReason(const SystemAbilityOnDemandReason& startReason);
|
||||
void SubscriberEvent();
|
||||
|
||||
private:
|
||||
class I18nServiceSubscriber : public EventFwk::CommonEventSubscriber {
|
||||
public:
|
||||
explicit I18nServiceSubscriber(const EventFwk::CommonEventSubscribeInfo& subscribeInfo,
|
||||
I18nServiceEvent& registry) : CommonEventSubscriber(subscribeInfo), registry_(registry)
|
||||
{}
|
||||
|
||||
~I18nServiceSubscriber() = default;
|
||||
|
||||
void OnReceiveEvent(const EventFwk::CommonEventData& data) override
|
||||
{
|
||||
registry_.OnReceiveEvent(data);
|
||||
}
|
||||
|
||||
private:
|
||||
I18nServiceEvent& registry_;
|
||||
};
|
||||
|
||||
void UnSubscriberEvent();
|
||||
void OnReceiveEvent(const EventFwk::CommonEventData& data);
|
||||
|
||||
void HandleSwitchUser(const EventFwk::CommonEventData& data) const;
|
||||
void HandleAddUser(const EventFwk::CommonEventData& data) const;
|
||||
void HandleRemoveUser(const EventFwk::CommonEventData& data) const;
|
||||
|
||||
using EventHandle = std::function<void(const EventFwk::CommonEventData&)>;
|
||||
typedef void (I18nServiceEvent::*HandleEventFunc)(const EventFwk::CommonEventData&) const;
|
||||
std::unordered_map<std::string, EventHandle> eventHandles;
|
||||
std::unordered_map<std::string, HandleEventFunc> handleEventFunc;
|
||||
std::shared_ptr<I18nServiceSubscriber> subscriber = nullptr;
|
||||
std::string userSwitchKey;
|
||||
std::string userAdded;
|
||||
std::string userRemoved;
|
||||
static const int RETRY;
|
||||
};
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H
|
@ -43,7 +43,6 @@ public:
|
||||
SET_USING_LOCAL_DIGIT = 4,
|
||||
ADD_PREFERRED_LANGUAGE = 5,
|
||||
REMOVE_PREFERRED_LANGUAGE = 6,
|
||||
VERIFY_LIBPHONENUMBER_UPDATE = 7,
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.global.II18nServiceAbility");
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "locale_config.h"
|
||||
#include "mem_mgr_client.h"
|
||||
#include "mem_mgr_proxy.h"
|
||||
#include "multi_users.h"
|
||||
#include "preferred_language.h"
|
||||
#include "preferences.h"
|
||||
#include "preferences_helper.h"
|
||||
@ -93,9 +94,15 @@ void I18nServiceAbility::UnloadI18nServiceAbility()
|
||||
}
|
||||
}
|
||||
|
||||
void I18nServiceAbility::OnStart()
|
||||
void I18nServiceAbility::OnStart(const SystemAbilityOnDemandReason& startReason)
|
||||
{
|
||||
HILOG_INFO_I18N("I18nServiceAbility start.");
|
||||
i18nServiceEvent = new I18nServiceEvent();
|
||||
if (i18nServiceEvent != nullptr) {
|
||||
i18nServiceEvent->SubscriberEvent();
|
||||
i18nServiceEvent->CheckStartReason(startReason);
|
||||
}
|
||||
MultiUsers::InitMultiUser();
|
||||
bool status = Publish(this);
|
||||
if (status) {
|
||||
HILOG_INFO_I18N("I18nServiceAbility Publish success.");
|
||||
@ -112,6 +119,10 @@ void I18nServiceAbility::OnStop()
|
||||
{
|
||||
int pid = getpid();
|
||||
Memory::MemMgrClient::GetInstance().NotifyProcessStatus(pid, 1, 0, I18N_SA_ID);
|
||||
if (i18nServiceEvent != nullptr) {
|
||||
delete i18nServiceEvent;
|
||||
i18nServiceEvent = nullptr;
|
||||
}
|
||||
HILOG_INFO_I18N("I18nServiceAbility Stop.");
|
||||
}
|
||||
} // namespace I18n
|
||||
|
136
services/src/i18n_service_event.cpp
Normal file
136
services/src/i18n_service_event.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <common_event_data.h>
|
||||
#include <common_event_manager.h>
|
||||
#include <common_event_support.h>
|
||||
#include "common_event_subscriber.h"
|
||||
#include "i18n_hilog.h"
|
||||
#include "multi_users.h"
|
||||
|
||||
#include "i18n_service_event.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Global {
|
||||
namespace I18n {
|
||||
const int I18nServiceEvent::RETRY = 3;
|
||||
|
||||
I18nServiceEvent::I18nServiceEvent()
|
||||
{
|
||||
userSwitchKey = "usual.event.USER_SWITCHED";
|
||||
userAdded = "usual.event.USER_ADDED";
|
||||
userRemoved = "usual.event.USER_REMOVED";
|
||||
handleEventFunc.emplace(userSwitchKey, &I18nServiceEvent::HandleSwitchUser);
|
||||
handleEventFunc.emplace(userAdded, &I18nServiceEvent::HandleAddUser);
|
||||
handleEventFunc.emplace(userRemoved, &I18nServiceEvent::HandleRemoveUser);
|
||||
for (auto& it : I18nServiceEvent::handleEventFunc) {
|
||||
eventHandles.emplace(it.first, std::bind(it.second, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
|
||||
I18nServiceEvent::~I18nServiceEvent()
|
||||
{
|
||||
eventHandles.clear();
|
||||
handleEventFunc.clear();
|
||||
UnSubscriberEvent();
|
||||
}
|
||||
|
||||
void I18nServiceEvent::SubscriberEvent()
|
||||
{
|
||||
if (subscriber) {
|
||||
return;
|
||||
}
|
||||
EventFwk::MatchingSkills matchingSkills;
|
||||
for (auto& event : handleEventFunc) {
|
||||
matchingSkills.AddEvent(event.first);
|
||||
}
|
||||
EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
|
||||
subscriber = std::make_shared<I18nServiceSubscriber>(subscribeInfo, *this);
|
||||
|
||||
int32_t retry = 3;
|
||||
do {
|
||||
bool status = EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber);
|
||||
if (status) {
|
||||
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent success.");
|
||||
return;
|
||||
}
|
||||
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent failed %{public}d.", retry);
|
||||
retry--;
|
||||
sleep(1);
|
||||
} while (retry);
|
||||
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent failed");
|
||||
}
|
||||
|
||||
void I18nServiceEvent::UnSubscriberEvent()
|
||||
{
|
||||
if (subscriber) {
|
||||
bool status = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber);
|
||||
if (status != 0) {
|
||||
HILOG_INFO_I18N("UnSubscriberEvent: UnSubscriberEvent failed");
|
||||
}
|
||||
subscriber = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void I18nServiceEvent::CheckStartReason(const SystemAbilityOnDemandReason& startReason)
|
||||
{
|
||||
std::string action = startReason.GetName();
|
||||
HILOG_INFO_I18N("CheckStartReason: start reason is %{public}s", action.c_str());
|
||||
if (action == userSwitchKey) {
|
||||
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
|
||||
MultiUsers::SwitchUser(localId);
|
||||
} else if (action == userAdded) {
|
||||
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
|
||||
MultiUsers::AddUser(localId);
|
||||
} else if (action == userRemoved) {
|
||||
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
|
||||
MultiUsers::RemoveUser(localId);
|
||||
}
|
||||
}
|
||||
|
||||
void I18nServiceEvent::OnReceiveEvent(const EventFwk::CommonEventData& data)
|
||||
{
|
||||
AAFwk::Want want = data.GetWant();
|
||||
std::string action = want.GetAction();
|
||||
auto it = eventHandles.find(action);
|
||||
if (it == eventHandles.end()) {
|
||||
HILOG_INFO_I18N("OnReceiveEvent: ignore event %{public}s", action.c_str());
|
||||
return;
|
||||
}
|
||||
HILOG_INFO_I18N("OnReceiveEvent: handle event %{public}s", action.c_str());
|
||||
it->second(data);
|
||||
}
|
||||
|
||||
void I18nServiceEvent::HandleSwitchUser(const EventFwk::CommonEventData& data) const
|
||||
{
|
||||
AAFwk::Want want = data.GetWant();
|
||||
std::string localId = std::to_string(data.GetCode());
|
||||
MultiUsers::SwitchUser(localId);
|
||||
}
|
||||
|
||||
void I18nServiceEvent::HandleAddUser(const EventFwk::CommonEventData& data) const
|
||||
{
|
||||
std::string localId = std::to_string(data.GetCode());
|
||||
MultiUsers::AddUser(localId);
|
||||
}
|
||||
|
||||
void I18nServiceEvent::HandleRemoveUser(const EventFwk::CommonEventData& data) const
|
||||
{
|
||||
std::string localId = std::to_string(data.GetCode());
|
||||
MultiUsers::RemoveUser(localId);
|
||||
}
|
||||
} // namespace I18n
|
||||
} // namespace Global
|
||||
} // namespace OHOS
|
Loading…
Reference in New Issue
Block a user