- PVSM.RU - https://www.pvsm.ru -

Всем доброго времени суток! Меня зовут Николай, я iOS-Lead в компании Touch Instinct [1]. В процессе разработки часто приходится иметь дело с проектами, которые должны работать на нескольких языках. Расскажу, к какому подходу мы пришли при работе с локализацией.
Есть несколько основных подходов для локализации iOS-приложения. Сперва стоит определиться, разрабатывается приложение с использованием storyboards или нет.
Можно локализовывать строки напрямую в storyboard. Однако, при таком подходе есть ряд минусов:
В этом случае локализуем всё в коде. Однако и тут есть ряд минусов. Дело в том, что файлы со строками локализации localizable.strings — магические. При изменении таких файлов очень велика вероятность возникновения ошибки из-за человеческого фактора. Изменения нельзя отследить, пока ошибка не будет найдена в процессе тестирования.
Таким образом, хотя для локализации уже есть готовые механизмы в iOS SDK, они имеют существенные минусы. Более подробно смотрите здесь [2].
Если стандартные решения не справляются, не стоит сразу бросаться делать свой «велосипед». Сформулируйте цели, которые нужно достичь.
Основные критерии, которым должно удовлетворять будущее решение:
Для начала необходимо создать отдельный репозиторий в используемой вами системе контроля версий. Что должно храниться в данном репозитории? Всё просто. Здесь хранятся json файлы вида common_strings_eng.json/common_strings_ru.json/etc. Под каждый язык создается отдельный json файл.
Рассмотрим содержание таких файлов. Json представляет из себя текстовый формат описания данных в виде пар key-value, поэтому мы создаем ключ-наименование для каждой локализованной строки и используем его во всех файлах. Value же является локализованным значением и будет отображаться в самом приложении.
В нашей компании есть styleguide [3], чтобы унифицировать ключи во всех приложениях и сделать их консистентными в рамках каждого проекта.
У внимательного читателя может возникнуть несколько вопросов:
1) При заполнении файлов json можно допустить ошибку и, к примеру, забыть заполнить value для какого-то ключа в определенном языке?
Да, это верно. Однако здесь ответственность эскалируется уже на уровень переводчика или одного-единственного человека. При этом с легкостью можно создать скрипт, который пройдет по всем файлам json и покажет, где и чего не хватает в файлах.
2) В данной системе используется «старинная» система для работы с Plural [4]. Удобно ли это?
Небольшой ликбез, что такое plural. Фактически, это формы существительного, зависящие от его количества. Пример: 1 день, 2 дня, 5 дней. Действительно, очень часто можно услышать от разработчиков, что работать с plural сложно. Однако, мы пришли к выводу, что таких ресурсов крайне мало в приложениях. Получая другие преимущества, этим можно пренебречь. Про работу стандартного механизма для работы с plural в виде словаря вы можете посмотреть здесь [5].
Теперь у нас есть отдельный репозиторий, в котором созданы локализованные ресурсы для проекта.
Пример:
{
"common_global_error": "Ошибка",
"common_notifications_no_new_notifications": "У вас нет новых уведомлений",
}
Репозиторий со строками необходимо подключить как submodule к вашему проекту. Что это даёт? Если вам не нужна последняя версия строк, вы просто не обновляете версию submodule, а переводчик/дизайнеры/другие заинтересованные лица могут спокойно создавать ресурсы для следующих версий.
В процессе разработки наших проектов решили использовать локализацию в коде, даже если используются storyboards.
После подключения submodule, нам всё равно как-то необходимо получить строки в приложении, чтобы их использовать. Для этого создаём script и добавляем его в build phases как run script.
Для самого script’a будем использовать php. Однако его вы можете переписать на любой другой скриптовый язык.
Положим данный скрипт [6] к нам в проект. Теперь добавляем в наш run script.
php ./common_strings/import_strings.php
Предварительно называете его, к примеру, «Localization». Очень часто приходится видеть сторонние проекты, в которые есть run scripts, которые никак не названы. Поэтому понять, что там происходит, сходу нельзя.

Заранее создайте в проекте пустые файлы localizable.strings, а также String+Localization.swift. После первого build (cmd+B) у нас в проекте есть заполненные файлы localizable.strings, а также файл String+Localization.swift. Если скрипт не выполняется или выполняется неправильно, убедитесь, что данные файлы у вас были заранее созданы, так как скрипт отвечает только за заполнение.

Пример готового файла Localizable.string (Russian)

Пример готового файла String+Localization.swift
Кроме этого, для простоты локализации создадим extension для String [7].
Теперь мы можем использовать строки из String+Localization в проекте. К примеру:
emptyLabel.text = .commonNotificationsNoNewNotifications
При этом, это уже не магическая строка. При наведении на неё можно также увидеть перевод слова на языке, который понятнее всего разработчикам проекта.

Если в проекте используется строка .commonNotificationsNoNewNotifications, а затем переводчик убирает её в новой версии, то у разработчика высветится ошибка компиляции. Потому что данной строки уже не существует в проекте и её нужно поправить. Мы предиктивно получили ошибку об изменении ресурса и не выпустили это в production/отдали тестировщикам/etc.
В результате мы получаем систему для работы с локализацией, которая отвечает всем поставленным целям. Таким способом сделали уже несколько проектов. Надеюсь, что эта техника поможет и вам упростить процесс локализации приложений, а также сделает его менее зависимым от разработчиков.
Автор: niklnd
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios-development/253707
Ссылки в тексте:
[1] компании Touch Instinct: https://touchin.ru/
[2] здесь: https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/LocalizingYourApp/LocalizingYourApp.html?utm_source=swifting.io&utm_medium=web&utm_campaign=blog%20post
[3] styleguide: https://github.com/TouchInstinct/team/blob/master/processes/Strings-And-Images-Naming-Rules.md
[4] система для работы с Plural: https://en.wikipedia.org/wiki/Plural
[5] вы можете посмотреть здесь: https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html
[6] данный скрипт: https://github.com/TouchInstinct/team/blob/master/iOS/Examples/import_strings.php
[7] extension для String: https://github.com/TouchInstinct/team/blob/master/iOS/Examples/String%2BLocalization.swift
[8] Источник: https://habrahabr.ru/post/327356/
Нажмите здесь для печати.