# 国际化(多语言)

# WEB端

# 语言包定义

  • WEB端项目语言包分为第三方全局页面按需加载语言包三种,其中最常用的页面语言包,我们设计了分目录的管理方式。
  • 可以在/src/lang/backend/语言/src/lang/frontend/语言目录下,建立任意目录和语言包文件,程序会自动进行动态批量加载。

TIP

您可以在/src/lang/autoload.ts内定义按需加载的额外加载映射关系;您还可能需要脱离按需加载,可以将语言包放置于/src/lang/common目录。

  • 以下代码仅为定义和后续的使用演示用示例,以方便读者理解,并非项目实际的语言包文件。
// 全局中文语言包文件 /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代码中使用

<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>

# 仅在模板中使用

<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公共的语言包文件,并准备好了页面语言包的按需加载句柄(页面语言包并没有真正的加载,相当于准备好了可加载列表)。
  • 在用户真正打开对应页面时,再根据路由的pathname进行加载,按需自动加载的工作是在/src/router/index.ts中定义的。
  • 页面语言包,支持无限目录层级加载,我们根据对应目录结构,实现了以.分隔的语言翻译key,比如:/@/lang/backend/zh-cn/auth/menu.ts语言包定义如下:
export default {
    name: '名称',
    stateList: {
        'state 1': '状态1',
        'state 2': '状态2',
    }
}
// 使用该语言翻译
// 它的格式是:目录.目录.翻译key
t('auth.menu.name')
t('auth.menu.stateList.state 1')
  • element-plus的语言包,我们只载入了中文英文,若需支持element-plus的其他语言包,请自行在/@/lang/index文件中添加。

重要提示

WEB端语言翻译的key请勿带有英文句号(.

# server端

SERVER端使用了Thinkphp8自带的多语言功能,并做了适当封装。

# 语言包定义

  • 一个应用下的语言包目录结构类似于:
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\ApiApi基类中,实现了对应控制器的语言包自动加载,所以可以直接使用语言翻译,而无需额外的语言包加载。


以下代码仅为定义和后续的使用演示用示例,以方便读者理解,并非项目实际的语言包文件。

// 应用公共英文语言包文件
// 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",
];

# 语言包使用

  • 我们定义了全局公共函数__,来进行语言翻译:

函数定义:

/**
 * 语言翻译
 * @param string $name 被翻译字符
 * @param array  $vars 替换字符数组
 * @param string $lang 指定翻译语言
 * @return string
 */
__(string $name, array $vars = [], string $lang = '');

函数使用:

__('Hello %s', ['BuildAdmin']);
__('Hello %s', ['BuildAdmin'], 'en');
__("Hello %s, I'm %s", ['BuildAdmin', '妙码生花'], 'zh-cn');

# 加载说明

  • 如果控制器继承了app\common\controller\Api,则可以实现语言包按控制器自动加载

# 假设当前为中文语言环境

# 访问
https://buildadmin.com/index.php/admin/auth.admin/index
# 自动加载语言包
app/admin/lang/zh-cn.php
app/admin/lang/zh-cn/auth/admin.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'
]);