npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-i18n-generator

v2.0.2

Published

Vue-i18n 国际化生成器,提取项目中的”中文“替换为多语言`$t(key)`,并导出翻译文件。

Downloads

1,564

Readme

vue-i18n-generator

介绍

Vue-i18n 国际化生成器,提取项目中的”中文“替换为多语言$t(key),并导出翻译文件。

安装

# 全局安装
npm install vue-i18n-generator -g

# 或本地安装
npm install vue-i18n-generator --save-dev

命令行参数

translator <env>  options

Arguments:
  env                        指定环境:dev、test、prod

Options:
  -d, --dir <dir>            提取的文件夹路径,默认 src/
  -o, --output <dir>         提取结果输出路径,默认 src/locales
  -e, --excludes <value...>  需要排除的文件或文件夹,可指定多个
  -l, --locales <value...>   需要生成的语言代码(符合BCP47标准),如 zh-CN
  -t, --translate <value...> 需要翻译的语言代码,对应--locales参数
  -p, --prefix <value>       多语言Key前缀,如 L1 L2 L3 custom
  -c, --channel <value>      翻译渠道 baidu(百度) youdao(有道) google(谷歌)
  -m, --key-mode <value>     Key生成模式,pinyin(拼音) | pinyin-hash(拼音+哈希) | hash(哈希)
  --appKey <value>           翻译api应用key
  --secretKey <value>        翻译api密钥
  --v2 <value>               是否为Vue2.x版本, 默认为Vue3.x版本
  • env参数详解:

    • dev 仅输出翻译文件。
    • test 输出翻译文件并生成.lang结尾的对照文件(可通过执行dev删除)。
    • prod 不输出翻译文件,仅将翻译key替换原文件中文,用于生产打包部署前命令。
  • 备注:

    • 谷歌翻译需提供 --appKey(Google Cloud Translation API v2)。百度和有道翻译需同时提供 --appKey--secretKey
    • 只对新增key翻译,需重新翻译可删除locale.json中的key后重新执行命令
    • prefix为多语言前缀,L1为路径层级文件夹名,路径中pages|views不计算层级
    • 生成的翻译key[前缀]_文件名.[Key生成策略],需注意中文修改后key将会被改变
    • 可添加自定义公共多语言(在根目录创建translator.json),适用于高频率出现的中文

注意事项definePropsdefineEmits的选项中不能使用t方法,故在它们选项中不能使用中文块,我们可引入全局i18n实例,然后使用实例的i18n.global.t方法来解决。因为它们会从setup中提升到模块的作用域,因此传入的选项不能引用在setup作用域中声明的局部变量,这样会引起编译报错,具体可查看官方文档。

语种编码对照

本项目使用的语言编码遵循 BCP 47 标准。不同翻译渠道的 API 对语言代码的格式要求不同,本工具已内置自动修正,无需手动转换,如无需使用翻译功能则可忽略。

| 语种 | 项目多语言编码 | 百度翻译 | 有道翻译 | 谷歌翻译 | |------|:---:|:---:|:---:|:---:| | 简体中文 | zh-CN | zh | zh-CHS | zh-CN | | 繁体中文(台湾) | zh-TW | cht | zh-CHT | zh-TW | | 繁体中文(香港) | zh-HK | cht | zh-CHT | zh-HK | | 英语(美国) | en-US/en | en | en | en | | 英语(英国) | en-GB/en | en | en | en | | 日语 | ja-JP/ja | jp | ja | ja |

说明:百度翻译使用自定义语种代码(繁体中文统一映射为 cht);有道翻译使用 zh-CHS/zh-CHT 后缀区分简繁体;谷歌翻译支持 BCP 47 标准,与项目编码完全一致。传入小写非标准代码(如 ja)也可被解析。

key-mode 参数详解

控制多语言 Key 的生成策略,解决不同中文字符串可能生成相同 Key 的碰撞问题。

| 模式 | 参数值 | Key 示例 (确认删除?) | 说明 | |------|--------|----------------------|------| | 拼音 | pinyin | que_ren_shan_chu | 全拼 ≤20 字符直接使用,超长用首字母或截取。可能碰撞 | | 拼音+哈希 | pinyin-hash | que_ren_shan_chu | 首次出现用可读拼音,同一 Key 再次出现或过长时追加 4~8 位 MD5 哈希 | | 哈希 | hash | fc98faab450a | 始终用原文的 12 位 MD5 哈希作为 Key,绝对唯一但不可读 |

碰撞示例:

| 中文原文 | pinyin(默认) | pinyin-hash | hash | |----------|:--:|:--:|:--:| | 确认删除? | que_ren_shan_chu | que_ren_shan_chu | fc98faab450a | | 确认删除! | que_ren_shan_chu ❌ 覆盖 | que_ren_shan_chu_450a ✅ | 450a828b3f1e | | 确认删除。 | que_ren_shan_chu ❌ 覆盖 | que_ren_shan_chu_04ad ✅ | 04ad497b2c8d | | 攻击 | gong_ji | gong_ji | 33781e80a9f2 | | 公鸡 | gong_ji ❌ 覆盖 | gong_ji_2daa ✅ | 2daa2de31b7c | | 一段很长的中文... | zsydfccdzw... | zsydfccdzw_5830a3f0 | 5830a3f012ef |

命令行使用

# 帮助文档
translator --help

# 开发环境:提取中文并生成翻译文件(百度翻译)
translator dev -d src/ -o src/locales -l zh-CN en-US -t en-US -c baidu --appKey YOUR_KEY --secretKey YOUR_SECRET

# 开发环境:使用谷歌翻译(需 API 密钥)
translator dev -d src/ -o src/locales -l zh-CN en-US -t en-US -c google --appKey YOUR_API_KEY

# 指定 Key 生成模式(推荐 pinyin-hash,防碰撞)
translator dev -d src/ -o src/locales -l zh-CN en-US -m pinyin-hash

# 测试环境:额外生成对照文件(.lang后缀)
translator test -l zh-CN zh-TW en-US --v2

# 生产环境:直接替换原文件
translator prod -l zh-CN zh-TW en-US --v2

项目中导入

  • 安装vue-i18n依赖包: npm install vue-i18n --save
  • 在Vue项目中的main.js文件中添加如下代码:

Vue2.0

// main.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import VueRouter from 'vue-router';
import ElementUI from 'element-ui';

import elementZhCN from 'element-ui/lib/locale/lang/zh-CN';
import elementEnUS from 'element-ui/lib/locale/lang/en';

import router from '@/router';
import { i18n } from '@/locales';

import App from './App.vue';

Vue.use(VueRouter);

// 合并 ElementUI 语言包
i18n.mergeLocaleMessage('zh-CN', elementZhCN);
i18n.mergeLocaleMessage('en-US', elementEnUS);

Vue.use(ElementUI, {
  i18n: (key, value) => i18n.t(key, value),
});

new Vue({
  router,
  i18n,
  render: (h) => h(App),
}).$mount('#app');

Vue3.0

// main.js
import { createApp } from 'vue';

import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';

import router from '@/router';
import i18n from '@/locales';

import App from './App.vue';

const app = createApp(App);
app.use(i18n);

app.use(router);
app.use(ElementPlus);

app.mount('#app');
<!-- App.vue -->
<template>
  <el-config-provider :locale="message">
    <RouterView />
  </el-config-provider>
</template>

<script setup lang="ts">
import elementPlusZhCN from 'element-plus/es/locale/lang/zh-cn';
import elementPlusEnUS from 'element-plus/es/locale/lang/en';
import { useI18n } from 'vue-i18n';
const { locale } = useI18n();

// 语言编码与生成的地区语言代码对应
const messages: any = {
  'zh-CN': elementPlusZhCN,
  'en-US': elementPlusEnUS,
};
const message = computed(() => messages[locale.value]);
</script>

示例

test.vue

<template title="用户设置">
  <div class="user-form">
    <!-- 纯文本节点 -->
    请填写以下用户信息

    <!-- 元素内中文(短文本 / 长文本→哈希Key / 中英混合) -->
    <p>基本信息</p>
    <p>名称长度需在7~13个字符之间</p>
    <p>机身号、项目名称 or 设备名称</p>

    <!-- 中文与模板语法混合(前缀 + 三元内嵌中文 + 后缀) -->
    <p>开始{{ isAutoMode ? '篮球' : '乒乓球' }}比赛</p>

    <!-- 静态属性(多属性 + Common短语匹配) -->
    <el-form-item label="持卡人" placeholder="请输入"></el-form-item>
    <el-date-picker start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>

    <!-- 动态属性(三元 / 字符串拼接 / 逻辑或+三元) -->
    <el-form-item :label="isAutoMode ? '地球' : '月球'"></el-form-item>
    <el-form-item :label="'检查项' + ' (' + userRole.length + ')'"></el-form-item>
    <el-form-item :label="isAutoMode || useContactPerson ? '设备号' : '机身号'"></el-form-item>

    <!-- 模板字符串(单变量 / 三元插槽 / 多插槽+嵌套三元) -->
    <p>{{ `测试共${charLimit}个字符 ` }}</p>
    <p>{{ `${isAutoMode ? '自动' : '手动'}:` }}</p>
    <p>{{ `您确定要删除${isAutoMode ? '自动清洗' : '手动清洗'}路线${isAutoMode ? '图片' : '定位'}吗?` }}</p>

    <!-- 动态属性中的模板字符串(单变量 / 三元插槽) -->
    <el-form-item :label="`${userRole}姓名`"></el-form-item>
    <el-form-item :label="`${isPhoneMode ? '手机号码' : '电话号码'}:`"></el-form-item>

    <!-- 深层嵌套 -->
    <div class="wrapper">
      <div class="inner">
        <span>嵌套层级中的提示信息</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      charLimit: 10,
      userRole: '管理员',
      isAutoMode: true,
      isPhoneMode: true,
      useContactPerson: true,
      currentDay: '星期一',
    };
  },
  computed: {
    // 计算属性中的模板字符串
    roleDisplayName() {
      return `当前${this.userRole}用户`;
    },
  },
  mounted() {
    // 生命周期钩子:debug 日志 + Common 短语匹配
    console.log('组件加载完成');
    this.$message('保存成功');
  },
  methods: {
    // 单行注释 + debug 日志 + 字符串替换(中文 / 纯英文 / 中英混合)
    handleStringReplacement() {
      console.log('这是一条调试日志');
      console.error('数据拉取失败');
      const accountInfo = '账户信息';
      const englishOnly = 'welcome';
      const mixedText = '聚会时间';
    },
    /*
     * 多行注释中的中文不影响替换
     * 含中文的业务说明文字
     */
    handleTemplateLiteral() {
      const contactText = `联系${this.useContactPerson ? '张三' : '李四'}`;
      const accountText = `这是(${this.userRole})的账户`;
      const greetingText = `${this.currentDay},${this.userRole}先生`;
      const confirmMsg = `统计:排行榜总计 ${Object.keys(obj).length} 条,本次新增 ${addCount} 条,删除 ${delCount} 条。`;
      this.$confirm(confirmMsg, () => {});
    },
    // 条件分支中的中文
    handleConditionalMessage() {
      if (this.isAutoMode) {
        this.$message('自动保存成功');
      } else {
        this.$message('手动保存成功');
      }
    },
  },
};
</script>

执行结果

<template>
  <div class="user-form">
    <!-- 纯文本节点 -->
    {{ $t('test.qtxyxyhxx') }}

    <!-- 元素内中文(短文本 / 长文本→哈希Key / 中英混合) -->
    <p>{{ $t('test.ji_ben_xin_xi') }}</p>
    <p>{{ $t('test.mccdxz713gzfzj') }}</p>
    <p>{{ $t('test.jshxmmcorsbmc') }}</p>

    <!-- 中文与模板语法混合(前缀 + 三元内嵌中文 + 后缀) -->
    <p>{{ $t('test.kai_shi') }}{{ isAutoMode ? $t('test.lan_qiu') : $t('test.ping_pang_qiu') }}{{ $t('test.bi_sai') }}</p>

    <!-- 静态属性(多属性 + Common短语匹配) -->
    <el-form-item :label="$t('test.chi_ka_ren')" :placeholder="$t('test.qing_shu_ru')"></el-form-item>
    <el-date-picker :start-placeholder="$t('test.kai_shi_ri_qi')" :end-placeholder="$t('test.jie_shu_ri_qi')"></el-date-picker>

    <!-- 动态属性(三元 / 字符串拼接 / 逻辑或+三元) -->
    <el-form-item :label="isAutoMode ? $t('test.di_qiu') : $t('test.yue_qiu')"></el-form-item>
    <el-form-item :label="$t('test.jian_cha_xiang') + ' (' + userRole.length + ')'"></el-form-item>
    <el-form-item :label="isAutoMode || useContactPerson ? $t('test.she_bei_hao') : $t('test.ji_shen_hao')"></el-form-item>

    <!-- 模板字符串(单变量 / 三元插槽 / 多插槽+嵌套三元) -->
    <p>{{ $t('test.csg$0gzf', [charLimit]) }}</p>
    <p>{{ $t('test.$0', [isAutoMode ? $t('test.zi_dong') : $t('test.shou_dong')]) }}</p>
    <p>{{ $t('test.nqdysc$0lx$1m', [isAutoMode ? $t('test.zi_dong_qing_xi') : $t('test.shou_dong_qing_xi'),isAutoMode ? $t('test.tu_pian') : $t('test.ding_wei')]) }}</p>

    <!-- 动态属性中的模板字符串(单变量 / 三元插槽) -->
    <el-form-item :label="$t('test.$0xing_ming', [userRole])"></el-form-item>
    <el-form-item :label="$t('test.$0', [isPhoneMode ? $t('test.shou_ji_hao_ma') : $t('test.dian_hua_hao_ma')])"></el-form-item>

    <!-- 深层嵌套 -->
    <div class="wrapper">
      <div class="inner">
        <span>{{ $t('test.qtcjzdtsxx') }}</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      charLimit: 10,
      userRole: this.$t('test.guan_li_yuan'),
      isAutoMode: true,
      isPhoneMode: true,
      useContactPerson: true,
      currentDay: this.$t('test.xing_qi_yi'),
    };
  },
  computed: {
    // 计算属性中的模板字符串
    roleDisplayName() {
      return this.$t('test.dang_qian$0yong_hu', [this.userRole]);
    },
  },
  mounted() {
    // 生命周期钩子:debug 日志 + Common 短语匹配
    console.log('组件加载完成');
    this.$message(this.$t('Common.com_save_success'));
  },
  methods: {
    // 单行注释 + debug 日志 + 字符串替换(中文 / 纯英文 / 中英混合)
    handleStringReplacement() {
      console.log('这是一条调试日志');
      console.error('数据拉取失败');
      const accountInfo = this.$t('test.zhang_hu_xin_xi');
      const englishOnly = 'welcome';
      const mixedText = this.$t('test.ju_hui_shi_jian');
    },
    /*
     * 多行注释中的中文不影响替换
     * 含中文的业务说明文字
     */
    handleTemplateLiteral() {
      const contactText = this.$t('test.lian_xi$0', [this.useContactPerson ? this.$t('test.zhang_san') : this.$t('test.li_si')]);
      const accountText = this.$t('test.zhe_shi$0de_zhang_hu', [this.userRole]);
      const greetingText = this.$t('test.$0$1xian_sheng', [this.currentDay,this.userRole]);
      const confirmMsg = this.$t('test.tjpxbzj$0t_a194f468', [Object.keys(obj).length,addCount,delCount]);
      this.$confirm(confirmMsg, () => {});
    },
    // 条件分支中的中文
    handleConditionalMessage() {
      if (this.isAutoMode) {
        this.$message(this.$t('test.zdbccg'));
      } else {
        this.$message(this.$t('test.sdbccg'));
      }
    },
  },
};
</script>

翻译文件 (locales/locale.json)

{
  "Common": {
    "com_yes": "是",
    "com_no": "否",
    "com_save_success": "保存成功",
    "com_copy_success": "复制成功"
  },
  "test": {
    "__filePath": "/test.vue",
    "__title": "用户设置",
    "dang_qian$0yong_hu": "当前{0}用户",
    "zhang_san": "张三",
    "li_si": "李四",
    "lian_xi$0": "联系{0}",
    "zhe_shi$0de_zhang_hu": "这是({0})的账户",
    "$0$1xian_sheng": "{0},{1}先生",
    "tjpxbzj$0t_a194f468": "统计:排行榜总计 {0} 条,本次新增 {1} 条,删除 {2} 条。",
    "guan_li_yuan": "管理员",
    "xing_qi_yi": "星期一",
    "zhang_hu_xin_xi": "账户信息",
    "ju_hui_shi_jian": "聚会时间",
    "zdbccg": "自动保存成功",
    "sdbccg": "手动保存成功",
    "csg$0gzf": "测试共{0}个字符 ",
    "zi_dong": "自动",
    "shou_dong": "手动",
    "$0": "{0}:",
    "zi_dong_qing_xi": "自动清洗",
    "shou_dong_qing_xi": "手动清洗",
    "tu_pian": "图片",
    "ding_wei": "定位",
    "nqdysc$0lx$1m": "您确定要删除{0}路线{1}吗?",
    "$0xing_ming": "{0}姓名",
    "shou_ji_hao_ma": "手机号码",
    "dian_hua_hao_ma": "电话号码",
    "qtxyxyhxx": "请填写以下用户信息",
    "ji_ben_xin_xi": "基本信息",
    "mccdxz713gzfzj": "名称长度需在7~13个字符之间",
    "jshxmmcorsbmc": "机身号、项目名称 or 设备名称",
    "kai_shi": "开始",
    "bi_sai": "比赛",
    "lan_qiu": "篮球",
    "ping_pang_qiu": "乒乓球",
    "chi_ka_ren": "持卡人",
    "qing_shu_ru": "请输入",
    "kai_shi_ri_qi": "开始日期",
    "jie_shu_ri_qi": "结束日期",
    "di_qiu": "地球",
    "yue_qiu": "月球",
    "jian_cha_xiang": "检查项",
    "she_bei_hao": "设备号",
    "ji_shen_hao": "机身号",
    "qtcjzdtsxx": "嵌套层级中的提示信息"
  }
}

CHANGELOG.md

## v2.0.2

- feat: 新增 `-m, --key-mode` 参数,支持 pinyin / pinyin-hash / hash 三种 Key 生成模式
- feat: 自动检测 `<script setup>`,Vue 3 Options API 模板自动使用 `$t` 前缀
- change: 模板占位符 `{0}` `{1}` 保留为 `$0` `$1`,不再替换为固定字符 `o`
- change: Key 生成保留 `$` 符号,并自动去除开头的数字(Key 不应以数字开头)
- change: 移除生成的通用多语言 `Common` 中时间戳 `__timestamp` 字段
- fix: 修复 `console.log/error/warn` 正则无法匹配嵌套括号的问题
- fix: 修复行首单行注释未被保护的 bug
- fix: 修复不同中文生成相同 Key 的碰撞问题(需使用 `--key-mode pinyin-hash`)
- fix: 修复部分 bug

## v1.0.0

- change: 新增`index.js`文件,并将语言代码文件移至`lang`文件夹中
- change: 移除内置的公共多语言,不再提供默认公共多语言
- fix: 修复部分 bug

## v0.5.1

- fix: 提升百度翻译每次请求效率,批量请求翻译
- fix: 新增有道翻译,谷歌翻译(需要科学上网)
- fix: 修复对新增数据翻译时旧翻译被覆盖问题
- fix: 修复部分 bug