Герои сериала «Шерлок»
Привет! Я Алексей Тимин, инженер из команды локализации Badoo. В этом посте я расскажу вам о том, как мы помогаем переводчикам в их нелёгком труде, и о новом Open Source-решении, позволяющем генерировать скриншоты дизайна, подготовленного в Sketch, для разных языков.
Если вы создаёте дизайны для мультиязычных проектов или работаете в компании, разрабатывающей такие проекты, то информация будет вам полезной.
В команде локализации Badoo всего лишь два разработчика, но мы держимся и создаём очень интересные инструменты:
- Translation Memory
- Collaborative Translation Platform, доступной по адресу https://translate.badoo.com/,
- функционал предоставления корректного перевода конкретному пользователю (в зависимости от языка, пола, склонения, числа),
- система подготовки переводов для A/B-тестирования (да, мы проводим тестирование вариантов перевода, чтобы определить, какая формулировка лучше),
- десяток интерфейсов для работы переводчиков,
- сбор статистики по работе переводчиков и использованию ими инструментов.
Перечисленные инструменты призваны помочь в процессе локализации сайта Badoo, двух мобильных приложений Badoo (для Android и iOS), а также партнёрских приложений Chappy, Bumble, Huggle, Hot or Not на 47 языков. Это огромный фронт работ.
Наши переводчики работают с лексемами (так мы называем неделимую единицу перевода: слово или предложение). Для каждой лексемы подбирается формулировка оптимальной длины, чтобы обеспечить корректное отображение приложения на экранах пользователей. Иногда перевод должен быть не только корректным, но и привлекательным (например, для маркетинговых нужд).
Процесс перевода выглядит так:
- Дизайнеры рисуют.
- Программисты программируют.
- Переводчики переводят.
- Релиз.
Как видно, переводчики вынуждены ждать прототип приложения от программистов. Или, если произошли изменения в переводах, им необходимо попросить разработчиков собрать заново тестовую версию, чтобы проверить отображение. Но у нас зародилась идея максимально ограничить участие программистов в процессе перевода и ускорить подготовку релиза.
По нашей задумке, процесс должен выглядеть так:
- Дизайнеры рисуют.
- Программисты программируют, а переводчики – переводят и могут каким-то способом сразу видеть результат.
- Релиз.
Чтобы вам было проще представить проблему, привожу схемы процесса до и после. Красным на первой схеме выделен оптимизируемый участок:
Наши дизайнеры работают в графическом редакторе Sketch. Мы выяснили, что идущая вместе с ним утилита sketch-tool
умеет генерировать скриншоты, а это значит, при добавлении перевода есть возможность сразу показывать скриншот переводчику! Но возник вопрос: как заменить исходные тексты в дизайне, чтобы получить локализованный скриншот?
В перерывах между вечеринками мы обсуждали возможные варианты реализации идеи. И выход был найден.
Давайте разберёмся, как устроен .sketch-файл
изнутри.
Представление данных внутри .sketch-файла
В 43-й версии Sketch разработчики стали использовать новый формат .sketch-файла
для «лучшей интеграции со сторонними сервисами».
Логически в подготовленном в Sketch дизайне выделяются Pages, Artboards и графические элементы. Каждой сущности – Pages, Artboards и графическим элементам – один раз (в момент создания) присваивается уникальный идентификатор (UUID), который впоследствии не меняется.
Схематично связи между сущностями можно изобразить так:
Смотрите картинку ниже, чтобы понять, что есть что в интерфейсе Sketch: iPhone SE и iPhone 7 – две из возможных Artboards, a Page 1 – это одна из возможных Pages.
Сохранённый в .sketch-файл дизайн представляет собой ZIP-архив, внутри которого находятся директории с PNG- и JSON-файлами. Выглядит просто?
Если мы разархивируем .sketch-файл, то дерево директорий получится примерно таким:
Информация о каждой Page и связанных объектах Artboard хранится в pages/*.json. Именем файла служит UUID объекта Page, каждому объекту Page соответствует один файл.
Мы можем запросто открыть любой pages/*.json
и отредактировать, например, название одного из Artboards. Чтобы определить конкретный файл для редактирования, запускаем:
$ grep -l ‘iPhone 7’ pages/*
И если изменить название – не проблема, то изменить, допустим, текст «Нажми меня» на кнопке уже сложнее. После блуждания по форумам и безрезультатных поисков подходящей библиотеки мы поняли, что многие другие люди тоже ищут решение.
…смерть его на конце иглы, та игла в яйце, то яйцо в утке, та утка в зайце, тот заяц в сундуке, а сундук стоит на высоком дубу...
«Царевна-лягушка»
Текст на кнопке упакован в бинарный plist
, закодированный в строку Base64, являющуюся значением атрибута сериализованного JS-объекта, находящегося в одном из файлов, сжатых ZIP-ом.
Не будем касаться вопросов разархивирования и чтения JSON из файлов, но стоит сказать о формате Property Lists (bplist на схеме выше). Чтобы модифицировать текст «Нажми меня», можно использовать утилиту plutil
. Она позволяет вставить новое и удалить старое значение некоего свойства, а ещё с её помощью можно преобразовать plist из бинарного вида в XML и обратно. XML – удобный формат, для работы с ним существует множество инструментов. Также возможен экспорт в JSON, но, во-первых, при этом происходит потеря типов данных, а во-вторых, не всегда plist может быть сконвертирован в JSON. Например, с plist-ом из .sketch-файла экспорт в JSON не сработал.
Итак, мы разобрались с внутренним представлением и наконец переходим к вариантам реализации нашей задумки.
Выбор подходящей реализации
Вариант 1. Ленивое решение
Мы пытались рассказать переводчикам про JSON, Base64 и bplist, научить их самостоятельно заменять тексты переводами и делать скриншоты. Но когда им показали консольную команду экспорта превью
$ sketchtool export artboards --items='42C53146-F9BF-4EEE-A4F8-BB489F0A3CDA,BF38A95A-F0CD-452E-BE26-E346EBD349CE' --formats=png --save-for-web example_design.sketch
поняли, что этот вариант не годится.
(Шутка, ничего переводчикам мы не рассказывали, а сразу перешли ко второму варианту).
Вариант 2. True way
Переводчики не должны думать о технических вопросах. Просто нужно, чтобы при сохранении перевода им был предоставлен скриншот.
Для этого мы решили разработать сервис, минимальным функционалом которого стало бы:
- Определение в .sketch-файле UUID графических элементов, содержащих текст.
- Генерация скриншотов с локализованным текстом.
Проект получил название Sketch Modifier и был опубликован на GitHub.
Работа со Sketch Modifier
Чтобы начать использовать Sketch Modifier, нужно установить Node.js. на macOS (где конечно уже должен быть установлен Sketch https://www.sketchapp.com/). Да, Sketch есть только под macOS. Но если ваш дизайнер работает в Sketch, то как минимум один Mac у вас есть.
Рассмотрим процесс работы со Sketch Modifier по шагам.
Шаг 1. Установка
Находите компьютер под управлением macOS. Скачиваете и устанавливаете на него Node.js
, что совсем просто.
Далее скачиваете архив или клонируете репозиторий с GitHub командой
$ git clone https://github.com/AlexTimin/sketch-modifier.git
Переходите в директорию проекта
$ cd sketch-modifier
Устанавливаете зависимости с помощью npm:
$ npm install
И, наконец, запускаете сервер
$ ./bin/www
Всё, теперь по адресу http://localhost:3000
у вас должен отзываться сервер. Можете перейти по этому адресу в браузере и проверить.
Шаг 2. Загрузка .sketch
-файла и определение исходных текстов
Для примера возьмем example_design.sketch
и загрузим его в систему. Для этого нужно отправить запрос из директории, в которую вы сохранили example_design.sketch
:
$ curl -F 'data=@example_design.sketch' http://localhost:3000/add-sketch/
.sketch
-файлу будет присвоен UUID. В ответ вы получите JSON следующего вида:
{
"8a2009c5-36ca-4328-87d6-16aa0c2e2800": { // присвоенный example_design.sketch UUID, у вас он будет другой
"5A0F429A-C974-460A-9482-93AED7456850": { // Page 1 UUID
"C1C29749-B967-494D-8D7E-A484EAB37534": { // iPhone SE Artboard UUID
"E335D359-9DF3-4DCC-8B79-E77E38824714": "Нажми меня" // UUID текста на кнопке
}
… // информация по другим Artboards
}
… // информация по другим Pages
}
}
Можете сохранить эти данные себе в базу, отправить в /dev/null или сделать ещё что-нибудь интересное. Но мы сохраняем их в базу.
Шаг 3. Генерация переведённых превью
Чтобы заменить текст, нужно отправить запрос на адрес http://localhost:3000/generate-preview/
с указанием параметров screens
и textReplaces
. Список необходимых команд будет ниже, а пока разберёмся со структурой параметров запроса.
В параметре screens
мы указываем список UUID тех Artboards, скриншоты которых хотим получить. Значение параметра имеет такую структуру:
{
Example Design UUID: [ // example_design.sketch
Artboard UUID, // iPhone SE
...
]
}
В textReplaces
мы указываем UUID текстовых элементов и новый текст. Значение параметра имеет такую структуру:
{
Text UUID: "новый текст, перевод",
...
}
Итак, формируем запрос для генерации скриншота. Заменим текст «Нажми меня» на «Start the party!», например. Для этого нам понадобится файл generate-preview-request-data, в котором мы укажем значения параметров запроса.
Содержимое файла generate-preview-request-data
:
textReplaces={
"E335D359-9DF3-4DCC-8B79-E77E38824714": "Start the party!"
}&screens={
"8a2009c5-36ca-4328-87d6-16aa0c2e2800" : [
"C1C29749-B967-494D-8D7E-A484EAB37534"
]
}
Выполняем команду из директории, в которую вы сохранили файл generate-preview-request-data
.
$ curl -X POST -d "@generate-preview-request-data" http://localhost:3000/generate-preview/
В ответ вы получите скриншоты в Base64. Структура ответа будет такая:
{
"C1C29749-B967-494D-8D7E-A484EAB37534": "data:image/7HYUIY786GFFDASeY+...;base64",
...
}
Наверное, вы догадались, что ключом в структуре ответа является UUID запрошенного скриншота, а в значении записано представление скриншота (напомню, мы запрашивали скриншот для iPhone SE) в Base64.
Если вы сохраните, допустим, в example.html следующий код с подставленным Base64-представлением картинки
<img src="скриншот в Base64">
а потом откроете example.html в браузере, то увидите переведённый скриншот:
C помощью Sketch Modifier вы можете делать скриншоты до локализации, в процессе и после локализации, что очень важно. Вы будете видеть, как ведёт себя дизайн при использовании реальных текстов, и понимать, что нужно доработать.
Заключение
Мы настраиваем работу со Sketch Modifier таким образом, что дизайн загружается один раз, а скриншоты генерируются при сохранении переводов. Переводчики будут сразу видеть, умещаются ли выбранные формулировки переводов в заданных областях. А значит, о проблемах будет известно заранее.
Исходный код реализации находится на GitHub.
Пользуйтесь, советуйте способы усовершенствования, пишите отзывы.
Автор: aatimin