[
  {
    "path": ".eslintrc.json",
    "content": "{\n    \"env\": {\n        \"browser\": false,\n        \"commonjs\": true,\n        \"es6\": true,\n        \"node\": true\n    },\n    \"parserOptions\": {\n        \"ecmaFeatures\": {\n            \"jsx\": true\n        },\n        \"sourceType\": \"module\"\n    },\n    \"rules\": {\n        \"no-const-assign\": \"warn\",\n        \"no-this-before-super\": \"warn\",\n        \"no-undef\": \"warn\",\n        \"no-unreachable\": \"warn\",\n        \"no-unused-vars\": \"warn\",\n        \"constructor-super\": \"warn\",\n        \"valid-typeof\": \"warn\"\n    }\n}"
  },
  {
    "path": ".gitattributes",
    "content": "# Set default behavior to automatically normalize line endings.\n* text=auto\n\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "on:\n  release:\n    types: [published]\nname: Deploy Extension\njobs:\n  Publish:\n    name: Publish\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@master\n    - name: Install\n      uses: actions/npm@master\n      with:\n        args: install --unsafe-perm\n    - name: Publish\n      uses: lannonbr/vsce-action@master\n      env:\n        VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }}\n      with:\n        args: publish -p $VSCE_TOKEN\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.vscode-test/\nserver/out/*\n*.vsix\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n\t// See http://go.microsoft.com/fwlink/?LinkId=827846\n\t// for the documentation about the extensions.json format\n\t\"recommendations\": [\n\t\t\"dbaeumer.vscode-eslint\"\n\t]\n}"
  },
  {
    "path": ".vscode/launch.json",
    "content": "// A launch configuration that launches the extension inside a new window\n// Use IntelliSense to learn about possible attributes.\n// Hover to view descriptions of existing attributes.\n// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n{\n\t\"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Extension\",\n            \"type\": \"extensionHost\",\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"${execPath}\",\n            \"args\": [\n                \"--extensionDevelopmentPath=${workspaceFolder}\"\n            ]\n        },\n        {\n            \"name\": \"Extension Tests\",\n            \"type\": \"extensionHost\",\n            \"request\": \"launch\",\n            \"runtimeExecutable\": \"${execPath}\",\n            \"args\": [\n                \"--extensionDevelopmentPath=${workspaceFolder}\",\n                \"--extensionTestsPath=${workspaceFolder}/test\"\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "// Place your settings in this file to overwrite default and user settings.\n{\n}"
  },
  {
    "path": ".vscodeignore",
    "content": ".vscode/**\n.vscode-test/**\ntest/**\n.gitignore\njsconfig.json\nvsc-extension-quickstart.md\n.eslintrc.json\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## 1.5.0\n- Refactor\n- Bug fixed\n- Dependencies bump\n- Performance improvements\n- Integration tests\n- Remove hover translation feature and typescript code\n\n## 1.4.13\n- Update translation dependencies\n\n## 1.4.12\n- Put back the mandatory modules\n\n## 1.4.11\n- Exclude extra files from release\n\n## 1.4.10\n- Hotfix for 403 error\n\n## 1.4.9\n- Fix Hebrew language\n\n## 1.4.8\n- Show's translations when hovering over code and text\n\n## 1.4.7\n- Translate camel case support\n\n## 1.4.6\n- Improve default language settings\n- Fix default shortcut\n\n## 1.4.5\n- Update translation library\n\n## 1.4.4\n- Add Uyghur language\n\n## 1.4.3\n- Add Chinese Traditional language\n\n## 1.4.2\n- Improve CI/CD\n\n## 1.4.1\n- Fix multi-line text translation\n\n## 1.4.0\n- Proxy support\n- Fix HTML entity not decoded\n- CI/CD with Github Actions\n\n## 1.3.3\n- Fix error messages not displayed\n\n## 1.3.2\n- Fix 'plugin stopped working' due to google unofficial api that stopped working\n\n## 1.3.1\n- Fix 'translation does nothing' random issue\n\n## 1.3.0\n- Add the translate of a line feature\n\n## 1.2.0\n- Prefered language setting\n\n## 1.1.5\n- Fix translation issue (#2)\n\n## 1.1.4\n- Change key biding to ALT+SHIFT+T to make it work with most of people\n- Update readme\n\n## 1.1.3\n- Change key biding to CTRL+SHIFT+T or CMD+SHIFT+T\n\n## 1.1.2\n- Code improvements\n- Better demo gif\n\n## 1.1.1\n- Add recently used languages\n\n## 1.1.0\n- Multiselect support\n- Update readme\n- MIT License\n- Gif example\n- Badges\n- Logo\n\n## 1.0.2\n- Minor improvements\n\n## 1.0.1\n- Minor improvements\n\n## 1.0.0\n- Initial release"
  },
  {
    "path": "LICENSE.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 HookyQR\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Vscode Google Translate\n\nQuickly translate text right in your code 🚀\n\n![Demo](demo.gif)\n\n## Usage\n\n### Translate selected text\n\n1. Select some text to translate\n1. Press `ALT+SHIFT+T`\n1. Select the output languages you want and enjoy 👍\n\n### Translate a line under cursor\n\nThis feature inserts a newline under the current one with translation\n\n1. Set cursor/cursors on line(s) to translate\n1. Select menu 'Translate line(s) under the cursor'\n1. Select the output languages you want and enjoy\n\n## Preferred language settings\n\nWant to quickly translate into a specific language?\nRun Command 'Set Preferred Language' or Set it in VSCode extension settings\n\n\n\n## Proxy Support\n\nYou can use a proxy to translate text with the following settings:\n\n```js\n\"vscodeGoogleTranslate.host\": \"120.0.0.1\"       // Proxy disabled if empty\n\"vscodeGoogleTranslate.port\": \"8080\"            // Proxy port\n\"vscodeGoogleTranslate.username\": \"admin\"       // Proxy auth disabled if empty\n\"vscodeGoogleTranslate.password\": \"password\"    // Proxy password\n```\n\n## Pull request\n\nPull request are welcome. Fork the project, clone it, install dependencies `npm i` and start coding :-).\n\nMany thanks to the people who participate for making it awesome!\n\n## Show your support\n\n**Give five stars 🤩**\n\nIf you like it, [rate it](https://marketplace.visualstudio.com/items?itemName=funkyremi.vscode-google-translate&ssr=false#review-details)\n"
  },
  {
    "path": "extension.js",
    "content": "const { initializeCommands } = require('./src/commands');\n\nfunction activate(context) {\n  initializeCommands(context);\n}\n\nexports.activate = activate;\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"target\": \"es6\",\n        \"checkJs\": false,  /* Typecheck .js files. */\n        \"lib\": [\n            \"es6\"\n        ]\n    },\n    \"exclude\": [\n        \"node_modules\"\n    ]\n}"
  },
  {
    "path": "languages.js",
    "content": "const languages = [\n\t{\n\t\tname: 'Afrikaans',\n\t\tvalue: 'af',\n\t}, {\n\t\tname: 'Albanian',\n\t\tvalue: 'sq',\n\t}, {\n\t\tname: 'Amharic',\n\t\tvalue: 'am',\n\t}, {\n\t\tname: 'Arabic',\n\t\tvalue: 'ar',\n\t}, {\n\t\tname: 'Armenian',\n\t\tvalue: 'hy',\n\t}, {\n\t\tname: 'Azeerbaijani',\n\t\tvalue: 'az',\n\t}, {\n\t\tname: 'Basque',\n\t\tvalue: 'eu',\n\t}, {\n\t\tname: 'Belarusian',\n\t\tvalue: 'be',\n\t}, {\n\t\tname: 'Bengali',\n\t\tvalue: 'bn',\n\t}, {\n\t\tname: 'Bosnian',\n\t\tvalue: 'bs',\n\t}, {\n\t\tname: 'Bulgarian',\n\t\tvalue: 'bg',\n\t}, {\n\t\tname: 'Catalan',\n\t\tvalue: 'ca',\n\t}, {\n\t\tname: 'Cebuano',\n\t\tvalue: 'ceb',\n\t}, {\n\t\tname: 'Chinese (Simplified)',\n\t\tvalue: 'zh-CN',\n\t}, {\n\t\tname: 'Chinese (Traditional)',\n\t\tvalue: 'zh-TW',\n\t}, {\n\t\tname: 'Corsican',\n\t\tvalue: 'co',\n\t}, {\n\t\tname: 'Croatian',\n\t\tvalue: 'hr',\n\t}, {\n\t\tname: 'Czech',\n\t\tvalue: 'cs',\n\t}, {\n\t\tname: 'Danish',\n\t\tvalue: 'da',\n\t}, {\n\t\tname: 'Dutch',\n\t\tvalue: 'nl',\n\t}, {\n\t\tname: 'English',\n\t\tvalue: 'en',\n\t}, {\n\t\tname: 'Esperanto',\n\t\tvalue: 'eo',\n\t}, {\n\t\tname: 'Estonian',\n\t\tvalue: 'et',\n\t}, {\n\t\tname: 'Finnish',\n\t\tvalue: 'fi',\n\t}, {\n\t\tname: 'French',\n\t\tvalue: 'fr',\n\t}, {\n\t\tname: 'Frisian',\n\t\tvalue: 'fy',\n\t}, {\n\t\tname: 'Galician',\n\t\tvalue: 'gl',\n\t}, {\n\t\tname: 'Georgian',\n\t\tvalue: 'ka',\n\t}, {\n\t\tname: 'German',\n\t\tvalue: 'de',\n\t}, {\n\t\tname: 'Greek',\n\t\tvalue: 'el',\n\t}, {\n\t\tname: 'Gujarati',\n\t\tvalue: 'gu',\n\t}, {\n\t\tname: 'Haitian Creole',\n\t\tvalue: 'ht',\n\t}, {\n\t\tname: 'Hausa',\n\t\tvalue: 'ha',\n\t}, {\n\t\tname: 'Hawaiian',\n\t\tvalue: 'haw',\n\t}, {\n\t\tname: 'Hebrew',\n\t\tvalue: 'iw',\n\t}, {\n\t\tname: 'Hindi',\n\t\tvalue: 'hi',\n\t}, {\n\t\tname: 'Hmong',\n\t\tvalue: 'hmn',\n\t}, {\n\t\tname: 'Hungarian',\n\t\tvalue: 'hu',\n\t}, {\n\t\tname: 'Icelandic',\n\t\tvalue: 'is',\n\t}, {\n\t\tname: 'Igbo',\n\t\tvalue: 'ig',\n\t}, {\n\t\tname: 'Indonesian',\n\t\tvalue: 'id',\n\t}, {\n\t\tname: 'Irish',\n\t\tvalue: 'ga',\n\t}, {\n\t\tname: 'Italian',\n\t\tvalue: 'it',\n\t}, {\n\t\tname: 'Japanese',\n\t\tvalue: 'ja',\n\t}, {\n\t\tname: 'Javanese',\n\t\tvalue: 'jw',\n\t}, {\n\t\tname: 'Kannada',\n\t\tvalue: 'kn',\n\t}, {\n\t\tname: 'Kazakh',\n\t\tvalue: 'kk',\n\t}, {\n\t\tname: 'Khmer',\n\t\tvalue: 'km',\n\t}, {\n\t\tname: 'Korean',\n\t\tvalue: 'ko',\n\t}, {\n\t\tname: 'Kurdish',\n\t\tvalue: 'ku',\n\t}, {\n\t\tname: 'Kyrgyz',\n\t\tvalue: 'ky',\n\t}, {\n\t\tname: 'Lao',\n\t\tvalue: 'lo',\n\t}, {\n\t\tname: 'Latin',\n\t\tvalue: 'la',\n\t}, {\n\t\tname: 'Latvian',\n\t\tvalue: 'lv',\n\t}, {\n\t\tname: 'Lithuanian',\n\t\tvalue: 'lt',\n\t}, {\n\t\tname: 'Luxembourgish',\n\t\tvalue: 'lb',\n\t}, {\n\t\tname: 'Macedonian',\n\t\tvalue: 'mk',\n\t}, {\n\t\tname: 'Malagasy',\n\t\tvalue: 'mg',\n\t}, {\n\t\tname: 'Malay',\n\t\tvalue: 'ms',\n\t}, {\n\t\tname: 'Malayalam',\n\t\tvalue: 'ml',\n\t}, {\n\t\tname: 'Maltese',\n\t\tvalue: 'mt',\n\t}, {\n\t\tname: 'Maori',\n\t\tvalue: 'mi',\n\t}, {\n\t\tname: 'Marathi',\n\t\tvalue: 'mr',\n\t}, {\n\t\tname: 'Mongolian',\n\t\tvalue: 'mn',\n\t}, {\n\t\tname: 'Myanmar',\n\t\tvalue: 'my',\n\t}, {\n\t\tname: 'Nepali',\n\t\tvalue: 'ne',\n\t}, {\n\t\tname: 'Norwegian',\n\t\tvalue: 'no',\n\t}, {\n\t\tname: 'Nyanja',\n\t\tvalue: 'ny',\n\t}, {\n\t\tname: 'Pashto',\n\t\tvalue: 'ps',\n\t}, {\n\t\tname: 'Persian',\n\t\tvalue: 'fa',\n\t}, {\n\t\tname: 'Polish',\n\t\tvalue: 'pl',\n\t}, {\n\t\tname: 'Portuguese',\n\t\tvalue: 'pt',\n\t}, {\n\t\tname: 'Punjabi',\n\t\tvalue: 'pa',\n\t}, {\n\t\tname: 'Romanian',\n\t\tvalue: 'ro',\n\t}, {\n\t\tname: 'Russian',\n\t\tvalue: 'ru',\n\t}, {\n\t\tname: 'Samoan',\n\t\tvalue: 'sm',\n\t}, {\n\t\tname: 'Scots Gaelic',\n\t\tvalue: 'gd',\n\t}, {\n\t\tname: 'Serbian',\n\t\tvalue: 'sr',\n\t}, {\n\t\tname: 'Sesotho',\n\t\tvalue: 'st',\n\t}, {\n\t\tname: 'Shona',\n\t\tvalue: 'sn',\n\t}, {\n\t\tname: 'Sindhi',\n\t\tvalue: 'sd',\n\t}, {\n\t\tname: 'Sinhala',\n\t\tvalue: 'si',\n\t}, {\n\t\tname: 'Slovak',\n\t\tvalue: 'sk',\n\t}, {\n\t\tname: 'Slovenian',\n\t\tvalue: 'sl',\n\t}, {\n\t\tname: 'Somali',\n\t\tvalue: 'so',\n\t}, {\n\t\tname: 'Spanish',\n\t\tvalue: 'es',\n\t}, {\n\t\tname: 'Sundanese',\n\t\tvalue: 'su',\n\t}, {\n\t\tname: 'Swahili',\n\t\tvalue: 'sw',\n\t}, {\n\t\tname: 'Swedish',\n\t\tvalue: 'sv',\n\t}, {\n\t\tname: 'Tagalog',\n\t\tvalue: 'tl',\n\t}, {\n\t\tname: 'Tajik',\n\t\tvalue: 'tg',\n\t}, {\n\t\tname: 'Tamil',\n\t\tvalue: 'ta',\n\t}, {\n\t\tname: 'Telugu',\n\t\tvalue: 'te',\n\t}, {\n\t\tname: 'Thai',\n\t\tvalue: 'th',\n\t}, {\n\t\tname: 'Turkish',\n\t\tvalue: 'tr',\n\t}, {\n\t\tname: 'Ukrainian',\n\t\tvalue: 'uk',\n\t}, {\n\t\tname: 'Urdu',\n\t\tvalue: 'ur',\n\t}, {\n\t\tname: 'Uyghur',\n\t\tvalue: 'ug',\n\t}, {\n\t\tname: 'Uzbek',\n\t\tvalue: 'uz',\n\t}, {\n\t\tname: 'Vietnamese',\n\t\tvalue: 'vi',\n\t}, {\n\t\tname: 'Welsh',\n\t\tvalue: 'cy',\n\t}, {\n\t\tname: 'Xhosa',\n\t\tvalue: 'xh',\n\t}, {\n\t\tname: 'Yiddish',\n\t\tvalue: 'yi',\n\t}, {\n\t\tname: 'Yoruba',\n\t\tvalue: 'yo',\n\t}, {\n\t\tname: 'Zulu',\n\t\tvalue: 'zu',\n\t}\n];\n\nmodule.exports = languages;\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"vscode-google-translate\",\n    \"displayName\": \"Vscode Google Translate\",\n    \"description\": \"Translate text right in your code\",\n    \"publisher\": \"funkyremi\",\n    \"version\": \"1.5.0\",\n    \"license\": \"MIT\",\n    \"icon\": \"icon.png\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"https://github.com/funkyremi/vscode-google-translate.git\"\n    },\n    \"engines\": {\n        \"vscode\": \"^1.29.0\"\n    },\n    \"categories\": [\n        \"Formatters\"\n    ],\n    \"activationEvents\": [\n        \"onCommand:extension.translateText\",\n        \"onCommand:extension.translateTextPreferred\",\n        \"onCommand:extension.translateLinesUnderCursor\",\n        \"onCommand:extension.setPreferredLanguage\",\n        \"onCommand:extension.translateLinesUnderCursorPreferred\"\n    ],\n    \"main\": \"./extension\",\n    \"contributes\": {\n        \"commands\": [\n            {\n                \"command\": \"extension.translateText\",\n                \"title\": \"Translate selection(s)\"\n            },\n            {\n                \"command\": \"extension.translateTextPreferred\",\n                \"title\": \"Translate selection(s) to preferred language\"\n            },\n            {\n                \"command\": \"extension.translateLinesUnderCursor\",\n                \"title\": \"Translate line(s) under the cursor\"\n            },\n            {\n                \"command\": \"extension.setPreferredLanguage\",\n                \"title\": \"Set preferred target language\"\n            },\n            {\n                \"command\": \"extension.translateLinesUnderCursorPreferred\",\n                \"title\": \"Translate line(s) under the cursor to preferred language\"\n            }\n        ],\n        \"configuration\": {\n            \"title\": \"Vscode Google Translate\",\n            \"type\": \"object\",\n            \"properties\": {\n                \"vscodeGoogleTranslate.preferredLanguage\": {\n                    \"type\": \"string\",\n                    \"enum\": [\n                        \"Afrikaans\",\n                        \"Albanian\",\n                        \"Amharic\",\n                        \"Arabic\",\n                        \"Armenian\",\n                        \"Azeerbaijani\",\n                        \"Basque\",\n                        \"Belarusian\",\n                        \"Bengali\",\n                        \"Bosnian\",\n                        \"Bulgarian\",\n                        \"Catalan\",\n                        \"Cebuano\",\n                        \"Chinese (Simplified)\",\n                        \"Chinese (Traditional)\",\n                        \"Corsican\",\n                        \"Croatian\",\n                        \"Czech\",\n                        \"Danish\",\n                        \"Dutch\",\n                        \"English\",\n                        \"Esperanto\",\n                        \"Estonian\",\n                        \"Finnish\",\n                        \"French\",\n                        \"Frisian\",\n                        \"Galician\",\n                        \"Georgian\",\n                        \"German\",\n                        \"Greek\",\n                        \"Gujarati\",\n                        \"Haitian Creole\",\n                        \"Hausa\",\n                        \"Hawaiian\",\n                        \"Hebrew\",\n                        \"Hindi\",\n                        \"Hmong\",\n                        \"Hungarian\",\n                        \"Icelandic\",\n                        \"Igbo\",\n                        \"Indonesian\",\n                        \"Irish\",\n                        \"Italian\",\n                        \"Japanese\",\n                        \"Javanese\",\n                        \"Kannada\",\n                        \"Kazakh\",\n                        \"Khmer\",\n                        \"Korean\",\n                        \"Kurdish\",\n                        \"Kyrgyz\",\n                        \"Lao\",\n                        \"Latin\",\n                        \"Latvian\",\n                        \"Lithuanian\",\n                        \"Luxembourgish\",\n                        \"Macedonian\",\n                        \"Malagasy\",\n                        \"Malay\",\n                        \"Malayalam\",\n                        \"Maltese\",\n                        \"Maori\",\n                        \"Marathi\",\n                        \"Mongolian\",\n                        \"Myanmar\",\n                        \"Nepali\",\n                        \"Norwegian\",\n                        \"Nyanja\",\n                        \"Pashto\",\n                        \"Persian\",\n                        \"Polish\",\n                        \"Portuguese\",\n                        \"Punjabi\",\n                        \"Romanian\",\n                        \"Russian\",\n                        \"Samoan\",\n                        \"Scots Gaelic\",\n                        \"Serbian\",\n                        \"Sesotho\",\n                        \"Shona\",\n                        \"Sindhi\",\n                        \"Sinhala\",\n                        \"Slovak\",\n                        \"Slovenian\",\n                        \"Somali\",\n                        \"Spanish\",\n                        \"Sundanese\",\n                        \"Swahili\",\n                        \"Swedish\",\n                        \"Tagalog\",\n                        \"Tajik\",\n                        \"Tamil\",\n                        \"Telugu\",\n                        \"Thai\",\n                        \"Turkish\",\n                        \"Ukrainian\",\n                        \"Urdu\",\n                        \"Uyghur\",\n                        \"Uzbek\",\n                        \"Vietnamese\",\n                        \"Welsh\",\n                        \"Xhosa\",\n                        \"Yiddish\",\n                        \"Yoruba\",\n                        \"Zulu\"\n                    ],\n                    \"description\": \"The preferred target language\"\n                },\n                \"vscodeGoogleTranslate.proxyHost\": {\n                    \"type\": \"string\",\n                    \"description\": \"The proxy host (set it to enable proxy) (Optional)\"\n                },\n                \"vscodeGoogleTranslate.proxyPort\": {\n                    \"type\": \"string\",\n                    \"description\": \"The proxy port (Optional)\"\n                },\n                \"vscodeGoogleTranslate.proxyUsername\": {\n                    \"type\": \"string\",\n                    \"description\": \"The proxy username (Optional)\"\n                },\n                \"vscodeGoogleTranslate.proxyPassword\": {\n                    \"type\": \"string\",\n                    \"description\": \"The proxy password (Optional)\"\n                }\n            }\n        },\n        \"keybindings\": [\n            {\n                \"key\": \"alt+shift+t\",\n                \"when\": \"editorTextFocus\",\n                \"command\": \"extension.translateText\"\n            }\n        ]\n    },\n    \"scripts\": {\n        \"test\": \"node ./test/runTest.js\"\n    },\n    \"devDependencies\": {\n        \"@types/mocha\": \"^10.0.6\",\n        \"@types/node\": \"^20.11.24\",\n        \"@vscode/test-electron\": \"^2.5.2\",\n        \"eslint\": \"^8.56.0\",\n        \"glob\": \"^11.0.3\",\n        \"mocha\": \"^11.7.2\"\n    },\n    \"dependencies\": {\n        \"@types/vscode\": \"^1.84.0\",\n        \"@vitalets/google-translate-api\": \"^9.2.1\",\n        \"camelcase\": \"^8.0.0\",\n        \"he\": \"^1.2.0\",\n        \"http-proxy-agent\": \"^7.0.2\",\n        \"humanize-string\": \"^3.0.0\",\n        \"typescript\": \"^5.3.3\"\n    }\n}\n"
  },
  {
    "path": "src/commands.js",
    "content": "const vscode = require('vscode');\nconst he = require(\"he\");\nconst languages = require('../languages.js');\nconst {\n    recentlyUsed,\n    updateLanguageList,\n    getSelectedText,\n    getSelectedLineText,\n    getPreferredLanguage,\n    setPreferredLanguage,\n} = require('./utils');\nconst { getTranslationPromise } = require('./translate');\n\nfunction getTranslationsPromiseArray(selections, document, selectedLanguage) {\n    return selections.map((selection) => {\n      const selectedText = getSelectedText(document, selection);\n      return getTranslationPromise(selectedText, selectedLanguage, selection);\n    });\n  }\n  \n  function getTranslationsPromiseArrayLine(\n    selections,\n    document,\n    selectedLanguage\n  ) {\n    return selections.map((selection) => {\n      const selectedLineText = getSelectedLineText(document, selection);\n      return getTranslationPromise(selectedLineText, selectedLanguage, selection);\n    });\n  }\n\nfunction initializeCommands(context) {\n    const translateText = vscode.commands.registerCommand(\n        \"extension.translateText\",\n        function () {\n          const editor = vscode.window.activeTextEditor;\n          const { document, selections } = editor;\n    \n          const quickPickData = recentlyUsed\n            .map((r) => ({\n              label: r,\n              description: \"(recently used)\",\n            }))\n            .concat(languages.map((r) => ({ label: r.name })));\n    \n          vscode.window\n            .showQuickPick(quickPickData)\n            .then((selectedLanguage) => {\n              if (!selectedLanguage) return;\n              updateLanguageList(selectedLanguage.label);\n              const translationsPromiseArray = getTranslationsPromiseArray(\n                selections,\n                document,\n                languages.find((r) => r.name === selectedLanguage.label).value\n              );\n              Promise.all(translationsPromiseArray)\n                .then(function (results) {\n                  editor.edit((builder) => {\n                    results.forEach((r) => {\n                      if (!!r.translation) {\n                        builder.replace(r.selection, he.decode(r.translation));\n                      }\n                    });\n                  });\n                })\n                .catch((e) => vscode.window.showErrorMessage(e.message));\n            })\n            .catch((err) => {\n              vscode.window.showErrorMessage(err.message);\n            });\n        }\n      );\n      context.subscriptions.push(translateText);\n    \n      const setPreferredLanguageFnc = vscode.commands.registerCommand(\n        \"extension.setPreferredLanguage\",\n        setPreferredLanguage\n      );\n      context.subscriptions.push(setPreferredLanguageFnc);\n    \n      const translateTextPreferred = vscode.commands.registerCommand(\n        \"extension.translateTextPreferred\",\n        async function () {\n          const editor = vscode.window.activeTextEditor;\n          const { document, selections } = editor;\n    \n          // vscodeTranslate.preferredLanguage\n          const preferredLanguage = await getPreferredLanguage();\n          const locale = languages.find(\n            (element) => element.name === preferredLanguage\n          ).value;\n          if (!locale) {\n            return;\n          }\n    \n          const translationsPromiseArray = getTranslationsPromiseArray(\n            selections,\n            document,\n            locale\n          );\n          Promise.all(translationsPromiseArray)\n            .then(function (results) {\n              editor.edit((builder) => {\n                results.forEach((r) => {\n                  if (!!r.translation) {\n                    builder.replace(r.selection, he.decode(r.translation));\n                  }\n                });\n              });\n            })\n            .catch((e) => vscode.window.showErrorMessage(e.message));\n        }\n      );\n      context.subscriptions.push(translateTextPreferred);\n    \n      const translateLinesUnderCursor = vscode.commands.registerCommand(\n        \"extension.translateLinesUnderCursor\",\n        function translateLinesUnderCursorcallback() {\n          const editor = vscode.window.activeTextEditor;\n          const { document, selections } = editor;\n    \n          const quickPickData = recentlyUsed\n            .map((r) => ({\n              label: r.name,\n              description: \"(recently used)\",\n            }))\n            .concat(languages.map((r) => ({ label: r.name })));\n    \n          vscode.window\n            .showQuickPick(quickPickData)\n            .then((selectedLanguage) => {\n              if (!selectedLanguage) return;\n              updateLanguageList(selectedLanguage.label);\n              const translationsPromiseArray = getTranslationsPromiseArrayLine(\n                selections,\n                document,\n                languages.find((r) => r.name === selectedLanguage.label).value\n              );\n              Promise.all(translationsPromiseArray)\n                .then(function (results) {\n                  editor.edit((builder) => {\n                    results.forEach((r) => {\n                      if (!!r.translation) {\n                        const ffix = [\"\", \"\\n\"];\n                        if (\n                          editor.document.lineCount - 1 ===\n                          r.selection.start.line\n                        )\n                          [ffix[0], ffix[1]] = [ffix[1], ffix[0]];\n                        const p = new vscode.Position(r.selection.start.line + 1);\n                        builder.insert(p, `${ffix[0]}${r.translation}${ffix[1]}`);\n                      }\n                    });\n                  });\n                })\n                .catch((e) => vscode.window.showErrorMessage(e.message));\n            })\n            .catch((err) => {\n              vscode.window.showErrorMessage(err.message);\n            });\n        }\n      );\n    \n      context.subscriptions.push(translateLinesUnderCursor);\n    \n      const translateLinesUnderCursorPreferred = vscode.commands.registerCommand(\n        \"extension.translateLinesUnderCursorPreferred\",\n        async function translateLinesUnderCursorPreferredcallback() {\n          const editor = vscode.window.activeTextEditor;\n          const { document, selections } = editor;\n          const preferredLanguage = await getPreferredLanguage();\n          const locale = languages.find(\n            (element) => element.name === preferredLanguage\n          ).value;\n          if (!locale) {\n            vscode.window.showWarningMessage(\n              \"Prefered language is requeried for this feature! Please set this in the settings.\"\n            );\n            return;\n          }\n    \n          const translationsPromiseArray = getTranslationsPromiseArrayLine(\n            selections,\n            document,\n            locale\n          );\n    \n          Promise.all(translationsPromiseArray)\n            .then(function (results) {\n              editor.edit((builder) => {\n                results.forEach((r) => {\n                  if (!!r.translation) {\n                    const ffix = [\"\", \"\\n\"];\n                    if (editor.document.lineCount - 1 === r.selection.start.line)\n                      [ffix[0], ffix[1]] = [ffix[1], ffix[0]];\n                    const p = new vscode.Position(r.selection.start.line + 1);\n                    builder.insert(p, `${ffix[0]}${r.translation}${ffix[1]}`);\n                  }\n                });\n              });\n            })\n            .catch((e) => vscode.window.showErrorMessage(e.message));\n        }\n      );\n      context.subscriptions.push(translateLinesUnderCursorPreferred);\n}\n\nmodule.exports = { initializeCommands };\n"
  },
  {
    "path": "src/translate.js",
    "content": "const { translate: gti } = require(\"@vitalets/google-translate-api\");\nconst { HttpProxyAgent } = require('http-proxy-agent');\nconst humanizeString = require(\"humanize-string\");\nconst camelcase = require(\"camelcase\");\nconst { getProxyConfig } = require(\"./utils\");\n\nasync function translate(text, options) {\n    const translateOptions = {\n      to: options.to,\n      fetchOptions: {}\n    };\n  \n    if (options && options.proxy) {\n      const proxyUrl = `http://${options.proxy.auth ? `${options.proxy.auth.username}:${options.proxy.auth.password}@` : ''}${options.proxy.host}:${options.proxy.port}`;\n      translateOptions.fetchOptions.agent = new HttpProxyAgent(proxyUrl);\n    }\n  \n    const { text: translatedText } = await gti(text, translateOptions);\n    // The old code expected an object with a 'data' array. We'll mimic that.\n    return { data: [translatedText] };\n  }\n\n  async function getTranslationPromise(selectedText, selectedLanguage, selection) {\n    const { host, port, username, password } = getProxyConfig();\n    const translationConfiguration = {\n      to: selectedLanguage,\n    };\n    if (!!host) {\n      translationConfiguration.proxy = {\n        host,\n        port: Number(port),\n      };\n      if (!!username) {\n        translationConfiguration.proxy.auth = {\n          username,\n          password,\n        };\n      }\n    }\n  \n    try {\n      let res = await translate(selectedText, translationConfiguration);\n  \n      if (!!res && !!res.data) {\n        // If google rejects the string it will return the same string as input\n        // We can try to split the string into parts, then translate again. Then return it to a\n        // camel style casing\n        if (res.data[0] === selectedText) {\n          const humanizedRes = await translate(humanizeString(selectedText), translationConfiguration);\n          if (!!humanizedRes && !!humanizedRes.data) {\n            return {\n              selection,\n              translation: camelcase(humanizedRes.data[0]),\n            };\n          } else {\n            throw new Error(\"Google Translation API issue on fallback\");\n          }\n        } else {\n          return {\n            selection,\n            translation: res.data[0],\n          };\n        }\n      } else {\n        throw new Error(\"Google Translation API issue\");\n      }\n    } catch (e) {\n      // The original function returned a Promise.reject, so we'll throw an error\n      // which will be caught by the caller's .catch block.\n      throw new Error(\"Google Translation API issue: \" + e.message);\n    }\n  }\n\n  module.exports = {\n      getTranslationPromise\n  }\n"
  },
  {
    "path": "src/utils.js",
    "content": "const vscode = require('vscode');\nconst languages = require('../languages.js');\n\n/**\n * The list of recently used languages\n *\n * @type {Array.<string>}\n */\nconst recentlyUsed = [];\n\n/**\n * Updates languages lists for the convenience of users\n *\n * @param {string} selectedLanguage The language code to update\n * @returns {undefined}\n */\nfunction updateLanguageList(selectedLanguage) {\n  const index = recentlyUsed.findIndex((r) => r === selectedLanguage);\n  if (index !== -1) {\n    // Remove the recently used language from the list\n    recentlyUsed.splice(index, 1);\n  }\n  // Add the language in recently used languages\n  recentlyUsed.splice(0, 0, selectedLanguage);\n}\n\n/**\n * Extracts a text from the active document selection\n *\n * @param {vscode.TextDocument} document The current document\n * @param {vscode.Selection} selection The current selection\n * @returns {string} A text\n */\nfunction getSelectedText(document, selection) {\n  const charRange = new vscode.Range(\n    selection.start.line,\n    selection.start.character,\n    selection.end.line,\n    selection.end.character\n  );\n  return document.getText(charRange);\n}\n\n/**\n * Gets a text of the first line from active selection\n *\n * @param {vscode.TextDocument} document The current document\n * @param {vscode.Selection} selection The current selection\n * @returns {string}\n */\nfunction getSelectedLineText(document, selection) {\n  return document.getText(\n    document.lineAt(selection.start.line).rangeIncludingLineBreak\n  );\n}\n\n/**\n * Returns user settings Preferred language.\n * If user hasn't set preferred lang. Prompt to set.\n */\nfunction getPreferredLanguage() {\n  return (\n    vscode.workspace\n      .getConfiguration(\"vscodeGoogleTranslate\")\n      .get(\"preferredLanguage\") || setPreferredLanguage()\n  );\n}\n\nasync function setPreferredLanguage() {\n  const quickPickData = recentlyUsed\n    .map((r) => ({\n      label: r,\n      description: \"(recently used)\",\n    }))\n    .concat(languages.map((r) => ({ label: r.name })));\n\n  const selectedLanguage = await vscode.window.showQuickPick(quickPickData);\n  if (!selectedLanguage) {\n    return;\n  }\n  vscode.workspace\n    .getConfiguration()\n    .update(\n      \"vscodeGoogleTranslate.preferredLanguage\",\n      selectedLanguage.label,\n      vscode.ConfigurationTarget.Global\n    );\n  return selectedLanguage.label;\n}\n\n/**\n * Returns user settings proxy config\n *\n * @returns {string}\n */\nfunction getProxyConfig() {\n  const config = vscode.workspace.getConfiguration(\"vscodeGoogleTranslate\");\n  return {\n    host: config.get(\"proxyHost\"),\n    port: config.get(\"proxyPort\"),\n    username: config.get(\"proxyUsername\"),\n    password: config.get(\"proxyPassword\"),\n  };\n}\n\nmodule.exports = {\n    recentlyUsed,\n    updateLanguageList,\n    getSelectedText,\n    getSelectedLineText,\n    getPreferredLanguage,\n    setPreferredLanguage,\n    getProxyConfig\n}\n"
  },
  {
    "path": "test/runTest.js",
    "content": "const path = require('path');\nconst { runTests } = require('@vscode/test-electron');\n\nasync function main() {\n  try {\n    // The folder containing the Extension Manifest package.json\n    // Passed to `--extensionDevelopmentPath`\n    const extensionDevelopmentPath = path.resolve(__dirname, '../');\n\n    // The path to the extension test script\n    // Passed to --extensionTestsPath\n    const extensionTestsPath = path.resolve(__dirname, './suite/index');\n\n    // Download VS Code, unzip it and run the integration test\n    await runTests({ extensionDevelopmentPath, extensionTestsPath });\n  } catch (err) {\n    console.error('Failed to run tests');\n    process.exit(1);\n  }\n}\n\nmain();\n"
  },
  {
    "path": "test/suite/extension.test.js",
    "content": "/* global suite, test, setup */\nconst assert = require('assert');\nconst vscode = require('vscode');\n\nsuite(\"Extension Command Tests\", function() {\n    setup(async () => {\n        // Set a preferred language to avoid the quick pick menu\n        await vscode.workspace.getConfiguration('vscodeGoogleTranslate').update('preferredLanguage', 'French', vscode.ConfigurationTarget.Global);\n    });\n\n    test(\"Should translate selected text\", async () => {\n        const document = await vscode.workspace.openTextDocument({ content: 'Hello World' });\n        const editor = await vscode.window.showTextDocument(document);\n        \n        const originalText = 'Hello World';\n        editor.selection = new vscode.Selection(new vscode.Position(0, 0), new vscode.Position(0, originalText.length));\n\n        // Give a moment for the extension to activate if it hasn't already\n        await new Promise(resolve => setTimeout(resolve, 1000));\n\n        await vscode.commands.executeCommand('extension.translateTextPreferred');\n\n        // Add a delay to allow for the translation and edit to occur\n        await new Promise(resolve => setTimeout(resolve, 2000));\n\n        const newText = editor.document.getText();\n\n        // We don't know the exact translation, but it should not be the original text.\n        assert.notStrictEqual(newText, originalText);\n        // A very basic check to see if it could be the French translation\n        assert.ok(newText.toLowerCase().includes('bonjour'));\n    }).timeout(5000); // Increase timeout to allow for API calls\n});\n"
  },
  {
    "path": "test/suite/index.js",
    "content": "const path = require('path');\nconst Mocha = require('mocha');\nconst { glob } = require('glob');\n\nfunction run() {\n    // Create the mocha test\n    const mocha = new Mocha({\n        ui: 'tdd',\n        color: true\n    });\n\n    const testsRoot = path.resolve(__dirname, '.');\n\n    return new Promise((c, e) => {\n        glob('**/**.test.js', { cwd: testsRoot })\n            .then(files => {\n                // Add files to the test suite\n                files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));\n\n                try {\n                    // Run the mocha test\n                    mocha.run(failures => {\n                        if (failures > 0) {\n                            e(new Error(`${failures} tests failed.`));\n                        } else {\n                            c();\n                        }\n                    });\n                } catch (err) {\n                    console.error(err);\n                    e(err);\n                }\n            })\n            .catch(err => {\n                return e(err);\n            });\n    });\n}\n\nmodule.exports = {\n    run\n};\n"
  }
]