写个vscode插件, 帮助阅读i18n项目的代码
介绍
ok按钮
的ok文案
都要翻译成不同国家的语言展示, 所以在代码里面往往我们不可以直接命名为ok
, 而是可能命名为user_base_plan_edit_ok_button
这类的名字, 并且为了区分i18n
与其它命名, 我们团队会采用全大写的方式类似USER_BASE_PLAN_EDIT_OK_BUTTON
, 而这样的代码多了之后阅读起来会让眼睛干涩
, 类似下面图里的伪代码:![](https://filescdn.proginn.com/32b57cc1d7e32ea536445b994392aa14/459a25e91f37f0af1357db3d1112411f.webp)
不好阅读
的问题我比较预期的效果是, 当鼠标悬浮在目标文字身上时会浮现出一个弹框, 而这个弹框至少要告诉我这个词语的中文或英文意思, 效果如下:![](https://filescdn.proginn.com/2281e93ae79c4c8e768bf6ffc954b4fb/aa11ae1627ad091b3790614991f47e0f.webp)
i18n
这个只是点上, 可以用在很多方面, 比如某个code103993283
这个code具体代表什么含义可以做个插件展示出来。一: 初始化vscode项目
记一次前端"vscode插件编写实战"超详细的分享会(建议收藏哦)(上篇)
记一次前端"vscode插件编写实战"超详细的分享会(建议收藏哦)(下篇)
i18n2c
yo code
![](https://filescdn.proginn.com/e3eb3fb5e3bd4f47f814e6bb16e1cf05/d4b6cbfe77b5d85070e883fe519095c1.webp)
二: 初始化架构
extension.js
文件我们清理干净:const vscode = require("vscode");
function activate(context) {
vscode.window.showInformationMessage("i18n翻译插件加载完成");
}
module.exports = {
activate,
};
package.json
文件: 设置当资源加载完就开始加载我们的插件{
// ...
"activationEvents": [
"onStartupFinished"
],
// ...
}
f5
开启调试模式, 出现下图就证明插件可以正常启动了:![](https://filescdn.proginn.com/78c120a8535987571d0c3503e572bf84/fa64ed17d47091dbb1684e137f57482b.webp)
三: 初始化hover文件
hover
后的逻辑都放在src里面:![](https://filescdn.proginn.com/bd8ece02d8b411a08d12f49dfb6ee63d/ccf182735c6ebcd47e65f7ccca01ee67.webp)
extension.js
, 把hover方法加进去: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
导出悬停时的处理方法const vscode = require("vscode");
module.exports = vscode.languages.registerHoverProvider("*", {
provideHover(document, position) {
return new vscode.Hover(`i18n插件前来助你渡劫`);
},
});
![](https://filescdn.proginn.com/08c50e5e4b5f9845255447d94d32e4db/802062008f8d1cccd8bed61ceabb4b1a.webp)
四: i18n目标文案的识别
i18n文案
都是大写, 并且使用下划线
相互链接, 而我发现全局除了i18n文案
外没有字符串里超过三个下划线
, 并且i18n文案
至少四个下划线
, 所以当前我使用的是判断字符串里面是否含有超过三个 '_'
。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
就是我们获取到的被悬停的文本
五: 如何翻译成中文
要被翻译
的文案, 这里我们就要研究如何翻译这个文案了, 一般针对i18n都会有个翻译的字典包, 我们团队的就是一个json文件
, 不同的是每个key是小写的, 大致的样子如下:![](https://filescdn.proginn.com/114ec79c20e37132b2c0d73d9a575021/6e9eaf6355182181a0a3fbd71ed19599.webp)
要被翻译
的文案转换为小写, 再去匹配一下就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()]}
`);
}
},
});
![](https://filescdn.proginn.com/e86cc8318a91e30a4fd29c91bb821baf/9468f9d6e60e8ad818e86c9bb8c68805.webp)
i18n字典
都是放在同一个文件夹里面的, 所以我只需要知道这个文件夹即可, 默认取出里面的中文与英文文案, 改造一下吧。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()]}
`);
}
},
});
![](https://filescdn.proginn.com/e86cc8318a91e30a4fd29c91bb821baf/9468f9d6e60e8ad818e86c9bb8c68805.webp)
i18nPath
当然可以由用户来配置啦, 接下来我们就把它研究。六: setting配置
写死
在插件里面, 很多时候需要用户自己来设置, 这时我们就需要vscode的setting的概念了, 具体如下图所示:![](https://filescdn.proginn.com/beda7d4df35b18916113415917241726/3b664793b881001aebcf919ed8ff5872.webp)
第一步: 初始化配置项
package.json
文件添加setting
配置项:{
"contributes": {
"configuration": {
"type": "object",
"title": "i18n翻译配置",
"properties": {
"vscodePluginI18n.i18nPath": {
"type": "string",
"default": "",
"description": "翻译文件的位置"
},
"vscodePluginI18n.open": {
"type": "boolean",
"default": true,
"description": "开启18n翻译"
}
}
}
},
}
type
设置为布尔
会自动生成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");
写在最上方, 可能会导致无法关闭悬停翻译效果, 这个里面有坑我们一会详细说说。第三步: 悬停时读取路径
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()]}
`);
}
}
},
});
七: 何时判断是否开启插件
extension.js
文件里面引入了hover
模块, 则就算我们判断了用户未开启i18n翻译
流程也会走到hover模块, 但是如果我们在判断用户是否开启i18n翻译
后进行引入hover
模块就会造成, 如果用户改变配置开始翻译无法及时响应, 需要用户重启一下, 所以具体这里如何设计需要大家酌情啦。八: 提示弹框
i18n翻译
但是没配置路径, 那么我们其实可以出现一个弹框提示用户是否要来填写这个翻译字典的路径, 类似下图的效果:![](https://filescdn.proginn.com/2c77ac8ff7935401371b8faa78204426/14e9e29f1779163b12d59a751ca1df50.webp)
extension.js
文件里面使用showInformationMessage
这个方法, 但是要增加两个参数: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("是否设置翻译文件路径", "是", "否")
.then((result) => {
if (result === "是") {
}
});
}
}
module.exports = {
activate,
};
九: 选择文件
vscode.window.showOpenDialog
方法, 他有四个主要的参数:canSelectFiles
是否可选文件canSelectFolders
是否可选文件夹canSelectMany
是否可以多选openLabel
提示文案返回值是数组, 第一个元素的path属性, 就是文件的全局路径
![](https://filescdn.proginn.com/edce0d22e4aa250bdf50ba60919eb638/de5903ddb4779622de1a8aa1ee05462e.webp)
update
方法主动更新一下全局的配置就可以啦。vscode.window
.showInformationMessage("是否设置翻译文件路径", "是", "否")
.then((result) => {
if (result === "是") {
vscode.window
.showOpenDialog({
canSelectFiles: false, // 是否可选文件
canSelectFolders: true, // 是否可选文件夹
canSelectMany: false, // 是否可以选择多个
openLabel: "请选择翻译文件夹",
})
.then(function (res) {
vscode.workspace
.getConfiguration()
.update("vscodePluginI18n.i18nPath", res[0].path, true);
});
}
});
}
end
![](https://filescdn.proginn.com/06268e4ad101de6b603f0013cd038d4e/9a596672f0029085d12c1cfeaa9364d0.webp)
评论