「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

网站建设1年前发布 123456
16 00

前言

要说哪个插件对效率提升最大,可能各有推荐,各有千秋。但我要说对初学者,以及英文有亿点点差的同学来讲:翻译,是日常开发中必不可少的一环。在下找过N个​​VSCode​​ 翻译插件 发现一个神器:

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

​VSCode 插件:Google Translate Extension​

这款插件不像其它要么需科学上网,要么强绑定快捷键的憨憨插件,有个最直观的功能:​选中悬浮翻译「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

啊这…也太作弊了吧,编程能力+10086。

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

因为这两年都在从事​​VSCode​​二次/插件 开发,这个功能深得我心,于是想捣腾一下,看看能不能写轮眼学习一番

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

撒话不说,开干!

1. 代码目录分析

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

其中代码逻辑都在​​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​​行。

2. 源码分析

精简完的入口文件:

// 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;

2.1 初始化配置

// 获取用户状态,防止重复使用
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);
}

2.2 编写触发函数

// 向文件类型提供悬停内容的简单方法
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 = `<strong>[Google Translate](https://translate.google.cn/?sl=auto&tl=${trans.lang.to}&text=${encodeURI(trans.text)})</strong>\n\n`;
console.log("word", word);
return new vscode.Hover(pre + word.replace(/\r\n/g, ' \r\n'));
} catch (error) {
return new vscode.Hover('<strong>[Error](https://github.com/imlinhanchao/vsc-google-translate/issues)</strong>\n\n' + error.message);
}
}

}
})

其中几个关键点:

  1. ​vscode.languages.registerHoverProvider({scheme: 'file'},{...}​​: 向文件类型提供悬停内容的简单方法。
  2. 中间的两端​​if​​: 检验 从后往前 或 从前往后 选择的内容是否满足需求。

然后到了悬停调用

await translate(editor.document.getText(selection), langTo);

2.3 触发翻译

再来看​​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;
  1. ​@imlinhanchao/google-translate-api​​:是作者集成的翻译API。
  2. ​getConfig​​​:获取当前​​vscode​​的首选和次选语言,若无则自动翻译(默认英语-> 汉语)。

整个文件导出一个翻译方法。

中间那段正则,可以解析出驼峰函数

word = word.replace(/([a-z])([A-Z])/g, "$1 $2")
.replace(/([_])/g, " ").replace(/=/g, ' = ')
.replace(/(\b)\.(\b)/g, '$1 \n{>}\n $2 ');

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

2.4 显示悬停

回到​​hoverDisposable​​:

let trans = await translate(editor.document.getText(selection), langTo);
if (!trans) return;
let word = trans.word
let pre = `<strong>[Google Translate](https://translate.google.cn/?sl=auto&tl=${trans.lang.to}&text=${encodeURI(trans.text)})</strong>\n\n`;
return new vscode.Hover(pre + word.replace(/\r\n/g, ' \r\n'));

拿到翻译结果后,触发显示为:

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

这里一个很有意思的点,给你拼装了一段可打开的​​Google Translate​​链接,非常体贴了可以说。

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

这个插件作为一个​​vscode​​插件开发初体验,是不错的。

2.5 额外小发现:​​google-translate-api​

​一个用于 Google 翻译的免费且无限制的 API​

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

总结

约有一年没写文章了,这段时间都在摸鱼以及健身。都在写​​vscode​​二次/插件开发。比较少关注新技术。准备重新出发,整整账号了。

源码:

​VSCode 插件:Google Translate Extension​

精简后的:​​https://github.com/roger-hiro/vscode-google-translate​

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

不想拉代码的同学可以试试​​CS​​的自定义模板

来自:​​https://cloudstudio.net/templates/5oulv1ZVoy​​,点击图标

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

「VS Code 整活」100行代码,写一个超实用的悬浮翻译插件

© 版权声明

相关文章