国际化(i18n)/本地化(l10n)配置:react-i18next库,vue-i18n库,TS,组件库(element)

50 篇文章 0 订阅

目录

设置语言

页面:html标签的 lang属性

浏览器->设置->语言

命名由来

原理

t参数

zh.json

en.json

react组件

传参和效果

本地资源:语言包对象

zh.ts

en.ts

staticData.ts:直接返回对象效率更高

适用于静态语言

若固定顺序,可遍历对象属性

public->locales->en->模块名.json

public->locales->zh->模块名.json

适用于动态语言,非固定顺序,零散重复使用

returnObjects: true,可遍历对象属性

react-i18next:hook、组件级

安装

react-i18next使用上下文API、或者 hook:

vue-i18n:原型链、全局

0.安装

1.配置语言包(src\i18n或language)

1.1注册vue-i18n 

1.2动态加载语言文件

1.3设置VueI18n的options中的messages登

1.4设置VueI18n的options中的locale

1.5创建 VueI18n 实例并导出

完整代码

2.main.js引入,实例化Vue

3.使用

.vue

.ts:如工具函数

ts

src/declare.d.ts:declare module 'VueI18n';

Element:UI组件库

全局加载

按需加载

无法兼容ts

main.ts

设置语言

页面:html标签的 lang属性

  • 英语: <html lang="en">
  • 中文: <html lang="zh"> 或 <html lang="zh-CN">

"CN" 则表示该语言的特定区域,即中华人民共和国(China)。

更符合语言标准的规范

  • 西班牙语: <html lang="es">
  • 法语: <html lang="fr">
  • 日语: <html lang="ja">

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Webpage Title</title>
</head>
<body>
    <!-- Your webpage content goes here -->
</body>
</html>

浏览器->设置->语言

命名由来

  1. 国际化(i18n)

    • i 表示单词 "internationalization" 的首字母。
    • 18 表示在 "i" 和 "n" 之间有 18 个字母。
  2. 本地化(l10n)

    • l 表示单词 "localization" 的首字母。
    • 10 表示在 "l" 和 "n" 之间有 10 个字母。
  3. react-i18next:i18n+extend(推测)

原理

从本地化资源文件中获取特定键的字符串,并且可以动态地插入变量。本地资源一般是.json,.xml,.ts存储对象

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Translation Example</title>
</head>
<body>

<script>
const translationContext = {
  t: (key) => {
    // 获取浏览器当前语言
    const userLanguage = navigator.language || navigator.userLanguage;

    // 默认翻译
    const defaultTranslations = {
      "No modifications at present.": "No modifications at present.",
      "Time Error: Current creation time is earlier than the server time, unable to submit.": "Time Error: Current creation time is earlier than the server time, unable to submit.",
      // 添加其他英文翻译
    };

    // 按语言选择翻译
    const zhCNTranslations = {
      "No modifications at present.": "当前无修改",
      "Time Error: Current creation time is earlier than the server time, unable to submit.": "时间异常,当前创建时间早于服务器端时间,无法提交",
      // 添加其他中文翻译
    };

    const currentTranslations = ['zh', 'zh-CN', 'cn'].includes(userLanguage) ? zhCNTranslations : defaultTranslations;
    
    // 示例翻译
    const translatedText = currentTranslations[key] || defaultTranslations[key] || key;
    
    // 在控制台输出翻译结果
    console.log(translatedText);
    console.log(userLanguage);
    // 可以将翻译结果插入到页面中
    // document.body.innerHTML = translatedText;

    return translatedText;
  },
};

// 示例使用
translationContext.t("No modifications at present.");
translationContext.t("Time Error: Current creation time is earlier than the server time, unable to submit.");
</script>

</body>
</html>

t参数

t (translate) 函数: 这个函数用于翻译文本,传入翻译文件(如下述home.json命名空间(namespace,如下述zh.json中的login)

i18n 对象: 包含国际化设置的对象,判断和切换语言

i18n.language 的默认值浏览器的语言首选项(navigator.language

i18n.language; // 当前语言环境

i18n.changeLanguage('en'); // 切换到英语
  1. 变量替换 (variables):

    • 用法:通过一个对象来传递需要替换的变量。
    • 示例t('welcomeMessage', { username: 'John' })
    • 说明:这种方式允许你将动态变量插入到翻译文本中,类似占位符的功能。
  2. 格式化 (format):

    • 用法:指定特定的格式化选项,例如日期、数字格式化等。
    • 示例t('date', { date: new Date(), format: 'longDate' })
    • 说明:在需要根据语言环境格式化日期、数字或其他类型的内容时特别有用。
  3. 复数形式 (count):

    • 用法:指定一个用于选择适当复数形式的数值。
    • 示例t('items', { count: 5 })
    • 说明:根据给定的数值选择文本的复数形式,如单数、复数等。
  4. 上下文 (context):

    • 用法:指定一个上下文参数,用于选择文本的特定变体。
    • 示例t('open', { context: 'verb' })
    • 说明:在需要根据不同语境下选择不同翻译版本时使用,例如动词形式和名词形式的不同翻译。
  5. 默认值 (defaultValue):

    • 用法:指定在找不到翻译键时返回的默认文本。
    • 示例t('nonExistentKey', { defaultValue: 'Default Text' })
    • 说明:确保在没有对应翻译键的情况下,能够提供一个合适的默认文本,避免出现空白或错误。
  6. { returnObjects: true } 选项来告诉 t 函数返回一个包含多个条目的对象

zh.json

{
"home": {
  "welcomeMessage": "欢迎,{{username}}!",
  "items": {
    "one": "一个项目",
    "other": "{{count}} 个项目"
  },
  "date": {
  "longDate": "{{date, YYYY年MM月DD日}}",
  "shortDate": "{{date, YYYY-MM-DD}}",
  "fullDateTime": "{{date, YYYY年MM月DD日Ah点mm分ss秒}}"
   }

  "open": {
    "verb": "打开",
    "noun": "开放"
  },
  "features": {
      "free": {
        "title": "免费",
        "description": [
          "免费注册",
          "免费试用"
        ]
    },
},
  "login": {
    "title": "登录",
    "username": "用户名",
    "password": "密码",
    "loginButton": "登录"
  }
}
  • 长日期 (longDate):例如 2024年07月13日
  • 短日期 (shortDate):例如 2024-07-13
  • 完整日期时间 (fullDateTime):例如 2024年07月13日下午02点30分00秒

en.json

{
"home": {
  "welcomeMessage": "Welcome, {{username}}!",
  "items": {
    "one": "One item",
    "other": "{{count}} items"
  },
   "date": {
  "longDate": "{{date, MMMM Do, YYYY}}",
  "shortDate": "{{date, MM/DD/YYYY}}",
  "isoDate": "{{date, YYYY-MM-DD}}",
  "fullDateTime": "{{date, MMMM Do YYYY, h:mm:ss a}}"
  "features": {
      "free": {
        "title": "Free",
        "description": [
          "Free registration",
          "Free trial"
        ]
      },
}

  "open": {
    "verb": "Open",
     "noun": "Openness"
  }
},
"login": {
    "title": "Login",
    "username": "Username",
    "password": "Password",
    "loginButton": "Login"
  }
}
  • 长日期 (longDate):例如 July 13th, 2024
  • 短日期 (shortDate):例如 07/13/2024
  • ISO 8601 格式 (isoDate):例如 2024-07-13
  • 完整日期时间 (fullDateTime):例如 July 13th 2024, 2:30:00 pm

react组件

//不传参的话加载所有的本地资源
const { t, i18n } = useTranslation(['home', 'login']);

import React from 'react';
import { useTranslation } from 'react-i18next';

function WelcomeComponent({ username, itemCount, date }) {
  //只加载home.json,就不用带前缀home,只在home内查找
  const { t } = useTranslation('home');


  return (
    <div>
      <p>{t('welcomeMessage', { username: username })}</p>
      <p>{t('items', { count: itemCount })}</p>
      <p>{t('date', { date: date, format: 'longDate' })}</p>
      <p>{t('open', { context: 'verb' })}</p>
      <p>{t('nonExistentKey', { defaultValue: 'Default Text' })}</p>
        <ul>
        {t('features.free.description', { returnObjects: true }).map((desc, index) =>             
       (<li key={index}>{desc}</li>))}
      </ul>
    </div>
  );
}

export default WelcomeComponent;

传参和效果

<WelcomeComponent
  username="张三"
  itemCount={3}
  date={new Date()}
/>

<div>
  <p>Welcome, 张三!</p>
  <p>3 items</p>
  <p>July 12th, 2024</p>
  <p>Open</p>
  <p>Default Text</p>
   ...
</div>

<div>
  <p>欢迎,张三!</p>
  <p>3 个项目</p>
  <p>2024年7月12日</p>
  <p>打开</p>
  <p>Default Text</p>
  ...
</div>

本地资源:语言包对象

zh.ts

export default {
    languageName: '简体中文',
    common: { //通用
        you: '你',
    }
}

en.ts

export default {
    languageName: 'English',
    common: { //通用
        you: 'you',
     },
}

staticData.ts:直接返回对象效率更高

  • 适用于静态语言

  • 若固定顺序,可遍历对象属性

例子可见下文的react-i18next

export function getFeatures(lang: string){
  if(lang==='cn'){
    return [
      {
        title: '免费',
        description:  [
          '你好',
           ...
        ],
      },
      {
       ...
      }
    ]
  }else{
    return [
      {
        title: 'Free',
        description: [
          'hi~~~😄',
           ....
        ],
      },
      {
       ....
        ],
      }
    ]
  }

}

public->locales->en->模块名.json

public->locales->zh->模块名.json

  • 适用于动态语言,非固定顺序,零散重复使用

  • returnObjects: true,可遍历对象属性

react-i18next:hook、组件级

安装

npm i i18next react-i18next 
  • i18next 提供了翻译的基本能力。
  • react-i18next 是 i18next 的一个插件,用来降低 react 的使用成本。

可选:

npm i i18next-browser-languagedetector i18next-http-backend
  • i18next-browser-languagedetector 检测浏览器语言的插件。
  • i18next-http-backend从服务器加载翻译资源文件

react-i18next使用上下文API、或者 hook:

React Context API实现状态和数据在组件树中的共享。它允许在组件之间共享数据,而无需手动通过props一层层地传递数据。尤其适用于全局数据、主题设置、用户身份验证等在整个应用程序中需要访问的数据。

hook只能在函数组件

import { useTranslation } from 'react-i18next';
import { getFeatures } from './staticData';

export default function HomeContent() {
  //解构变量,根据本地的home和login文件设置i18n
  const { t, i18n } = useTranslation(['home', 'login']);
  const features = getFeatures(['zh', 'zh-CN', 'cn'].includes(i18n.language) ? 'cn' : 'en')

getFeatures见上文中的staticData.ts

<h1 className="font-bold text-2xl">{t('Sign in/Sign up')}</h1>
{features?.map((item, index) => (
          <div className='flex flex-col items-center p-4 md:w-1/2' key={item.title}>
            <div className=' min-w-full h-full bg-[#2A2935] rounded-lg p-4'>
              <div className=' text-2xl leading-loose md:leading-tight'>{item.title}
                {item.subtitle && <span className=' text-xs text-gray-400 ml-2'>( {item.subtitle} )</span>}
              </div>
              {item.description.map((item, index) => (
                <div className=' text-xs text-gray-400 leading-relaxed' key={index}>- {item}</div>
              ))}
            </div>
          </div>
        ))}

vue-i18n:原型链、全局

0.安装

npm install vue-i18n

Vue I18n官方文档

1.配置语言包(src\i18n或language)

整合语言包对象和创建 VueI18n 实例并配置

1.1注册vue-i18n 

import Vue from "vue"
import VueI18n from "vue-i18n"
Vue.use(VueI18n) // 将 VueI18n 注入到 Vue 实例中的所有子组件

在 Vue.js 中,插件通常通过 Vue.use() 方法来注册和安装。

vue-i18n 注册后,将 i18n 实例挂载到原型链上。

  1. 全局可访问任何 Vue 组件中都可以通过 this.$i18n 访问到国际化实例

  2. 一致性:保证所有组件使用同一个 i18n 实例,避免了不同组件间状态管理的复杂性和冗余性。

1.2动态加载语言文件

let langFileds = require.context('./locales', false, /\.ts$/)
let dateTimeFormatsFileds = require.context('./dateTimeFormats', false, /\.ts$/)
let regExp = /\.\/([^\.\/]+)\.([^\.]+)$/

require.context 是 webpack 提供的一种函数,用于在编译时动态地引入模块。它接受三个参数:require.context(path,deep,regExp)

  1. path(目录路径): 表示需要搜索的目录路径。
  2. deep(是否搜索子目录): 表示是否搜索该目录下的子目录。
  3. regExp(匹配文件的正则表达式): 表示匹配文件的正则表达式。

日期时间格式文件(zh.ts+en.ts一致)

export default {
  shortMonth: {
    month: 'short',
  },
  numberMonth: {
    month: 'narrow',
  },
  shortYear: {
    year: 'numeric'
  }
}

shortMonth:

month: 'short' 表示月份的简短格式。具体格式(比如 'Jan'、'Feb')取决于具体的本地化设置,通常是缩写形式的月份名称。

numberMonth:

month: 'narrow' 表示月份的窄格式。这种格式可能比 'short' 更加紧凑,通常用于较窄的显示空间或者日历视图中。

shortYear:

year: 'numeric' 表示年份的数字格式。这种格式通常是完整的四位数字年份(例如 2023)。

1.3设置VueI18n的options中的messages登

langFileds.keys().forEach((key:any) => {
        let prop = regExp.exec(key)//正则匹配en|zh这样的值

        if(prop){
            //messages[prop]相当于 messages['en'] = {table:{...}}
            messages[prop[1]] = langFileds(key).default
//对于 ./en.ts,prop 将会是 ['en', 'ts']
//.default 表示 ES6 默认导出的内容,因为 webpack 在处理 ES6 模块时会将其包装为一个包含 default 属性的对象。
        }
})
dateTimeFormatsFileds.keys().forEach((key:any) => {
  let prop = regExp.exec(key)//正则匹配en|zh这样的值
  if(prop){
      dateTimeFormats[prop[1]] = dateTimeFormatsFileds(key).default
  }
})

messages 对象:

{
    en: {
        greeting: 'Hello!',
        farewell: 'Goodbye!'
    },
    zh: {
        greeting: '你好!',
        farewell: '再见!'
    }
}

1.4设置VueI18n的options中的locale

let locale = window.xxx.appLocaleInfo.appLanguage || "zh" //从localstorag中获取

1.5创建 VueI18n 实例并导出

export default new VueI18n({
    locale, // 指定当前的语言环境
    messages, // 语言包对象,包含不同语言的翻译
    dateTimeFormats // 日期时间格式对象,包含不同语言的日期时间格式配置
})

完整代码

import Vue from "vue"
import VueI18n from "vue-i18n"
Vue.use(VueI18n) //注入到所有的子组件

let langFileds = require.context('./locales', false, /\.ts$/)
let dateTimeFormatsFileds = require.context('./dateTimeFormats', false, /\.ts$/)

let regExp = /\.\/([^\.\/]+)\.([^\.]+)$/ //正则用于匹配 ./en.js中的'en'

let messages = {} //声明一个数据模型,对应i18n中的message属性
let dateTimeFormats = {}

langFileds.keys().forEach((key:any) => {
        let prop = regExp.exec(key)//正则匹配en|zh这样的值
        if(prop){
            //messages[prop]相当于 messages['en'] = {table:{...}}
            messages[prop[1]] = langFileds(key).default
        }
})
dateTimeFormatsFileds.keys().forEach((key:any) => {
  let prop = regExp.exec(key)//正则匹配en|zh这样的值
  if(prop){
      dateTimeFormats[prop[1]] = dateTimeFormatsFileds(key).default
  }
})

let locale = window.xxx.appLocaleInfo.appLanguage || "zh" //从localstorag中获取

export default new VueI18n({
    locale,//指定语言字段
    messages,//定义语言字段
    dateTimeFormats
})

2.main.js引入,实例化Vue

import i18n from "./i18n"

//渲染函数 (render):动态地生成虚拟 DOM,适合复杂的逻辑和定制化需求。
new Vue({
  i18n,
  render: h => h(App)
}).$mount('#app')
​//模板字符串 (template):适合基本的应用程序结构和布局,易读和维护。
new Vue({
  i18n, // 语言国际化配置
  template: '<App/>', // 模板字符串,指定根组件
  components: { App } // 注册根组件
}).$mount('#app')

3.使用

.vue

//标签文本内容
<span>{{$t("workplace.updateRecurringSchedule")}}</span>
//标签属性
:placeholder="$t('chartSend.addScheduleTheme')"

//js
this.$t("chartSend.waitBotReply")

//键值对:removeMsg:'确定将 {nickname} 移除群聊吗?',
const item.nickname={nickname:'M7'}
this.$t("chartSend.removeMsg", {nickname: item.nickname})

.ts:如工具函数

import i18n from '@/i18n'

class IMConListUtil {
i18n.t('common.private'),

}

ts

src/declare.d.ts:declare module 'VueI18n';

TypeScript项目中,当第三方库或模块不是由 TypeScript 编写的,因此可能没有原生的 TypeScript 类型定义文件。

会创建一个 declare.d.ts 文件,声明模块的类型信息,以便在编译时进行类型检查和提供类型提示。

declare module 'element-ui';
declare module 'vuex';
declare module 'vue';
declare module 'VueI18n';
declare module 'axios';
eclare module 'lodash';
declare module 'vue-router';

Element:UI组件库

全局加载

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Element from 'element-ui'
import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'

Vue.use(VueI18n)
Vue.use(Element)
//设置默认语言
Vue.config.lang = 'zh-cn'
//注册了中文(简体)和英文的本地化资源
Vue.locale('zh-cn', zhLocale)
Vue.locale('en', enLocale)

按需加载

import Vue from 'vue'
import DatePicker from 'element/lib/date-picker'
import VueI18n from 'vue-i18n'

import enLocale from 'element-ui/lib/locale/lang/en'
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
import ElementLocale from 'element-ui/lib/locale'

Vue.use(VueI18n)
Vue.use(DatePicker)

const messages = {
  en: {
    message: 'hello',
    ...enLocale
  },
  zh: {
    message: '你好',
    ...zhLocale
  }
}
// Create VueI18n instance with options
const i18n = new VueI18n({
  locale: 'en', // set locale
  messages, // set locale messages
})

ElementLocale.i18n((key, value) => i18n.t(key, value))

无法兼容ts

手动将'element-ui/lib/locale/lang/en','element-ui/lib/locale/lang/zh-CN'中相关内容粘贴合并到本地语言包文件中即可

在实现功能时可以节省时间,但不利于工程化

main.ts

import ElementLocale from 'element-ui/lib/locale'

ElementLocale.i18n((key:any, value:any) => i18n.t(key, value))

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值