rn_for_openharmony商城项目app实战-语言设置实现

案例开源地址:https://atomgit.com/nutpi/rn_openharmony_buy

写在前面

语言设置这个功能,对于面向国际市场的 App 来说是必须的。但说实话,大部分国内 App 都不做这个功能,因为用户群体就是中国人,没必要支持其他语言。

不过作为一个完整的商城项目,我还是把这个功能加上了。一方面是为了演示怎么做多语言切换,另一方面是万一以后要出海呢?提前把架子搭好,后面加语言包就方便了。

这篇文章记录一下语言设置页面的实现过程。页面本身很简单,就是一个语言列表,用户点击选择就行。但背后的多语言方案值得聊一聊。

支持哪些语言

先定义支持的语言列表:

tsx 复制代码
const languages = [
  {code: 'zh-CN', name: '简体中文', flag: '🇨🇳'},
  {code: 'zh-TW', name: '繁體中文', flag: '🇹🇼'},
  {code: 'en', name: 'English', flag: '🇺🇸'},
  {code: 'ja', name: '日本語', flag: '🇯🇵'},
  {code: 'ko', name: '한국어', flag: '🇰🇷'},
];

每种语言有三个属性:

code :语言代码,遵循 BCP 47 标准。zh-CN 是简体中文,zh-TW 是繁体中文,en 是英语,以此类推。

name:语言名称,用该语言自己的文字显示。比如日语显示"日本語"而不是"Japanese",这样不管用户当前用什么语言,都能认出自己的母语。

flag:国旗 emoji,让列表更直观。

为什么选这五种语言?简体中文是主要用户群,繁体中文覆盖港澳台用户,英语是国际通用语言,日语和韩语是东亚主要市场。当然,实际项目中要根据目标市场来定。

引入需要的依赖

tsx 复制代码
import React from 'react';

这个页面不需要本地状态,语言设置存在全局状态里。

tsx 复制代码
import {View, Text, StyleSheet, TouchableOpacity, Alert} from 'react-native';

TouchableOpacity 让每个语言选项可点击。Alert 用来弹出设置成功的提示。

tsx 复制代码
import {useApp} from '../store/AppContext';
import {Header} from '../components/Header';

useApp 里有 settings 对象和 updateSettings 方法。

获取全局状态

tsx 复制代码
export const LanguageScreen = () => {
  const {settings, updateSettings, goBack} = useApp();

三个东西:

settings :当前设置,里面有 language 字段存储当前语言代码

updateSettings:更新设置的方法

goBack:返回上一页

选择语言的逻辑

tsx 复制代码
const handleSelect = (code: string) => {
  updateSettings('language', code);
  Alert.alert('设置成功', '语言设置已更新', [{text: '确定', onPress: goBack}]);
};

逻辑很简单:更新全局状态里的 language 字段,然后弹个提示,用户点确定返回上一页。

实际项目中,切换语言后应该立即生效,整个 App 的文字都要变。这需要配合 i18n 库来实现,后面会讲。我们这里只是保存了语言设置,没有真正实现多语言切换。

页面结构

tsx 复制代码
return (
  <View style={styles.container}>
    <Header title="语言设置" />

    <View style={styles.content}>
      {languages.map(lang => (
        // 语言选项
      ))}
    </View>
  </View>
);

结构很简单,一个 Header,下面是语言列表。

渲染语言选项

tsx 复制代码
{languages.map(lang => (
  <TouchableOpacity 
    key={lang.code} 
    style={styles.item} 
    onPress={() => handleSelect(lang.code)}
  >
    <Text style={styles.flag}>{lang.flag}</Text>
    <Text style={styles.langName}>{lang.name}</Text>
    {settings.language === lang.code && <Text style={styles.check}>✓</Text>}
  </TouchableOpacity>
))}

每个语言选项包含三部分:

国旗:左边显示国旗 emoji,让用户快速识别

语言名称:中间显示语言名称

选中标记:如果是当前选中的语言,右边显示一个勾

选中标记用条件渲染:settings.language === lang.code 时才显示。

样式定义

typescript 复制代码
const styles = StyleSheet.create({
  container: {flex: 1, backgroundColor: '#f5f5f5'},
  content: {flex: 1, backgroundColor: '#fff', marginTop: 12},

灰色背景上放白色的列表区域。

typescript 复制代码
  item: {
    flexDirection: 'row', 
    alignItems: 'center', 
    padding: 16, 
    borderBottomWidth: 1, 
    borderBottomColor: '#f0f0f0'
  },

每个选项横向排列,用 borderBottomWidth 加分割线。最后一个选项的分割线会显示出来,如果觉得不好看可以用 FlatListItemSeparatorComponent 来处理。

typescript 复制代码
  flag: {fontSize: 24, marginRight: 12},

国旗用 24 号字,比较大,容易识别。

typescript 复制代码
  langName: {flex: 1, fontSize: 16, color: '#333'},

flex: 1 让语言名称占据中间的空间,把选中标记挤到右边。

typescript 复制代码
  check: {fontSize: 20, color: '#3498db', fontWeight: 'bold'},
});

选中标记用蓝色,加粗,比较醒目。

关于多语言实现方案

上面只是做了语言设置的 UI,真正的多语言实现需要更多工作。聊一下常见的方案:

方案一:react-native-i18n / react-i18next

这是最常用的方案。把所有文案抽取到语言包文件里,根据当前语言加载对应的语言包。

tsx 复制代码
// 语言包文件 zh-CN.json
{
  "home": "首页",
  "cart": "购物车",
  "profile": "我的"
}

// 语言包文件 en.json
{
  "home": "Home",
  "cart": "Cart", 
  "profile": "Profile"
}

使用的时候:

tsx 复制代码
import {useTranslation} from 'react-i18next';

const {t} = useTranslation();
<Text>{t('home')}</Text>  // 根据当前语言显示"首页"或"Home"

这个方案的好处是成熟稳定,社区支持好。缺点是要把所有文案都抽取出来,工作量不小。

方案二:自己实现简易版

如果项目不大,可以自己实现一个简易版:

tsx 复制代码
const translations = {
  'zh-CN': {home: '首页', cart: '购物车'},
  'en': {home: 'Home', cart: 'Cart'},
};

const t = (key: string) => {
  const lang = settings.language || 'zh-CN';
  return translations[lang][key] || key;
};

这个方案简单直接,但功能有限,不支持复数、插值等高级特性。

方案三:后端返回多语言

把文案存在后端,根据用户的语言设置返回对应语言的内容。

这个方案的好处是改文案不用发版,但增加了网络请求,而且离线时可能有问题。

我们这个项目为了简化,没有真正实现多语言,只是保存了语言设置。实际项目中建议用 react-i18next,功能完善,文档齐全。

多语言开发的一些经验

做过几个多语言项目,分享一些经验:

1. 文案长度差异

同样的意思,不同语言的文案长度可能差很多。比如"设置"两个字,英文是"Settings"八个字母。如果 UI 是按中文设计的,换成英文可能放不下。

解决办法:设计 UI 时留足空间,或者用 numberOfLinesellipsizeMode 处理超长文案。

2. 文字方向

阿拉伯语、希伯来语是从右往左书写的(RTL)。如果要支持这些语言,整个 UI 布局都要镜像。

React Native 支持 RTL,但需要额外处理。如果不打算支持 RTL 语言,可以先不管。

3. 日期和数字格式

不同地区的日期格式不一样。美国是 MM/DD/YYYY,中国是 YYYY-MM-DD,欧洲是 DD/MM/YYYY。数字的千位分隔符也不一样,有的用逗号,有的用点。

可以用 Intl API 或者 moment.js / dayjs 来处理。

4. 图片里的文字

如果图片里有文字(比如 Banner),切换语言后图片也要换。这个容易被忽略。

解决办法:尽量不在图片里放文字,或者为每种语言准备不同的图片。

5. 翻译质量

机器翻译的质量参差不齐,重要的文案最好人工翻译。特别是涉及到法律、金融的内容,翻译错了可能有法律风险。

语言设置的存储

语言设置应该持久化存储,不然用户每次打开 App 都要重新设置。

tsx 复制代码
// 保存语言设置
await AsyncStorage.setItem('language', 'en');

// 读取语言设置
const language = await AsyncStorage.getItem('language') || 'zh-CN';

App 启动时读取存储的语言设置,应用到全局状态。如果没有存储过,就用默认语言(一般是简体中文,或者跟随系统语言)。

跟随系统语言

有些用户希望 App 语言跟随系统设置。可以加一个"跟随系统"选项:

tsx 复制代码
const languages = [
  {code: 'system', name: '跟随系统', flag: '🌐'},
  {code: 'zh-CN', name: '简体中文', flag: '🇨🇳'},
  // ...
];

选择"跟随系统"后,用 react-native-localize 获取系统语言:

tsx 复制代码
import * as RNLocalize from 'react-native-localize';

const systemLanguage = RNLocalize.getLocales()[0].languageCode;

这个功能挺实用的,很多用户不想手动设置,跟随系统最省事。

小结

语言设置页面本身很简单,就是一个选择列表。但背后的多语言实现是个大话题。

几个关键点:

  • 语言名称用该语言自己的文字显示
  • 国旗 emoji 让列表更直观
  • 选中状态用勾标记
  • 切换后弹提示告知用户

关于多语言实现:

  • 推荐用 react-i18next
  • 注意文案长度差异
  • 日期数字格式要本地化
  • 语言设置要持久化存储
  • 可以加"跟随系统"选项

多语言是个细活,做好了能让 App 走向国际市场,做不好会闹笑话。如果有出海计划,建议从项目一开始就考虑多语言架构。

下一篇写主题设置页面,敬请期待。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
AdleyTales2 小时前
vscode识别不了@提示找不到路径解决
前端·javascript·vscode
飞Link2 小时前
【Sqoop】Sqoop 使用教程:从原理到实战的完整指南
数据库·hadoop·sqoop
此生只爱蛋2 小时前
【Redis】事务
数据库·redis·缓存
野犬寒鸦2 小时前
从零起步学习MySQL || 第十六章:MySQL 分库分表的考量策略
java·服务器·数据库·后端·mysql
前端九哥2 小时前
装个依赖把公司电脑干报废了?npm i 到底背着我干了啥?
前端·javascript
cyhysr2 小时前
2025sql大赛题:仅用sql处理数独
数据库·sql·oracle
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通, —— 知识点详解(1)
数据库·学习·oracle
程序猿追2 小时前
【鸿蒙PC桌面端开发】使用ArkTS做出RGB 色环选择器
华为·harmonyos
溪海莘2 小时前
React入门:跟读官方快速入门教程(前端小白)
前端·react.js·前端框架