VScode 插件开发 国际化资助工具

打印 上一主题 下一主题

主题 1014|帖子 1014|积分 3042

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一、功能实现

  1. // The module 'vscode' contains the VS Code extensibility API
  2. // Import the module and reference it with the alias vscode in your code below
  3. const vscode = require('vscode');
  4. const fs = require('fs');
  5. const path = require('path')
  6. const axios = require('axios');
  7. const crypto = require('crypto');
  8. const YOUDAO_API_URL = 'https://openapi.youdao.com/api';
  9. const targetLanguage = 'zh'; // 目标语言,例如中文
  10. // This method is called when your extension is activated
  11. // Your extension is activated the very first time the command is executed
  12. /**
  13. * @param {vscode.ExtensionContext} context
  14. */
  15. function activate(context) {
  16.         // Use the console to output diagnostic information (console.log) and errors (console.error)
  17.         // This line of code will only be executed once when your extension is activated
  18.         // console.log('Congratulations, your extension "gn-i18n-helper" is now active!');
  19.         // The command has been defined in the package.json file
  20.         // Now provide the implementation of the command with  registerCommand
  21.         // The commandId parameter must match the command field in package.json
  22.         const disposable = vscode.commands.registerCommand(
  23.                 'extension.getSelectedText',  // 这个名称必须与package.json中的命令名称一致
  24.                 async () => {
  25.                         const editor = vscode.window.activeTextEditor;
  26.                         if (editor) {
  27.                                 // 选中的文本
  28.                                 const selection = editor.selection;
  29.                                 const selectedText = editor.document.getText(selection);
  30.                                 // 获取当前工作区的文件夹
  31.                                 const workspaceFolders = vscode.workspace.workspaceFolders;
  32.                                 // 获取文件内容
  33.                                 const filePath1 = path.join(workspaceFolders[0].uri.fsPath, 'LANGUAGEI18n/LANGUAGEI18nCommon.md');
  34.                                 const filePath2 = path.join(workspaceFolders[0].uri.fsPath, 'LANGUAGEI18n/LANGUAGEI18nFrontend.md');
  35.                                 const filePath3 = path.join(workspaceFolders[0].uri.fsPath, 'LANGUAGEI18n/LANGUAGEI18nPage.md');
  36.                                 const filePath4 = path.join(workspaceFolders[0].uri.fsPath, 'LANGUAGEI18n/LANGUAGEI18nGeneral.md');
  37.                                 const fileContent1 = fs.readFileSync(filePath1, 'utf8');
  38.                                 const fileContent2 = fs.readFileSync(filePath2, 'utf8');
  39.                                 const fileContent3 = fs.readFileSync(filePath3, 'utf8');
  40.                                 const fileContent4 = fs.readFileSync(filePath4, 'utf8');
  41.                                 let fileContent = fileContent1 + fileContent2 + fileContent3 + fileContent4;
  42.                                 if (editor.document.languageId === 'vue') {
  43.                                         const document = editor.document;
  44.                                         const position = editor.selection.active; // 获取光标位置
  45.                                         const lineText = document.lineAt(position.line).text; // 获取当前行文本
  46.                                         const currentFileContent = document.getText(); // 获取文件内容
  47.                                        
  48.                                         // 默认 template,防止出现多个 template 标签
  49.                                         // 使用正则表达式匹配 <javaScript> 和 </javaScript> 之间的内容
  50.                                         let section = 'template';
  51.                                         const javaScriptRegex = /<script>([\s\S]*?)<\/script>/i;
  52.                                         const javaScriptMatch = currentFileContent.match(javaScriptRegex);
  53.                                         if (javaScriptMatch && javaScriptMatch[1]) {
  54.                                                 const matchContent = javaScriptMatch[1].trim(); // 提取内容并去除多余空格
  55.                                                 if(matchContent.includes(lineText)){
  56.                                                         section = 'javaScript';
  57.                                                 }
  58.                                         }
  59.                                         // 处理选中的内容,截取需要搜索的文字
  60.                                         let searchText = '';
  61.                                         if(selectedText.includes('=')){
  62.                                                 searchText = selectedText.split('=')[1].replace(/"/g, "").trim();
  63.                                         }else{
  64.                                                 searchText = selectedText;
  65.                                         }
  66.                                        
  67.                                         const searchResult = fileContent.search(new RegExp(searchText, 'g'));
  68.                                         let isMatch = false;
  69.                                         if (searchResult !== -1) {
  70.                                                 // 截取文件内容 - 提高搜索效率
  71.                                                 // let copyFileContent = fileContent.slice(searchResult - 1000, searchResult + 1000);
  72.                                                 const lines = fileContent.split('\n'); // 按行分割文本
  73.                                                 const regex = /(\w+)\("([^"]+)", "([^"]+)", "([^"]+)",/;
  74.                                                 for (const line of lines) {
  75.                                                         const match = line.match(regex);
  76.                                                         if (match) {
  77.                                                                 const docKey = match[2];
  78.                                                                 const docValue = match[3];
  79.                                                                 const docText = match[4].replace(/"/g, "");
  80.                                                                 let newText = '';
  81.                                                                 if(section == 'template'){
  82.                                                                         if(selectedText.includes('=')){
  83.                                                                                 // placeholder="验证码" -> :placeholder="$t('common.verifyCode')"
  84.                                                                                 const prop = selectedText.split('=')[0];
  85.                                                                                 newText = `:${prop}="$t('${docKey}.${docValue}')"`
  86.                                                                         }else{
  87.                                                                                 // 验证码 -> {{$t('common.username')}}
  88.                                                                                 newText = `{{$t('${docKey}.${docValue}')}}`
  89.                                                                         }
  90.                                                                 }else if(section == 'javaScript'){
  91.                                                                         // "验证码" -> this.$t('common.username')
  92.                                                                         newText = `this.$t('${docKey}.${docValue}')`
  93.                                                                 }
  94.                                                                
  95.                                                                 if(docText == searchText){
  96.                                                                         isMatch = true;
  97.                                                                         if (docKey && docValue) {
  98.                                                                                 vscode.window.showInformationMessage(editor.selection, newText);
  99.                                                                                 if(section == 'template'){
  100.                                                                                         editor.edit(editBuilder => {
  101.                                                                                                 editBuilder.replace(editor.selection, newText);
  102.                                                                                         });
  103.                                                                                 }else if(section == 'javaScript'){
  104.                                                                                         const start = selection.start;
  105.                                                                                         const end = selection.end;
  106.                                                                                         // 获取当前选中内容的前后字符位置
  107.                                                                                         const newStart = new vscode.Position(start.line, Math.max(start.character - 1, 0));
  108.                                                                                         const newEnd = new vscode.Position(end.line, Math.min(end.character + 1, document.lineAt(end.line).text.length));
  109.                                                                                         // 设置新的选择区域
  110.                                                                                         editor.selection = new vscode.Selection(newStart, newEnd);
  111.                                                                                        
  112.                                                                                         editor.edit(editBuilder => {
  113.                                                                                                 editBuilder.replace(editor.selection, newText); // 替换选中的内容
  114.                                                                                         });
  115.                                                                                 }
  116.                                                                                 break; // 找到后退出循环
  117.                                                                         }
  118.                                                                 }
  119.                                                         }
  120.                                                 }
  121.                                                 // 如果没有找到精准匹配的内容
  122.                                                 if(!isMatch){
  123.                                                         addWordToFile(searchText, filePath4);
  124.                                                         // vscode.window.showInformationMessage(`未找到匹配内容:${searchText}`);
  125.                                                 }
  126.                                         } else {
  127.                                                 addWordToFile(searchText, filePath4);
  128.                                         }
  129.                                 }
  130.                         } else {
  131.                                 vscode.window.showInformationMessage('No active editor found.');
  132.                         }
  133.                 },
  134.         );
  135.         context.subscriptions.push(disposable);
  136. }
  137. // 添加词条到文件
  138. async function addWordToFile(searchText, filePath4) {
  139.         const translatedText = await translateText(searchText, targetLanguage);
  140.         const simplifyText = simplify(translatedText);
  141.         const camelCaseText = toCamelCase(simplifyText);
  142.         // 向文件中添加翻译后的文本
  143.         const generationFilePath = filePath4;
  144.         const generationFileContent = fs.readFileSync(generationFilePath, 'utf8');
  145.         // GENERAL_UPDATELOG("general", "updateLog", "更新日志", "updateLog", "更新日志"),
  146.         const insertText = `GENERAL_${camelCaseText.toUpperCase()}("general", "${camelCaseText}", "${searchText}", "${simplifyText}", "${searchText}"),`;
  147.         const newGenerationFileContent = generationFileContent + '\n' + insertText;
  148.         fs.writeFileSync(generationFilePath, newGenerationFileContent);
  149. }
  150. async function translateText(text, targetLanguage) {
  151.     const appKey = ''; // 替换为您的 App Key
  152.     const appSecret = ''; // 替换为您的 App Secret
  153.     const salt = Date.now();
  154.     const curtime = Math.floor(Date.now() / 1000);
  155.   
  156.     const sign = crypto.createHash('sha256')
  157.         .update(appKey + truncate(text) + salt + curtime + appSecret)
  158.         .digest('hex');
  159.     const response = await axios.get(YOUDAO_API_URL, {
  160.         params: {
  161.             q: text,
  162.             from: 'zh-CHS',
  163.             to: targetLanguage,
  164.             appKey: appKey,
  165.             salt: salt,
  166.             sign: sign,
  167.                         signType: "v3",
  168.             curtime: curtime,
  169.         },
  170.     });
  171.     return response.data.translation[0];
  172. }
  173. function truncate(text) {
  174.     return text.length > 200 ? text.slice(0, 200) : text;
  175. }
  176. function toCamelCase(str) {
  177.         // 将 - 替换为 " "
  178.         str = str.replace(/-/g, " ");
  179.     return str
  180.         .split(/\s+/) // 按空格分割
  181.         .map((word, index) => {
  182.             if (index === 0) {
  183.                 return word.toLowerCase(); // 第一个单词小写
  184.             }
  185.             return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); // 其他单词首字母大写
  186.         })
  187.         .join('');
  188. }
  189. function simplify(text) {
  190.     // 示例: 删除多余空格和停用词
  191.     const stopWords = ['the', 'is', 'in', 'at', 'and', 'of', 'to', 'a', 'that', 'it', 'on', 'for'];
  192.     const words = text.split(' ').filter(word => !stopWords.includes(word.toLowerCase()));
  193.     return words.join(' ').trim(); // 返回精简后的文本
  194. }
  195. // This method is called when your extension is deactivated
  196. function deactivate() {
  197.         vscode.window.showInformationMessage(`Congratulations, your extension "gn-i18n-helper" is now active!`);
  198. }
  199. module.exports = {
  200.         activate,
  201.         deactivate
  202. }
复制代码
二、快捷键界说

  1. {
  2.   "name": "gn-i18n-helper",
  3.   "displayName": "gn-i18n-helper",
  4.   "description": "A VS Code extension to help with i18n.",
  5.   "publisher": "guniao",
  6.   "version": "2.0.2",
  7.   "icon": "resources/i18n.png",
  8.   "engines": {
  9.     "vscode": "^1.96.0"
  10.   },
  11.   "categories": [
  12.     "Other"
  13.   ],
  14.   "activationEvents": [],
  15.   "main": "./extension.js",
  16.   "contributes": {
  17.     "commands": [
  18.       {
  19.         "command": "extension.getSelectedText",
  20.         "title": "Get Selected Text"
  21.       }
  22.     ],
  23.     "keybindings": [
  24.       {
  25.         "command": "extension.getSelectedText",
  26.         "key": "alt+r",
  27.         "when": "editorTextFocus"
  28.       }
  29.     ]
  30.   },
  31.   "scripts": {
  32.     "lint": "eslint .",
  33.     "pretest": "npm run lint",
  34.     "test": "vscode-test"
  35.   },
  36.   "devDependencies": {
  37.     "@types/mocha": "^10.0.10",
  38.     "@types/node": "20.x",
  39.     "@types/vscode": "^1.96.0",
  40.     "@vscode/test-cli": "^0.0.10",
  41.     "@vscode/test-electron": "^2.4.1",
  42.     "eslint": "^9.16.0"
  43.   },
  44.   "dependencies": {
  45.     "axios": "^1.7.9"
  46.   }
  47. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天津储鑫盛钢材现货供应商

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表