前端开源组件库 NutUI-React 国际化能力设计实现

背景

随着京东国际团队的加入,多语言能力已是必然,而且还可以加速 nutui-react 组件库在公司内部项目中的落地,更加及时的发现 nutui-react 存在的问题,从而不断的进行打磨。

NutUI-React 国际化版本示例

1.安装 nutui-react

css 复制代码
npm i @nutui/nutui-react

2.通过 ConfigProvider 组件配置多语言

javascript 复制代码
// 引入多语言包
import en from "@nutui/nutui-react/dist/locales/en-US"
// 引入 ConfigProvider 组件
import {ConfigProvider} from "@nutui/nutui-react";
// 通过 ConfigProvider 包裹应用
ReactDOM.render(<ConfigProvider locale={en}>
    <App/>
</ConfigProvider>, querySelector('#root'))

NutUI-React 如何实现国际化

nutui-react 多语言能力设计主要分为两个方面:对外( nutui-react 用户)提供具有国际化能力的组件和机制,目前 nutui-react 组件库提供 ConfigProvider 组件用于配制多语言。目前 nutui-react 组件库提供了中文简体、中文繁体、英文三个语言包,未来可能会增加泰语、印尼语、俄语、西班牙语等;对内(nutui-react 的贡献者)需要提供多语言基础能力支持,例如:本地预览多语言版本、多语言包规范、多语言文档翻译规范等。

NutUI-React 国际化实现

对于 nutui-react 的用户而言,ConfigProvider 组件是一大重点,其次便是 nutui-react 包中提供的多语言文件,文件路径为 @nutui/nutui-react/dist/locales 下。在此目录下除多语言文件外,还提供了对应的 typescript 类型文件。

nutui-react 用户除了可以使用 locales 文件夹下的多语言文件,也可以开发特有的多语言文件,只需按照 nutui-react 提供的多语言文件格式,创建新的文件即可。

csharp 复制代码
{
  save: '保存',
  confirm: '确认',
  cancel: '取消',
  done: '完成',
  noData: '暂无数据',
  placeholder: '请输入内容',
  select: '请选择',
  video: {
    errorTip: '视频加载失败',
    clickRetry: '点击重试',
  },
// 非完整版本,完整版本参考 nutui-react 代码库
  ...
}

上面代码是组件库中的 zh-CN 文案结构,实际使用以安装的 nutui-react 包中的结构为准。

假设在我的项目中,增加 nutui-react 未提供的泰文文案,只需在项目中创建相应的 js 文件,将上述代码进行翻译。

arduino 复制代码
const TH = {
    save: 'บันทึก',
    confirm: 'ยืนยัน',
    cancel: 'ยกเลิก',
    done: 'เสร็จสิ้น',
    noData: 'ยังไม่มีข้อมูล',
    placeholder: 'โปรดป้อน',
    select: 'โปรดเลือก',
    video: {
        errorTip: 'โหลดวิดีโอไม่สําเร็จ',
        clickRetry: 'คลิกเพื่อลองอีกครั้ง',
    },
 // 非完整版本,完整版本参考 nutui-react 代码库
   ...
}
export default TH

之后将 ConfigProvider 组件的 locale 属性设置为 TH。ConfigProvider 组件的实现依赖 React 中的 Context,ConfigProvider 组件创建 Context 的 Provider,并提供 useConfig 方法,useConfig 方法在 nutui-react 的各个组件中引入,从而实现多语言文案的支持。

javascript 复制代码
export const useConfig = () => {
  return useContext(ConfigContext) ?? getDefaultConfig()
}

// 创建一个 Context 对象
const ConfigContext = createContext<ConfigProviderProps | null>(null)

export const ConfigProvider: FunctionComponent<
  Partial<ConfigProviderProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
  const { children, ...config } = { ...defaultProps, ...props }
  const parentConfig = useConfig()

  return (
    <ConfigContext.Provider
      value={{
        ...parentConfig,
        ...config,
      }}
    >
      {children}
    </ConfigContext.Provider>
  )
}

对于 nutui-react 的贡献者而言,组件库需要提供给他们开发多语言组件的能力,其中主要的部分有文档和 Demo 的多语言支持、组件文案多语言替换。

文档和 Demo 最初只有中文,多语言需要对文档和 Demo 进行扩展。文档主要采用的方案是多份语言文档,例如 button 组件同时提供了 doc.mddoc.zh-TW.mddoc.en-US.md 文件。Demo 文件需要提取原有的文案,转成对应的语言包。

在文档的加载过程中,需要创建 docs.ts 文件来集合各个组件中的 *.md 文件,这里主要借助 vite 的 import raw 特性:

javascript 复制代码
import CountDown from '@/packages/countdown/doc.md?raw';

通过 ?raw 我们将 doc.md 倒入为字符串,用于之后的 react-markdown 的处理。由于要支持多语言,也就意味着要解析不同语言的 doc.md 文件所以需要一种机制来匹配加载哪种语言文件。如上图所示,我们在流程中增加了多语言路由支持,并借助 useLocale hook 实现。

Demo 文件对于组件库来讲就是一个普通的 React 组件,Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:

arduino 复制代码
const modulesPage = import.meta.glob('/src/packages/**/demo.tsx')

我们可以将所有的 Demo 组件导入,并通过遍历的形式处理路由映射关系。

ini 复制代码
{routes.map((item: any, index: number) => {
  const C = loadable(item.component)
  return (
    <Route
      key={Math.random()}
      path={`${locale ? `/${locale}` : ''}${item.path}`}
      component={WithNavRouter(C)}
    />
  )
})

由于 Demo 预览功能是一个 React 应用,而且组件内部实现已经处理过多语言,所以我们在这里对多语言的处理和普通的业务应用处理方式一致,通过 ConfigProvider 组件实现多语言切换。

ini 复制代码
<Configprovider locale={languages[locale]}>
      <Switch>
        {routes.map((item: any, index: number) => {
          const C = loadable(item.component)
          return (
            <Route
              key={Math.random()}
              path={`${locale ? `/${locale}` : ''}${item.path}`}
              component={WithNavRouter(C)}
            />
          )
        })}
      </Switch>
    </Configprovider>

组件内部的多语言工作

组件内部文案的多语言支持主要以提取多语言包为主,并替换组件内部的对应的固定文案。组件所使用多语言包文件目前存放在 src/locales 目录中,在目前的代码仓库中有三个中语言的文件,分别是:en-US.ts、zh-CN.ts、zh-TW.ts 文件。多语言包的引入和使用主要借助于 configProvider 中提供的 useConfig 来处理。useConfig 会返回对应语言的 key-value 数据。

Demo 文件内的文案提取

Demo 文件的多语言实现要借助 useTranslate hook,并按照语言包的形式提供对应的 key-value 结构,然而自己逐条文案提取对应的 key-value 结构枯燥而低效,所以对于 Demo 内部的文案,我们开发了提取文案的脚本,方便 Demo 文案的翻译工作。

例如 Radio 组件中,我们将用到的文案通过 node scripts/extract-language.js 提取出 key-value 的结构,这一结构的实施依赖我们提供的 useTranslate hook。这样便将 Demo 翻译最繁琐的一步给简化了。

extract-language.js 中主要通过正则进行文案的提取和替换,这主要得利于 Demo 文件的标准化。 useTranslate 通过对监听 popstate 事件,从而选择当前的语言方案。

总结

本次主要介绍了 NutUI-React 组件库对于多语言支持的实现思路,目前已经有部分组件实现了对多语言的支持,在未来逐步的迭代中全部组件都将实现对多语言的支持。

加入我们

期待您早日成为我们共建大军中的一员!

微信群:hanyuxinting(暗号:NutUI-React)

官网GitHub: 点击进入

欢迎共建、使用!

相关推荐
Luckyfif2 分钟前
🤯由 性能指标 散发开来的 Performance API 被问爆了呀
前端·面试·性能优化
咸虾米5 分钟前
在uniCloud云对象内使用unipay的微信退款出现错误“uniPayCo.refund Error: token校验未通过”的解决方案
前端·后端
前端Hardy11 分钟前
HTML&CSS:产品卡片动画效果
前端·javascript
货拉拉技术16 分钟前
货拉拉开源:鸿蒙路由 TheRouter
android·前端·harmonyos
中杯可乐多加冰19 分钟前
工业4.0数字孪生新引擎:星图云开发者平台全景评测
前端·低代码·掘金·金石计划
云边小卖铺.25 分钟前
运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.
前端·javascript·vue.js
我是若尘27 分钟前
前端处理大量并发请求的实用技巧
前端
Lstmxx28 分钟前
Electron:使用数据流的形式加载本地视频
前端·electron·node.js
JunjunZ36 分钟前
unibest框架开发uniapp项目:兼容小程序问题
前端·vue.js
lyc23333338 分钟前
鸿蒙Next应用启动框架AppStartup:流程管理与性能优化🚀
前端