一个next项目的前端国际化i18n

693 阅读2分钟

简单介绍我们的项目

一个基于next的国际化ssr项目

前端国际化是什么?

在web站点中,通过切换国家或地区实现站点的语言切换. 比如中文, 英语, 西语...

为什么是i18n: i到n之间有18个字母

用到了哪些框架?

react-intl

国际化的三个重要部分

  1. react-intl库: 提供翻译context, 方便收集分发翻译, 日期格式化和货币格式化等功能
  2. i18n-www静态仓库: 存放不同语言的json文件
  3. onesky翻译平台: 一个专门托管语言的json文件, 方便翻译人员的操作台, 提供了上传下载接口, 功能齐全

流程图

  1. 第一步: 本地增加一个字段, 采用base语言en进行开发, 完成开发后上传到onesky, 通知运营翻译该字段
  2. 第二步: 下载最新的翻译json文件,上传到i18n-www仓库并发布该项目, 配置中心更新翻译时间戳, 站点翻译被更新

Untitled Diagram (3).png

拉取翻译文件的流程

  1. 有刷新的访问国际化站点时候
  2. 在国际化站点中进行无刷新的路由跳转

Untitled Diagram (2).png

解释一下关于[拉取翻译文件的流程]中的node端缓存和浏览器端缓存

node缓存

  1. node连接配置中心, 更新配置中心时间戳, 202208301516
  2. 时间戳发生变化, node服务更新缓存key为: i18n_202208301516_1, 并把时间戳写到cookie中

浏览器缓存

  1. 在站点无刷跳转时, 从cookie中读取时间戳, 然后根据时间戳相应的key(i18n_202208301516_1)去读取对应的localStorage中的缓存

202208301516: 表示时间戳, 1: 表示地区

上代码

  1. 基于next框架的ssr项目, 在_app.tsx中:
import { IntlProvider } from 'react-intl';

// messages的数据就是翻译的json文件 - en.json
const messages = {
  g0: 'download',
  g1: 'SignUp'
};

<IntlProvider 
    messages={messages}
    locale: 'en'
    formats: {
      date: {
        normal: {
          hour12: false,
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit'
        }
      }
    }
>
    <Component />
</IntlProvider>
  1. 国际化字段为了确保不出现重复, 所以把所有的字段统一到locale/global.ts文件中
import { defineMessages } from 'react-intl';

const locale = defineMessages({
  download: {
    id: 'g0',
    defaultMessage: 'Download'
  },
  startFreeTrial: {
    id: 'g1',
    defaultMessage: 'Start Free Trial'
  }
});

解释: 这里的id必须是唯一的, 不能重复. 因为这才是最后生成的en.json文件中的key

同样出于考虑en.json文件大小问题, id = 'g0' 而不是 id = 'download'

  1. 在src/components/download/index.tsx组件中
import { useIntl } from 'react-intl';
import GLocale from '@locale/global';

const View = () => {
  const { formatMessage: fm }= useIntl();
  return <div>{fm(Glocale.startFreeTrial)}</div>
};