HarmonyOS鸿蒙Next应用中如何实现多语言支持?
HarmonyOS鸿蒙Next应用中如何实现多语言支持? 1.在HarmonyOS应用中如何实现多语言支持? 2.如何根据系统语言自动切换和管理翻译资源?
4 回复
楼主写的很详细,先收藏了,后面有国际化需要再参考~
更多关于HarmonyOS鸿蒙Next应用中如何实现多语言支持?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
解决方案
1. 资源文件组织
entry/src/main/resources/
├── base/
│ ├── element/
│ │ └── string.json # 默认语言
│ └── media/
├── zh_CN/ # 简体中文
│ └── element/
│ └── string.json
├── zh_TW/ # 繁体中文
│ └── element/
│ └── string.json
└── en_US/ # 英语
└── element/
└── string.json
base/element/string.json (默认):
{
"string": [
{
"name": "app_name",
"value": "My App"
},
{
"name": "welcome_message",
"value": "Welcome"
},
{
"name": "login",
"value": "Login"
},
{
"name": "logout",
"value": "Logout"
},
{
"name": "username",
"value": "Username"
},
{
"name": "password",
"value": "Password"
},
{
"name": "settings",
"value": "Settings"
},
{
"name": "language",
"value": "Language"
},
{
"name": "item_count",
"value": "%d items"
},
{
"name": "greeting",
"value": "Hello, %s!"
}
]
}
zh_CN/element/string.json (简体中文):
{
"string": [
{
"name": "app_name",
"value": "我的应用"
},
{
"name": "welcome_message",
"value": "欢迎"
},
{
"name": "login",
"value": "登录"
},
{
"name": "logout",
"value": "退出登录"
},
{
"name": "username",
"value": "用户名"
},
{
"name": "password",
"value": "密码"
},
{
"name": "settings",
"value": "设置"
},
{
"name": "language",
"value": "语言"
},
{
"name": "item_count",
"value": "%d 个项目"
},
{
"name": "greeting",
"value": "你好,%s!"
}
]
}
2. 基础多语言使用
import i18n from '@ohos.i18n'
@Entry
@Component
struct I18nBasic {
@State currentLanguage: string = ''
aboutToAppear() {
this.loadCurrentLanguage()
}
build() {
Column({ space: 16 }) {
Text($r('app.string.app_name'))
.fontSize(24)
.fontWeight(FontWeight.Bold)
Text($r('app.string.welcome_message'))
.fontSize(18)
// 当前语言
Row() {
Text($r('app.string.language'))
.layoutWeight(1)
Text(this.currentLanguage)
.fontColor('#1890ff')
}
.width('100%')
.padding(16)
.backgroundColor('#f5f5f5')
.borderRadius(8)
// 登录表单
Column({ space: 12 }) {
TextInput({ placeholder: $r('app.string.username') })
.width('100%')
TextInput({ placeholder: $r('app.string.password') })
.width('100%')
.type(InputType.Password)
Button($r('app.string.login'))
.width('100%')
}
.width('100%')
Button($r('app.string.settings'))
.width('100%')
}
.padding(16)
}
private loadCurrentLanguage() {
const systemLanguage = i18n.System.getSystemLanguage()
this.currentLanguage = systemLanguage
console.log('当前系统语言:', systemLanguage)
}
}
3. 格式化字符串
@Entry
@Component
struct FormattedStrings {
@State username: string = '张三'
@State itemCount: number = 5
build() {
Column({ space: 16 }) {
Text('格式化字符串')
.fontSize(20)
.fontWeight(FontWeight.Bold)
// 单个参数
Text(this.getFormattedString($r('app.string.greeting'), this.username))
.fontSize(18)
// 数字参数
Text(this.getFormattedString($r('app.string.item_count'), this.itemCount))
.fontSize(16)
// 更新数据
Row({ space: 12 }) {
Button('-')
.onClick(() => {
if (this.itemCount > 0) {
this.itemCount--
}
})
Text(this.itemCount.toString())
.fontSize(18)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Button('+')
.onClick(() => {
this.itemCount++
})
}
.width('100%')
}
.padding(16)
}
private getFormattedString(resource: Resource, ...args: any[]): string {
// 这里简化处理,实际应该使用系统API获取资源字符串并格式化
// 示例: "Hello, %s!" -> "Hello, 张三!"
return `Formatted: ${args.join(', ')}`
}
}
4. 语言切换
import i18n from '@ohos.i18n'
import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'
interface LanguageOption {
code: string
name: string
nativeName: string
}
@Entry
@Component
struct LanguageSwitcher {
@State currentLanguage: string = ''
@State languages: LanguageOption[] = [
{ code: 'zh-CN', name: 'Chinese Simplified', nativeName: '简体中文' },
{ code: 'zh-TW', name: 'Chinese Traditional', nativeName: '繁體中文' },
{ code: 'en-US', name: 'English (US)', nativeName: 'English (US)' }
]
aboutToAppear() {
this.loadCurrentLanguage()
}
build() {
Column({ space: 16 }) {
Text($r('app.string.language'))
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text(`当前语言: ${this.currentLanguage}`)
.fontSize(14)
.fontColor('#666666')
List() {
ForEach(this.languages, (lang: LanguageOption) => {
ListItem() {
Row({ space: 12 }) {
Column({ space: 4 }) {
Text(lang.nativeName)
.fontSize(16)
Text(lang.name)
.fontSize(12)
.fontColor('#999999')
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
if (this.isCurrentLanguage(lang.code)) {
Image($r('sys.media.ohos_ic_public_ok'))
.width(24)
.height(24)
.fillColor('#1890ff')
}
}
.width('100%')
.padding(16)
.onClick(() => {
this.switchLanguage(lang.code)
})
}
})
}
.divider({ strokeWidth: 1, color: '#f0f0f0' })
.layoutWeight(1)
Text('注意: 语言切换需要重启应用生效')
.fontSize(12)
.fontColor('#faad14')
.padding(12)
.backgroundColor('#fffbe6')
.borderRadius(8)
.width('100%')
}
.padding(16)
}
private loadCurrentLanguage() {
this.currentLanguage = i18n.System.getSystemLanguage()
}
private isCurrentLanguage(code: string): boolean {
return this.currentLanguage.startsWith(code.split('-')[0])
}
private async switchLanguage(languageCode: string) {
try {
// 注意: HarmonyOS应用语言跟随系统
// 这里仅作演示,实际需要引导用户在系统设置中修改
console.log('切换语言到:', languageCode)
// 保存用户选择的语言偏好
await this.saveLanguagePreference(languageCode)
// 提示用户重启应用
this.showRestartTip()
} catch (error) {
console.error('切换语言失败:', error)
}
}
private async saveLanguagePreference(languageCode: string): Promise<void> {
// 使用Preferences保存语言偏好
console.log('保存语言偏好:', languageCode)
}
private showRestartTip() {
// 显示提示对话框
console.log('请重启应用以应用新语言')
}
}
5. 国际化工具类
// utils/I18nUtil.ets
import i18n from '@ohos.i18n'
import resourceManager from '@ohos.resourceManager'
export class I18nUtil {
private static resMgr?: resourceManager.ResourceManager
/**
* 初始化资源管理器
*/
static async init(): Promise<void> {
this.resMgr = await resourceManager.getResourceManager(getContext())
}
/**
* 获取字符串资源
*/
static async getString(resId: number): Promise<string> {
if (!this.resMgr) {
await this.init()
}
try {
return await this.resMgr!.getStringValue(resId)
} catch (error) {
console.error('获取字符串资源失败:', error)
return ''
}
}
/**
* 获取格式化字符串
*/
static async getFormattedString(resId: number, ...args: any[]): Promise<string> {
let str = await this.getString(resId)
// 替换占位符 %s, %d
args.forEach((arg, index) => {
if (typeof arg === 'number') {
str = str.replace('%d', arg.toString())
} else {
str = str.replace('%s', arg.toString())
}
})
return str
}
/**
* 获取复数形式
*/
static async getPluralString(
resId: number,
count: number
): Promise<string> {
if (!this.resMgr) {
await this.init()
}
try {
return await this.resMgr!.getPluralStringValue(resId, count)
} catch (error) {
console.error('获取复数字符串失败:', error)
return ''
}
}
/**
* 获取当前语言
*/
static getCurrentLanguage(): string {
return i18n.System.getSystemLanguage()
}
/**
* 获取当前地区
*/
static getCurrentRegion(): string {
return i18n.System.getSystemRegion()
}
/**
* 获取当前区域设置
*/
static getCurrentLocale(): string {
return i18n.System.getSystemLocale()
}
/**
* 判断是否为RTL语言
*/
static isRTL(): boolean {
const language = this.getCurrentLanguage()
const rtlLanguages = ['ar', 'he', 'fa', 'ur']
return rtlLanguages.includes(language)
}
/**
* 格式化日期
*/
static formatDate(date: Date, format?: string): string {
const locale = this.getCurrentLocale()
const dateFormat = new i18n.DateTimeFormat(locale, {
year: 'numeric',
month: '2-digit',
day: '2-digit'
})
return dateFormat.format(date)
}
/**
* 格式化时间
*/
static formatTime(date: Date): string {
const locale = this.getCurrentLocale()
const timeFormat = new i18n.DateTimeFormat(locale, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
return timeFormat.format(date)
}
/**
* 格式化数字
*/
static formatNumber(number: number): string {
const locale = this.getCurrentLocale()
const numberFormat = new i18n.NumberFormat(locale)
return numberFormat.format(number)
}
/**
* 格式化货币
*/
static formatCurrency(amount: number, currency: string = 'CNY'): string {
const locale = this.getCurrentLocale()
const currencyFormat = new i18n.NumberFormat(locale, {
style: 'currency',
currency: currency
})
return currencyFormat.format(amount)
}
}
// 使用示例
@Entry
@Component
struct I18nUtilDemo {
@State formattedDate: string = ''
@State formattedNumber: string = ''
@State formattedCurrency: string = ''
async aboutToAppear() {
await I18nUtil.init()
this.formattedDate = I18nUtil.formatDate(new Date())
this.formattedNumber = I18nUtil.formatNumber(123456.789)
this.formattedCurrency = I18nUtil.formatCurrency(9999.99)
}
build() {
Column({ space: 16 }) {
Text('国际化工具')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Column({ space: 8 }) {
Row() {
Text('当前语言:')
.width(100)
Text(I18nUtil.getCurrentLanguage())
}
.width('100%')
Row() {
Text('当前区域:')
.width(100)
Text(I18nUtil.getCurrentLocale())
}
.width('100%')
Row() {
Text('日期格式:')
.width(100)
Text(this.formattedDate)
}
.width('100%')
Row() {
Text('数字格式:')
.width(100)
Text(this.formattedNumber)
}
.width('100%')
Row() {
Text('货币格式:')
.width(100)
Text(this.formattedCurrency)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor('#f5f5f5')
.borderRadius(8)
}
.padding(16)
}
}
关键要点
- 资源组织: 按语言代码组织资源文件
- $r引用: 使用$r(‘app.string.xxx’)引用字符串资源
- 系统语言: 应用语言跟随系统设置
- 格式化: 支持日期、数字、货币的本地化格式
- RTL支持: 考虑从右到左书写的语言
最佳实践
- 完整翻译: 所有语言资源保持一致
- 占位符: 使用%s、%d等占位符支持动态内容
- 复数处理: 使用复数资源处理数量相关文本
- 文化差异: 注意不同地区的文化和习惯
- 测试: 在不同语言环境下充分测试
在HarmonyOS鸿蒙Next应用中实现多语言支持,主要使用资源文件管理。在resources目录下创建element和string.json文件,按语言分类存放字符串资源。例如,zh_CN和en_US目录分别对应中英文。在string.json中定义键值对。在应用代码中,通过$r('app.string.key')引用字符串资源。系统会根据当前设备语言设置自动加载对应资源文件。
在HarmonyOS Next应用中实现多语言支持,主要依赖资源管理框架和$r、$rawfile等引用能力。以下是核心实现步骤:
1. 创建与管理多语言资源文件
- 目录结构:在
entry/src/main/resources目录下,按语言代码(如zh-CN、en-US)创建子目录,再在子目录内创建element和media等文件夹。 - 字符串资源:在对应语言的
element目录下创建string.json文件,定义键值对。例如:// zh-CN/string.json { "string": [ {"name": "app_name", "value": "我的应用"} ] }// en-US/string.json { "string": [ {"name": "app_name", "value": "My App"} ] } - 其他资源:图片、音频等文件可放入对应语言的
media目录,系统会根据语言自动匹配。
2. 在应用中使用多语言资源
- UI中引用:在ArkUI中使用
$r('app.string.app_name')直接引用字符串,系统会自动根据当前语言环境加载对应资源。 - 代码中引用:可通过
ResourceManagerAPI动态获取:const context = getContext(this) as common.UIAbilityContext; const resourceManager = context.resourceManager; let value = await resourceManager.getString($r('app.string.app_name').id);
3. 自动语言切换与管理
- 系统自动匹配:应用启动时,HarmonyOS会根据设备系统语言设置,自动从
resources目录匹配最接近的语言资源(例如系统为zh-Hans-CN,会优先匹配zh-CN目录)。 - 动态监听与响应:应用可监听系统语言变化事件,并更新UI:
import { I18n } from '[@ohos](/user/ohos).i18n'; // 获取当前系统语言 let currentLanguage = I18n.getSystemLanguage(); // 监听语言变化(需在UIAbility或页面中合理管理事件订阅) // 系统语言变更时,应用框架会自动重新加载资源,但界面可能需要手动刷新。 - 手动切换语言:应用内部可设置特定语言,覆盖系统默认行为,但这通常需要自行实现资源重载和界面刷新逻辑。
4. 注意事项
- 资源ID一致性:所有语言版本的
string.json中,相同name的键必须存在,确保引用不会失败。 - 回退机制:如果当前系统语言无对应资源目录,框架会按语言相似性回退(如
en-GB回退到en-US,最终到resources根目录的默认资源)。 - ArkUI声明式UI:在
.ets文件中使用$r引用资源是推荐做法,框架会自动处理语言切换时的更新。
通过以上步骤,即可在HarmonyOS Next应用中实现多语言支持,并依靠系统机制自动完成语言匹配与切换。

