Appearance
国际化(多语言)
WEB端
语言包定义
TIP
您可以在 /src/lang/autoload.ts
内定义按需加载的 额外加载
映射关系;您还可能需要脱离按需加载,可以直接将语言包放置于 /src/lang/common
目录,这样就能随处使用了。
- WEB端项目语言包分为
第三方、全局、页面按需加载
语言包三种,其中最常用的页面语言包
,我们设计了分目录的管理方式。 - 可以在
/src/lang/backend/语言
和/src/lang/frontend/语言
目录下,建立任意目录和语言包文件,程序会自动进行动态批量加载。
以下代码仅为定义
和后续的使用
演示用示例,以方便读者理解,并非项目实际的语言包文件。
ts
// 全局中文语言包文件 /src/lang/globs-zh-cn.ts
export default {
// 语言翻译的key请勿带有英文句号(.)
Home: '首页',
}
// 全局英文语言包文件 /src/lang/globs-en.ts
export default {
Home: 'Home',
}
// 管理员后台`控制台页面`的中文语言包文件 /src/lang/backend/zh-cn/dashboard.ts(页面语言包,后台放在 backend 目录)
export default {
republish: '重新发布',
}
// 管理员后台`控制台页面`的英文语言包文件 /src/lang/backend/en/dashboard.ts(页面语言包,后台放在 backend 目录)
export default {
republish: 'Republish',
}
// 会员前台`会员登录`页面的中文语言包文件 /src/lang/frontend/zh-cn/user/login.ts(页面语言包,前台放在 frontend 目录)
export default {
title: '登录到会员中心',
}
// 会员前台`会员登录`页面的英文语言包文件 /src/lang/frontend/en/user/login.ts(页面语言包,前台放在 frontend 目录)
export default {
title: 'Login',
}
语言包使用
在模板和 TS 代码中使用
vue
<template>
<!-- 全局翻译 -->
<span :title="t('Home')"></span>
<span>{{ t('Home') }}</span>
<!-- 控制台页面可以使用的语言翻译 -->
<!-- 系统根据路由的 name 和 path 自动加载对应目录结构的语言包 -->
<span :title="t('dashboard.republish')"></span>
<span>{{ t('dashboard.republish') }}</span>
<!-- 会员登录页面可以使用的语言翻译 -->
<!-- 系统根据路由的 name 和 path 自动加载对应目录结构的语言包 -->
<span :title="t('user.login.title')"></span>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const globs = t('Home') // 使用全局翻译
const dashboard = t('dashboard.republish') // 在控制台页面内可以使用的语言翻译
const login = t('user.login.title') // 在会员登录页面内可以使用的语言翻译
</script>
仅在模板中使用
vue
<template>
<!-- 全局翻译 -->
<span :title="$t('Home')"></span>
<span>{{ $t('Home') }}</span>
<!-- 页面语言翻译 -->
<span :title="$t('dashboard.republish')"></span>
<span>{{ $t('dashboard.republish') }}</span>
</template>
<script setup lang="ts"></script>
实现介绍
- web端的国际化使用了
vue-i18n
实现。 - 我们只加载了当前环境对应的语言包,比如
zh-cn
或者en
的语言包文件,所以切换语言包,站点会自动刷新。 - 我们在
main.js
文件中调用/@/lang/index
文件内的loadLang
函数对多语言支持进行了初始化。 - 在
/@/lang/index
文件中,我们利用import.meta.glob
批量加载了element、公共
的语言包文件,并准备好了页面
语言包的按需加载句柄(页面语言包并没有真正的加载,相当于准备好了可加载列表)。 - 在用户真正打开对应页面时,再根据路由的
path
和name
进行加载,按需自动加载的工作是在/src/router/index.ts
中定义的。 页面
语言包,支持无限目录层级加载,我们根据对应目录结构,实现了以.
分隔的语言翻译key
,比如:/@/lang/backend/zh-cn/auth/menu.ts
语言包定义如下:
ts
export default {
name: '名称',
stateList: {
'state 1': '状态1',
'state 2': '状态2',
},
}
ts
// 使用该语言翻译
// 它的格式是:目录.目录.翻译key
t('auth.menu.name')
t('auth.menu.stateList.state 1')
element-plus
的语言包,我们只载入了 中文
和 英文
,若需支持 element-plus
的其他语言包,请自行在 /@/lang/index
文件中添加。
重要提示
WEB端语言翻译的 key
请勿带有英文句号(.
)
Server端
Server端使用了 Thinkphp8
自带的多语言功能,并做了适当封装。
语言包定义
一个应用下的语言包目录结构类似于:
bash
app/admin/lang
├─lang
│ │ en.php 应用公共英文语言包
│ │ zh-cn.php 应用公共中文语言包
│ │
│ ├─en
│ │ │ index.php Index控制器英文语言包
│ │ │
│ │ └─user
│ │ moneylog.php user/MoneyLog控制器英文语言包
│ │
│ └─zh-cn
│ │ index.php Index控制器中文语言包
│ │
│ └─user
│ moneylog.php user/MoneyLog控制器中文语言包
我们已经在 app\common\controller\Api
Api基类中,实现了对应控制器的语言包自动加载,所以可以直接使用语言翻译,而无需额外的语言包加载。
以下代码仅为 定义
和后续的 使用
演示用示例,以方便读者理解,并非项目实际的语言包文件。
php
// 应用公共英文语言包文件
// app/admin/lang/en.php
return [
'Hello %s' => 'Hello,%s',
"Hello %s, I'm %s" => "Hello %s, I'm %s",
];
// 应用公共中文语言包文件
// app/admin/lang/zh-cn.php
return [
'Hello %s' => '你好,%s',
"Hello %s, I'm %s" => "你好%s,我是%s",
];
语言包使用
我们定义了全局公共函数 __
,来进行语言翻译:
函数定义:
php
/**
* 语言翻译
* @param string $name 被翻译字符
* @param array $vars 替换字符数组
* @param string $lang 指定翻译语言
* @return string
*/
__(string $name, array $vars = [], string $lang = '');
函数使用:
php
__('Hello %s', ['BuildAdmin']);
__('Hello %s', ['BuildAdmin'], 'en');
__("Hello %s, I'm %s", ['BuildAdmin', '妙码生花'], 'zh-cn');
加载说明
如果控制器继承了 app\common\controller\Api
,则可以实现语言包按控制器自动加载。
假设当前为中文语言环境
bash
# 访问
https://buildadmin.com/index.php/admin/auth.admin/index
bash
# 自动加载语言包
app/admin/lang/zh-cn.php
app/admin/lang/zh-cn/auth/admin.php
有时我们需要在当前控制器导入其他语言包文件,可以参考以下代码进行加载:
php
$langset = $this->app->lang->getLangSet();
$this->app->lang->load([
app_path() . 'lang' . DIRECTORY_SEPARATOR . $langset . DIRECTORY_SEPARATOR . (str_replace('/', DIRECTORY_SEPARATOR, $this->app->request->controllerPath)) . '.php'
]);