OpenHarmony國際化I18n開發范例
概念介紹
在開發應用中可能會遇到多國家多地區場景,應用要提供不同的語言、時間、時區給目標用戶和市場,開發者往往需要提供多個不同版本以保證不同地區用戶方便使用。
本例基于國際化示例應用,為大家介紹I18n組件,該組件提供系統相關的或者增強的國際化能力。
接口
I18n官方文檔 @ohos.i18n。
類名 | 接口名稱 | 描述 |
System | getDisplayCountry(country:string,locale:string,sentenceCase?:boolean):string<sup>9+</sup> | 獲取國家的本地化表示。 |
System | getDisplayLanguage(language:string,locale:string,sentenceCase?:boolean):string<sup>9+</sup> | 獲取語言的本地化表示。 |
System | getSystemLanguages():Array<string><sup>9+</sup> | 獲取系統語言列表。 |
System | getSystemCountries(language: string):Array<string><sup>9+</sup> | 獲取針對輸入語言系統支持的國家或地區列表。 |
System | isSuggested(language: string, region?: string): boolean<sup>9+</sup> | 判斷當前語言和地區是否匹配 |
System | getSystemLanguage():string<sup>9+</sup> | 獲取系統語言。 |
System | setSystemLanguage(language: string)<sup>9+</sup> | 設置系統語言。 |
System | getSystemRegion():string<sup>9+</sup> | 獲取系統地區。 |
System | setSystemRegion(region: string)<sup>9+</sup> | 設置系統地區。 |
System | getSystemLocale():string<sup>9+</sup> | 獲取系統Locale。 |
System | setSystemLocale(locale: string)<sup>9+</sup> | 設置系統Locale。 |
System | is24HourClock():boolean<sup>9+</sup> | 判斷系統時間是否為24小時制。 |
System | set24HourClock():boolean<sup>9+</sup> | 修改系統時間的24小時制設置。 |
System | addPreferredLanguage(language: string, index?: number)<sup>9+</sup> | 在系統偏好語言列表的指定位置添加偏好語言。 |
System | removePreferredLanguage(index: number)<sup>9+</sup> | 刪除系統偏好語言列表中指定位置的偏好語言。 |
System | getPreferredLanguageList()<sup>9+</sup> | 獲取系統偏好語言列表。 |
System | getFirstPreferredLanguage()<sup>9+</sup> | 獲取系統偏好語言列表中的第一個偏好語言。 |
System | getAppPreferredLanguage()<sup>9+</sup> | 獲取應用偏好語言。 |
System | setUsingLocalDigit(flag: boolean)<sup>9+</sup> | 設置系統是否使用本地數字。 |
System | getUsingLocalDigit()<sup>9+</sup> | 判斷系統是否使用本地數字。 |
isRTL(locale:string):boolean<sup>9+</sup> | locale對應的語言是否為從右到左語言。 |
具體實現
配置文件
應用需要在項目的module.json5配置文件中逐個聲明所需的權限,否則應用將無法獲取授權。
在配置文件的requestPermissions屬性數組中配置所需的權限,包含3個屬性。
{
...
"requestPermissions": [
{
"name": "ohos.permission.UPDATE_CONFIGURATION"
},
{
"name": "ohos.permission.SET_TIME_ZONE"
},
{
"name": "ohos.permission.SET_TIME"
}
]
}
- 更新配置權限:ohos.permission.UPDATE_CONFIGURATION
- 設置時區權限:ohos.permission.SET_TIME_ZONE
- 設置系統時間權限:ohos.permission.SET_TIME
引入I18n模塊
import i18n from '@ohos.i18n';
語言和地區
- 使用getSystemRegion和getSystemLocale分別獲取當前系統地區和系統區域,并傳入getDisplayCountry獲取指定國家的本地化顯示文本。
this.currentRegion = i18n.System.getDisplayCountry(i18n.System.getSystemRegion(), i18n.System.getSystemLocale());
- 使用getSystemLanguage獲取當前系統支持的語言列表。
this.localLanguage = i18n.System.getSystemLanguage();
- 使用getSystemCountries方法獲取針對輸入語言系統支持的國家或地區列表,隨后可以遍歷列表,并且調用isSuggested方法判斷當前語言和地區是否匹配。
try {
this.countryIds = i18n.System.getSystemCountries(this.currentRegion);
} catch (err) {
Logger.error(`getSystemCountries failed, code is ${err.code}, message is ${err.message}`);
}
this.countryIds.forEach(id => {
let country = i18n.System.getDisplayCountry(id, this.localLanguage);
this.countries.push({ key: country, value: '' });
let isSuggested: boolean;
try {
isSuggested = i18n.System.isSuggested(this.localLanguage, id);
} catch (err) {
Logger.error(`isSuggested failed, code is ${err.code}, message is ${err.message}`);
}
if (isSuggested) {
this.suggestIds.push(id);
this.suggestCounties.push({ key: country, value: '' });
}
})
實現某時區城市在該區域的本地化顯示列表:
使用getAvailableZoneCityIDs獲取系統支持的時區城市ID。
使用getCityDisplayName格式化。
getTimeZoneSrc() {
this.timeZoneSrc = [];
let zoneCityIDs = i18n.TimeZone.getAvailableZoneCityIDs();
for (let zoneCityId of zoneCityIDs) {
let cityDisplayName = i18n.TimeZone.getCityDisplayName(zoneCityId, "zh-Hans");
let timeZone = i18n.TimeZone.getTimezoneFromCity(zoneCityId);
this.timeZoneSrc.push({
key: timeZone.getID(),
timeZone: timeZone,
display: cityDisplayName
});
};
}
日期和時間
- 引入systemDateTime模塊獲取當前系統時間和時區。
- 引入Intl模塊,該模塊提供基礎的應用國際化能力,包括時間日期格式化、數字格式化、排序等。
import systemDateTime from '@ohos.systemDateTime';
import Intl from '@ohos.intl';
systemDateTime模塊官方文檔@ohos.systemDateTimeintl模塊官方文檔@ohos.intl。
- 編寫格式化時間方法。
Intl.DateTimeFormat方法用來創建時間日期格式化對象。
使用時間日期格式化對象的format方法格式化時間日期字符串。
getDateString() {
let locale = i18n.System.getSystemLocale();
let language = i18n.System.getSystemLanguage();
let params = [language, locale];
let dateFormat = new Intl.DateTimeFormat(params, options);
let date = new Date();
let formatString = dateFormat.format(date);
if (language === 'zh-Hans') {
let format = formatString.split(' ');
return [format[0], format[1]];
} else {
let format = formatString.split(', ');
return [`${format[0]}, ${format[1]}`, format[2]];
}
}
- 格式化時區:
getRawOffset方法用來獲取時區對象表示的時區與UTC時區的偏差。
getSystemLanguage方法獲取系統語言。
getDisplayName方法用來獲取時區對象的本地化表示。
getTimeZoneString(timeZone: i18n.TimeZone) {
let offset = timeZone.getRawOffset();
return `GMT${offset > 0 ? '+' : '-'}${this.getTimeString(offset)} ${timeZone.getDisplayName(i18n.System.getSystemLanguage())}`;
}
上述代碼中通過判斷偏差來格式化時區顯示。
- 獲取系統時間后調用I18n的getTimeZone方法獲取系統時區并使用上述方法格式化。
getTimeDisplay() {
let timeZone = await systemTime.getTimezone();
let zone = i18n.getTimeZone(timeZone);
this.timeZone = this.getTimeZoneString(zone);
let timeInfo = this.getDateString();
this.date = timeInfo[0];
this.time = timeInfo[1];
}
區域格式示例
本模塊進入界面展示當前區域,當前系統語言下的時間、數字、貨幣、百分比、單復數、屏幕方向等信息的格式化顯示。
build() {
Column() {
TitleBar({ hasBackPress: true, title: $r('app.string.format_example') })
this.TextView({ text: this.language })
Column() {
this.TextView({ text: this.date })
this.TextView({ text: this.time })
ForEach(this.numberFormat, (item, index) => {
this.TextView({ text: item });
}, item => item)
this.TextView({ text: this.pluralFormat })
this.TextView({ text: this.timeZoneDetect })
this.TextView({ text: this.normalizer })
this.TextView({ text: this.mDirection })
}
頁面代碼中的language、data和time已經在上述方法中獲取到,下面分別看一下剩下的數據如何獲取。
- numberFormat
getNumberFormatString() {
let currentLocale = new Intl.Locale();
let locale = i18n.System.getSystemLocale();
let numfmt = new Intl.NumberFormat();
let options = numfmt.resolvedOptions();
options.locale = locale;
options.numberingSystem = currentLocale.numberingSystem;
options.currency = 'CNY';
options.currencySign = 'symbol';
options.localeMatcher = 'best fit';
options.style = 'decimal';
let params = [i18n.System.getSystemLanguage(), locale];
let numberFormat = new Intl.NumberFormat(params, options);
options.style = 'currency';
let currencyFormat = new Intl.NumberFormat(params, options);
options.style = 'percent';
let percentFormat = new Intl.NumberFormat(params, options);
// 此處返回的只是一個示例,因此1234567,123456,78.9并不具有實際意義
return [numberFormat.format(1234567), currencyFormat.format(123456), percentFormat.format(78.9)];
}
該方法主要使用Intl.NumberFormat()方法創建數字格式化對象。
示例:
// 使用 en-GB locale創建NumberFormat對象,style設置為decimal,notation設置為scientific
let numfmt = new Intl.NumberFormat("en-GB", {style:'decimal', notation:"scientific"});
NumberFormat對象中resolvedOptions方法用來獲取該對象的格式化選項。
- NumberFormat對象的部分選項
名稱 | 類型 | 可讀 | 可寫 | 說明 |
locale | string | 是 | 否 | 區域參數, 如:“zh-Hans-CN”。locale屬性默認值為系統Locale。 |
currency | string | 是 | 是 | 貨幣單位, 如:“EUR”,“CNY”,"USD"等。 |
currencySign | string | 是 | 是 | 貨幣單位的符號顯示,取值包括: “symbol”,“narrowSymbol”,“code”,“name” 。currencySign屬性默認值為standard。 |
localeMatcher | string | 是 | 是 | 要使用的區域匹配算法,取值包括:“lookup”, “best fit”。localeMatcher屬性默認值為best fit。 |
style | string | 是 | 是 | 數字的顯示格式,取值包括:“decimal”, “currency”, “percent”, “unit”。style屬性默認值為decimal。 |
numberingSystem | string | 是 | 是 | 數字系統,取值包括:“adlm”, “ahom”, “arab”, “arabext”, “bali”, “beng”, “bhks”, “brah”, “cakm”, “cham”, “deva”, “diak”, “fullwide”, “gong”, “gonm”, “gujr”, “guru”, “hanidec”, “hmng”, “hmnp”, “java”, “kali”, “khmr”, “knda”, “lana”, “lanatham”, “laoo”, “latn”, “lepc”, “limb”, “mathbold”, “mathdbl”, “mathmono”, “mathsanb”, “mathsans”, “mlym”, “modi”, “mong”, “mroo”, “mtei”, “mymr”, “mymrshan”, “mymrtlng”, “newa”, “nkoo”, “olck”, “orya”, “osma”, “rohg”, “saur”, “segment”, “shrd”, “sind”, “sinh”, “sora”, “sund”, “takr”, “talu”, “tamldec”, “telu”, “thai”, “tibt”, “tirh”, “vaii”, “wara”, “wcho”。numberingSystem屬性默認值為locale的默認數字系統。 |
pluralFormat 復數字符串。
首先引入common模塊。
import common from '@ohos.app.ability.common';
調用getPluralStringValue,根據指定數量獲取指定ID字符串表示的單復數字符串。
getPluralString(id: number, num: number) {
let context = getContext(this) as common.UIAbilityContext;
let plural = await context.resourceManager.getPluralStringValue(id, num);
return pluralFormat;
}
resourceManager官方文檔@ohos.resourceManager。
- timeZoneDetect
調用getTimezonesByLocation創建某經緯度對應的時區對象數組。
const LONGITUDE = 116.20;
const LATITUDE = 39.56;
getTimeZoneDetect() {
this.timeZoneDetect = await ResourceUtil.getString($r('app.string.coordinate').id);
this.timeZoneDetect += '(' + LONGITUDE + ',' + LATITUDE + ') ' +
i18n.TimeZone.getTimezonesByLocation(LONGITUDE, LATITUDE)[0].getDisplayName();
}
- normalizer
調用Normalizer.getInstance獲取文本正則化對象。
getNormalizer() {
let nl = i18n.Normalizer.getInstance(i18n.NormalizerMode.NFC);
this.normalizer = '\u1100 +\u1161 +\u11A8 = ' + nl.normalize('\u1100\u1161\u11A8');
}
- mDirection
調用getDirection方法獲取設備的配置,拿到屏幕方向屬性。
async getDirection() {
let context = getContext(this) as common.UIAbilityContext;
let configuration = await context.resourceManager.getConfiguration();
if (configuration.direction === 1) { // 1代表Horizontal,0代表Vertical
return 'Horizontal';
} else {
return 'Vertical';
}
}
}