10 шокирующих фактов о JSON Translator: как перевести ваш код за секунды и избавиться от рутины локализации
14 ноября 2025 г.Вступление
Локализация – один из самых «мокрых» и одновременно критически важных процессов в разработке современных веб‑ и мобильных приложений. Когда приложение выходит на международный рынок, каждый пользователь ожидает увидеть интерфейс на своём родном языке, а значит, каждый текстовый ресурс должен быть корректно переведён. Традиционно этим занимаются переводчики, сторонние сервисы и, конечно, разработчики, которые вручную копируют строки в файлы ресурсов. Но чем больше растёт количество языков и сложность структуры данных (JSON, YAML, XML), тем громоздче становится процесс.
В прошлом году одна команда создала XML Strings Translator для Android‑приложения, а затем, улучшив веб‑версию, поняла, что им нужен аналогичный инструмент для JSON‑файлов. За выходные они построили JSON Translator, который обещает переводить JSON‑данные более чем на 130 языков, поддерживает загрузку целых файлов и даже позволяет переводить сразу в несколько языков.
Эта история – отличный пример того, как небольшая идея может превратиться в полноценный продукт, способный решить реальную проблему тысяч разработчиков. Ниже мы разберём пост, комментарии, технические детали и предложим практические рекомендации.
И в завершение вступления – японский хокку, отражающий суть поиска простого решения в сложном мире кода:
Код как река,
Перевод – тихий мост,
Тишина в строках.
Пересказ Reddit‑поста своими словами
Автор поста (пользователь combinecrab) рассказал, что их команда в прошлом году разработала переводчик XML‑строк, чтобы решить задачу локализации Android‑приложения. Позже они улучшили веб‑версию и заметили, что им не хватает аналогичного инструмента для JSON‑данных, которые используют в большинстве современных веб‑приложений.
В результате за один уик‑энд они создали JSON Translator. Инструмент умеет:
- Переводить любой JSON‑объект более чем на 130 языков.
- Принимать целый JSON‑файл через загрузку.
- Переводить сразу в несколько целевых языков – процесс идёт последовательно, но результаты появляются по мере готовности.
Ссылка на сервис: https://jsontranslator.com. Автор приглашает всех протестировать, оставить отзывы и предложения.
Суть проблемы, хакерский подход и основные тенденции
Проблема локализации в JSON‑файлах состоит в трёх основных аспектах:
- Масштабируемость. При росте количества поддерживаемых языков каждый новый перевод требует отдельного файла или ветки в репозитории.
- Контекстность. Машинный перевод часто «теряет» смысл, особенно в технических терминах, названиях брендов и юридических формулировок.
- Автоматизация. Разработчики ищут способы интегрировать перевод в CI/CD‑pipeline, чтобы не тратить часы на ручную правку.
Хакерский подход к решению – использовать готовые API машинного перевода (Google, DeepL, Yandex) и обернуть их в удобный веб‑интерфейс, который принимает JSON, разбирает его на отдельные строки, переводит и собирает обратно. При этом важно сохранять структуру, типы данных и специальные ключи, которые не должны переводиться.
Тенденции 2024‑го года:
- Рост популярности LLM‑моделей (Large Language Models) для контекстного перевода.
- Интеграция переводов непосредственно в IDE (расширения типа i18n‑ally).
- Увеличение количества «no‑translate»‑правил, позволяющих исключать из перевода имена брендов, коды, технические термины.
Детальный разбор проблемы с разных сторон
Техническая сторона
JSON – это лёгкий формат, но в нём могут скрываться сложные структуры: вложенные объекты, массивы, динамические ключи. При переводе необходимо:
- Рекурсивно обходить дерево, находя только строковые значения.
- Сохранять порядок и типы (числа, булевы значения, null) без изменений.
- Обрабатывать специальные символы (HTML‑теги, переменные вида
{username}).
Если переводчик «переведёт» такие переменные, приложение может сломаться.
Лингвистическая сторона
Машинный перевод часто «транслитерирует» вместо «переводит», особенно для языков с разными алфавитами. Это критично для юридических текстов, названий компаний и технической терминологии. Пользователь magenta_placenta в комментариях указал, что иногда нужно исключать из перевода определённые ключи (например, названия штатов США).
Юридическая сторона
Сервис имеет Disclaimer of Warranties, но пользователь magenta_placenta задаётся вопросом о юридической ответственности за автоматический перевод юридических документов. Без проверки человеком такие переводы могут стать причиной недоразумений.
Экономическая сторона
Стоимость API машинного перевода может быстро расти при больших объёмах данных. Инструмент, который позволяет переводить «по запросу», а не «по подписке», может быть более привлекательным для небольших стартапов.
Практические примеры и кейсы
Рассмотрим два типичных сценария.
Кейс 1: Перевод интерфейса SaaS‑продукта
Компания «Acme SaaS» поддерживает 12 языков. Каждый релиз добавляет новые строки в en.json. Раньше переводчики получали файл, переводили вручную и отправляли обратно. С JSON Translator процесс выглядит так:
- Разработчик загружает
en.jsonв сервис. - Выбирает целевые языки (es, fr, de, ru, zh).
- Сервис переводит и возвращает готовые файлы
es.json,fr.jsonи т.д. - Файлы автоматически коммитятся в репозиторий через CI‑pipeline.
В результате время на локализацию сократилось с 3 дней до 2 часов.
Кейс 2: Исключение из перевода технических терминов
В приложении есть список стран и их кодов. Переводать названия стран нужно, а коды (ISO‑3166) – нет. С помощью правила «no‑translate» можно указать, что ключи code и id остаются без изменений. Это реализуется через конфигурационный файл ignore_keys.json:
{
"ignore_keys": ["code", "id", "company_name"]
}
Сервис читает этот файл и пропускает указанные поля.
Экспертные мнения из комментариев
«I had the same idea a few months ago and was very proud of how quickly I made the translator... if only I had googled the problem, I would have found a solution much quicker» – combinecrab
Автор признаёт, что поиск готовых решений мог бы ускорить процесс. Это подчёркивает важность сообщества и открытого кода.
«I came across this vscode extension which builds the translations directly into the IDE so you can see how the string translates in different languages (directly in the code). It also tells you if there are any missing keys in any languages» – combinecrab
Расширение i18n‑ally позволяет видеть переводы в реальном времени и проверять полноту локализации. Это альтернатива веб‑сервису, интегрированная в рабочий процесс.
«this is something not even the most advanced translating tool out there can do, and you expect a random guy from reddit?» – Hot‑Charge198
Скептицизм относительно качества автоматического перевода подчёркивает, что даже лучшие сервисы не заменят человеческую проверку.
«Can it handle not translating certain keys or sub‑trees? ... Your Disclaimer of Warranties looks moderately OK to me, but IANAL. Did you happen to run that by a lawyer? I'd be mostly concerned with people blindly translating legalese content and just running with it without personal review.» – magenta_placenta
Вопрос о гибкости инструмента и юридических рисках – важные аспекты, которые следует учитывать при внедрении.
«I did come across that extension however it uses normal machine translation and relies on services like Google Translate and DeepML. They tend to transliterate strings instead of contextual translation for a lot of languages hence we decided to not go that route.» – idris3396
Автор отмечает, что обычные API часто «транслитерируют», а не «переводят» контекстно, что делает их менее пригодными для сложных языков.
Возможные решения и рекомендации
- Выбор подходящего API. Для большинства языков подойдёт Google Translate, но для европейских языков лучше DeepL, а для азиатских – специализированные модели.
- Настройка правил исключения. Создайте файл
ignore_keys.jsonи интегрируйте его в процесс перевода. - Контекстный перевод. Используйте LLM‑модели (например, OpenAI GPT‑4) для перевода фраз, где важен смысл, а не дословный перевод.
- Интеграция в CI/CD. Автоматизируйте загрузку, перевод и коммит новых файлов через скрипты.
- Пост‑переводная проверка. Запускайте линтеры, проверяющие отсутствие незаполненных переменных (
{username}) и корректность JSON‑синтаксиса. - Юридический аудит. Для юридических текстов всегда привлекайте профессионального переводчика, даже если предварительно использовали машинный перевод.
Заключение с прогнозом развития
JSON Translator – яркий пример того, как небольшая команда может решить реальную проблему, используя готовые API и открытый код. В ближайшие годы мы ожидаем:
- Увеличения роли LLM‑моделей в контекстном переводе, что повысит точность и уменьшит количество «транслитераций».
- Более тесной интеграции переводчиков в IDE и CI‑системы, что сделает процесс локализации почти полностью автоматическим.
- Расширения возможностей «no‑translate»‑правил, позволяющих задавать сложные условия (регулярные выражения, типы данных).
- Повышения требований к юридической ответственности сервисов, предлагающих автоматический перевод.
Для разработчиков это значит, что в ближайшие годы локализация будет всё менее «ручной» и всё более «интеллектуальной». Главное – не забывать проверять результаты и сохранять контроль над тем, что именно переводится.
Практический пример на Python
Ниже представлен скрипт, который демонстрирует, как можно автоматизировать процесс перевода JSON‑файла, учитывая правила «не переводить» и используя сервис DeepL (в примере – условный API‑ключ). Скрипт:
# -*- coding: utf-8 -*-
"""
Пример автоматического перевода JSON‑файла с учётом исключений.
Используется API DeepL (https://www.deepl.com/docs-api).
"""
import json
import os
import requests
from typing import Any, Dict, List
# ----------------------------------------------------------------------
# Конфигурация
# ----------------------------------------------------------------------
DEEPL_API_KEY = os.getenv('DEEPL_API_KEY') # ключ берётся из переменной окружения
DEEPL_ENDPOINT = 'https://api-free.deepl.com/v2/translate'
TARGET_LANGUAGES = ['DE', 'FR', 'RU'] # коды целевых языков (Deutsch, Français, Русский)
IGNORE_KEYS = {'code', 'id', 'company_name'} # ключи, которые не переводятся
def load_json(path: str) -> Dict[str, Any]:
"""Загружает JSON‑файл."""
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
def save_json(data: Dict[str, Any], path: str) -> None:
"""Сохраняет словарь в JSON‑файл с отступами."""
with open(path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
def translate_text(text: str, target_lang: str) -> str:
"""
Переводит одиночную строку через DeepL.
Args:
text: Текст для перевода.
target_lang: Целевой язык (например, 'DE', 'FR', 'RU').
Returns:
Переведённый текст.
"""
payload = {
'auth_key': DEEPL_API_KEY,
'text': text,
'target_lang': target_lang
}
response = requests.post(DEEPL_ENDPOINT, data=payload)
response.raise_for_status()
result = response.json()
return result['translations'][0]['text']
def recursive_translate(
obj: Any,
target_lang: str,
path: List[str] = None
) -> Any:
"""
Рекурсивно проходит по структуре JSON и переводит только строковые значения,
пропуская ключи из IGNORE_KEYS.
Args:
obj: Текущий элемент (dict, list, str, int, ...).
target_lang: Целевой язык.
path: Текущий путь в дереве (для отладки).
Returns:
Новый объект с переведёнными строками.
"""
if path is None:
path = []
if isinstance(obj, dict):
new_dict = {}
for k, v in obj.items():
# Если ключ в списке игнорируемых – оставляем значение без изменений
if k in IGNORE_KEYS:
new_dict[k] = v
continue
new_path = path + [k]
new_dict[k] = recursive_translate(v, target_lang, new_path)
return new_dict
if isinstance(obj, list):
return [recursive_translate(item, target_lang, path + [f'[{i}]']) for i, item in enumerate(obj)]
if isinstance(obj, str):
# Пропускаем строки, содержащие шаблоны вида {variable}
if '{' in obj and '}' in obj:
return obj
try:
return translate_text(obj, target_lang)
except Exception as e:
# В случае ошибки возвращаем оригинал и выводим предупреждение
print(f'Ошибка перевода по пути {".".join(path)}: {e}')
return obj
# Для всех остальных типов (int, float, bool, None) возвращаем как есть
return obj
def translate_json_file(input_path: str, output_dir: str) -> None:
"""
Переводит один JSON‑файл во все целевые языки и сохраняет результаты.
Args:
input_path: Путь к исходному файлу (английская версия).
output_dir: Папка, куда будут записаны переведённые файлы.
"""
data = load_json(input_path)
base_name = os.path.splitext(os.path.basename(input_path))[0]
for lang in TARGET_LANGUAGES:
print(f'Переводим в {lang}...')
translated = recursive_translate(data, lang)
out_path = os.path.join(output_dir, f'{base_name}_{lang.lower()}.json')
save_json(translated, out_path)
print(f'Сохранено: {out_path}')
if __name__ == '__main__':
# Пример использования:
INPUT_JSON = 'locales/en.json' # исходный файл
OUTPUT_DIR = 'locales/translated' # директория для результатов
os.makedirs(OUTPUT_DIR, exist_ok=True)
translate_json_file(INPUT_JSON, OUTPUT_DIR)
Скрипт рекурсивно обходит JSON‑структуру, переводит только строки, оставляя без изменений ключи из IGNORE_KEYS и шаблоны вида {username}. Для каждого целевого языка создаётся отдельный файл, что упрощает дальнейшую интеграцию в проект.
Оригинал