【unibest】uniapp 最佳多语言实践,更高的视野,降维打击!

4,759 阅读4分钟

【unibest】uniapp 最佳多语言实践,更高的视野,降维打击!

最近了解到有几个粉丝写 unibest 时有 多语言 的需求,并且是很多个语言,不只是 uniapp 官方默认支持的 5 个语言;同时粉丝觉得 uniapp 官方默认的 json 文件不能写注释,key 全部是平铺的,不能分模块等各种体验不佳,希望能改善一下。

菲鸽 最乐于助人,粉丝的需求肯定是要满足的,实现思路:

  • 使用 ts/jsonc/json5/js 的方式编写文件,使用文件监听的方式,自动生成 json 文件。
  • 支持使用 模块化 的方式编写,支持 平铺 + 非平铺 的方式编写多语言文件。

所有代码都已经放到 unibest 项目地址


我们正式开始,文章分 5 部分

  • uniapp 多语言基础:主要介绍 基本的 uniapp 多语言怎么引入和使用的
  • uniapp 多语言进阶:主要介绍 文件监听 的方式自动生成 json 文件
  • uniapp 多语言进化:主要介绍 模块化平铺 + 非平铺 的方式。
  • uniapp 多语言升化:主要介绍 使用第三方服务(比如百度翻译),自动翻译
  • uniapp 多语言气化:主要介绍 如何把上诉东西编写成一个 vite 插件就像 @uni-helper/vite-plugin-uni-pages 一样

一、uniapp 多语言基础(熟悉的同学可以跳过本节)

src/locale 里面写 en.json, zh-Hans.json 等多语言文件,如下:

./src/locale
├── en.json
├── index.ts
└── zh-Hans.json

统一在 src/locale/index.ts 中引入这些 json 文件,并使用 vue-i18ncreateI18n 函数生成 i18n 实例,最后在 src/main.tsapp.use(i18n) 即可。

// filename: src/main.ts
import { createSSRApp } from 'vue'
import App from './App.vue'
+ import i18n from './locale/index'

export function createApp() {
  const app = createSSRApp(App)
+  app.use(i18n)
  return {
    app,
  }
}

下面的 src/locale/index.ts 文件,除了实现最基础的功能之外,还实现了 translate 函数,方便在 非 vue 文件 (一般是 ts 文件)中使用多语言,这也是一个粉丝提到的一个功能。

// filename: src/locale/index.ts
import { createI18n } from 'vue-i18n'

import en from './en.json'
import zhHans from './zh-Hans.json' // 简体中文

const messages = {
  en,
  'zh-Hans': zhHans, // key 不能乱写,查看截图 screenshots/i18n.png
}

const i18n = createI18n({
  locale: uni.getLocale(), // 获取已设置的语言,fallback 语言需要再 manifest.config.ts 中设置
  messages,
})

console.log(uni.getLocale())
console.log(i18n.global.locale)

/**
 * 非 vue 文件使用这个方法
 * @param { string } localeKey 多语言的key,eg: "app.name"
 */
export const translate = (localeKey: string) => {
  if (!localeKey) {
    console.error(`[i18n] Function translate(), localeKey param is required`)
    return ''
  }
  const locale = uni.getLocale()
  console.log('locale:', locale)

  const message = messages[locale]
  if (Object.keys(message).includes(localeKey)) {
    return message[localeKey]
  }
  return localeKey
}
export default i18n

vue 文件怎么写呢?$t 函数包裹即可,支持传参数

<view class="m-4">{{ $t('weight', { heavy: 100 }) }}</view>

对应的 json 文件如下,以 en.json 为例:

{
  "weight": "{heavy} KG",
}

怎么切换多语言呢?通常为写一个 radio,在里面的 @change 事件中编写:

<view class="uni-list">
  <radio-group @change="radioChange" class="radio-group">
    <label class="uni-list-cell uni-list-cell-pd" v-for="item in languages" :key="item.value">
      <view>
        <radio :value="item.value" :checked="item.value === current" />
      </view>
      <view>{{ item.name }}</view>
    </label>
  </radio-group>
</view>

对应的 script setup 如下:

import i18n from '@/locale/index'
const current = ref(uni.getLocale())
const languages = [
  {
    value: 'zh-Hans',
    name: '中文',
    checked: 'true',
  },
  {
    value: 'en',
    name: '英文',
  },
]
const radioChange = (evt) => {
  // console.log(evt)
  current.value = evt.detail.value
  // 下面2句缺一不可!!!
  uni.setLocale(evt.detail.value)
  i18n.global.locale = evt.detail.value
}

最后,多语言标题怎么办? 需要在 pages.json 中把 navigationBarTitleText 写成 %xxx% 这种形式,eg:

{
  "path": "pages/demo/i18n",
  "type": "page",
  "style": {
    "navigationBarTitleText": "%app.name%"
  }
}

注意事项:

    1. 默认支持 5 种语言,其他语言 uniapp 不认识 (不是 vue-i18n 不认识)。
    • 英语 en
    • 中文简体 zh-Hans
    • 繁体 zh-Hant
    • 法语 fr
    • 西班牙语 es locale

    如果是其他语言,vue 文件里面的是认识的,但是 uniapp 的标题 navigationBarTitleText 就不会自动翻译了,这个时候需要使用 uni.setNavigationBarTitle 手动处理,并且需要监听多语言的切换(很重要!)。

    1. 多语言文件夹为 src/locale ,不能改为 locales 或其他。
    1. json 文件的 key 是平铺的,不能写成对象的形式。

总结

本文一步一步完成了 uniapp 多语言的最佳实践,步骤如下:

  • uniapp 多语言基础:主要介绍 基本的 uniapp 多语言怎么引入和使用的
  • uniapp 多语言进阶:主要介绍 文件监听 的方式自动生成 json 文件
  • uniapp 多语言进化:主要介绍 模块化平铺 + 非平铺 的方式。
  • uniapp 多语言升化:主要介绍 使用第三方服务(比如百度翻译),自动翻译
  • uniapp 多语言气化:主要介绍 如何把上诉东西编写成一个 vite 插件就像 @uni-helper/vite-plugin-uni-pages 一样

好文推荐

🔥2024 年最好用的 uniapp 开发模板,近一个月 star 数飙升!🔥 - 点赞数:304, 收藏数:650 (前端收藏榜榜第八)