* Copyright (c) 2021-2026 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.
*/
package ohos.ace.plugin.i18nplugin;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.icu.text.NumberingSystem;
import android.os.Build;
import android.os.LocaleList;
import android.text.format.DateFormat;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import ohos.ace.adapter.ALog;
* INTL android plugin module
*
* @since 2023-04
*/
public class I18NPlugin {
private static final String LOG_TAG = "I18NPlugin";
private static final String LANGUAGE_SHARE_PREFERENCE = "language_prefs";
private static final String KEY_LANGUAGE = "app_language";
private static I18NSetAppPreferredLanguage mRestartFunc = null;
private static final Map<String, String> localDigitMap = new HashMap<String, String>() {{
put("ar", "arab");
put("as", "beng");
put("bn", "beng");
put("fa", "arabext");
put("mr", "deva");
put("my", "mymr");
put("ne", "deva");
put("ur", "latn");
}};
private Context mContext;
* INTLPlugin
*
* @param context context of the application
*/
public I18NPlugin(Context context) {
mContext = context;
nativeInit();
}
* is24HourClock
*
* @return System use 24 hour clock or not
*/
public boolean is24HourClock() {
if (mContext == null) {
ALog.e(LOG_TAG, "I18NPlugin: context not registered");
return true;
}
return DateFormat.is24HourFormat(mContext);
}
* getSystemLocale
*
* @return System locale
*/
public String getSystemLocale() {
Locale systemLocale = getSystemLocaleCompat();
String localeTag = "";
if (systemLocale != null) {
localeTag += systemLocale.getLanguage();
if (systemLocale.getScript().length() > 0) {
localeTag += "-" + systemLocale.getScript();
}
if (systemLocale.getCountry().length() > 0) {
localeTag += "-" + systemLocale.getCountry();
}
}
return localeTag;
}
* getSystemLanguage
*
* @return System language
*/
public String getSystemLanguage() {
Locale systemLocale = getSystemLocaleCompat();
String languageTag = "";
if (systemLocale != null) {
languageTag += systemLocale.getLanguage();
if (systemLocale.getScript().length() > 0) {
languageTag += "-" + systemLocale.getScript();
}
}
return languageTag;
}
* getSystemRegion
*
* @return System region
*/
public String getSystemRegion() {
Locale systemLocale = getSystemLocaleCompat();
if (systemLocale == null) {
return "";
}
return systemLocale.getCountry();
}
* getSystemTimezone
*
* @return System time zone
*/
public String getSystemTimezone() {
return TimeZone.getDefault().getID();
}
* getAppPreferredLanguage
*
* @return app preferred language
*/
public String getAppPreferredLanguage() {
if (mContext == null) {
ALog.w(LOG_TAG, "I18NPlugin: context not registered");
return getSystemLocale();
}
SharedPreferences prefs =
mContext.getSharedPreferences(LANGUAGE_SHARE_PREFERENCE, Context.MODE_PRIVATE);
String savedLang = prefs.getString(KEY_LANGUAGE, null);
if (savedLang != null && !savedLang.isEmpty()) {
return savedLang;
} else {
return getSystemLocale();
}
}
* setAppPreferredLanguage
*
* @param languageTag app preferred language
*/
public void setAppPreferredLanguage(String languageTag) {
if (mContext == null) {
ALog.w(LOG_TAG, "I18NPlugin: context not registered");
return;
}
SharedPreferences.Editor editor =
mContext.getSharedPreferences(LANGUAGE_SHARE_PREFERENCE, Context.MODE_PRIVATE).edit();
editor.putString(KEY_LANGUAGE, languageTag);
editor.commit();
if (mRestartFunc != null) {
mRestartFunc.restartApp();
}
}
* setRestartFunc
*
* @param func function to restart app
*/
public static void setRestartFunc(I18NSetAppPreferredLanguage func) {
mRestartFunc = func;
}
* clear Restart function
*/
public static void clearRestartFunc() {
mRestartFunc = null;
}
* nativeInit
*/
protected native void nativeInit();
private Locale getSystemLocaleCompat() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Resources.getSystem().getConfiguration().getLocales().get(0);
} else {
return Locale.getDefault();
}
}
* getSystemLanguages
*
* @return System languages
*/
public String[] getSystemLanguages() {
Locale[] availableLocales = Locale.getAvailableLocales();
Set<String> languageSet = new LinkedHashSet<>();
for (int index = 0; index < availableLocales.length; index++) {
String languageTag = "";
if (availableLocales[index] != null) {
languageTag += availableLocales[index].getLanguage();
if (availableLocales[index].getScript().length() > 0) {
languageTag += "-" + availableLocales[index].getScript();
}
languageSet.add(languageTag);
}
}
return languageSet.toArray(new String[languageSet.size()]);
}
* getAvailableIDs
*
* @return System time zone IDs
*/
public String[] getAvailableIDs() {
return TimeZone.getAvailableIDs();
}
* getSystemCountries
*
* @param language language
* @return Countries
*/
public String[] getSystemCountries(String language) {
Locale[] availableLocales = Locale.getAvailableLocales();
Set<String> countrySet = new LinkedHashSet<>();
for (int index = 0; index < availableLocales.length; index++) {
if (availableLocales[index] == null || availableLocales[index].getCountry() == null ||
availableLocales[index].getCountry().isEmpty()) {
continue;
}
if (availableLocales[index].getCountry().matches("\\d{3}")) {
continue;
}
if (language == null || language.isEmpty()) {
countrySet.add(availableLocales[index].getCountry().toUpperCase(Locale.ROOT));
continue;
}
if (availableLocales[index].getLanguage().toUpperCase(Locale.ROOT)
.equals(language.toUpperCase(Locale.ROOT))) {
countrySet.add(availableLocales[index].getCountry().toUpperCase(Locale.ROOT));
}
}
return countrySet.toArray(new String[countrySet.size()]);
}
private boolean checkParamValid(String param) {
if (param == null || param.isEmpty()) {
return false;
}
return true;
}
private boolean checkLocaleValid(Locale locale) {
if (locale == null ||
locale.getLanguage() == null ||
locale.getLanguage().isEmpty() ||
locale.getCountry() == null ||
locale.getCountry().isEmpty()) {
return false;
}
return true;
}
* isSuggested
*
* @param language language
* @param region region
* @return Is suggested language
*/
public boolean isSuggested(String language, String region) {
if (!checkParamValid(language)) {
return false;
}
String resolvedRegion = region;
if (!checkParamValid(resolvedRegion)) {
Locale systemLocale = getSystemLocaleCompat();
if (systemLocale == null) {
return false;
}
resolvedRegion = systemLocale.getCountry();
}
Locale[] availableLocales = Locale.getAvailableLocales();
for (int index = 0; index < availableLocales.length; index++) {
if (!checkLocaleValid(availableLocales[index])) {
continue;
}
if (availableLocales[index].getCountry().equals(resolvedRegion) &&
availableLocales[index].getLanguage().equals(language)) {
return true;
}
}
return false;
}
* getPreferredLanguageList
*
* @return The preferred language list
*/
public String[] getPreferredLanguageList() {
LocaleList locales = LocaleList.getDefault();
String[] localesResult = new String[locales.size()];
for (int index = 0; index < locales.size(); index++) {
String languageTag = "";
if (locales.get(index) != null) {
languageTag += locales.get(index).getLanguage();
if (locales.get(index).getScript().length() > 0) {
languageTag += "-" + locales.get(index).getScript();
}
localesResult[index] = languageTag;
}
}
return localesResult;
}
* getFirstPreferredLanguage
*
* @return The preferred language
*/
public String getFirstPreferredLanguage() {
String languageTag = "";
LocaleList locales = LocaleList.getDefault();
String[] localesResult = new String[locales.size()];
for (int index = 0; index < locales.size(); index++) {
if (locales.get(index) != null) {
languageTag += locales.get(index).getLanguage();
if (locales.get(index).getScript().length() > 0) {
languageTag += "-" + locales.get(index).getScript();
}
return languageTag;
}
}
return languageTag;
}
* getUsingLocalDigit
*
* @return Using local digit
*/
public boolean getUsingLocalDigit() {
Locale locale = getSystemLocaleCompat();
if (locale == null) {
return false;
}
if (localDigitMap.containsKey(locale.getLanguage())) {
NumberingSystem numberingSystem = NumberingSystem.getInstance(locale);
if (numberingSystem == null) {
return false;
}
return localDigitMap.get(locale.getLanguage()).equals(numberingSystem.getName());
}
return false;
}
}