Как локализовать номера для приложения iPhone? - PullRequest
10 голосов
/ 27 октября 2009

В моем приложении для iPhone мне нужно отобразить количество объектов, которые я затем локализую, так как английский язык различает единственное и множественное число, я делаю следующее

// псевдокод

if (objectList.count == 1)
{
   NSLog(@"%@", NSLocalizedString(@"1 object", @"display one objects");
}
else
{
  NSLog(@"%@", NSLocalizedString(@"%d objects", @"display multiple objects");
}

Это работает для английского языка, но во многих других языках форма существительного во множественном числе не просто создается путем добавления "s".

Как объясняется на этой странице , между языками могут существовать две вещи:

  • Форма создания множественного числа отличается. Это проблема с языки, которые имеют много нарушения. Немецкий, например, это радикальный случай. Хотя английский и Немецкий язык является частью одного языка семейный (германский), почти регулярный формирование множественного числа существительных (добавляя "s") вряд ли можно найти в Немецкий.
  • Количество множественных форм отличается. Это несколько удивительно для тех, кто имеет опыт работы только с румынским и германские языки, так как здесь номер один и тот же (их два).

Как мне поступить с этим в моем коде?

Ответы [ 5 ]

11 голосов
/ 08 января 2010

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

Если ваш переводчик приходит к вам и говорит, что для поддержки марсианского вам нужно раздельное написание для четных и нечетных чисел, тогда вы можете настроить свой код на что-то вроде:

if (objectList.count == 1) {
    NSLocalizedString(@"ObjectCount1", @"display one");
} else if (objectList.count % 2 == 0) {
    NSLocalizedString(@"ObjectCountEven", @"display even");
} else if (objectList.count % 2 == 0) {
    NSLocalizedString(@"ObjectCountOdd", @"display odd");
}

en.lproj / Localizable.strings:

ObjectCount1 = "1 object";
ObjectCountEven = "%d objects";
ObjectCountOdd = "%d objects"; // same as ObjectCountEven

mars.lproj / Localizable.strings:

ObjectCount1 = "1 object-o";
ObjectCountEven = "%d object-e";
ObjectCountOdd = "%d object-o"; // same as ObjectCount1

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

4 голосов
/ 28 марта 2013

Компания Smartling выпустила платформу с открытым исходным кодом для поддержки множественного числа, соответствующего стандарту CLDR.

https://github.com/Smartling/ios-i18n

Чтобы использовать его, вы добавляете специальный маркер в ваши ключи, который следует за маркировкой стиля CLDR, и вызываете SLPluralizedString вместо NSLocalizedString. Во время выполнения библиотека выберет правильную строку для использования в зависимости от языка, на котором в данный момент запущено приложение.

Итак, ваш английский .strings файл будет иметь:

"%@ apples##{one}" = "One apple";
"%@ apples##{other}" = "%@ apples";

Русский файл .strings:

"%@ apples##{one}" =   "%@ яблоко";
"%@ apples##{few}" =   "%@ яблока";
"%@ apples##{many}" =  "%@ яблок";
"%@ apples##{other}" = "%@ яблока";

и код для его вызова может выглядеть так:

    NSString *s2 = [NSString stringWithFormat:SLPluralizedString(@"%@ apples", number, nil), number];

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

На момент написания статьи я являюсь менеджером по продукту в компании Smartling.

4 голосов
/ 19 июля 2012

Я только что опубликовал JJPluralForm , адаптацию для PluralForm в Mozilla.

При этом вам не придется беспокоиться о выполнении всего кода if-else, switch-case для локализации в вашем коде, что становится невозможным для поддержки по мере роста количества локализаций.

С примером, который вы привели, можно справиться:

[[JJPluralForm sharedManager] pluralStringForNumber:numberOfObjects
                                    withPluralForms:NSLocalizedString(@"N_OBJECTS_PLURAL_STRING", @"")
                                    localizeNumeral:YES];

Каждый файл Localizable.strings затем локализует N_OBJECTS_PLURAL_STRING как разделенный точкой с запятой список множественных форм. Для английского языка это будет "%@ object;%@ objects".

Проверьте проект для получения более подробной информации.

2 голосов
/ 15 июля 2014

Кстати, начиная с iOS 7 и Mac OS X 10.9, есть встроенная поддержка множественного числа в локализации. См. WWDC 2013 видео «Создание приложения, готового к миру», начиная с 16:10. Множественные значения локализуются в файле .stringsdict plist, а затем вы просто делаете

NSLog(@"%@", [NSString localizedStringWithFormat:
          NSLocalizedString(@"%d objects", @"display multiple objects"), n]);
0 голосов
/ 12 июня 2014

Существует еще более мощное решение этой проблемы. Взгляните на библиотеку Tr8n с TranslationExchange.com

https://github.com/tr8n/tr8n_objc_clientsdk

Библиотека использует TML TranslationExchange (Language Markup Language), что делает процесс интернационализации очень простым. Во-первых, вам даже больше не нужно иметь дело с XML-файлами Strings, на самом деле ... - Tr8n SDK будет создавать и управлять вашими String-файлами для вас на лету - вы никогда не будете смотреть на них снова.

Ваш конкретный пример будет просто:

Tr8nLocalizedStringWithTokens(@"{count || object}", @{@"count": objectList.count}) 

Библиотека Tr8n автоматически подберет для вас нужную форму множественного числа на любом языке. Хах? Да, это волшебно. Полная форма приведенного выше примера токена на самом деле:

{count:number || one: object, other: objects}

Это означает, что токен "count" имеет числовой тип, который отображается на английское множественное число с использованием ключевых слов "one" и "other" .... Но Tr8n достаточно умен, чтобы не вводить все это. Он также достаточно умен, чтобы сопоставить последовательность параметров с соответствующими значениями правила. И, конечно, он знает, что «количество» связано с числовыми правилами через соглашение об именах. Так что это просто становится:

{count || object}

Кстати, так как вы упомянули русский язык, русский перевод для вышеупомянутого будет просто:

"{count || object}" = "{count || объект, объекта, объектов}"

Этот пример был слишком простым, давайте посмотрим на более интересный:

Tr8nLocalizedStringWithTokens(
   @"{user} uploaded {count || photo} to {user | his, her} photo album.", 
   @{@"user": user, @"count": 5}
) 

Прежде всего, удачи в переводе этого предложения с использованием стандартной библиотеки iOS i18n (или любой другой библиотеки в этом отношении) ... это шутка - но на самом деле нет способа сделать это, используя что-либо, кроме Tr8n.

TML, переведенный на русский язык, будет просто:

@"{user || загрузил, загрузила} {count || фотографию, фотографии, фотографий} в свой фотоальбом." 

Здесь мы имеем дело с гендерными правилами так же, как мы работаем с числовыми правилами. Но вместо «один», «несколько», «другой» мы имеем «мужской», «женский», «неизвестный» - ну, у каждого языка могут быть разные гендерные и числовые правила. Tr8n справится с этим, так что вам не придется.

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

Tr8nLocalizedAttributedStringWithTokens(
  @"{user} uploaded [bold: {count || photo}] to {user | his, her} photo album.", 
  @{
    @"user": user, 
    @"count": 5, 
    @"bold": @{@"font":@{@"name": @"system", @"size": @12, @"type": @"bold"}}
  }
) 

[жирный шрифт: ...] - жетон украшения. Вы заметили, что мы переключили макрос на версию AttributedString? Этот макрос фактически создает NSAttributedString, используя собственный механизм оформления iOS. Можете ли вы догадаться, что перевод на русский будет?

@"{user || загрузил, загрузила} [bold: {count || фотографию, фотографии, фотографий}] в свой фотоальбом."

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

Давайте сделаем еще один последний пример ... Скажем, у вас есть новостная лента в следующей форме:

Tr8nLocalizedAttributedStringWithTokens(
  @"{actor} sent {target} [bold: {count || gift}].", 
  @{
    @"actor": user1, 
    @"target": user2, 
    @"count": 5
  }
) 

На английском это не выглядит интересно. Но это на русском или любых других языках, которые поддерживают языковые падежи. Имя {target}, если оно написано на русском языке, на самом деле должно использовать регистр русского языка.

http://en.wikipedia.org/wiki/Dative_case

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

@"{actor || подарил, подарила} {target::dat} [bold: {count || подарок, подарка, подарков}].", 

Tr8n достаточно умен, чтобы использовать мощный движок языковых правил и применять регистр языка Dative к русским именам, передаваемым через токен {target} ...

Это был длинный ответ на простой числовой вопрос. Спасибо, что прочитали это так далеко. Надеюсь, поможет.

Отказ от ответственности: я являюсь создателем платформы Tr8n и языка TML. Если у вас есть какие-либо вопросы, пожалуйста, позвоните мне, и я хотел бы помочь вам со всеми вашими вопросами перевода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...