0.9.5-beta • Published 17 days ago

translate-compiler v0.9.5-beta

Weekly downloads
-
License
ISC
Repository
-
Last release
17 days ago

translate-compiler

介绍

Vue 国际化 i18n 编译器,自动提取项目(.vue)文件中的”中文“并替换为多语言($t(key)),并导出全部翻译到指定文件。

安装

npm install translate-compiler --save-dev [-g]

命令行参数

translate <env>  options

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

Options:
  -d, --dir <dir>            翻译的文件夹
  -l, --locals <value...>    需要生成的地区语言,参考下方常见语种列表
  -t, --translate <value...> 需要翻译的语言,对应locals语种代码
  -c, --channel <value>      翻译渠道 baidu百度,youdao有道
  --appKey <value>           翻译api 应用key
  --secretKey <value>        翻译api 密钥
  -s, --suffix <value>       翻译的文件名后缀,默认:.vue
  -e, --excludes <value...>  排除翻译的文件,可指定多个
  -o, --output <file>        翻译输出文件写入的文件(夹)路径,默认:locals/local.js
  --strict                   是否严格模式, 严格模式只提取$t()内中文,否则提取全局
  • env参数详解:

    • dev 仅仅导出翻译文件。
    • test 为每个翻译文件生成后缀前加.lang的新文件,以便查看翻译后对照,并导出翻译文件。
    • prod 翻译 key 直接替换原文件,用于生产打包部署前命令,并导出翻译文件。
  • 自动翻译:

    • 设置了channelappKeysecretKeytranslate(locals参数含有该语言 key),才会执行翻译,默认填充中文。
    • 原翻译文件存在的 key 不会再做翻译,如需翻译可以删改该 key 或直接删除翻译文件重新生成。
  • 其他备注:

    • test生成的文件后缀前加.lang的新文件,如需删除可执行 dev/prod
    • 指定locals参数将在输出output文件(夹)的同时也会输出对应语种的文件,如en
    • output支持输出到文件或文件夹,文件支持.js.json格式,指定文件夹则默认文件名为local.js
    • 指定locals生成的语种文件中已做过翻译时,新生成的翻译不会覆盖原有已经翻译过的 key,output指定的文件则会覆盖。
    • 生成的翻译 key 默认为文件名_[处理过的中文拼音],长度 < 50,中文修改后 key 会改变,这点需要注意

常见语种列表

名称百度翻译代码有道翻译代码(Element Plus)本项目中使用
简体中文zhzh-CHSzh-cnzh
英语enenenen
繁体中文chtzh-CHTzh-twzh-tw
日语jpjajaja
韩语korkokoko
德语dededede
法语frafrfrfr

自定义翻译字典

在根目录创建translate.json文件,添加自定义翻译对照,内包含的中文则会使用指定的 key 作为键,适用于项目高频率出现的中文,防止生成过多重复多语言(不同文件相同中文会生成不同的 key),如下:

{
  "com_yes": "是",
  "com_no": "否",
  "com_success": "成功",
  "com_fail": "失败",
  "com_enable": "启用",
  "com_disable": "禁用",
  "com_confirm": "确定",
  "com_cancel": "取消",
  "com_add": "新增",
  "com_edit": "编辑",
  "com_modify": "修改",
  "com_delete": "删除",
  "com_save": "保存",
  "com_handle": "操作",
  "com_add_success": "新增成功",
  "com_edit_success": "编辑成功",
  "com_modify_success": "修改成功",
  "com_delete_success": "删除成功",
  "com_save_success": "保存成功",
  "com_handle_success": "操作成功",
  "com_query": "查询",
  "com_close": "关闭",
  "com_reset": "重置",
  "com_back": "返回",
  "com_reminder": "提示",
  "com_copy": "拷贝",
  "com_export": "导出",
  "com_detail": "查看",
  "com_details": "详情",
  "com_lookup": "查找",
  "com_set": "设置",
  "com_all": "全部",
  "com_sel_all": "全选",
  "com_clear": "清空",
  "com_finish": "完成",
  "com_no_data": "暂无数据",
  "com_more_action": "更多操作",
  "com_please_select": "请选择",
  "com_please_input": "请输入",
  "com_required": "必填项",
  "com_prev_step": "上一步",
  "com_next_step": "上一步",
  "com_rules_length_max": "长度最长{0}个字符",
  "com_rules_length_range": "长度在{0}到{1}个字符"
}

执行翻译

全局安装
  • 帮助文档
translate --help
  • 执行翻译
translate dev --dir src --excludes app.vue -o locals/local.json -l en cn --strict
本地安装
  • package.json中添加
  "scripts": {
    "translate": "translate dev --dir src",
    "translate:test": "translate test --dir src -l cn en --strict",
    "translate:prod": "translate prod --dir src -l cn en"
  },

示例

test.vue

<template>
  <div>
    <!-- 严格模式 -->
    <div>
      <p>{{ $t("使用") }}</p>
      <p>{{ isOk ? $t("确定") : $t("取消") }}</p>
      <p>{{ $t("清洁时长(min)") }}</p>
      <p>{{ $t("密码8-16位,必须包含数字、符号、字母任意两种") }}</p>
    </div>
    <div>
      <el-form-item :label="$t('用户名')"></el-form-item>
      <el-input :placeholder="$t('请输入')"></el-input>
    </div>
    <div>
      <p>{{ $t(`最多上传${limit}个文件`) }}</p>
      <p>{{ $t(`最多上传${limit ? "0" : "1个"}个文件`) }}</p>
      <p>{{ $t(`您确定要删除${user}的${num}个文件吗?`) }}</p>
      <el-form-item :label="$t(`${platform}账号:`)"></el-form-item>
      <el-form-item
        :label="$t(`${platform ? '谷歌' : '微信'}账号:`)"
      ></el-form-item>
    </div>

    <!-- 非严格模式 -->
    <div>
      <p>基础信息</p>
      <p>新增成功</p>
      <p>长度要在7~13个字符</p>
      <p>机身号、项目名称or设备名称</p>
      <p>测试文本{{ userName }}</p>
      <p>开始{{ isOk ? "篮球" : "兵乒球" }}比赛</p>
    </div>
    <div>
      <el-form-item label="持卡人"></el-form-item>
      <el-input per-label="权限" placeholder="请输入"></el-input>
    </div>
    <div>
      <p>{{ "使用记录" }}</p>
      <p>{{ isOk ? "使用记录" : "历史记录" }}</p>
      <p>{{ isOk ? "开始" : `结束` }}</p>
      <p>{{ `员工姓名` }}</p>
      <p>{{ `长度最长${max}个字符` }}</p>
      <p>{{ `确定要删除${type ? "自动清洗" : "手动清洗"}路线吗` }}</p>
      <p>{{ `您确定要选择${type}路线${state}吗` }}</p>
      <el-form-item :label="`${area}负责人`"></el-form-item>
    </div>
  </div>
</template>

<script>
export default {
  computed: {
    weekday() {
      return this.$t("星期日");
    },
    timeDay() {
      return "早上好";
    },
  },
  methods: {
    onTable: function () {
      const test11 = this.$t("初始日期");
      const test22 = this.$t("kpi结束时间");
      const test33 = this.$t(`kpi结束${this.label}`);
      const test44 = this.$t(`标签名称${this.label == "today" ? "王" : "二"}`);
    },
    onExport: function () {
      const t1 = "转账信息";
      const t2 = "pary时间";
      const t3 = `标签名称${this.timeDay == "today" ? "李" : "林"}`;
      const t4 = `这是(${this.user})的账号`;
      const t5 = `${this.timeDay},${this.user}先生`;
    },
  },
};
</script>

执行结果

<template>
  <div>
    <div>
      <p>{{ $t("test_shi_yong") }}</p>
      <p>{{ isOk ? $t("com_confirm") : $t("com_cancel") }}</p>
      <p>{{ $t("test_qjscmin") }}</p>
      <p>{{ $t("test_mm816wbxbhszfhzmrylz") }}</p>
    </div>
    <div>
      <el-form-item :label="$t('test_yong_hu_ming')"></el-form-item>
      <el-input :placeholder="$t('com_please_input')"></el-input>
    </div>
    <div>
      <p>{{ $t("test_zdscogwj", [limit]) }}</p>
      <p>{{ $t("test_zdscogwj", [limit ? "0" : $t("test_1ge")]) }}</p>
      <p>{{ $t("test_nqdyscodogwjm", [user, num]) }}</p>
      <el-form-item :label="$t('test_ozhang_hao', [platform])"></el-form-item>
      <el-form-item
        :label="
          $t('test_ozhang_hao', [
            platform ? $t('test_gu_ge') : $t('test_wei_xin'),
          ])
        "
      ></el-form-item>
    </div>

    <div>
      <p>{{ $t("test_ji_chu_xin_xi") }}</p>
      <p>{{ $t("com_add_success") }}</p>
      <p>{{ $t("test_cdyz713gzf") }}</p>
      <p>{{ $t("test_jshxmmcorsbmc") }}</p>
      <p>{{ $t("test_ce_shi_wen_ben") }}{{ userName }}</p>
      <p>
        {{ $t("test_kai_shi")
        }}{{ isOk ? $t("test_lan_qiu") : $t("test_bing_ping_qiu")
        }}{{ $t("test_bi_sai") }}
      </p>
    </div>
    <div>
      <el-form-item :label="$t('test_chi_ka_ren')"></el-form-item>
      <el-input
        :per-label="$t('test_quan_xian')"
        :placeholder="$t('com_please_input')"
      ></el-input>
    </div>
    <div>
      <p>{{ $t("test_shi_yong_ji_lu") }}</p>
      <p>{{ isOk ? $t("test_shi_yong_ji_lu") : $t("test_li_shi_ji_lu") }}</p>
      <p>{{ isOk ? $t("test_kai_shi") : $t("test_jie_shu") }}</p>
      <p>{{ $t("test_yuan_gong_xing_ming") }}</p>
      <p>{{ $t("com_rules_length_max", [max]) }}</p>
      <p>
        {{
          $t("test_qdyscolxm", [
            type ? $t("test_zi_dong_qing_xi") : $t("test_shou_dong_qing_xi"),
          ])
        }}
      </p>
      <p>{{ $t("test_nqdyxzolxom", [type, state]) }}</p>
      <el-form-item :label="$t('test_ofu_ze_ren', [area])"></el-form-item>
    </div>
  </div>
</template>

<script>
export default {
  computed: {
    weekday() {
      return this.$t("test_xing_qi_ri");
    },
    timeDay() {
      return this.$t("test_zao_shang_hao");
    },
  },
  methods: {
    onTable: function () {
      const test11 = this.$t("test_chu_shi_ri_qi");
      const test22 = this.$t("test_kpijie_shu_shi_jian");
      const test33 = this.$t("test_kpijie_shuo", [this.label]);
      const test44 = this.$t("test_bqmco", [
        this.label == "today" ? this.$t("test_wang") : this.$t("test_er"),
      ]);
    },
    onExport: function () {
      const t1 = this.$t("test_zhuan_zhang_xin_xi");
      const t2 = this.$t("test_paryshi_jian");
      const t3 = this.$t("test_bqmco", [
        this.timeDay == "today" ? this.$t("test_li") : this.$t("test_lin"),
      ]);
      const t4 = this.$t("test_zhe_shiode_zhang_hao", [this.user]);
      const t5 = this.$t("test_ooxian_sheng", [this.timeDay, this.user]);
    },
  },
};
</script>

翻译文件 (locals./local.js)

exports.__esModule = true;
exports.default = {
  "test_shi_yong": "使用",
  "com_confirm": "确定",
  "com_cancel": "取消",
  "test_qjscmin": "清洁时长(min)",
  "test_mm816wbxbhszfhzmrylz": "密码8-16位,必须包含数字、符号、字母任意两种",
  "test_yong_hu_ming": "用户名",
  "com_please_input": "请输入",
  "test_xing_qi_ri": "星期日",
  "test_chu_shi_ri_qi": "初始日期",
  "test_kpijie_shu_shi_jian": "kpi结束时间",
  "test_zdscogwj": "最多上传{0}个文件",
  "test_1ge": "1个",
  "test_nqdyscodogwjm": "您确定要删除{0}的{1}个文件吗?",
  "test_ozhang_hao": "{0}账号:",
  "test_gu_ge": "谷歌",
  "test_wei_xin": "微信",
  "test_jie_shu": "结束",
  "test_yuan_gong_xing_ming": "员工姓名",
  "test_zi_dong_qing_xi": "自动清洗",
  "test_shou_dong_qing_xi": "手动清洗",
  "test_qdyscolxm": "确定要删除{0}路线吗",
  "test_nqdyxzolxom": "您确定要选择{0}路线{1}吗",
  "test_ofu_ze_ren": "{0}负责人",
  "test_ji_chu_xin_xi": "基础信息",
  "com_add_success": "新增成功",
  "test_cdyz713gzf": "长度要在7~13个字符",
  "test_jshxmmcorsbmc": "机身号、项目名称or设备名称",
  "test_ce_shi_wen_ben": "测试文本",
  "test_kai_shi": "开始",
  "test_bi_sai": "比赛",
  "test_lan_qiu": "篮球",
  "test_bing_ping_qiu": "兵乒球",
  "test_shi_yong_ji_lu": "使用记录",
  "test_li_shi_ji_lu": "历史记录",
  "test_chi_ka_ren": "持卡人",
  "test_quan_xian": "权限",
  "test_kpijie_shuo": "kpi结束{0}",
  "test_wang": "王",
  "test_er": "二",
  "test_bqmco": "标签名称{0}",
  "test_li": "李",
  "test_lin": "林",
  "test_zhe_shiode_zhang_hao": "这是({0})的账号",
  "test_ooxian_sheng": "{0},{1}先生",
  "test_zao_shang_hao": "早上好",
  "test_zhuan_zhang_xin_xi": "转账信息",
  "test_paryshi_jian": "pary时间"
}

项目中使用

import zhLocale from './locals/zh';
import enLocale from './locals/en';
import jaLocale from './locals/ja';

// ...
Vue.use(VueI18n);

const i18n = new VueI18n({
  locale: 'CN',
  silentTranslationWarn: true,
  messages: {
    ZH: { ...elementZhLocale, ...zhLocale },
    EN: { ...elementEnLocale, ...enLocale },
    JA: { ...elementJaLocale, ...jaLocale },
  },
});

// ...

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

多语言切换

// 方案一:本地切换,对接口层含翻译的(字典,表格列等)做统一事件触发更新
this.$i18n.locale = item.value;

// 方案二:页面强制刷新,适用于有较多接口层翻译的情况
Cookies.set('langCode', item.value, { path: '/' }); // VueI18n初始化取的地方
this.$router.go(0); //强制刷新
0.8.5-beta

18 days ago

0.9.2-beta

18 days ago

0.8.2-beta

19 days ago

0.9.5-beta

17 days ago

0.8.8-beta

18 days ago

0.8.6-beta

18 days ago

0.9.0-beta

18 days ago

0.9.3-beta

18 days ago

0.8.3-beta

19 days ago

0.8.7-beta

18 days ago

0.9.4-beta

17 days ago

0.9.1-beta

18 days ago

0.2.6-beta

21 days ago

0.8.1-beta

19 days ago

0.8.0-beta

19 days ago

0.7.0-beta

19 days ago

0.6.0-beta

19 days ago

0.2.5-beta

21 days ago

0.2.4-beta

22 days ago

0.2.3-beta

22 days ago

0.2.2-beta

22 days ago

0.2.1-beta

22 days ago

0.2.0-beta

22 days ago

0.1.1-beta

23 days ago

0.1.0-beta

23 days ago

0.1.0

23 days ago

0.0.1-beta.2

23 days ago

0.0.1-beta.1

23 days ago