vue-i18n-generator
v0.5.4
Published
Vue-i18n 国际化生成器,提取项目中的”中文“替换为多语言`$t(key)`,并导出翻译文件。
Downloads
202
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...> 需要生成的地区语言代码,如 zh-ch zh-tw en
-t, --translate <value...> 需要翻译的地区语言代码,对应--locales参数
-c, --channel <value> 翻译渠道 baidu百度,youdao有道,google谷歌
--appKey <value> 翻译api应用key
--secretKey <value> 翻译api密钥
--v2 <value> 是否为Vue2版本, 默认为Vue3版本env参数详解:- dev 仅导出翻译文件。
- test 导出翻译文件同时生成编译对照文件(
.lang结尾的新文件)。 - prod 不导出翻译文件,直接将翻译
key替换原文件,用于生产打包部署前命令。
备注:
- 谷歌翻译无需
appKey、secretKey参数,百度翻译和有道翻译则必传。 - 只对新增
key翻译,重新翻译可删除locale.json中对应的key后重新执行命令。 - 在
test环境生成的文件后缀前加.lang的新文件,可通过执行dev/prod删除。 - 生成的翻译
key为文件名.[处理过的拼音 <= 20],需注意中文修改后key将会改变。 - 添加自定义
公共多语言(根目录创建translator.json),适用于项目高频率出现的中文。
- 谷歌翻译无需
注意事项:
defineProps和defineEmits的选项中不能使用t方法,故在它们选项中不能使用中文块,我们可引入全局i18n实例,然后使用实例的i18n.global.t方法来解决。因为它们会从setup中提升到模块的作用域,因此传入的选项不能引用在setup作用域中声明的局部变量,这样会引起编译报错,具体可查看官方文档。
基本使用
# 帮助文档
translator --help
# 开发环境:提取中文并生成翻译文件
translator dev -d src -o src/locales -l zh-cn zh-tw en --v2
# 测试环境:额外生成对照文件(.lang后缀)
translator test -d src -o src/locales -l zh-cn zh-tw en --v2
# 生产环境:直接替换原文件
translator prod集成到package.json中使用
{
"scripts": {
"i18n:dev": "translator dev -o src/locales -l zh-cn en -t en --channel baidu --appKey YOUR_KEY --secretKey YOUR_SECRET",
"i18n:test": "translator test -o src/locales -l zh-cn en --v2",
"i18n:prod": "translator prod"
}
}示例
test.vue
<template title="附加信息">
<div class="container">
<!-- 基础字符串 -->
字符串
<p>基础</p>
<p>新增成功</p>
<p>长度要在7~13个字符</p>
<p>机身号、项目名称or设备名称</p>
<p>十大经典排序{{ title }}</p>
<p>开始{{ isAuto ? '篮球' : '兵乒球' }}比赛</p>
<el-form-item label="持卡人" placeholder="'请输入'"></el-form-item>
<el-form-item label="会员号"></el-form-item>
<el-form-item :label="isAuto ? '地球' : '月球'"></el-form-item>
<el-form-item :label="isAuto || isContact ? '设备号' : '机身号'"></el-form-item>
<el-form-item :label="'检查项' + ' (' + title.length + ')'"></el-form-item>
<el-date-picker start-placeholder="开始日" end-placeholder="结束日"></el-date-picker>
<!-- 模板字符串 -->
<p>{{ `test_${max}个字符 ` }}</p>
<p>{{ `长度最长${max}个字符 ` }}</p>
<p>{{ `${isAuto ? '自动' : '手动'}:` }}</p>
<p>{{ `您确定要删除${isAuto ? '自动清洗' : '手动清洗'}路线${isAuto ? '图片' : '定位'}吗?` }}</p>
<el-form-item :label="`${title}姓名`"></el-form-item>
<el-form-item :label="`${isMobile ? '手机号码' : '电话号码'}:`"></el-form-item>
<el-form-item :label="`确认${isContact ? '联系人' : '负责人'}:`"></el-form-item>
</div>
</template>
<script>
export default {
data() {
return {
max: 10,
title: '测试',
isAuto: true,
isMobile: true,
isContact: true,
timeDay: '星期一',
};
},
methods: {
// 这是一条单行注释
handle: function () {
console.log('这是一条debug日志');
const t1 = '转账信息';
const t2 = 'welcome';
const t3 = 'pary时间';
const t4 = '信息';
},
/*
多行注释注释第一行
多行注释注释第二行
*/
handle: function () {
const t1 = `联系${this.isContact ? '李二' : '林三'}`;
const t2 = `这是(${this.title})的账号`;
const t3 = `${this.timeDay},${this.title}先生`;
this.$confirm(`统计:- 排行榜,总计 ${Object.keys(obj).length} 条,本次新增 ${addCount} 条、删除 ${delCount} 条。`, () => {});
},
},
};
</script>执行结果
<template>
<div class="container">
<!-- 基础字符串 -->
{{ $t('test.zi_fu_chuan') }}
<p>{{ $t('test.ji_chu') }}</p>
<p>{{ $t('Common.com_add_success') }}</p>
<p>{{ $t('test.cdyz713gzf') }}</p>
<p>{{ $t('test.jshxmmcorsbmc') }}</p>
<p>{{ $t('test.sdjdpx') }}{{ title }}</p>
<p>{{ $t('test.kai_shi') }}{{ isAuto ? $t('test.lan_qiu') : $t('test.bing_ping_qiu') }}{{ $t('test.bi_sai') }}</p>
<el-form-item :label="$t('test.chi_ka_ren')" :placeholder="$t('Common.com_please_input')"></el-form-item>
<el-form-item :label="$t('test.hui_yuan_hao')"></el-form-item>
<el-form-item :label="isAuto ? $t('test.di_qiu') : $t('test.yue_qiu')"></el-form-item>
<el-form-item :label="isAuto || isContact ? $t('test.she_bei_hao') : $t('test.ji_shen_hao')"></el-form-item>
<el-form-item :label="$t('test.jian_cha_xiang') + ' (' + title.length + ')'"></el-form-item>
<el-date-picker :start-placeholder="$t('test.kai_shi_ri')" :end-placeholder="$t('test.jie_shu_ri')"></el-date-picker>
<!-- 模板字符串 -->
<p>{{ $t('test.test_oge_zi_fu', [max]) }}</p>
<p>{{ $t('test.cdzcogzf', [max]) }}</p>
<p>{{ $t('test.o', [isAuto ? $t('test.zi_dong') : $t('test.shou_dong')]) }}</p>
<p>{{ $t('test.nqdyscolxom', [isAuto ? $t('test.zi_dong_qing_xi') : $t('test.shou_dong_qing_xi'), isAuto ? $t('test.tu_pian') : $t('test.ding_wei')]) }}</p>
<el-form-item :label="$t('test.oxing_ming', [title])"></el-form-item>
<el-form-item :label="$t('test.o', [isMobile ? $t('test.shou_ji_hao_ma') : $t('test.dian_hua_hao_ma')])"></el-form-item>
<el-form-item :label="$t('test.que_reno', [isContact ? $t('test.lian_xi_ren') : $t('test.fu_ze_ren')])"></el-form-item>
</div>
</template>
<script>
export default {
data() {
return {
max: 10,
title: this.$t('test.ce_shi'),
isAuto: true,
isMobile: true,
isContact: true,
timeDay: this.$t('test.xing_qi_yi'),
};
},
methods: {
// 这是一条单行注释
handle: function () {
console.log('这是一条debug日志');
const t1 = this.$t('test.zhuan_zhang_xin_xi');
const t2 = 'welcome';
const t3 = this.$t('test.paryshi_jian');
const t4 = this.$t('test.xin_xi');
},
/*
多行注释注释第一行
多行注释注释第二行
*/
handle: function () {
const t1 = this.$t('test.lian_xio', [this.isContact ? this.$t('test.li_er') : this.$t('test.lin_san')]);
const t2 = this.$t('test.zhe_shiode_zhang_hao', [this.title]);
const t3 = this.$t('test.ooxian_sheng', [this.timeDay, this.title]);
this.$confirm(this.$t('test.tjpxbzjotbcxzotscot', [Object.keys(obj).length, addCount, delCount]), () => {});
},
},
};
</script>翻译文件 (locales/locale.json)
{
"test": {
"__filePath": "/test.vue",
"__title": "附加信息",
"li_er": "李二",
"lin_san": "林三",
"lian_xio": "联系{0}",
"zhe_shiode_zhang_hao": "这是({0})的账号",
"ooxian_sheng": "{0},{1}先生",
"tjpxbzjotbcxzotscot": "统计:- 排行榜,总计 {0} 条,本次新增 {1} 条、删除 {2} 条。",
"ce_shi": "测试",
"xing_qi_yi": "星期一",
"zhuan_zhang_xin_xi": "转账信息",
"paryshi_jian": "pary时间",
"xin_xi": "信息",
"test_oge_zi_fu": "test_{0}个字符 ",
"cdzcogzf": "长度最长{0}个字符 ",
"zi_dong": "自动",
"shou_dong": "手动",
"o": "{0}:",
"zi_dong_qing_xi": "自动清洗",
"shou_dong_qing_xi": "手动清洗",
"tu_pian": "图片",
"ding_wei": "定位",
"nqdyscolxom": "您确定要删除{0}路线{1}吗?",
"oxing_ming": "{0}姓名",
"shou_ji_hao_ma": "手机号码",
"dian_hua_hao_ma": "电话号码",
"lian_xi_ren": "联系人",
"fu_ze_ren": "负责人",
"que_reno": "确认{0}:",
"zi_fu_chuan": "字符串",
"ji_chu": "基础",
"cdyz713gzf": "长度要在7~13个字符",
"jshxmmcorsbmc": "机身号、项目名称or设备名称",
"sdjdpx": "十大经典排序",
"kai_shi": "开始",
"bi_sai": "比赛",
"lan_qiu": "篮球",
"bing_ping_qiu": "兵乒球",
"chi_ka_ren": "持卡人",
"hui_yuan_hao": "会员号",
"di_qiu": "地球",
"yue_qiu": "月球",
"she_bei_hao": "设备号",
"ji_shen_hao": "机身号",
"jian_cha_xiang": "检查项",
"kai_shi_ri": "开始日",
"jie_shu_ri": "结束日"
}
}项目中使用
import { createI18n } from 'vue-i18n';
// 本地语言包
import localeZhCn from '@/locales/locale.json';
import localeEnUs from '@/locales/en-us.json';
import localeZhTw from '@/locales/zh-tw.json';
export const i18n = createI18n({
legacy: false,
globalInjection: true, // 全局生效,可直接使用$t
missing: () => ' ', // 缺省值
locale: sessionStorage.getItem('locale'), // 当前语种
messages: {
'zh-cn': localeZhCn,
'zh-tw': localeZhTw,
'en-us': localeEnUs,
},
});main.ts
// ...
app.use(i18n);CHANGELOG.md
## v0.2.0
- fix: vue3 中自动检测`useI18n`和`t`方法导入情况,未导入则添加导入
## v0.2.1
- fix: 排除对`console.log`中的中文翻译
## v0.3.3
- fix: 保留模板中的中文代码注释和日志输出
- fix: 优化模板字符串(\`)匹配情况
- fix: 修复部分 bug
## v0.5.1
- fix: 提升百度翻译每次请求效率,批量请求翻译
- fix: 新增有道翻译,谷歌翻译(需要科学上网)
- fix: 修复对新增数据翻译时旧翻译被覆盖问题
- fix: 修复部分 bug
## v0.5.3
- fix: 排除对`console.warn`、`console.error`中的中文翻译
## Future
- fix: 文件名相同覆盖问题,页面都用 index.vue 命名 ? ?
- fix: 引用图片等资源路径包含中文 ??