Вступление
При поиске в google по запросам Core Data или Autolayout, первый результат поиска содержит обновляемую информацию в «новом формате документации». Потратив определенный объем времени, читая и следуя инструкциям, достаточно не сложно ознакомиться с основными инструментами предоставляемыми той или иной технологией(особенно если чтение на английским не является для вас серьезным препятствием).
Аналогичную информацию можно найти и по локализации продукта. Но в отличии от примеров указанных выше она:
- Имеет старый менее удобный, как по мне, формат для чтения.
- Она даже не будет первой в выдаче по запросу «site:developer.apple.com internationalization»
- И что самое, интересное имеет в заголовке очень любопытное замечание: «Important: This document is no longer being updated. For the latest information about Apple SDKs, visit the documentation website.»
A первой в выдаче мы видим страницу, которая в большей мере выглядит, как инструмент продажи локализации разработчикам и менеджерам, когда основной интерес представляют разрозненные ссылки в разделах WWDC Session Videos и Documentation and Sample Code.
В данной статье, я попытаюсь коротко упомянуть все инструменты, которые помогут вам в этом, как выяснилось для меня, нелегком деле. Каждый пункт я попытаюсь снабдить несколькими ссылками, пройдя по которым вы сможете получить более исчерпывающую информацию. Хватит вступительных слов, к делу.
Используйте форматеры данных
Начиная разрабатывать, я не знал о их существовании, но относительно недавно я услышал о них в лекции на WWDC.
При желании самим создавать строковые представления данных стоит зайти в.
System Preferences/Language & Region/Advanced и посмотреть все предоставляемые настройки.
Просмотр данных настроек, напрочь у меня отбил желание писать велосипеды, теперь я всегда в первую очередь ищу подходящий форматер, и за последний год не было случая, чтобы я не смог найти нужный мне.
Как по мне, список стилей в NumberFormatter, очень ярко показывает, широкий список возможностей, которые будут работать «из коробки», без дополнительных затрат со стороны разработчика приложения.
Пример:
let dateComponents = DateComponents(hour: 3, minute: 2, second: 10)
let dateComponentsForatter = DateComponentsFormatter()
dateComponentsForatter.unitsStyle = .short
Swift.print("(dateComponentsForatter.string(from: dateComponents)!)")
dateComponentsForatter.unitsStyle = .full
Swift.print("(dateComponentsForatter.string(from: dateComponents)!)")
dateComponentsForatter.unitsStyle = .spellOut
Swift.print("(dateComponentsForatter.string(from: dateComponents)!)")
/*
Output for English:
3 hrs, 2 min, 10 secs
3 hours, 2 minutes, 10 seconds
three hours, two minutes, ten seconds
Output for Russian:
3 ч, 2 мин, 10 с
3 часа, 2 минуты, 10 секунд
три часа, два минуты, десять секунд
*/
У форматтеров есть большое разнообразие настроек и стилей, рассматривать их тут все, как по мне будет излишним, но я уверен, что пройдясь по данным в этой части ссылкам вы явно найдете для себя что-то стоящее, если ранее их не активно использовали.
Не задавайте явно dateFormat у DateFormatter используйте setLocalizedDateFormatFromTemplate. (WWDC)
Как добавить поддержку нового языка
Я добавлю скрины, и думаю, что слова тут будут излишни. Единственное, что хочется отметить, это то, что язык можно добавлять только в проект, а не в один из таргетов.
В появившемся модальном окне оставьте галочки только рядом с теми файлами, которые планируете локализировать.
Импорт/Экспорт
В реальном приложении у вас будет много файлов локализации. «xib», «strings», «stringsdict», «plist»(кол-во которых ограничивает лишь ваша фантазия.)… собирать их все в один архив, после отправлять переводчикам, а после перевода, распихивать по проекту это то еще удовольствие.
Осознавая это Apple предоставила нам весьма удобный инструмент для работы с локализацией строковых ресурсов: Импорт/Экспорт xliff файлов (рассказ на WWDC).
Для использования этой функциональности, выберите ваш проект как показано на скрине
Далее зайдите в пункт меню Editor, Export For Localization, выберите список языков на локализацию, сохраните в желаемое место на диске.
Вуаля! вы только что вынесли все строковые ресурсы вашего проекта в одну папочку, которую можно смело отправлять на перевод.
После модификации данных файлом переводчиком вы сможете экспортировать их в пару кликов используя пункт меню Editor/Import Localizations.
Вот пример работы с xliff от хабражителя. Не совсем согласен с минусами указанными им, да и много чего поменялось с выходом XCode 10, но это весьма подробный пример, следуя которому можно достаточно быстро понять всю технику работы с xliff.
Как локализировать файл
Для этого выберете файл в дереве проекта, после чего в панели утилит выберете первую вкладку.
Нажмите на кнопку «Localize...».
В появившемся окне, выберите требуемый язык, нажмите на «Localize».
В дереве проекта появились файлы локализации.
А в правой панели, расставляя галочки, вы можете удалять/добавлять файлы локализации.
Как быстро переключить язык при тестировании в XCode
Нажимаем на таргет правее от кнопок «Build and Run» & «Stop».
Выбираем «Edit Scheme». В появившемся окне выбираем «Run» в левом вертикальном списке и «Options» в шапке правой части окна.
В появившемся окне выбираем желаемый язык. Закрываем окно «Edit Scheme»
Следующий запуск программы уже будет с выбранным вами языком.
Следует отдельно обратить внимание на то, что внизу выпадающего списка, на последнем скриншоте, есть 2 пункта (псевдоязыка):
- Right to Left Pseudolanguage
- Double Length Pseudolanguage
Они могут помочь вам в тестировании.
Autolayout
Что тут сказать. Если вы по каким-то причинам все еще используете явное задание координат, вам придется тяжко. Все что я могу сказать: «Постарайтесь свести явное задание координат к минимуму. Autolayout ваш лучший помощник в этом вопросе».
На чем бы я сакцентировал внимание:
- Избегайте выставления явных размеров элементам с меняющимся контентом(кнопки, надписи, прочие...)
- Проверьте при случае лишний раз "content hugging and content compression resistance priorities"
- Если у вас есть пробелы в понимании основных принципов расстановки NSLayoutConstraint, всем будет лучше, если вы закроете их, а после приступите к локализации.
- Сразу определитесь, какие элементы в вашем приложении могут быть многострочными, а какие нет.
- Выставьте всем надписям NSLineBreakMode
- Не рассчитывайте на то, что текст будет меньше определенной величины, это не верно в общем случае. И на практике вы с этим столкнетесь. Удостоверьтесь в том, что элемент ограничен со всех сторон. И даже маленькая кнопка в левой части экрана имеет ограничение справа (это не даст ей вылезти за пределы экрана и налезть на другой элемент справа). Интересно, что при работе в storyboard на маке отсутствие такого ограничения приводит к отображению варнинга, а в xib нет.
- Будьте осторожны с «Content Compression Resistance» > 500 на мак. Такие элементы могут расширять NSWindow, на которых лежат. При необходимости такого расширения ставьте элементу ограничения на размер в виде неравенства. Это тот редкий случай, когда значение придется подбирать интуитивно.
- Большинство языков относятся к left-to-right languages (пишем слева направо), но часть часть языков, таких как арабский и иврит относятся к right-to-left languages. Для поддержки данной вариативности выбирайте leading вместо left и trailing вместо right. Но, как всегда, к этому сдедует подходить с умом и не менять местами части света на компасе, например. (WWDC about right-to-left languages)
- В некоторых случаях вам придется менять установленные ограничения (NSLayoutConstraint) в зависимости от текущего языка.
Порядок слов может меняться при переводе
При формировании сроки используя скажем -[NSString stringWithFormat:] мы можем в спецификаторе задавать номер аргумента, который следует вставить.
Swift.print("(String(format: "%@ %@", "s1", "s2"))")
Swift.print("(String(format: "%1$@ %2$@", "s1", "s2"))")
Swift.print("(String(format: "%2$@ %1$@", "s1", "s2"))")
Swift.print("(String(format: "%1$@ %1$@", "s1", "s2"))")
Swift.print("(String(format: "%1$@ %2$@ %3$@", "s1", "s2", "s3"))")
Swift.print("(String(format: "%1$@ %3$@", "s1", "s2", "s3"))")//(**)
/*
Output:
s1 s2
s1 s2
s2 s1
s1 s1
s1 s2 s3
s1 s2
*/
Следует помнить, что пропуск одного из аргументов может привести к непредвиденному поведению.
When numbered argument specifications are used, specifying the Nth argument requires that all the leading arguments, from the first to the (N-1)th, are specified in the format string.
Локализация NSAttributedString
Иногда приходится локализировать не только обычные строки, но атрибутные. Для этой цели можно использовать Atributika.
let b = Style("b").font(.boldSystemFont(ofSize: 20)).foregroundColor(.red)
label.attributedText = "Hello <b>World</b>!!!".style(tags: b).attributedString
В Objective-C Analyzer позволяет найти часть не локализированного контента.
Заходим в настройки проекта, выставляем флаг «Missing Localizability» в YES.
В меню XCode выбираем «Product/Analyze». Видим, что появился warning аналайзера.
Нажав на него видим причину.
Подправив код
self.label.stringValue = NSLocalizedString(@"Test Label", @"");
Перезапускаем аналайзер и варнинг пропал.
Что еще стоит глянуть, но у меня не хватило времени чтобы описать в этой части
- В Xcode 10 при импорте/экспорте вы работаете не просто с xliff файлом, а с пакетом содержащим все локализированные ресурсы, в который так-же входит и описанный в моей статье xliff + картинки + ксибки +…
- Можно локализировать ксибку, не используя никакой код.
- Можно прописав в коде NSLocalizedString простым вызовом скрипта вытянуть все тексты/комментарии в strings файлы с соответствующим названием.
- Используя Stringsdict можно описать все формы множественных чисел.
- При ограниченном бюджете, или вопросов о переводе, можно легко подглядеть в переводы программ Apple
- Локализировать стоит не только тексты, одна картинна может быть привычной для вас, но совершенно не ясна людям по ту сторону земного шара.
- Один и тот-же текст в английском, может иметь разные переводы в зависимости от контекста, из чего следует 2 вещи. Комментарии крайне важны и не стоит сокращать кол-во переводов объединяя по ключам(Как перевести «Book» без контекста? это «книга» или действие «бронировать»?)
Пы. Сы. (страх и раскаяние автора)
В первую очередь хочу сказать, что остается еще много чего о чем стоит рассказать(как минимум заметки из предыдущего раздела). Так что если статья зайдет, то я постараюсь выделить время и написать продолжение разобрав некоторые части более подробно, и описать фичи вовсе не затронутые мной.(я долго пытался написать исчерпывающую статью, но понял, что это потребует приблизительно вечность.)
Отдельно прошу прощение за упущенные знаки препинания и прочие недочеты…
Буду рад любым вашим отзывам :)
Автор: Возле ректора