Главная iPhone Mac OS X Форум О себе

Локализация приложений в Mac OS

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

Локализация, применительно к разрабатываемым для Mac OS приложениям, должна включать в себя одну или несколько следующих частей:

  • локализация и модификация nib-файлов
  • перевод статического текста в коде программы
  • локализация иконок и графические элементы
  • звуковые файлы, содержащие сообщения на иностранном языке, должны иметь переведенные аналоги
  • если ваше приложение имеет онлайновую документацию, то нужно не забывать о доступности ее текстов для пользователей всех стран, где будут использовать вашу программу
  • динамический текст (включая дату, время и числа) должен быть приведен к формату согласно текущей локали
  • код, обеспечивающий поддержку обработки текста, должен вычислять корректные места переносов в словах

Интернационализация приложений

Правильно проведенный процесс интернационализации значительно снижает объем работы по дальнейшей локализации приложения и добавление дополнительных поддерживаемых языков в программу.

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

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

Calculator.app/                      сборка (bundle)
    Contents/
        MacOS/
            Calculator               исполняемый файл
        Info.plist
        Resources/                   папка с ресурсами
            Calculator.icns
            tapeButton.tif           не локализованные ресурсы
            English.lproj/           папка с ресурсами, локализованными для англоязычной аудитории
                Localizable.strings  динамически отображаемые строки
                Calculator.nib       интерфейс приложения
                CalculatorHelp/      файлы документации и помощи
            ru.lproj/                папка с ресурсами, локализованными для русскоязычной аудитории
                Localizable.strings
                Calculator.nib       
                CalculatorHelp/ ...

Процесс создания папок lproj и версий ресурсов для каждой из них лежит на плечах XCode, а вот ответственность за перевод и локализацию — на ваших.

Интернационализацию или подготовку приложения к дальнейшей локализации можно условно разделить на два этапа:

  1. Модификация кода приложения и использование консольной утилиты genstrings для формирования файла, содержащего все строки, используемые в коде приложения, которые требуют перевода
  2. Создание затребованного количества папок lproj под локализацию и модификация ресурсов в них для указанных языков

Начнем с первого этапа и воспользуемся созданным нами в прошлых постах приложением txtEdit в качестве основы для наших экспериментов.

Чтобы показать все возможные варианты локализации нам потребуется внести в код проекта некоторые изменения. Во-первых, удалите из класса mainViewController метод awakeFromNib, в котором мы формировали подпись “Back” к кнопке возврата. Прелесть создания приложений в XCode (как, собственно, и в любом языке) заключается в том, что к одному и тому же результату можно прийти несколькими путями. Дело в том, что свойство backBarButtonItem доступно для изменения не только программным путем, но и в Interface Builder.

Откройте файл MainWindow.xib и, раскрыв все дерево подчинения элементов, выберите в нем Navigation Item, принадлежащий mainViewController.

Окно объектов в Interface Builder

В инспекторе свойств перейдите на закладку атрибуты и установите значение поля Back Button как “Back”.

Инспектор свойств в Interface Builder

Благодаря нашим стараниям, в интерфейсе приложения появится новый элемент BarButtonItem, отождествленный с нашей кнопкой возврата.

Появление второго Bar Button Item

Для каждой версии перевода мы впишем новое значение подписи к кнопке. Сохраните и закройте файл MainWindow.xib.

Для создания файла переводов для строк, используемых в коде приложения, нам, прежде всего, необходимо подготовить сам код к локализации, ведь в более общей ситуации нам нет нужны переводить все используемые в приложении строки и фразы. Чтобы показать, что для данного текста будет браться его локализованный вариант согласно текущей языковой настройки пользователя, необходимо конвертировать строку в вызов метода NSLocalizedString. Для примера, сделаем перевод кнопки “Done”, которую мы использовали в классе txtEditViewController.

Вы помните, что мы создавали кнопку вручную, используя метод initWithBarButtonSystemItem:target:action:, где в качестве параметров не указывается подпись к кнопке. Поэтому нам потребуется заменить строку инициализации на следующую:


UIBarButtonItem *buttonDone = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", @"")
                                                               style:UIBarButtonItemStyleDone
                                                              target:self
                                                              action:@selector(doneAction:)];

Во-первых, мы использовали конструктор кнопки с указанием подписи к ней, а во-вторых, добавили вызов NSLocalizedString, тем самым указав на выборку переведенной версии строки “Done”. В реальности NSLocalizedString является не методом, а макросом, скрывающим следующий вызов:


[[NSBundle mainBundle] localizedStringForKey:@"Done" value:@"" table:nil];

Для обращения к ресурсам приложения используются метода класса NSBundle. localizedStringForKey:value:table возвращает перевод указанной строки. В случае, если значения перевода не существует, используется значение value. Параметр table указывает на название файла перевода. По умолчанию, это Localizable.strings.

Нам осталось только сформировать данный файл. Для этого запустите терминал и перейдите в папку Classes нашего приложения. Находясь в этой папке, запустите команду:


genstrings ./*.m

Результатом выполнения команды станет сформированный в том же каталоге файл перевода для всех используемых в приложении классов. Добавьте файл Localizable.strings в проект, обязательно указав при его импортировании кодировку UTF-16.

Добавление файла Localizable.strings в проект XCode

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


"File %@ not found." = "Le fichier %@ n’existe pas.";

Локализация приложений

Процесс локализации приложений в Mac OS легок и прост. Исполняемый файл программы отделен от локализованных ресурсов (текстов, изображений, звуков), сгруппированных по отдельным папкам. Как вы видели выше, локализованные ресурсы хранятся в отдельной .lproj директории для каждого поддерживаемого языка. Папки .lproj названы согласно спецификациям ISO. Содержимое всех таких папок должно быть одинаковым.

В региональных настройках Mac OS вы указываете свой основной язык и список дополнительных языков. В случае, если приложение не поддерживает ваш основной язык, то будет использоваться язык из указанного списка. Если ни для одного из указанных языков не было найдено файлов перевода, то приложение будет использовать язык, указанный по умолчанию при разработке программы. Это значение указывается в переменной “Localization native development region” (эквивалент в xml-варианте — CFBundleDevelopmentRegion) в файле Info.plist.

Различают идентификатор языка и идентификатор локали. Оба состоят из двух частей: идентификатора языка и идентификатора региона. Разница в том, что первый из них в качестве разделителя использует дефис, второй — знак подчеркивания. Идентификатор языка вида en-US описывает язык или диалект языка, в то время как en_US описывает регион, где разговаривают на данном языке. Несмотря на кажущуюся общность определений, имеется различие. Идентификатор языка описывает только разговорный и язык письма, а идентификатор локали — описывает регион, его специфику, культурную составляющую, в частности формат представления данных.

В своих программах вы можете использовать обобщения для представления единых данных для ряда регионов. Например, создание пакета ресурсов en.lproj, единого для США, Великобритании и Австралии вместо отдельных en_US.lproj, en_GB.lproj, и en_AU.lproj, позволит вам уменьшить размер вашей сборки. В качестве имени для папки с локализованными версиями ресурсов можно использовать полное название языка, например, Russian, German, Japanese, но поддержка такого наименования может быть убрана из будущих версий Mac OS и лучше придерживаться принятых в ISO обозначений.

Как я говорил выше, XCode берет на себя работу по созданию lproj директорий, и пришло время показать как он это делает. В нашем приложении мы будем локализовать два файла: MainWindow.xib и Localizable.strings. Найдите их в списке файлов в проекте XCode и последовательно для каждого выполните следующие действия.

Нажмите правой кнопкой мыши на файл и выберите пункт Get Info.

Открытие свойств для ресурса в XCode

Находясь в закладке General, нажмите кнопку Make File Localizable.

Создание локализованной версии файла

Переключитесь обратно на закладку General, убедитесь, что локализация для языка проекта по умолчанию сформирована и добавьте еще один язык, нажав кнопку Add Localization, используя в качестве названия - ru

Добавление новой локализации для файла

Если теперь вы заглянете через Finder в папку нашего проекта, то увидите две новых директории: English.lproj и ru.lproj, содержащие по копии файлов MainWindow.xib и Localizable.strings. Аналогичная группировка ресурсов по папкам видна и в XCode.

Список ресурсов в XCode

Процесс локализации строк прост до безумия. Откройте файл Localizable.strings из папки ru.lproj и впишите новое значение для подписи к кнопке возврата.


"Done" = "Готово";

Просто, верно? С такой же легкостью мы сейчас создадим перевод для файла интерфейса. Процесс локализации nib-файлов проходит в Interface Builder. Локализатор переводит подписи к элементам интерфейса, заменяет звуковые и файлы изображений, также изменяет размеры тех или иных элементов на форме, если переведенный текст не помещается полностью в пределах их размеров.

Откройте MainWindow.xib в Interface Builder и впишите новое значение для Back Button.

Подпись к кнопке Back Button

При локализации nib-файлов необходимо придерживаться условия — связи между объектами не должны быть нарушены в ходе процесса локализации.

Вот и все. Запустите txtEdit. По умолчанию в симуляторе в качестве основного установлен английский язык и наше приложение использует англоязычные ресурсы для отображения данных. Стоит нам переключиться в Настройках на русский (Settings->General->International->Language), как надписи на кнопках сменятся на кирилицу.

Локализованная на два языка версия txtEdit

Если изменение языка в Настройках не приводит к изменениям в интерфейсе, удалите папку build из директории вашего проекта и пересоберите приложение.

На этом процесс локализации нашего приложения завершен, но для более сложных программ вам придется совершить немало дополнительных телодвижений. Я совершенно не затронул в своем посте тему приведения отображаемых данных в приложениях к формату выбранного региона, как то форматирование даты, чисел, денежных сумм и прочего — разобраться в этом помогут дополнительные источники информации, приведенные в конце статьи.

Скачать архив проекта (28Кб)

Дополнительные источники информации:

Комментарий

Комментарии

kronos 2.09.2020 14:15

Ждем еще статей!

ответить
Михаил 2.09.2020 14:20

А почему не используются принятые обозначения культур? Типа EN-US, EN-UK, RU-RU и т.д.?

ответить
Evgeniy Krysanov 2.09.2020 14:54

В качестве имен папок переводов можно использовать названия вида en_us, en_ca, en_uk, и вообще любой идентификатор локали. Т.е. можно легко создать локализацию для en_us и en_ca, и оба перевода будут доступны по отдельности, соответственно в США и Канаде.

ответить
serj 2.09.2020 15:51

Спасибо за статью. Мне вот интересно, есть например проект с локализацией на 15 языков. И тут вдруг в nib файл (которых 15 копий в 15-ти директориях) надо добавить новую кнопочку, или надпись… Есть какая нибудь автоматизация этого процесса? А еще хуже, если надо поменять что-то, что не локализуется — размер поменять, или местами поменять элементы.

ответить
Evgeniy Krysanov 2.09.2020 16:39

Интересный вопрос. Для каждого локализованного файла можно сделать Remove All Localization, затем внести изменения, а после — заново создать 15 переводов, но это ход через одно место. Похоже, что помочь в подобной ситуации может AppleGlot, но мне не приходилось им пользоваться, так что не ручаюсь (описание работы с программой на русском).

ответить
Michael 3.09.2020 21:57

AppleGlot определенно поможет.

Вообще нормальный процесс таков: изначально делается одна локаль (обычно, English.lproj), все остальные (в данном случае, 14) — готовятся для уже готовой программы с помощью AppleGlot (или другого инструмента локализации, например, iLocalize — отличная штука, но, в отличие от AppleGlot, стоит денег). В этом случае, помимо всего прочего, еще и перевод всяких стандартных элементов, вроде Edit = Правка, Services = Службы и т.п., подставляется автоматически по словарю. (коррекция размеров/расположения элементов интерфейса всегда происходит в InterfaceBuilder). Все переводы (и перемещения/изменения кнопочек и т.п.) запоминаются в «рабочем словаре». Поэтому, когда добавили кнопочку или надпись, останется снова запустить AppleGlot, перевести только то, что добавилось, и, возможно, подправить размещение этого элемента.

ответить
Evgeniy Krysanov 3.09.2020 22:54

Большое спасибо за отличное объяснение. Вы, если не ошибаюсь, как раз и есть владелец сайта macedu.org.ru? :)

Преклоняюсь перед учителями. Без шуток, большое спасибо за вашу работу. Скажите, на уроках информатики в вашей школе удается рассказывать о Маках? На “живых” примерах?

ответить
Michael 3.09.2020 23:01

Не ошибаетесь. Пока что работаем на «живых примерах». Но стареньких (iMac G3 ~ 2000 г. и iBook G3 2002 г.). Получается, скорее, антиреклама :-(

ответить
Evgeniy Krysanov 3.09.2020 23:16

Это лучше, чем ничего. Вам же не видео кодировать детей учить, а для знакомства с Mac OS и Маками G3 очень даже не плохи.

Самостоятельно что-нибудь писали под Мак? Есть чем интересным поделиться, кроме того, что у вас есть на сайте? Спрашиваю не без корыстных побуждений, в попытке склонить вас напечатать пару статей на pyobjc.ru:)

ответить
Michael 4.09.2020 8:13

Мне ж не только Finder показывать ;) А когда дети видят скорость работы G3 по сравнению с их домашними компьютерами, впечатление переносится на всю платформу.

Можно считать, что не писал ничего. Единственная программулина: http://macedu.narod.ru/soft/files/son-10.sit написана лет пять назад, да и в ней использованы только самые-самые простейшие вещи. Так что по теме сайта pyobjc.ru я могу только читать, но не писать ;)

ответить
Evgeniy Krysanov 4.09.2020 12:47

Все равно спасибо, а статьи у вас интересные есть. Так что думаю, будет не лишним посетителям моего сайта ознакомиться с материалами на вашем. На всякий случай привожу еще раз ссылку macedu.org.ru

ответить
Andy 2.09.2020 18:39

Скажите, а как решить проблему падежей (терминатор/терминатор_а_/терминатор_ов_)

ответить
Evgeniy Krysanov 2.09.2020 18:50

Самодельно написанным методом. Больше ничего в голову не приходит. Т.е., например, подставлять в строчку вида NSLocalizedString(“Всего: %@”) будем не объект, а результат вызова метода, в который, кроме передачи количества единиц, будет передаваться еще и 3 словоформы (терминатор, терминатора, терминаторов), а он уже в ответ формировать строку с корректным склонением.

ответить
ZYV 4.09.2020 11:58

А в GNU gettext поддержка падежей есть по-умолчанию, а кроме того, для PO/POT-файлов есть отличный редактор, начиная от POEdit и заканчивая KBabel. Поэтому правильная локализация делается через gettext. Скажем НЕТ “1 овцы”!

Так-то! (c)

ответить
Andy 4.09.2020 13:07

А в GNU gettext поддержка падежей есть по-умолчанию

Вы меня опередили. Только что сам хотел отписать.

ответить
Jack 17.01.2020 22:29

Да в сад gettext даешь sattelite assemblies используя SWF под моно! выглядит хоть криво (в 2.6 версии обещают native SWF driver для Carbon), но локализация, IMO, проще.

Еще понт под .NET — есть прога в составе СДК позволяющая не только локализацию ресурсов делать, но и менять свойства элементов управления под определенную локаль, типа расширить окошко, чтоб текст влезал и т.д. причем изменения заносятся в виде дифа, что позволяет попутно дорабатывать форму прогерами — добавлять на нее чтото, удалять.

Так-то =)! ©

ответить
Val 30.01.2020 20:14

Спасибо. С помощью этих советов полностью локализовал программу на 23 языка, даже на те языки, которых в iPhone  нет! Думаю это мировой рекорд. iTunes Store пустил к себе, ссылка http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=303513809&mt=8 Стараничка программы   EUtreaty http://slavamax.com/

Одна ремарка. Я не локализовывал файлы .xib их у меня 3. Я локализовывал лишь Localizable.strings  правда пришлось помучиться с матрицей переводов 23x22  языка. Типа с гаэльского на мальтийский.

ответить

Форма комментирования для «Локализация приложений в Mac OS»

Обязательное поле. Не больше 30 символов.

Обязательное поле

captcha image Пожалуйста, введите символы, которые вы видите на изображении

.