{"id":33838914,"url":"https://github.com/acidsugarx/babel.nvim","last_synced_at":"2026-03-01T16:05:22.679Z","repository":{"id":332327095,"uuid":"1111427695","full_name":"acidsugarx/babel.nvim","owner":"acidsugarx","description":"🌍 Translate text without leaving Neovim","archived":false,"fork":false,"pushed_at":"2025-12-07T13:17:47.000Z","size":42,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T13:48:08.018Z","etag":null,"topics":["neovim-plugin"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/acidsugarx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-06T23:05:55.000Z","updated_at":"2025-12-15T00:06:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/acidsugarx/babel.nvim","commit_stats":null,"previous_names":["acidsugarx/babel.nvim"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/acidsugarx/babel.nvim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acidsugarx%2Fbabel.nvim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acidsugarx%2Fbabel.nvim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acidsugarx%2Fbabel.nvim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acidsugarx%2Fbabel.nvim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/acidsugarx","download_url":"https://codeload.github.com/acidsugarx/babel.nvim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/acidsugarx%2Fbabel.nvim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29974342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T15:41:30.362Z","status":"ssl_error","status_checked_at":"2026-03-01T15:37:07.343Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["neovim-plugin"],"created_at":"2025-12-08T01:00:30.293Z","updated_at":"2026-03-01T16:05:22.674Z","avatar_url":"https://github.com/acidsugarx.png","language":"Lua","readme":"\u003cdiv align=\"center\"\u003e\n\n# 🌍 babel.nvim\n\n**Translate text without leaving Neovim**\n\n[![Neovim](https://img.shields.io/badge/Neovim-0.9+-57A143?style=for-the-badge\u0026logo=neovim\u0026logoColor=white\u0026color=a6e3a1)](https://neovim.io)\n[![Lua](https://img.shields.io/badge/Lua-5.1+-2C2D72?style=for-the-badge\u0026logo=lua\u0026logoColor=white\u0026color=89b4fa)](https://lua.org)\n[![License](https://img.shields.io/badge/License-MIT-pink?style=for-the-badge\u0026color=f5c2e7)](./LICENSE)\n\n\u003c/div\u003e\n\n---\n\n\u003c!-- TODO: Add GIF demo --\u003e\n\u003c!-- ![Demo](assets/demo.gif) --\u003e\n\n## ✨ Features\n\n- 🔤 Translate selected text or word under cursor\n- 🪟 Multiple display modes (float, picker)\n- 🔍 Auto-detect installed picker\n- 📋 Copy translation to clipboard with `y`\n- ⚡ Async translation (non-blocking)\n\n### Supported Pickers\n\n| Picker | Status |\n|--------|:------:|\n| Native float | ✅ |\n| [snacks.nvim](https://github.com/folke/snacks.nvim) | ✅ |\n| [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim) | ✅ |\n| [fzf-lua](https://github.com/ibhagwan/fzf-lua) | ✅ |\n| [mini.pick](https://github.com/echasnovski/mini.pick) | ✅ |\n\n## ⚡ Requirements\n\n- Neovim \u003e= 0.9.0\n- `curl`\n\n**Optional** (for picker display):\n\n- snacks.nvim, telescope.nvim, fzf-lua, or mini.pick\n\n## 📦 Installation\n\n### [lazy.nvim](https://github.com/folke/lazy.nvim)\n\n```lua\n{\n  \"acidsugarx/babel.nvim\",\n  version = \"*\", -- recomended for the latest tag, not main\n  opts = {\n    target = \"ru\",  -- target language\n  },\n  keys = {\n    { \"\u003cleader\u003etr\", mode = \"v\", desc = \"Translate selection\" },\n    { \"\u003cleader\u003etw\", desc = \"Translate word\" },\n  },\n}\n```\n\n## ⚙️ Configuration\n\n### Minimal Setup\n\n```lua\nrequire(\"babel\").setup({\n  target = \"ru\",\n})\n```\n\n### Full Options\n\n\u003cdetails\u003e\n\u003csummary\u003eDefault Configuration\u003c/summary\u003e\n\n```lua\nrequire(\"babel\").setup({\n  source = \"auto\",        -- source language (auto-detect)\n  target = \"ru\",          -- target language\n  provider = \"google\",    -- translation provider: \"google\", \"deepl\"\n  network = {\n    connect_timeout = 5,   -- curl connect timeout in seconds\n    request_timeout = 15,  -- max request time in seconds\n  },\n  cache = {\n    enabled = false,       -- enable in-memory translation cache\n    limit = 200,           -- max cache entries\n  },\n  history = {\n    enabled = false,       -- keep in-memory translation history\n    limit = 20,            -- max saved entries\n  },\n  fallback_chain = {\n    deepl = { \"google\" }, -- if DeepL fails, try Google\n    google = {},\n  },\n  display = \"float\",      -- \"float\" or \"picker\"\n  picker = \"auto\",        -- \"auto\", \"telescope\", \"fzf\", \"snacks\", \"mini\"\n  float = {\n    border = \"rounded\",\n    mode = \"center\", -- \"center\" or \"cursor\"\n    max_width = 80,\n    max_height = 20,\n    auto_close_ms = 0, -- auto-close delay, 0 = disabled\n    pin = true, -- allow pin toggle with `p` when auto-close is enabled\n    copy_original = false, -- allow copying original text with `Y`\n    nvim_open_win = {}, -- extra nvim_open_win() options (overrides defaults)\n  },\n  keymaps = {\n    translate = \"\u003cleader\u003etr\",\n    translate_word = \"\u003cleader\u003etw\",\n  },\n  -- DeepL provider settings (optional)\n  deepl = {\n    api_key = nil,        -- or use DEEPL_API_KEY env variable\n    pro = nil,            -- nil = auto-detect, true = Pro, false = Free\n    formality = \"default\", -- \"default\", \"more\", \"less\", \"prefer_more\", \"prefer_less\"\n  },\n})\n```\n\n\u003c/details\u003e\n\n### Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `source` | string | `\"auto\"` | Source language (auto-detect) |\n| `target` | string | `\"ru\"` | Target language code |\n| `provider` | string | `\"google\"` | Translation provider: `\"google\"`, `\"deepl\"` |\n| `network.connect_timeout` | number | `5` | Network connect timeout (seconds) |\n| `network.request_timeout` | number | `15` | Network request timeout (seconds) |\n| `cache.enabled` | boolean | `false` | Enable in-memory translation cache |\n| `cache.limit` | number | `200` | Maximum cache entries |\n| `history.enabled` | boolean | `false` | Enable in-memory translation history |\n| `history.limit` | number | `20` | Maximum stored history entries |\n| `fallback_chain` | table | `{ deepl = {\"google\"}, google = {} }` | Per-provider fallback chain |\n| `display` | string | `\"float\"` | Display mode: `\"float\"` or `\"picker\"` |\n| `picker` | string | `\"auto\"` | Picker: `\"auto\"`, `\"telescope\"`, `\"fzf\"`, `\"snacks\"`, `\"mini\"` |\n| `float.mode` | string | `\"center\"` | Float preset: `\"center\"` or `\"cursor\"` |\n| `float.auto_close_ms` | number | `0` | Auto-close timeout in milliseconds (`0` disables) |\n| `float.pin` | boolean | `true` | Enable pin toggle key (`p`) when auto-close is enabled |\n| `float.copy_original` | boolean | `false` | Enable copying original text with `Y` |\n| `float.nvim_open_win` | table | `{}` | Extra `nvim_open_win()` options for float window |\n| `deepl.api_key` | string | `nil` | DeepL API key (or use `DEEPL_API_KEY` env) |\n| `deepl.pro` | boolean | `nil` | Force Pro/Free endpoint (`nil` = auto-detect by key) |\n| `deepl.formality` | string | `\"default\"` | Formality: `\"default\"`, `\"more\"`, `\"less\"`, `\"prefer_more\"`, `\"prefer_less\"` |\n\n### Cursor-follow float preset\n\nFor a smaller popup that follows your cursor, use:\n\n```lua\nrequire(\"babel\").setup({\n  float = {\n    mode = \"cursor\",\n    max_width = 60,\n    max_height = 10,\n  },\n})\n```\n\n### Network timeout customization\n\nYou can tune provider request timeouts for slow/unstable networks:\n\n```lua\nrequire(\"babel\").setup({\n  network = {\n    connect_timeout = 3,\n    request_timeout = 25,\n  },\n})\n```\n\n### Translation history\n\nYou can keep the latest successful translations in memory:\n\n```lua\nrequire(\"babel\").setup({\n  history = {\n    enabled = true,\n    limit = 50,\n  },\n})\n```\n\n### Fallback chain and cache\n\nYou can control provider fallback behavior and enable in-memory caching:\n\n```lua\nrequire(\"babel\").setup({\n  provider = \"deepl\",\n  fallback_chain = {\n    deepl = { \"google\" },\n    google = {},\n  },\n  cache = {\n    enabled = true,\n    limit = 500,\n  },\n})\n```\n\n### Float window customization\n\nYou can override Babel's default float settings by passing options directly to `nvim_open_win()`:\n\n```lua\nrequire(\"babel\").setup({\n  float = {\n    max_width = 60,\n    max_height = 10,\n    nvim_open_win = {\n      relative = \"cursor\",\n      row = 1,\n      col = 0,\n      anchor = \"NW\",\n      border = \"single\",\n      title = \" Babel \",\n    },\n  },\n})\n```\n\n### Language Codes\n\n\u003cdetails\u003e\n\u003csummary\u003eCommon language codes\u003c/summary\u003e\n\n| Code | Language |\n|------|----------|\n| `en` | English |\n| `ru` | Russian |\n| `de` | German |\n| `fr` | French |\n| `es` | Spanish |\n| `it` | Italian |\n| `pt` | Portuguese |\n| `zh` | Chinese |\n| `ja` | Japanese |\n| `ko` | Korean |\n| `ar` | Arabic |\n| `hi` | Hindi |\n| `tr` | Turkish |\n| `pl` | Polish |\n| `uk` | Ukrainian |\n\n\u003c/details\u003e\n\n## 🚀 Usage\n\n### Keymaps\n\n| Keymap | Mode | Description |\n|--------|------|-------------|\n| `\u003cleader\u003etr` | Visual | Translate selection |\n| `\u003cleader\u003etw` | Normal | Translate word under cursor |\n\n### Commands\n\n| Command | Description |\n|---------|-------------|\n| `:Babel [text]` | Translate provided text |\n| `:[range]Babel` | Translate selected line range (e.g. `:10,20Babel`) |\n| `:BabelWord` | Translate word under cursor |\n| `:BabelRepeat` | Repeat last translation input |\n\n### In Translation Window\n\n| Key | Action |\n|-----|--------|\n| `q` / `\u003cEsc\u003e` / `\u003cCR\u003e` | Close window |\n| `y` | Copy translation to clipboard |\n| `Y` | Copy original text (if `float.copy_original = true`) |\n| `p` | Pin/unpin auto-close timer (if enabled) |\n| `j` / `k` | Scroll |\n\n## 🌐 Providers\n\n| Provider | Status | API Key | Notes |\n|----------|:------:|:-------:|-------|\n| Google Translate | ✅ | No | Default, unofficial API |\n| [DeepL](https://deepl.com) | 🧪 | Yes (free tier) | Best quality, 500k chars/month free |\n| [LibreTranslate](https://libretranslate.com) | 🔜 | No | Open source, self-hostable |\n| [Yandex](https://translate.yandex.ru) | 🔜 | Yes | Great for Russian |\n| [Lingva](https://lingva.ml) | 🔜 | No | Google proxy, no rate limits |\n\n### Provider capabilities\n\nYou can inspect provider capabilities from Lua:\n\n```lua\nlocal caps = require(\"babel\").get_provider_capabilities()\n-- caps.google.supports_formality == false\n-- caps.deepl.supports_formality == true\n\nlocal deepl = require(\"babel\").get_provider_capabilities(\"deepl\")\n```\n\n\u003e **🧪 Testing:** DeepL provider is implemented but needs testing. If you have a DeepL API key and want to help test, please [open an issue](https://github.com/acidsugarx/babel.nvim/issues) with your feedback!\n\n\u003cdetails\u003e\n\u003csummary\u003eDeepL Setup\u003c/summary\u003e\n\n1. Get a free API key at [deepl.com/pro#developer](https://www.deepl.com/pro#developer) (500k chars/month free)\n\n2. Set up the API key (choose one):\n\n   **Option A:** Environment variable\n   ```bash\n   export DEEPL_API_KEY=\"your-api-key-here\"\n   ```\n\n   **Option B:** In config\n   ```lua\n   require(\"babel\").setup({\n     provider = \"deepl\",\n     deepl = {\n       api_key = \"your-api-key-here\",\n     },\n   })\n   ```\n\n3. The endpoint (Free/Pro) is auto-detected from the key suffix (`:fx` = Free). You can override with `deepl.pro = true/false`.\n\n4. If no API key is found, babel.nvim will automatically fall back to Google Translate with a warning.\n\n\u003c/details\u003e\n\n## 🤝 Contributing\n\nContributions are welcome! Feel free to:\n\n- 🐛 Report bugs\n- 💡 Suggest features\n- 🔧 Submit pull requests\n\nIf you use AI coding assistants, check `AGENTS.md` for project architecture, quality gates, and safe-change checklist.\n\n## 🙏 Acknowledgments\n\nThanks to the amazing Neovim plugin ecosystem:\n\n- [folke](https://github.com/folke) for [snacks.nvim](https://github.com/folke/snacks.nvim) and [lazy.nvim](https://github.com/folke/lazy.nvim)\n- [nvim-telescope](https://github.com/nvim-telescope) for [telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)\n- [ibhagwan](https://github.com/ibhagwan) for [fzf-lua](https://github.com/ibhagwan/fzf-lua)\n- [echasnovski](https://github.com/echasnovski) for [mini.nvim](https://github.com/echasnovski/mini.nvim)\n\n## 📝 License\n\n[MIT](./LICENSE) © Ilya Gilev\n","funding_links":[],"categories":["Language"],"sub_categories":["Assembly"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facidsugarx%2Fbabel.nvim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Facidsugarx%2Fbabel.nvim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Facidsugarx%2Fbabel.nvim/lists"}