---
url: /docs/5.0/server/lang.md
---
# 国际化

在 `v4.2.5` 版本中，专业版已经将后台语言数据使用后端提供，使用 laravel 框架的多语言功能。在根目录下`lang`目录。目前包含两个语言

* zh
* en

目录结构如下

```php
├─lang
│  ├─zh (中文)
│  |  generate.php
|  |  login.php
│  |  module.php
│  |  register.php
│  |  system.php
│  ├─en (英文)
│  |  generate.php
|  |  login.php
│  |  module.php
│  |  register.php
│  |  system.php
```

规定以文件名作为某个功能模块的 key 使用，所以具体实现如下

```php
public function translate($lang)
{
    //return admin_cache('lang_'.$lang, 300, function () use ($lang) {
        $translations = [];
        $files = File::allFiles(lang_path($lang));

        foreach ($files as $file) {
            $translations[$file->getFilenameWithoutExtension()] = require $file->getRealPath();
        }


        return $translations;
    // });
}
```

:::warning
默认是不使用缓存的，如果需要，你可以打开缓存，毕竟文件查找得过程是需要耗费时间，尤其是数据多了之后得情况下
:::

前端还是在`i18n`目录下，跟之前的有所区别，但区别不大，只是加入异步加载得功能，具体实现如下

```js
import Cache from '@/support/cache'
import { createI18n } from 'vue-i18n'
import type { App } from 'vue'
import http from '@/support/http'

// 语言包缓存的键名
const LANG_CACHE_KEY = 'cached_lang_pack_'

// 创建i18n实例
const i18n = createI18n({
  locale: Cache.get('language') || 'zh',
  fallbackLocale: 'zh',
  globalInjection: true,
  legacy: false,
  messages: {} // 初始化为空对象，语言包将从后端加载
})

// 扩展 i18n 类型
declare module 'vue-i18n' {
  interface I18n {
    loadLanguage: (lang: string) => Promise<boolean>
  }
}

/**
 * 从后端加载语言包
 * @param locale 语言代码
 * @returns Promise<boolean> 加载是否成功
 */
const loadTranslations = async (locale: string): Promise<boolean> => {
    // 如果没有缓存，从后端获取语言包
    try {
      const response = await http.get(`/lang/${locale}`)

      if (response.data && response.data.data) {
        // 设置语言包
        i18n.global.setLocaleMessage(locale, response.data.data)

        // 更新当前语言
        i18n.global.locale.value = locale

        // 保存语言设置到缓存
        Cache.set('language', locale)

        // 缓存语言包数据
        Cache.set(`${LANG_CACHE_KEY}${locale}`, response.data.data)

        return true
      }
      return false
    } catch (error) {
      // 如果是默认语言且没有缓存，则失败
      if (locale === 'zh') {
        return false
      }
      return loadTranslations('zh')
    }
}

// 将 loadLanguage 方法挂载到 i18n 对象上
i18n.loadLanguage = loadTranslations

/**
 * 初始化i18n
 * @param app Vue应用实例
 */
export async function bootstrapI18n(app: App): Promise<void> {
  // 加载默认语言包
  const defaultLocale = Cache.get('language') || 'zh'

  try {
    // 尝试加载默认语言包
    const success = await loadTranslations(defaultLocale)

    // 如果默认语言加载失败且不是中文，尝试加载中文
    if (!success && defaultLocale !== 'zh') {
      await loadTranslations('zh')
    }
  } catch (error) {
    // 如果加载失败，创建一个空的语言包以避免应用崩溃
    i18n.global.setLocaleMessage('zh', {})
    i18n.global.locale.value = 'zh'
  }

  // 注册i18n插件
  app.use(i18n)
}

export default i18n

```

当然这整个过程还是需要前后端配合的，前端依旧使用 `t` 函数进行多语言翻译。所以整个开发过程中，前后端需要定义好翻译的 key，前端使用

```js
// t 函数进行翻译
t('generate.code.xxxx.xxxx')
```

这样就可以使用后端来输出翻译数据给前端，即使修改了数据则不需要重新打包
