12

Develop vscode plugin variable translation from zero to one

The reason for the demand is that English slag often encounters a variable in the development process that knows what Chinese is called, but the English word may be forgotten or unknown. At this time, I used to open the browser, open Google Translate, and enter Chinese. , copy the English, then switch back to vscode, paste the result. It's really troublesome. When I was young, my memory was good. I could remember most of the English words. The number of times is also increasing, so I developed this plug-in after thinking about it. Because I am also the plug-in development that I have learned from scratch in the past few days, this article completely records the plug-in development road developed by Xiaobai. The content is mainly an introduction to actual combat, mainly from four aspects to fully display the entire plug-in. The complete journey from functional design to release.

  1. feature design
  2. Environment construction
  3. Plug-in function development
  4. Plug-in package release

The plugin has been launched, the vscode plugin store can search for Translate Variable to experience it, and the code is also open source, the source code here

feature design

The function is mainly two functions, Chinese to English, other languages to Chinese

  1. Replace Chinese variables with translated English variables. Multiple words need to be automatically humped. The solution is the "English stuck" that is often encountered in daily development.
  2. Word translation, automatically translates various languages into Chinese. This solves the scenario that sometimes when you look at the comments of the source code of foreign projects, you may encounter words that you cannot understand and do not know what they mean, which affects the efficiency.

Environment construction

The first step to get started, the environment is built

  1. Install scaffolding, yo and generator-code , these two tools can help us build projects quickly, see Github

    //安装
    yarn global add yo generator-code
  2. Install vsce, vsce can be used to package the developed code into a file with a .vsix suffix, which is convenient for uploading to the Microsoft plug-in store or local installation

    yarn global add vsce
  3. Generate and initialize the project, fill in the initialization information according to your own situation

    //初始化生成项目
    yo code

    After this step, choose to open directly, Open with code

    image-20211230215507341 will automatically create a workspace after opening, and generate these files. You can delete the files according to your own needs. After this step, we can directly develop and debug

    image-20211230215823987

    How does

    Go to run and debug panel and click Run Extention , or shortcut key F5 , you can directly click the debug button on the touch bar on mac

    image-20211230220226620

    After opening, a new vscode window will pop up, this new window is your test environment ( extension development host ), the plug-in function you do is to test in this new window, and the printed message is debugged In the console , such as the built-in example, in our new window cmd/ctrl+shift+p and input Hello world , some information will be printed on the console of the previous window

    image-20211230221707832

    At this point, the development preparation environment is ready, and the next step is to start the official plug-in function development

Plug-in function development

In the plugin development, there are two important files, one is package.json , the other is extention.js

Important Document Description

package.json

image-20211230222536296

  • activationEvents used to register activation events to indicate under what circumstances the active function in extension.js will be activated. Common ones are onLanguage , onCommand ... For more information, see vscode documentation activationEvents
  • main represents the main entry of the plugin
  • Contributes to registration command (Commands) , binding shortcuts (the KeyBindings) , configuration settings (the Configuration) and so on, more configurable items to see document
extention.js

The main function of extention.js is to serve as the implementation point of the plug-in function. The development of the plug-in function is completed through the active and deactive functions, as well as the api provided by vscode and some event hooks.

Implement translation function

The translation here mainly uses 3 services, Google, Baidu translation, Youdao translation.

  1. Google Translate uses @vitalets/google-translate-api , no configuration is required, but you need to be able to access the external network environment

    const translate = require('@vitalets/google-translate-api');
    async function getGoogleTransResult(text, opt) {
      const { from, to } = opt;
      try {
        const result = await translate(text, { from: from, to: to });
        console.log("[ 谷歌翻译 ]", result);
        return result.text;
      } catch (error) {
        console.log(error);
      }
    }
    
    module.exports = getGoogleTransResult
  1. Baidu translation, Baidu translation is relatively simple, apply for a service, get the appid and key, and then construct the request url to directly request it. If you don’t know how to apply, you can check my previous article Electron+Vue creates a local file from scratch Translator to apply

    const md5 = require("md5");
    const axios = require("axios");
    const config = require('../config/index.js');
    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('百度翻译结果', res.data.trans_result[0]);
            return res.data.trans_result[0];
        } catch (error) {
            console.log({ error });
        }
    }
    
    module.exports = getBaiduTransResult;
  2. Youdao translation needs to apply for an app id and an app key. Newcomers register to provide 50 free coupons, but they will be charged after they are used up, which is not very cost-effective.

    
    const config = require('../config/index.js');
    const { createHash } = require('crypto');
    const qs = require('querystring');
    const axios = require("axios");
    
    function hash(string) {
      return createHash('sha256').update(string).digest('hex');
    }
    
    function getInput(text) {
      if (!text) {
        return;
      }
      let input;
      const strLength = text.length;
      if (strLength <= 20) {
        input = text;
      } else {
        input = `${text.substring(0, 10)}${strLength}${text.substring(strLength - 10, strLength)}`;
      }
      return input;
    }
    
    async function getYouDaoTransResult(text, opt = {}) {
      const { from, to, appid, secretKey } = opt;
      const input = getInput(text);
      const salt = (new Date).getTime();
      const curtime = Math.round(new Date().getTime() / 1000);
      const str = `${appid}${input}${salt}${curtime}${secretKey}`;
      const sign = hash(str);
      const params = {
        q: text,
        appKey: appid,
        salt: salt,
        from: from,
        to: to,
        sign: sign,
        signType: "v3",
        curtime: curtime,
      }
      try {
        const res = await axios.post(config.youdaoBaseUrl, qs.stringify(params));
        console.log(`有道翻译结果 ${res.data.translation[0]}`);
        return res.data.translation[0];
      }
      catch (err) {
        console.log(error);
      }
    }
    
    module.exports = getYouDaoTransResult
    

get selected text

Use the event hook onDidChangeTextEditorSelection to get the selected text

    onDidChangeTextEditorSelection(({ textEditor, selections }) => {
        text = textEditor.document.getText(selections[0]);
    })

Get updates for configuration items

Obtain the configuration items of the workspace through vscode.workspace.getConfiguration , and then monitor the changes onDidChangeConfiguration

Get the update configuration item

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

Monitor configuration item changes

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

//监听变动
const disposeConfig = onDidChangeConfiguration(() => {
  config = getConfiguration();
})

Monitor the changes of individual configuration items

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

Get the currently open editor object

vscode.window.activeTextEditor represents the currently open editor. If you switch tabs without setting monitoring, this object will not be updated automatically, so you need to use onDidChangeActiveTextEditor to monitor and replace the previous editor object

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

Word-marking translation hover prompt

By vscode.languages.registerHoverProvider registered a Hover, then activeTextEditor translation to get the selected words, and then by new new vscode.Hover will prompt translation results suspension

// 划词翻译检测
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 === 'google') {
            response = await getGoogleTransResult(selected, { from: 'auto', to: 'zh-cn' });
            responseText = response.text;
        }

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

replace selected text

Get to activeTextEditor , calling his Edit method, and then use the callback the replace

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

copy to clipboard

use vscode.env.clipboard.writeText;

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

Camel handling

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

module.exports = toHump;

Shortcut key bindings

Register the keybindings set in package.json before binding through vscode.commands.registerCommand . It should be noted that the first parameter of registerCommand needs to be consistent with the command of keybindings before binding.

registerCommand('translateVariable.toEN', async() => {
  //do something
})


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

Plug-in package release

Bale

vsce package

After packaging, a plugin with a .vsix suffix will be generated in the directory

release

Plug-in release is mainly to transfer the packaged vsix suffix plug-in to the Microsoft vscode plug-in store, and of course it can also be installed and used locally.

incoming store

To publish online, you need to to the 161dda72b2e978 Microsoft Plugin Store management page to create the publisher information. If you do not have a Microsoft account, you need to apply for it.

image-20211229224224632

Once created, choose to publish to vscode store

image-20211229224338826

install

You can directly install the .vsix suffix plugin locally, find the plugin menu

image-20211229224545688

Select installation from the VSIX , install packaged plug-ins like the above

image-20211229224658287

At last

The Chinese information of vscode is a bit small. This time I spent most of my time reading English documents and looking for information on the Internet. English is really important. I will learn more English later. I hope I will use this plugin I made myself. The number of times will be less and less, the project has been open source, instructions and source code portal


kerin
497 声望572 粉丝

前端菜鸟