Skip to content

获取代码中的所有中文文本

使用 fe-js-utils

cmd
pnpm add fe-js-utils -D

package.json 中添加以下 scripts:

json
{
  "scripts": {
    "cleanInvalidComments": "fe-js-utils cleanInvalidComments",
    "checkAny": "fe-js-utils checkAny",
    "extractChinese": "fe-js-utils extractChinese",
    "extractCommonLocaleValues": "fe-js-utils extractCommonLocaleValues",
    "findModuleInCommonLocaleValues": "fe-js-utils findModuleInCommonLocaleValues",
    "autoGenerateLocaleModules": "fe-js-utils autoGenerateLocaleModules",
    "autoReplaceChinese": "fe-js-utils autoReplaceChinese"
  }
}

在项目根目录创建 fe-js-utils.config.ts

ts
const commonLocaleModules = ['SiderNav']
const langFile = './extract-en-results.js'
const langName = 'en_US'

export default {
  extractChinese: {
    targetDir: './src',
    outputFile: langFile,
    extFiles: ['.js', '.ts', '.vue'],
    excludeDirs: ['node_modules', 'dist', 'build', 'locales'],
  },

  extractCommonLocaleValues: {
    outputFile: `./src/locales/${langName}/Common.ts`,
  },

  autoGenerateLocaleModules: {
    // 输入文件路径(中文提取结果文件)
    inputFile: langFile,
    outputDir: `./src/locales/${langName}`,
    runExtractFirst: false, // 自动先执行extractChinese
    autoExtractCommonLocale: true, // 自动执行extractCommonLocaleValues
  },

  findModuleInCommonLocaleValues: {
    localeDir: `./src/locales/${langName}`,
    commonLocaleModule: 'Common',
    localModules: commonLocaleModules,
  },

  autoReplaceChinese: {
    localeDir: './src/locales/zh_CN',
    commonLocaleModule: 'Common',
    localModules: commonLocaleModules,
    // 变量声明插入位置,默认为 // #region Hooks,如果值为空或在文件中未找到,则插入到 import 语句的最后
    variableDeclarationInsertPosition: '',
    // 显示详细日志
    verbose: false,
    // 自定义 import 语句的回调函数
    customImportStatements: (
      imports: string[],
      filePath: string,
      localModule: string
    ) => {
      // 返回一个 import 语句字符串的数组,为空时不会添加任何 import 语句
      return [
        "import { useI18n  } from 'vue-i18n'",
        "import i18n from '@/i18n'",
      ]
    },
    // 自定义变量声明的回调函数
    customVariableDeclarations: (
      fileContent: string,
      filePath: string,
      localModule: string,
      needsCommon: boolean
    ) => {
      // 返回一个变量声明字符串,为空时不会添加任何变量声明
      return 'const { t } = useI18n()'
    },
    // 自定义替换文本的回调函数
    customReplaceTextFunction: (
      filePath: string,
      localModule: string,
      chineseKey: string,
      englishValue: string,
      isCommon: boolean,
      context: string
    ) => {
      // 返回一个替换后的字符串,为空时将不会替换任何中文字符
      // 示例:
      return `$t('${localModule}.${englishValue}')`
    },
  },
}

extractChinese(中文提取)

将代码中所有中文按照组件位置提取出来

cmd
pnpm extractChinese

extractCommonLocaleValues(提取公共语言包)

根据组件生成 extract-chinese-results.js ,可以自己手动通过翻译此文件生成其他语言版本,最后再生成模块化语言包配置到 vue-i18n 中

cmd
pnpm extractCommonLocaleValues

autoGenerateLocaleModules(生成模块化语言包)

生成根据组件路径区分的多个语言键值配置文件

cmd
pnpm autoGenerateLocaleModules

autoReplaceChinese(替换源码中的中文)

cmd
pnpm autoReplaceChinese

配置 vue-i18n

下载

cmd
pnpm add vue-i18n@11

创建 i18n/index.ts

ts
// src/i18n/index.ts
import { createI18n } from 'vue-i18n'
import type { I18nInstance } from 'vue-i18n'
import messages from '../locales/index' // fe-js-utils 生成的语言包

// 从 localStorage 读取保存的语言(默认 zh-CN)
const getSavedLocale = (): string => {
  if (typeof window !== 'undefined') {
    return localStorage.getItem('app-locale') || 'zh-CN'
  }
  return 'zh-CN'
}

// 创建 i18n 实例
const i18n: I18nInstance = createI18n({
  legacy: false, // 开启 Vue 3 组合式 API 支持
  locale: getSavedLocale(), // 初始语言(优先从本地存储读取)
  fallbackLocale: 'en', // 降级语言
  messages: messages, // 注册 fe-js-utils 生成的语言包
})

export default i18n

main.ts 中导入

ts
import i18n from './i18n'

const app = createApp(App)

app.use(i18n)

设置语言文件

创建 locales/index.ts

ts
// src/locale/index.ts(示例结构)
import zh from './zh' // 中文语言包
import en from './en' // 英文语言包
// 其他语言...

// 导出所有语言包(key 是语言标识,value 是对应语言的键值对)
export default {
  'zh': zh,
  'en': en,
  // 如:'ja': ja, 'ko': ko...
}

语言包示例

ts
export default {
  按键选择: 'Key Selection',
  开始调试: 'Start Calibration',
}

配置 store

创建 stores/i18nStore.ts

ts
// src/stores/i18nStore.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'

export const useI18nStore = defineStore('i18n', () => {
  const { locale, t } = useI18n()

  // 可用语言列表
  const availableLocales = ref([
    { code: 'en', name: 'English' },
    { code: 'zh', name: '中文' },
  ])

  // 当前语言
  const currentLocale = computed(() => locale.value)

  // 切换语言
  const setLocale = (lang: string) => {
    locale.value = lang
    localStorage.setItem('preferred-language', lang)
  }

  // 响应式组件获取文本
  // const trans = (key: string) => computed(() => t(key))
  const trans = (key: string) => t(key)

  // 初始化语言
  const initLocale = () => {
    const saved = localStorage.getItem('preferred-language')
    const browserLang = navigator.language
    const defaultLang =
      saved || (browserLang.startsWith('zh') ? 'zh' : 'en')
    setLocale(defaultLang)
  }

  return {
    availableLocales,
    currentLocale,
    setLocale,
    initLocale,
    trans,
    t
  }
})

组件中使用

vue
<script>
import { useI18nStore } from '@/stores/i18nStore'

const i18nStore = useI18nStore()

</script>
<template>
	<div class="first-content">
        <div
          class="nav-item"
          v-for="item in fixedNavData.first.navItems"
          :class="{ 'is-select': item.isSelect }"
          :key="item.path"
        >
          <div>
            <!-- {{ item.svg }} -->
            <SvgIcon
              :icon-class="item.icon"
              size="2em"
              :color="item.isSelect ? '#b4b47b' : ''"
            />
          </div>
          <div>{{ i18nStore.trans(item.name) }}</div>
        </div>
      </div>
      <div>{{ i18nStore.trans('文本内容作为键') }}</div>

</template>

Released under the GPL License.