要说哪个插件对效率提升最大,可能各有推荐,各有千秋。但我要说对初学者,以及英文有亿点点差的同学来讲:翻译,是日常开发中必不可少的一环。在下找过N个VSCode
翻译插件 发现一个神器:
VSCode 插件:Google Translate Extension
这款插件不像其它要么需访问国外网站,要么强绑定快捷键的憨憨插件,有个最直观的功能:选中悬浮翻译
啊这...也太作弊了吧,编程能力+1s。
因为这两年都在从事VSCode
二次/插件 开发,这个功能深得我心,于是想捣腾一下,看看能不能写轮眼学习一番
撒话不说,开干!
其中代码逻辑都在src
目录里。
command.js //全部命令
extension.js //插件入口文件
tranlate.js //翻译工具函数
先从入口文件extension.js
出发:
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const command = require('./command')
function activate(context) {
console.log('Congratulations, your extension "vsc-google-translate" is now active!');
command.initSetting(context);
context.subscriptions.push(command.hoverDisposable);
context.subscriptions.push(command.tranDisposable);
context.subscriptions.push(command.switchDisposable);
context.subscriptions.push(command.copyDisposable);
context.subscriptions.push(command.replaceDisposable);
context.subscriptions.push(command.canDisposable);
context.subscriptions.push(command.switchLangDisposable);
context.subscriptions.push(command.fromLangDisposable);
context.subscriptions.push(command.settingsDisposable);
}
exports.activate = activate;
function deactivate() {
}
exports.deactivate = deactivate;
可以看到相当整洁,其中我们关注的功能只有hoverDisposable
和tranDisposable
,为了方便阅读,我精简了一遍。从500
行减到100
行。
精简完的入口文件:
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const command = require('./command')
function activate(context) {
console.log('Congratulations, your extension "vsc-google-translate" is now active!');
command.initSetting(context);
context.subscriptions.push(command.hoverDisposable);
}
exports.activate = activate;
function deactivate() {
}
exports.deactivate = deactivate;
// 获取用户状态,防止重复使用
function initSetting(cxt) {
hoverOpen = cxt.globalState.get('hover') || false;
langFrom = cxt.globalState.get('fromLang') || 'auto'
if (!translate.languages.isSupported(langFrom)) langFrom = 'auto';
cxt.globalState.update('hover', hoverOpen);
}
// 向文件类型提供悬停内容的简单方法
let hoverDisposable = vscode.languages.registerHoverProvider({scheme: 'file'}, {
provideHover: async (document, position, token) => {
// 获取正在激活的编辑器窗口区域
let editor = vscode.window.activeTextEditor;
if (!editor || !hoverOpen) {
return; // No open text editor
}
let length = editor.selections.length;
for (let i = 0; i < length; i++) {
let selection = editor.selections[i];
let line = {
begin: Math.min(selection.anchor.line, selection.active.line),
end: Math.max(selection.anchor.line, selection.active.line)
}, character = {
begin: Math.min(selection.anchor.character, selection.active.character),
end: Math.max(selection.anchor.character, selection.active.character)
};
// 这里是检验 从后往前 或 从前往后 选择的内容。
if (line.begin > position.line || character.begin > position.character) continue;
if (line.end < position.line || character.end < position.character) continue;
try {
// 开始翻译
let trans = await translate(editor.document.getText(selection), langTo);
if (!trans) return;
let word = trans.word
// 悬停显示的内容
let pre = `**[Google Translate](https://translate.google.cn/?sl=auto&tl=${trans.lang.to}&text=${encodeURI(trans.text)})**\n\n`;
console.log("word", word);
return new vscode.Hover(pre + word.replace(/\r\n/g, ' \r\n'));
} catch (error) {
return new vscode.Hover('**[Error](https://github.com/imlinhanchao/vsc-google-translate/issues)**\n\n' + error.message);
}
}
}
})
其中几个关键点:
vscode.languages.registerHoverProvider({scheme: 'file'},{...}
: 向文件类型提供悬停内容的简单方法。if
: 检验 从后往前 或 从前往后 选择的内容是否满足需求。然后到了悬停调用
await translate(editor.document.getText(selection), langTo);
再来看tranlate.js
,我稍微精简了下:
const vscode = require('vscode');
const translator = require('@imlinhanchao/google-translate-api');
let config = {};
async function translate(text, lang) {
try{
let result = await translator(text, {
from: lang.from == 'auto' ? undefined : lang.from,
to: lang.to,
})
return {
lang,
text,
word: result.text || '',
candidate: result.candidates
};
} catch (err) {
throw new Error(`Translate failed, Error message: '${err.message}'. Please post an issues for me.`);
}
}
function getConfig() {
let keys = [
'google-translate.firstLanguage',
'google-translate.secondLanguage',
];
let values = {};
keys.forEach(k => values[k] = vscode.workspace.getConfiguration().get(k))
return values;
}
module.exports = async (word, l, from='auto') => {
if (word == '') return null;
config = getConfig();
let lang = {
from,
to: l || config['google-translate.firstLanguage']
};
// 解析驼峰函数。
word = word.replace(/([a-z])([A-Z])/g, "$1 $2")
.replace(/([_])/g, " ").replace(/=/g, ' = ')
.replace(/(\b)\.(\b)/g, '$1 \n{>}\n $2 ');
let tran = await translate(word, lang);
// 若翻译无结果,则调用翻译成第二语言
if (tran.word.replace(/\s/g, '') == word.replace(/\s/g, '') || !tran.word.trim()) {
lang.to = config['google-translate.secondLanguage'];
let tranSecond = await translate(word, lang);
if (tranSecond.word) tran = tranSecond;
}
// 去除多余字符
tran.word = tran.word.replace(/\n{>}\n/g, '.');
tran.candidate = tran.candidate.map(c => c.replace(/{([^>]*?)>}/g, '$1\n{>}').replace(/\n{>}\n/g, '.'));
return tran;
};
module.exports.getConfig = getConfig;
module.exports.languages = translator.languages;
@imlinhanchao/google-translate-api
:是作者集成的翻译API。getConfig
:获取当前vscode
的首选和次选语言,若无则自动翻译(默认英语-> 汉语)。整个文件导出一个翻译方法。
中间那段正则,可以解析出驼峰函数
word = word.replace(/([a-z])([A-Z])/g, "$1 $2")
.replace(/([_])/g, " ").replace(/=/g, ' = ')
.replace(/(\b)\.(\b)/g, '$1 \n{>}\n $2 ');
回到hoverDisposable
:
let trans = await translate(editor.document.getText(selection), langTo);
if (!trans) return;
let word = trans.word
let pre = `**[Google Translate](https://translate.google.cn/?sl=auto&tl=${trans.lang.to}&text=${encodeURI(trans.text)})**\n\n`;
return new vscode.Hover(pre + word.replace(/\r\n/g, ' \r\n'));
拿到翻译结果后,触发显示为:
这里一个很有意思的点,给你拼装了一段可打开的Google Translate
链接,非常体贴了可以说。
这个插件作为一个vscode
插件开发初体验,是不错的。
google-translate-api
一个用于 Google 翻译的免费且无限制的 API💵
约有一年没写文章了,这段时间都在摸鱼以及健身。都在写vscode
二次/插件开发。比较少关注新技术。准备重新出发,整整账号了。
VSCode 插件:Google Translate Extension
精简后的:https://github.com/roger-hiro/vscode-google-translate
不想拉代码的同学可以试试CS
的自定义模板