vue i18n-collect工具開發

goblin_pitcher發表於2022-05-15
專案地址https://github.com/goblin-pitcher/i18n-collector
老專案引入i18n國際化後,需要對專案中所有中文包裹$t('中文')方法,物件不同,包裹的方法也有差異:
  1. vuetemplate中,直接對中文包裹$t('中文')
  2. vue的元件程式碼中,由於$t是全域性引入,因此需包裹成this.$t('中文')
  3. 對於純js部分,需import i18n模組,並對中文包裹i18n.t('中文')
  4. 對於帶數字的字串,如【共計${count}條資料】,需轉換為$t('共計count條資料', {count: 100})的結構,轉換前的程式碼在不同地方可能有不一樣的表示,比如在vuetemplate中,轉換前的詞條可能是這樣:【共計{{count}}條資料

問題分析

面對此類問題,首先想到的自然是將程式碼轉換成ast樹,對其中的中文字串進行處理,再轉換為程式碼,但實際會遇到以下幾個問題:

  1. 一般的parser(如@bable/parser)只能處理jsjsx檔案,無法處理vue模板,利用vue-loader.vue檔案轉換成.js檔案雖然可以配合@bable/parser進行解析,但轉換成.js檔案後的程式碼,沒有相關的轉換器將其反過來轉換成.vue程式碼,這和我們的需求不符
  2. 即使有.vue檔案的parser(如vue-eslint-parser),但是沒有對應的traverse和generator工具,不能將解析的ast反過來轉換成程式碼
  3. 即使有.vue檔案的parser、traverse、generator配套工具,重新生成的vue程式碼格式很大概率無法滿足eslint校驗,需要自動進行格式修正

解決思路

通過對當前問題的分析,目前面臨的問題有兩個:

  1. 需要有.vue檔案配套的解析、生成工具
  2. 解決轉換後程式碼的eslint格式問題

問題2可以通過在生成處理後的.vue檔案時,執行專案中的eslint --fix命令實現,若專案不校驗格式,自然不會安裝eslint,但若校驗格式,則必定會安裝eslint,也就是可以執行eslint --fix命令。

當前主要矛盾是問題1,而觀察問題1,.vue檔案中js檔案有配套的轉換工具,主要矛盾集中在template上,而目前雖然沒有template的生成工具,但可以將其視作html解析,template特性的解析作為html parser的外掛完成。

main-flow

用法

npm i git+https://github.com/goblin-pitcher/i18n-collector.git -D
---------------------------------
npx i18n-collect

引數

引數名簡寫說明預設值
dird需要進行國際化處理的目錄./
ignorediri需要忽略的檔案或者資料夾 如 -i car.js 會忽略掉所有以 car.js結尾的檔案無論傳不傳此引數,都會忽略掉i18n資料夾
fixf執行完collect之後是否自動執行eslint --fix, 預設開啟,--fix false即關閉eslint執行true

配置

新建i18n-collect.config.js檔案可傳入具體配置,預設配置如下:

const defConfig = {
  // 轉換當前目錄下的檔案
  dir: './',
  // 忽略項
  ignoredir: [],
  // 是否執行eslint --fix
  fix: true,
  // 收集中文詞條的檔名
  output: 'zh-CN.js',
  // 檔案處理配置
  file: {
    // 模板中包裹中文的函式名,如$t('中文')
    template: { prefix: "$t" },
    // 對於純js檔案的處理
    js: {
      // 若有中文詞條需要提取,需要先引入i18n相關包才能包裹,該配置為新增引入檔案的配置
      // 預設引入時新增 import {i18n} from '@/utils/i18n.utils'
      addImport: {
        from: "@/utils/i18n.utils",
        data: ["i18n"],
      },
      // 包裹中文詞條的方法,如i18n.t('中文')
      prefix: "i18n.t",
    },
    // .vue檔案中script包裹中文的方法, 如this.$t('中文')
    // 遇到sparePrefix配置,即i18n.t('中文')的欄位,也會當作已包裹轉換方法的字串,而不會再用this.$t包裹一次
    vue: { prefix: "this.$t", sparePrefix: 'i18n.t' }
  }
};

相關文章