All articles
Article
July 23, 20266 min

Translation and localization: which models are strong in Russian

LLMs translate better than classic engines if you set the task properly. Glossaries, tone, preserving markup, and choosing a model for Russian.

Yenisei team


Translation and localization: which models are strong in Russian

LLMs have overtaken classic translators where context matters: they know that "bank" in a text about a river is a riverbank, and they do not translate product names. But for that to work, you have to set the task the way you would for a human translator, not a "translate" button.

Which models are strong in Russian

Not all models are equally good in Russian; many are trained mostly on English and produce calques.

  • DeepSeek, Qwen write clean Russian, with no Latin letters in the middle of a phrase and no borrowed words where a normal one exists.
  • Yenisei Max (yenisei-max) is strong on localization and conveys register and style well.
  • Test on your own domain: legal Russian and conversational Russian are different tasks, and a model can be good at one and weak at the other.

Set the task as you would for a human

Bad: "translate into Russian". Good: with context and requirements:

system = """You are a professional translator of IT documentation, EN to RU.
Rules:
- Translate glossary terms strictly according to the glossary.
- Do NOT translate product names, API methods, or code.
- Tone: technical, formal address, no bureaucratic language.
- Preserve the Markdown markup and the order of paragraphs."""

A glossary is mandatory

Without a glossary the model will translate one term three ways across three pages. Feed it straight into the prompt:

glossary = {"deployment": "развёртывание", "rollback": "откат",
"endpoint": "эндпоинт", "rate limit": "лимит запросов"}
system += "\n\nGlossary:\n" + "\n".join(f"{k} → {v}" for k, v in glossary.items())

Preserving markup

The main pain of machine translation is broken markup: the model eats **, translates text inside code blocks, mangles placeholders like {count}. Forbid this explicitly in the prompt and check the result with a regex for balanced tags. Placeholders are best protected: replace them with __PH_0__ before translating and restore them afterwards.

Batches and consistency

Translate related strings in one request rather than one at a time: that way the model keeps a uniform tone and terminology. For interface strings, pass them as a keyed list:

resp = client.chat.completions.create(
model="deepseek-pro",
messages=[{"role": "system", "content": system},
{"role": "user", "content": json.dumps(strings, ensure_ascii=False)}],
temperature=0.2,
response_format={"type": "json_object"},
)

A low temperature is critical for translation: 0.1 to 0.3. Freedom of phrasing only gets in the way here.

Pitfalls

  • Too literal or too loose. Ask for "natural Russian, not a word-for-word gloss, but nothing added".
  • Form of address. The model jumps between the informal and the formal "you". Fix it explicitly.
  • Units and formats. Dates, currencies, decimal separators for the locale: either ask to adapt them or leave them as they are, but decide in advance.

For quality control, run back-translation on a sample: RU to EN, then compare the meaning with the original. It is a cheap way to catch gross distortions before release.