目录
功能设计
环境搭建
插件功能开发
最后
首页 开发工具 VSCode 手把手从0教你开发一个vscode变量翻译插件

手把手从0教你开发一个vscode变量翻译插件

Dec 31, 2021 pm 07:40 PM
vscode 插件开发

本篇文章带大家从0开发一个vscode变量翻译插件,本文会从四个方面来完整的展示整个插件从功能设计到发布的完整历程,希望对大家有所帮助!

手把手从0教你开发一个vscode变量翻译插件

需求的起因是英语渣在开发的过程中经常遇到一个变量知道中文叫啥,但是英文单词可能就忘了,或者不知道,这个时候,我之前做法是打开浏览器,打开谷歌翻译,输入中文,复制英文,然后切回vscode,粘贴结果。

实在是太麻烦了,年轻的时候还好,记性好,英文单词大部分都能记住,但随着年纪越来越大,头发越来越少,记性也是越来越差,上面的步骤重复的次数也越来越多,所以痛定思痛,就开发了这款插件。

因为自己也是这几天从零开始学习的插件开发,所以本文完全的记录了一个小白开发的插件开发之路,内容主要是实战类的介绍,主要从四个方面介绍来完整的展示整个插件从功能设计到发布的完整历程。

  • 功能设计

  • 环境搭建

  • 插件功能开发

  • 插件打包发布

1-1.gif

【推荐学习:《vscode入门教程》】

功能设计

功能主要是两个功能,中译英,其他语言翻译成中文

  • 将中文变量替换为翻译后的英文变量,多个单词需要自动驼峰,解决的场景就是日常开发经常碰到的“英语卡壳”

  • 划词翻译,自动将各种语言翻译成中文,这解决的场景是有时候看国外项目源代码的注释碰到不会的单词不知道啥意思影响效率

环境搭建

上手的第一步,环境搭建

  • 安装脚手架, yogenerator-code,这两个工具可以帮助我们快速构建项目,详情可见(https://github.com/Microsoft/vscode-generator-code)

    //安装
    yarn global add yo generator-code
    登录后复制
  • 安装vsce,vsce可用来将开发的代码打包成.vsix后缀的文件,方便上传至微软插件商店或者本地安装

    yarn global add vsce
    登录后复制
  • 生成并初始化项目,初始化信息根据自己情况填写

    //初始化生成项目
    yo code
    登录后复制

    到这一步后,选择直接打开,Open with code

2.png

打开后会自动建立一个工作区,并生成这些文件,可根据自己需要对文件进行删减,完成这步后,我们可以直接进行开发与调试了

3.png

如何进行调试?

运行与调试面板点击Run Extention,或者快捷键F5,mac可以直接点击触控栏的调试按钮

4.png

打开后会弹出一个新的vscode窗口,这个新的窗口就是你的测试环境(扩展开发宿主),你做的插件功能就是在这个新的窗口测试,打印的消息在前一个窗口的调试控制台中,比如自带的例子,在我们新窗口 cmd/ctrl+shift+p后输入Hello world后会在前一个窗口的控制台打印一些信息

5.png

到这里,开发准备环境就准备好了,下一步就是开始正式的插件功能开发

插件功能开发

插件开发中,有两个重要的文件,一个是 package.json,一个是 extention.js

重要文件说明

package.json

6.png

  • activationEvents用来注册激活事件,用来表明什么情况下会激活extention.js中的active函数。常见的有onLanguage,onCommand...更多信息可查看vscode文档activationEvents(https://code.visualstudio.com/api/references/activation-events)

  • main表示插件的主入口

  • contributes用来注册命令(commands),绑定快捷键(keybindings),**配置设置项(configuration)**等等,更多可配置项可看文档(https://code.visualstudio.com/api/references/contribution-points)

extention.js

extention.js主要作用是作为插件功能的实现点,通过active,deactive函数,以及vscode提供的api以及一些事件钩子来完成插件功能的开发

实现翻译功能

翻译这里主要是使用了两个服务,谷歌和百度翻译。

谷歌翻译参考了别人的做法,使用google-translate-token获取到token,然后构造请求url,再处理返回的body,拿到返回结果。这里还有一个没搞懂的地方就是请求url的生成很迷,不知道这一块是啥意思。

const qs = require('querystring');
const got = require('got');
const safeEval = require('safe-eval');
const googleToken = require('google-translate-token');
const languages = require('../utils/languages.js');
const config = require('../config/index.js');

// 获取请求url
async function getRequestUrl(text, opts) {
    let token = await googleToken.get(text);
    const data = {
        client: 'gtx',
        sl: opts.from,
        tl: opts.to,
        hl: opts.to,
        dt: ['at', 'bd', 'ex', 'ld', 'md', 'qca', 'rw', 'rm', 'ss', 't'],
        ie: 'UTF-8',
        oe: 'UTF-8',
        otf: 1,
        ssel: 0,
        tsel: 0,
        kc: 7,
        q: text
    };
    data[token.name] = token.value;
    const requestUrl = `${config.googleBaseUrl}${qs.stringify(data)}`;
    return requestUrl;
}

//处理返回的body
async function handleBody(url, opts) {
    const result = await got(url);
    let resultObj = {
        text: '',
        from: {
            language: {
                didYouMean: false,
                iso: ''
            },
            text: {
                autoCorrected: false,
                value: '',
                didYouMean: false
            }
        },
        raw: ''
    };

    if (opts.raw) {
        resultObj.raw = result.body;
    }
    const body = safeEval(result.body);

    // console.log('body', body);
    body[0].forEach(function(obj) {
        if (obj[0]) {
            resultObj.text += obj[0];
        }
    });

    if (body[2] === body[8][0][0]) {
        resultObj.from.language.iso = body[2];
    } else {
        resultObj.from.language.didYouMean = true;
        resultObj.from.language.iso = body[8][0][0];
    }

    if (body[7] && body[7][0]) {
        let str = body[7][0];

        str = str.replace(/<b><i>/g, &#39;[&#39;);
        str = str.replace(/<\/i><\/b>/g, &#39;]&#39;);

        resultObj.from.text.value = str;

        if (body[7][5] === true) {
            resultObj.from.text.autoCorrected = true;
        } else {
            resultObj.from.text.didYouMean = true;
        }
    }
    return resultObj;
}

//翻译
async function translate(text, opts) {
    opts = opts || {};
    opts.from = opts.from || &#39;auto&#39;;
    opts.to = opts.to || &#39;en&#39;;

    opts.from = languages.getCode(opts.from);
    opts.to = languages.getCode(opts.to);

    try {
        const requestUrl = await getRequestUrl(text, opts);
        const result = await handleBody(requestUrl, opts);
        return result;
    } catch (error) {
        console.log(error);
    }
}

// 获取翻译结果
const getGoogleTransResult = async(originText, ops = {}) => {
    const { from, to } = ops;
    try {
        const result = await translate(originText, { from: from || config.defaultFrom, to: to || defaultTo });
        console.log(&#39;谷歌翻译结果&#39;, result.text);
        return result;
    } catch (error) {
        console.log(error);
        console.log(&#39;翻译失败&#39;);
    }
}

module.exports = getGoogleTransResult;
登录后复制

百度翻译,百度翻译的比较简单,申请服务,获得appid和key,然后构造请求url直接请求就行

不知道如何申请的,可查看我之前的一篇文章 Electron+Vue从零开始打造一个本地文件翻译器 进行申请

https://juejin.cn/post/6899581622471884813

const md5 = require("md5");
const axios = require("axios");
const config = require(&#39;../config/index.js&#39;);
axios.defaults.withCredentials = true;
axios.defaults.crossDomain = true;
axios.defaults.headers.post["Content-Type"] =
    "application/x-www-form-urlencoded";

// 百度翻译
async function getBaiduTransResult(text = "", opt = {}) {
    const { from, to, appid, key } = opt;
    try {
        const q = text;
        const salt = parseInt(Math.random() * 1000000000);
        let str = `${appid}${q}${salt}${key}`;
        const sign = md5(str);
        const query = encodeURI(q);
        const params = `q=${query}&from=${from}&to=${to}&appid=${appid}&salt=${salt}&sign=${sign}`;
        const url = `${config.baiduBaseUrl}${params}`;
        console.log(url);
        const res = await axios.get(url);
        console.log(&#39;百度翻译结果&#39;, res.data.trans_result[0]);
        return res.data.trans_result[0];
    } catch (error) {
        console.log({ error });
    }
}

module.exports = getBaiduTransResult;
登录后复制

获取选中的文本

使用事件钩子onDidChangeTextEditorSelection,获取选中的文本

    onDidChangeTextEditorSelection(({ textEditor, selections }) => {
        text = textEditor.document.getText(selections[0]);
    })
登录后复制

配置项的获取更新

通过vscode.workspace.getConfiguration获取到工作区的配置项,然后通过事件钩子onDidChangeConfiguration监听配置项的变动。

获取更新配置项

const { getConfiguration } = vscode.workspace;
const config = getConfiguration();

//注意get里面的参数其实就是package.json配置项里面的contributes.configuration.properties.xxx
const isCopy = config.get(IS_COPY);
const isReplace = config.get(IS_REPLACE);
const isHump = config.get(IS_HUMP);
const service = config.get(SERVICE);
const baiduAppid = config.get(BAIDU_APPID);
const baiduKey = config.get(BAIDU_KEY);

//更新使用update方法,第三个参数为true代表应用到全局
config.update(SERVICE, selectedItem, true);
登录后复制

监听配置项的变动

const { getConfiguration, onDidChangeConfiguration } = vscode.workspace;
const config = getConfiguration();

//监听变动
const disposeConfig = onDidChangeConfiguration(() => {
  config = getConfiguration();
})
登录后复制

监听个别配置项的变动

const disposeConfig = onDidChangeConfiguration((e) => {
    if (e && e.affectsConfiguration(BAIDU_KEY)) {
        //干些什么
    }
})
登录后复制

获取当前打开的编辑器对象

vscode.window.activeTextEditor代表当前打开的编辑器,如果切换标签页,而没有设置监听,那么这个这个对象不会自动更新,所以需要使用onDidChangeActiveTextEditor来监听,并替换之前的编辑器对象

const { activeTextEditor, onDidChangeActiveTextEditor } = vscode.window;
let active = activeTextEditor;
const edit = onDidChangeActiveTextEditor((textEditor) => {
  console.log(&#39;activeEditor改变了&#39;);
  //更换打开的编辑器对象
  if (textEditor) {
      active = textEditor;
  }
})
登录后复制

划词翻译悬浮提示

通过vscode.languages.registerHoverProvider注册一个Hover,然后通过activeTextEditor拿到选中的词语进行翻译,然后再通过new vscode.Hover将翻译结果悬浮提示

// 划词翻译检测
const disposeHover = vscode.languages.registerHoverProvider("*", {
    async provideHover(document, position, token) {
        const service = config.get(SERVICE);
        const baiduAppid = config.get(BAIDU_APPID);
        const baiduKey = config.get(BAIDU_KEY);

        let response, responseText;
        const selected = document.getText(active.selection);
        // 谷歌翻译
        if (service === &#39;google&#39;) {
            response = await getGoogleTransResult(selected, { from: &#39;auto&#39;, to: &#39;zh-cn&#39; });
            responseText = response.text;
        }

        // 百度翻译
        if (service === &#39;baidu&#39;) {
            response = await getBaiduTransResult(selected, { from: "auto", to: "zh", appid: baiduAppid, key: baiduKey });
            responseText = response.dst;
        }
        // 悬浮提示
        return new vscode.Hover(`${responseText}`);
    }
})
登录后复制

替换选中的文本

获取到activeTextEditor,调用他的edit方法,然后使用回调中的replace

//是否替换原文
if (isReplace) {
  let selectedItem = active.selection;
  active.edit(editBuilder => {
    editBuilder.replace(selectedItem, result)
  })
}
登录后复制

复制到剪贴板

使用vscode.env.clipboard.writeText;

// 是否复制翻译结果
if (isCopy) {
  vscode.env.clipboard.writeText(result);
}
登录后复制

驼峰处理

function toHump(str) {
    if (!str) {
        return
    }
    const strArray = str.split(&#39; &#39;);
    const firstLetter = [strArray.shift()];
    const newArray = strArray.map(item => {
        return `${item.substring(0,1).toUpperCase()}${item.substring(1)}`;
    })
    const result = firstLetter.concat(newArray).join(&#39;&#39;);
    return result;
}

module.exports = toHump;
登录后复制

快捷键绑定

通过vscode.commands.registerCommand注册绑定之前package.json中设置的keybindings,需要注意的是registerCommand的第一个参数需要与keybindings的command保持一致才能绑定

registerCommand(&#39;translateVariable.toEN&#39;, async() => {
  //do something
})


//package.json
"keybindings": [{
  "key": "ctrl+t",
  "mac": "cmd+t",
  "when": "editorTextFocus",
  "command": "translateVariable.toEN"
}],
登录后复制

插件打包发布

打包

vsce package
登录后复制

打包后会在目录下生成.vsix后缀的插件

发布

插件发布主要是把打包的vsix后缀插件,传入微软vscode插件商店,当然也能本地安装使用。

传入商店

发布到线上需要到 微软插件商店管理页面(https://marketplace.visualstudio.com/manage/createpublisher),创建发布者信息,如果没有微软账号,需要去申请。

7.png

创建完成后,选择发布到vscode商店

8.png

本地安装

本地是可以直接安装.vsix后缀插件的,找到插件菜单

9.png

选择从VSIX安装,安装上面打包的插件就好了

10.png

最后

vscode的中文资料有点少,这次开发大多数时间都在看英文文档,以及上外网寻找资料,真的英语太重要了,后面得多学点英语了,希望后面我使用自己做的这个插件的次数会越来越少,项目已开源,使用说明与源码传送门(https://github.com/Kerinlin/translate-variable)

更多关于VSCode的相关知识,请访问:vscode教程!!

以上是手把手从0教你开发一个vscode变量翻译插件的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vscode怎么查看word文档 vscode查看word文档的方法 vscode怎么查看word文档 vscode查看word文档的方法 May 09, 2024 am 09:37 AM

首先,在电脑上打开vscode软件,点击左边的【Extension】(扩展)图标,如图中①所示然后,在扩展界面的搜索框中输入【officeviewer】,如图中②所示接着,从搜索结果中选择【officeviewer】安装,如图中③所示最后,打开文件,如docx,pdf等,如下图

vscode怎么绘制流程图_visual_studio code绘制流程图的方法 vscode怎么绘制流程图_visual_studio code绘制流程图的方法 Apr 23, 2024 pm 02:13 PM

首先要打开电脑中的visualstudiocode,点击左侧四个方块按钮然后在搜索框中输入draw.io查询插件,点击安装安装好后,新建一个test.drawio文件接着选中test.drawio文件,进入编辑模式左侧有各种图形,随意选择,就可以绘制流程图了绘制好后,点击文件→嵌入→svg下面再选择嵌入复制svg代码将复制的svg代码粘贴到html代码中打开html网页,就可以看到绘制的流程图了点击网页上的图片,就可以跳转页面在该页面可以放大缩小流程图在这里,我们选择点击右下角的铅笔图案,跳转网

加州理工华人用AI颠覆数学证明!提速5倍震惊陶哲轩,80%数学步骤全自动化 加州理工华人用AI颠覆数学证明!提速5倍震惊陶哲轩,80%数学步骤全自动化 Apr 23, 2024 pm 03:01 PM

LeanCopilot,让陶哲轩等众多数学家赞不绝口的这个形式化数学工具,又有超强进化了?就在刚刚,加州理工教授AnimaAnandkumar宣布,团队发布了LeanCopilot论文的扩展版本,并且更新了代码库。图片论文地址:https://arxiv.org/pdf/2404.12534.pdf最新实验表明,这个Copilot工具,可以自动化80%以上的数学证明步骤了!这个纪录,比以前的基线aesop还要好2.3倍。并且,和以前一样,它在MIT许可下是开源的。图片他是一位华人小哥宋沛洋,他是

vscode工作区怎么添加文件 vscode工作区添加文件的方法 vscode工作区怎么添加文件 vscode工作区添加文件的方法 May 09, 2024 am 09:43 AM

1.首先,打开vscode软件,点击资源管理器图标,找到工作区窗口2.然后,点击左上角的文件菜单,找到将文件夹添加到工作区选项3.最后,在本地磁盘中找到文件夹位置,点击添加按钮即可

vscode怎么开启后台更新 vscode开启后台更新方法 vscode怎么开启后台更新 vscode开启后台更新方法 May 09, 2024 am 09:52 AM

1.首先,打开界面后,点击左上角的文件菜单2.随后,在首选项栏目中点击设置按钮3.接着,在跳转的设置页面中,找到更新板块4.最后,鼠标点击勾选启用在Windows上后台下载和安装新的VSCode版本按钮,并重启程序即可

vscode怎么禁止wsl配置文件 vscode禁止wsl配置文件方法 vscode怎么禁止wsl配置文件 vscode禁止wsl配置文件方法 May 09, 2024 am 10:30 AM

1.首先,打开设置菜单中的settings选项2.随后,在跳转的commonlyused页面中找到terminal栏目3.最后,在该栏目右侧取消勾选usewslprofiles按钮即可

VScode怎么设置动画平滑插入 VScode设置动画平滑插入教程 VScode怎么设置动画平滑插入 VScode设置动画平滑插入教程 May 09, 2024 am 09:49 AM

1.首先,打开界面后,点击工作区界面2.然后,在打开的编辑面板中,点击文件菜单3.随后,点击首选项栏目下的设置按钮4.最后,鼠标点击勾选CursorSmoothCaretAnimation按钮,保存设置即可

Vscode怎么打开工作区信任权限 Vscode打开工作区信任权限方法 Vscode怎么打开工作区信任权限 Vscode打开工作区信任权限方法 May 09, 2024 am 10:34 AM

1.首先,打开编辑窗口后,点击左下角的配置图标2.随后,在打开的子菜单中点击管理工作区信任按钮3.接着,在编辑窗口中找到该页面4.最后,根据自己的办公需求勾选相关指令即可

See all articles