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.