DE

DeepL-Powered Auto-Translation in Neovim

Documentations, articles, and blogs are often made available in multiple languages. Machine translations are an effective means to get started. While the results of online services like DeepL or Google Translate are far from perfect, personally I find it more convenient to improve upon their suggestions rather than translating from scratch.

With translate.nvim, these services can be integrated into Neovim. It provides a custom command to quickly translate lines or selected portions of text. The response is almost instantaneous and accurately handles Markdown or similar syntax.

DeepL

The plugin uses Google Translate by default but also supports DeepL, which currently outperforms its main competitor in benchmarks. In addition, other services can be accessed via Translate Shell.

An API key is required for DeepL, so you’ll have to register if you want to use the service. After logging in, click your initials at the top, navigate to Account, and open the API Keys tab to create the necessary key.

Users of the free version can use all functions and translate up to 500,000 characters per month. For many purposes this should be more than enough. DeepL Write is not yet part of the API, which is why LSP-supported style diagnoses unfortunately won’t be possible at the moment.

Configuration

As usual, translate.nvim can quickly be installed via a plugin manager like lazy.nvim:

  {
    "uga-rosa/translate.nvim",
    lazy = true,
  },

The translations provided by the service can be displayed in various ways, for example in a pop-up window, in a new split or in the buffer next to the line from which it was generated. We want to use the plugin so that the input text in the buffer is replaced by the translation. To do this, "replace" is set as output.

The required API key must be stored in the deepl_api_auth_key variable. The key should not be entered directly, especially if you store your dotfiles in a public repository. Instead, we can save the information in a separate file and read it from there.

The configuration can be saved under after/plugins/translate.lua:

local filepath_to_authkey = vim.fn.expand("~/.secrets/deepl")
vim.g.deepl_api_auth_key = vim.fn.readfile(filepath_to_authkey)[1]

require("translate").setup({
  default = {
    command = "deepl_free",
    output = "replace",
  },
})

Usage

For translations, the plugin provides a custom command with the following synopsis:

:[range]Translate {target-lang} [{-options}...]

With the given configuration, :Translate en would insert the English translation of the current line into the buffer. The source language is detected automatically.

In addition to translating the current line, we can visually select the input. The range is injected into the command when switching from visual mode to command-line mode, so that’s why you see the preceding '<,'> when hitting :. You can either use V to select multiple lines, or v to select individual parts of a line.

For selection by text-objects as well as a more convenient usage in general, key bindings can be defined:

vim.keymap.set("n", "tee", ":Translate EN<CR>", { desc = 'Translate line into English', noremap = true, silent = true })
vim.keymap.set("v", "tee", ":'<,'>Translate EN<CR>", { desc = 'Translate selection into English', noremap = true, silent = true })
vim.keymap.set("n", "tce", ":Translate EN -comment<CR>", { desc = 'Translate comments into English', noremap = true, silent = true })
vim.keymap.set("n", "tw", "viw:Translate EN<CR>", { desc = 'Translate word into English', noremap = true, silent = true })

Article from November 26, 2024.