Автор: LinguaLeo
Почти с самого своего рождения Lingualeo замышлялся как глобальный сервис, с помощью которого студенты по всему миру будут учить английский язык. В качестве полигона для отработки процесса выхода на новые рынки была выбрана Бразилия.
Уже летом 2012 года перед командой встала задача — локализация сервиса Lingualeo на португальский язык. При этом необходимо было создать процесс, легко масштабируемый на другие языки.
Процесс локализации продукта рождался в Черногории, куда команда Lingualeo выезжала для интенсивной работы над новыми фичами. По первоначальной оценке на локализацию должно было потребоваться всего пару недель разработки перед тем, как систему можно будет отдать переводчикам. Оценки оказались чересчур оптимистичными, команда “встряла” на 1,5 месяца. Lingualeo прошла сложный путь и столкнулась с целым рядом проблем, которых другие могут избежать, прочитав этот пост до конца. Мы попросили Игоря Любимова, Head of localization, почетного ветерана локализации Lingualeo, пересказать сюжет в деталях.
Выбор системы
Для того, чтобы выбрать подходящий инструмент, необходимо было определить, какие задачи он будет решать. Прежде всего, нам было важно, чтобы продукт поддерживал локализацию на нескольких платформах: несколько форматов файлов для веб-сайта, Android-приложение, iOS-приложение, Windows Phone-приложение, а так же нас интересовал API — для тесной интеграции CI-системы и платформы для перевода.
Изначально мы рассматривали старый-добрый Pootle, так как наш бэкэнд был написан на PHP, и для локализации использовали gettext с .po-файлами. Быстро поняли, что это не наш вариант, так как для перевода JSON и прочих файлов приходилось писать кучу конвертеров – Pootle не поддерживал весь необходимый нам “зоопарк” форматов. Плюс, не хотелось хостить платформу для переводов у себя, потому начали искать какое-нибудь SaaS-решение.
Наши критерии для выбора: поддержка всех возможных форматов из коробки, возможность добавления новых строк через API, удобный менеджмент прав пользователей, высокий uptime, короткий срок интеграции, а также возможность запустить crowdsource-локализацию в будущем.
В итоге, мы остановились на простом, но функциональном сервисе WebTranslateIt.com (далее – “WTI”), так как он подходил под все наши требования.
Замечу, что если бы мы выбирали систему сейчас, то остановились бы на Crowdin. Она удобнее и интереснее той, которую мы используем, но не настолько, чтобы инвестировать в рефакторинг многих частей проекта.
Итак, WebTranslateIt.com. Это небольшая готовая SaaS-платформа, ее создал француз Эдуард Триер (Édouard Brière). 3-4 года назад она стала настоящей находкой для Lingualeo. На тот момент она нам очень понравилась. У нее было хорошее API и она отвечала основному требованию — возможность локализации различных форматов и платформ. Плюс, дружелюбный создатель очень оперативно отвечал на все вопросы и делал доработки специально для нас.
Кстати, мы написали и опубликовали в Open Source библиотеку под composer (PHP) для работы с WebTranslateIt.com: https://packagist.org/packages/lingualeo/wti-api. Ждём ваших пулл-реквестов!
Процесс интеграции
Веб, расширения для браузеров и мобильная версии
Основная задача, которая стояла перед нами, не нагружать разработчиков лишними задачами по обслуживанию локализации, а сделать все возможное для того, чтобы они были заняты непосредственно созданием продукта. Вопросы локализации должны быть вынесены из основоного workflow. Представляли мы себе это так: разработчик пишет новые строки, отправляет в систему (либо одной командой, либо вообще автоматически), а дальше они переводятся на несколько языков и возвращаются в проект, без каких-либо явных усилий разработчика. Мантра “Что может быть автоматизировано, то должно быть автоматизировано” часто проскакивает в разговорах наших разработчиков.
Наши размышления привели нас к созданию специальной утилиты, которая была призвана облегчить жизнь разработчиков. Для веб-сайта мы написали пару консольных утилит.
Первая добавляет новую строку в выбранный файл.
$ wti-add localizationFilename.json uniqueStringKey
Please provide russian text
> Привет, Хабр!
String is added
Иногда это бывает удобно, но наибольшую пользу приносит вторая утилита, которая парсит наши шаблоны, вытаскивает из них строки для локализации, добавляет их в WTI и делает прочую магию. Чтобы утилита правильно понимала, какие строки стоит переводить, а какие — нет, разработчикам надо просто обрамить соответсвующий текст символом @.
Пример для наших клиентских шаблонов:
<!– someTemplate.jst до локализации –>
<h1>Привет! Я Лео!</h1>
<!– someTemplate.jst подготовленный к локализации –>
<h1>@Привет! Я Лео!@</h1>
После этого выполняем:
$ wti-parse someTemplate.jst localizationFilename.json
1 string to add found
Please provide key for “Привет! Я Лео!”
> hi_i_am_leo
1 string parsed and added
И в WTI создается новая строка в файле someTemplate.jst с ключом hi_i_am_leo и русским текстом Привет! Я Лео!, а наш шаблон принимает другой вид:
<!– someTemplate.jst подготовленный к локализации –>
<h1><%=i18n.localizationFilename.hi_i_am_leo%></h1>
Разработчику остается только закомитить изменения и не париться о переводах.
Подобные парсеры были сделаны и для остальных форматов шаблонов, включая Twig и простые PHP-скрипты с бизнес-логикой. В зависимости от расширения файла, используются разные форматы замены плэйсхолдеров.
В своем процессе работы с git-ветками мы придерживаемся правил git-flow. Это позволяет нам связать CI-систему с задачами из Jira, помогает поддерживать порядок в репозитории, да и вообще, это круто. Раз по номеру тикета у нас опредляется ветка, почему бы её же не использовать и для определения строк для локализации? Вопрос “Какие строки были добавлены в рамках задачи DEV-1940?” снимется сам собой. Мы сделали апгрейд улититы wti-parse – она берет номер текущей ветки и добавляет все строки с дополнительной меткой задачи. В итоге в интерфейсе WTI это выглядит вот так:
Строки добавлены, программист идет дальше делать продукт, больше от него по части переводов ничего не требуется.
Далее, при каждой сборке на нашем CI-сервере, из WTI выгружаются последние версии переводов, и это работает, как часы 🙂
Курсы
В эту же систему мы интегрировали перевод курсов. Курсы – это не интрефейсные строки, их создают контент-менеджеры. Изначально мы пытались делать переводы вручную, через перессылку Word-файлов, но быстро поняли, что это плохая идея: это возможный, но абсолютно не масштабируемый процесс. Вскоре конструктор курсов был интегрирован с WTI. И теперь, как только контент–менеджеры Lingualeo производят какие-либо изменения в курсах (добавляют упражнения, изменяют формулировки и т.д.), они тут же отражаются в WTI. Все переводчики получают уведомления, и запускается выше описанный алгоритм. Таким образом, нам не нужно вручную управлять процессом перевода: всё работает автоматически.
Email-рассылки
Как и любой сервис, выстраивающий тесный диалог со своими пользователями, Lingualeo делает различные email-рассылки. Около 13 000 000 пользователей, десятки миллионов отправляемых писем каждый месяц – в нашем случае не было смысла реализовывать всю инфрастуктуру внутри, поэтому мы используем внешнего email-провайдера. Но вот беда: у нашего провайдера нет встроенных механизмов локализации шаблонов писем, и поэтому мы изобрели очередной “велосипед”, скрестив два API — Emarsys (а именно они рассылают все наши письма) и WTI.
Раз в 6 часов несколько скриптов забирают из Emarsys русские шаблоны писем, выделяют из них строки для локализации, формируют из них файлы для WTI, а из WTI забирают готовые переводы и создают в Emarsys шаблоны на нужных языках. А уже в настройках рассылок используются те или иные шаблоны, в зависимости от родного языка пользователя.
Процесс работы с переводчиками
Для одновременного перевода на несколько языков мы придерживаемся следующей схемы работы. Сначала создаем строки на русском, потом переводим на английский язык, а с английского — на остальные языки (турецкий, испанский, португальский, пара испанских диалектов и т.д.).
Мы договорились, что переводчик на английский язык заходит в систему во вторник и четверг с утра. Забирает строки, и в течение нескольких часов готовит все необходимые переводы. Переводчики на остальные языки заходят в те же самые дни, но вечером. Таким образом, в течение суток мы получаем все переводы. График подстроен под наш цикл релизов для того, чтобы у нас вовремя появлялись новые строки. Конечно, иногда все-таки бывают проблемы, но это случается только тогда, когда разработчик в самый последний момент добавил строки, она была быстро протестирована и уже на следующий день ушла в релиз.
Эта система подходит не только для работы с агентствами по переводу, фри-лансерами или штатными переводчиками, но и для использования крауд-сорсинга в переводе. Когда мы запустили проект “Переведи Lingualeo” и пригласили наших пользователей перевести хотя бы несколько строк на знакомые им языки, мы создали лэндинг и интегрировали страничку со статистикой из WTI с сайтом.
Так выглядит форма для перевода фраз:
Интернационализация
В результате, была разработана технологическая платформа и процессы локализации Lingualeo. Это работает и для веба и для мобильных приложений, не требуя постоянного участия членов команды. Локализация прозрачна для разработчиков: они просто пишут код, разрабатывают продукт для целевых рынков. Переводчики делают свою работу независимо от них. Сегодня добавление готовых переводов занимает всего 1-2 дня.
Конечно, перевод продукта – это лишь часть процесса по подготовке продукта к запуску на новых языковых рынках. Локальные валюты, платежные системы, словари для новых языков, создание специальных курсов, заведение групп в социальных сетях на новых языках – все эти активности также максимально упрощены и автоматизированны. Весь процесс настройки сводится к правке нескольких YML-файлов конфигурации, и требуется буквально несколько часов на настройку всего окружения. Но это уже материал для следующей статьи.