В английской версии недавно выпущенного анализатора Cache-Control отображался японский текст: вместо «Fresh» статус был «新鮮». Ошибка была вызвана общей логикой, которая возвращала жестко закодированные японские строки, в то время как сама страница предоставляла только английские метки.

Разработчик создает серию легковесных браузерных инструментов, каждый из которых имеет английскую и японскую версии страниц, использующие одни и те же функции парсинга и основную логику. Должны различаться только видимые формулировки. Когда анализатор Cache-Control был выпущен, английский интерфейс отображал правильные метки, но значения, которые он выводил, поступали из уровня логики, где все еще содержались японские литералы. Ошибок в консоли не было; страница выглядела нормально, однако информация, представленная англоязычным пользователям, была неверной.

Почему общая логика может подвести при переводе

Баг стал следствием архитектурного решения: основная функция, определяющая, что именно нужно показать, возвращала строковые литералы на японском языке. Уровень страницы, отвечающий за окружающий английский текст, так и не получил возможности заменить эти значения. Поскольку логика и UI были четко разделены, проблема оставалась незаметной во время тестирования — технически всё «работало», хотя язык, отображаемый пользователю, был неверным.

Недостаток заключается в том, что язык, используемый внутри общего модуля, становится языком по умолчанию для любого фронтенда, который его использует. Если требуется другой язык, этот «дефолт» превращается в скрытый баг.

Исправление: ключи, пакеты и страховочная сетка

Автор переписал архитектуру, чтобы разделить зоны ответственности:

  • Пакеты сообщений теперь содержат все читаемые человеком строки для каждого языка.
  • Общая логика возвращает только символьные ключи, а не сырой текст.
  • Страницы ищут подходящее слово в соответствующем пакете на основе ключа.

Если сообщение должно включать число, новый код использует небольшую функцию вместо шаблонной строки. Это позволяет каждому языку самостоятельно определять место для числа, учитывая различия в порядке слов.

Также был добавлен простой этап статического анализа: процесс сборки сканирует общие файлы на наличие японских символов. Если они обнаруживаются, разработчик немедленно получает уведомление, что предотвращает повторное появление жестко закодированного иностранного текста.

Чему этот опыт научил автора

  1. Перевод служит этапом проверки. При написании английских сообщений автор заметил, что некоторые японские эквиваленты были расплывчатыми. Перевод заставил использовать более четкие формулировки на обоих языках.
  2. Общие функции, возвращающие строки, фиксируют язык для всех. Если функция сама определяет язык, любой потребитель, ожидающий другой язык, наследует эту ошибку. Баг — это не сбой UI, а ошибка в логике.

Рекомендации для тех, кто поддерживает многоязычные инструменты

  • Возвращайте ключи, а не строки, из основных функций. Позвольте уровню UI заниматься локализацией.
  • Или передавайте нужные строки в функцию в качестве параметров. Это сделает логику независимой от языка.
  • Проверяйте общие модули на наличие жестко закодированного текста на родном языке. Быстрый поиск не-ASCII символов поможет выявить скрытые проблемы.
  • Добавьте проверку наличия иностранных символов в общем коде на этапе сборки. Раннее обнаружение лучше, чем путаница после релиза.

На что обратить внимание в будущем

Вывод: Если в вашем проекте код разделяется между языковыми версиями, убедитесь, что общая часть никогда не определяет формулировки. Пусть каждая страница предоставляет свои собственные слова, и тогда вы избежите неловкости, когда английская страница внезапно начинает говорить по-японски.