<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          寫個(gè)vscode插件, 幫助閱讀i18n項(xiàng)目的代碼

          共 12271字,需瀏覽 25分鐘

           ·

          2021-10-09 19:25

          作者:lulu_up
          來源:SegmentFault 思否社區(qū)
          介紹

          作者當(dāng)前參與的項(xiàng)目是面向全球用戶的, 項(xiàng)目免不了要做國(guó)際化處理, 哪怕只是一個(gè)簡(jiǎn)單的ok按鈕ok文案都要翻譯成不同國(guó)家的語言展示, 所以在代碼里面往往我們不可以直接命名為ok, 而是可能命名為user_base_plan_edit_ok_button這類的名字, 并且為了區(qū)分i18n與其它命名, 我們團(tuán)隊(duì)會(huì)采用全大寫的方式類似USER_BASE_PLAN_EDIT_OK_BUTTON, 而這樣的代碼多了之后閱讀起來會(huì)讓眼睛干澀, 類似下面圖里的偽代碼:


          為了解決這個(gè)不好閱讀的問題我比較預(yù)期的效果是, 當(dāng)鼠標(biāo)懸浮在目標(biāo)文字身上時(shí)會(huì)浮現(xiàn)出一個(gè)彈框, 而這個(gè)彈框至少要告訴我這個(gè)詞語的中文或英文意思, 效果如下:


          可以看出這個(gè)插件如果做好了不一定只能用在i18n這個(gè)只是點(diǎn)上, 可以用在很多方面, 比如某個(gè)code103993283這個(gè)code具體代表什么含義可以做個(gè)插件展示出來。

          一: 初始化vscode項(xiàng)目

          沒做過vscode插件的同學(xué)推薦先讀讀我寫的入門教程:
          • 記一次前端"vscode插件編寫實(shí)戰(zhàn)"超詳細(xì)的分享會(huì)(建議收藏哦)(上篇)

          https://segmentfault.com/a/1190000038553748
          • 記一次前端"vscode插件編寫實(shí)戰(zhàn)"超詳細(xì)的分享會(huì)(建議收藏哦)(下篇)

          https://segmentfault.com/a/1190000038617902

          這次做的插件是針對(duì)我當(dāng)前工程的, 沒有廣泛應(yīng)用能力所以就沒發(fā)布到vscode官方, 開發(fā)好后打包發(fā)到公司內(nèi)網(wǎng)與群里就ok了。
          創(chuàng)建項(xiàng)目: 這里項(xiàng)目名暫定叫i18n2c
          yo code

          二: 初始化架構(gòu)

          extension.js文件我們清理干凈:
          const vscode = require("vscode");

          function activate(context) {
            vscode.window.showInformationMessage("i18n翻譯插件加載完成");
          }

          module.exports = {
            activate,
          };
          修改package.json文件: 設(shè)置當(dāng)資源加載完就開始加載我們的插件
          {
          // ...

            "activationEvents": [
              "onStartupFinished"
            ],

          // ...
          }

          點(diǎn)擊f5開啟調(diào)試模式, 出現(xiàn)下圖就證明插件可以正常啟動(dòng)了:

          三: 初始化hover文件

          我們把hover后的邏輯都放在src里面:


          簡(jiǎn)單改造一下extension.js, 把hover方法加進(jìn)去:
          const vscode = require("vscode");
          const hover = require("./src/hover");

          function activate(context) {
            vscode.window.showInformationMessage("i18n翻譯插件加載完成");

            context.subscriptions.push(hover);
          }

          module.exports = {
            activate,
          };

          hover.js 導(dǎo)出懸停時(shí)的處理方法
          const vscode = require("vscode");

          module.exports = vscode.languages.registerHoverProvider("*", {
            provideHover(document, position) {
              return new vscode.Hover(`i18n插件前來助你渡劫`);
            },
          });

          當(dāng)你懸停在任何位置的時(shí)候效果如下:

          四: i18n目標(biāo)文案的識(shí)別

          每個(gè)團(tuán)隊(duì)的技術(shù)方案都不一樣, 這里我只針對(duì)我們團(tuán)隊(duì)的方案進(jìn)行設(shè)計(jì), 希望起到一個(gè)拋磚引玉的目的:
          我們團(tuán)隊(duì)的i18n文案都是大寫, 并且使用下劃線相互鏈接, 而我發(fā)現(xiàn)全局除了i18n文案外沒有字符串里超過三個(gè)下劃線, 并且i18n文案至少四個(gè)下劃線, 所以當(dāng)前我使用的是判斷字符串里面是否含有超過三個(gè) '_'
          const vscode = require("vscode");

          module.exports = vscode.languages.registerHoverProvider("*", {
            provideHover(document, position) {
              const word = document.getText(document.getWordRangeAtPosition(position));

              if (word.split("_").length > 3) {
                return new vscode.Hover(`i18n插件前來助你渡劫`);
              }

            },
          });

          上面的word就是我們獲取到的被懸停的文本

          五: 如何翻譯成中文

          上面我們找到了要被翻譯的文案, 這里我們就要研究如何翻譯這個(gè)文案了, 一般針對(duì)i18n都會(huì)有個(gè)翻譯的字典包, 我們團(tuán)隊(duì)的就是一個(gè)json文件, 不同的是每個(gè)key是小寫的, 大致的樣子如下:


          我要做的就是讀取這個(gè)文件, 然后將要被翻譯的文案轉(zhuǎn)換為小寫, 再去匹配一下就ok了。
          const vscode = require("vscode");
          const fs = require("fs");

          module.exports = vscode.languages.registerHoverProvider("*", {
            provideHover(document, position) {
              const word = document.getText(document.getWordRangeAtPosition(position));

              let jsonCN = JSON.parse(
                fs.readFileSync("/xxxx/xxxxx/langs/zh-CN.json")
              );

              if (word.split("_").length > 3) {
                return new vscode.Hover(`i18n插件前來助你渡劫:
          - 中文: ${jsonCN[word.toLocaleLowerCase()]}
                `);
              }

            },
          });



          我們的i18n字典都是放在同一個(gè)文件夾里面的, 所以我只需要知道這個(gè)文件夾即可, 默認(rèn)取出里面的中文與英文文案, 改造一下吧。
          const vscode = require("vscode");
          const fs = require("fs");

          module.exports = vscode.languages.registerHoverProvider("*", {
            provideHover(document, position) {
              const word = document.getText(document.getWordRangeAtPosition(position));

              if (word.split("_").length > 3) {
                const i18nPath = "/xxxx/xxxxx/langs";
                const jsonUrlCN = i18nPath + "/zh-CN.json";
                const jsonUrlEN = i18nPath + "/en.json";
                let jsonCN = JSON.parse(fs.readFileSync(jsonUrlCN));
                let jsonEN = JSON.parse(fs.readFileSync(jsonUrlEN));
                return new vscode.Hover(`i18n插件前來助你渡劫:
          - 中文: ${jsonCN[word.toLocaleLowerCase()]}
          - 英文: ${jsonEN[word.toLocaleLowerCase()]}
                `);
              }
            },
          });


          這里的i18nPath當(dāng)然可以由用戶來配置啦, 接下來我們就把它研究。

          六: setting配置

          我們翻譯字典文件所在的位置肯定不能寫死在插件里面, 很多時(shí)候需要用戶自己來設(shè)置, 這時(shí)我們就需要vscode的setting的概念了, 具體如下圖所示:
          第一步: 初始化配置項(xiàng)
          我們來到package.json文件添加setting配置項(xiàng):
          {
            "contributes": {
              "configuration": {
                "type""object",
                "title""i18n翻譯配置",
                "properties": {
                  "vscodePluginI18n.i18nPath": {
                    "type""string",
                    "default""",
                    "description""翻譯文件的位置"
                  },
                  "vscodePluginI18n.open": {
                    "type""boolean",
                    "default"true,
                    "description""開啟18n翻譯"
                  }
                }
              }
            },
          }

          type設(shè)置為布爾會(huì)自動(dòng)生成CheckBox還挺方便的。
          第二步: 初始插件讀取配置
          extension.js文件:
          const vscode = require("vscode");

          function activate(context) {
            const i18nPath = vscode.workspace
              .getConfiguration()
              .get("vscodePluginI18n.i18nPath");
            const open = vscode.workspace.getConfiguration().get("vscodePluginI18n.open");

            if (open && i18nPath) {
              vscode.window.showInformationMessage("i18n翻譯插件已就位");
              const hover = require("./src/hover");
              context.subscriptions.push(hover);
            }
          }

          module.exports = {
            activate,
          };

          這里要注意, 如果const hover = require("./src/hover"); 寫在最上方, 可能會(huì)導(dǎo)致無法關(guān)閉懸停翻譯效果, 這個(gè)里面有坑我們一會(huì)詳細(xì)說說。
          第三步: 懸停時(shí)讀取路徑
          hover.js文件:
          const vscode = require("vscode");
          const fs = require("fs");

          module.exports = vscode.languages.registerHoverProvider("*", {
            provideHover(document, position) {
              const i18nPath = vscode.workspace
                .getConfiguration()
                .get("vscodePluginI18n.i18nPath");
              const open = vscode.workspace
                .getConfiguration()
                .get("vscodePluginI18n.open");

              if (i18nPath && open) {
                const word = document.getText(document.getWordRangeAtPosition(position));

                if (word.split("_").length > 3) {
                  const i18nPath = "/xxxxx/xxxx/langs";
                  const jsonUrlCN = i18nPath + "/zh-CN.json";
                  const jsonUrlEN = i18nPath + "/en.json";
                  let jsonCN = JSON.parse(fs.readFileSync(jsonUrlCN));
                  let jsonEN = JSON.parse(fs.readFileSync(jsonUrlEN));
                  return new vscode.Hover(`i18n插件前來助你渡劫:
          - 中文: ${jsonCN[word.toLocaleLowerCase()]}
          - 英文: ${jsonEN[word.toLocaleLowerCase()]}
                `);
                }
              }
            },
          });

          七: 何時(shí)判斷是否開啟插件

          如果在extension.js文件里面引入了hover模塊, 則就算我們判斷了用戶未開啟i18n翻譯流程也會(huì)走到hover模塊, 但是如果我們?cè)谂袛嘤脩羰欠耖_啟i18n翻譯后進(jìn)行引入hover模塊就會(huì)造成, 如果用戶改變配置開始翻譯無法及時(shí)響應(yīng), 需要用戶重啟一下, 所以具體這里如何設(shè)計(jì)需要大家酌情啦。

          八: 提示彈框

          如果用戶開啟了i18n翻譯但是沒配置路徑, 那么我們其實(shí)可以出現(xiàn)一個(gè)彈框提示用戶是否要來填寫這個(gè)翻譯字典的路徑, 類似下圖的效果:


          extension.js文件里面使用showInformationMessage這個(gè)方法, 但是要增加兩個(gè)參數(shù):
          const vscode = require("vscode");

          function activate(context) {
            const i18nPath = vscode.workspace
              .getConfiguration()
              .get("vscodePluginI18n.i18nPath");
            const open = vscode.workspace.getConfiguration().get("vscodePluginI18n.open");

            if (open && i18nPath) {
              vscode.window.showInformationMessage("i18n翻譯插件已就位");
              const hover = require("./src/hover");
              context.subscriptions.push(hover);
            } else if (open && !i18nPath) {
              vscode.window
                .showInformationMessage("是否設(shè)置翻譯文件路徑""是""否")
                .then((result) => {
                     if (result === "是") {

                     }
                });
            }
          }

          module.exports = {
            activate,
          };

          九: 選擇文件

          當(dāng)用戶點(diǎn)擊'是'的時(shí)候我們需要借助vscode提供的api進(jìn)行文件的選擇, 并且拿到文件的返回值進(jìn)行主動(dòng)的設(shè)置操作:
          vscode.window.showOpenDialog 方法, 他有四個(gè)主要的參數(shù):
          1. canSelectFiles 是否可選文件

          2. canSelectFolders 是否可選文件夾

          3. canSelectMany 是否可以多選

          4. openLabel 提示文案

          5. 返回值是數(shù)組, 第一個(gè)元素的path屬性, 就是文件的全局路徑


          最后再用update方法主動(dòng)更新一下全局的配置就可以啦。
          vscode.window
                .showInformationMessage("是否設(shè)置翻譯文件路徑""是""否")
                .then((result) => {
                  if (result === "是") {
                    vscode.window
                      .showOpenDialog({
                        canSelectFiles: false, // 是否可選文件
                        canSelectFolders: true, // 是否可選文件夾
                        canSelectMany: false, // 是否可以選擇多個(gè)
                        openLabel: "請(qǐng)選擇翻譯文件夾",
                      })
                      .then(function (res) {
                        vscode.workspace
                          .getConfiguration()
                          .update("vscodePluginI18n.i18nPath", res[0].path, true);
                      });
                  }
                });
            }

          end

          這次就是這樣, 希望與你一起進(jìn)步。


          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -

          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人人操,人人摸,人人透, | 亚洲综合另类 | 亚洲无码成人片 | 99热精品在线 | 精品久久久久黄色片 |