На тему этой статьи меня натолкнула история из очень недавнего прошлого. Я зашёл на страничку продукта, именуемого Суперсайтом, компании Не Будем Тыкать Пальцами LLC (но люди из домейнерской индустрии узнают). Заходил я из своего уютного офиса в Латвии и с удивлением обнаружил следующую картину:


И меня, мягко говоря, смутила валюта, в которой была указана стоимость услуг. Ведь на дворе вторая половина 2018 года, а латвийский лат официально прекратил своё существование в январе 2014 и был заменён на евро. И за 4 года не упомянутая выше компания не удосужилась провести ревизию используемых локалей.

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

Определения


Логично будет разобраться в начале, что есть что, и договориться, как мы что будем называть в дальнейшем. Итак…

  • Интернационализация (internationalization, i18n) — подготовка программного продукта к работе с различными языками и локальными отличиями без необходимости доработки напильником при их внедрении. Много букв, потому объясню на примерах. Отрисовать Ваш сайтик так, чтобы он без дополнительного вмешательства напильника верстальщика работал для правописаний слева-направо и справа-налево — интернационализация. Заменить весь хардкод текста на языковые переменные — она же. Научить продукт форматировать даты — опять она же. Кстати, число 18 в i18n обозначает всего лишь количество букв между первой и последней в слове internationalization. Я ленивый Для удобства я буду в дальнейшем использовать i18n.
  • Локализация (localization, L10n) — адаптация интернационализированного ПО под стандарты конкретного региона (локали). Т.е. когда Вы отдаёте список языковых переменных для перевода на бушменский английский и задаёте формат чисел для индийцев, это — L10n.
  • Локаль (locale) — набор параметров, определяющий язык и специфические настройки пользовательского интерфейса, соответствующие привычкам пользователей из определённого региона.

Зачем это Вам?


Хороший вопрос. Многие современные языки программирования содержат встроенные алгоритмы для базовой локализации (форматирование дат, чисел, валют). И если Вам пофиг Вы всецело готовы довериться выбранной Вами технологии, и Вам плевать на пользователей Ваше видение i18n для Вашего продукта не выходит за эти рамки, единственная возможная причина — праздное любопытство и общее развитие.

Впрочем, дьявол кроется в мелочах. И на эти мелочи порой не обращают внимание, что сильно может раздражать пользователей. Если у Вас уже есть солидный опыт в i18n, скорее всего, Вы мало что найдёте нового в этой статье (разве что некоторые примеры из жизни). В этом случае я буду благодарен, если Вы добавите комментарии из своего опыта (и исправите меня, если я в чём-то ошибся). Остальные, надеюсь, найдут пищу для раздумий.

Какие аспекты включает в себя локаль?


Часто локаль задают как совокупность языка и страны. Этих параметров достаточно, чтобы задать совокупность языковых нюансов и прочих параметров, используемых в регионе. Для некоторых специфических задач может потребоваться более сложное деление (например, налоговые юрисдикции некоторых стран). В таком случае ещё задаётся третий параметр — вариация (например, для определённого региона, операционной системы и т.п.). Также многое зависит от того, насколько близки Вы хотите быть к своему пользователю (например, на Филиппинах существует 12 языков коренных народов с количеством носителей более миллиона человек, им бы было приятно).

Итак, что включает в себя локаль?

Популярное и очевидное


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

  • Перевод — тут всё понятно, никакой язык программирования за Вас этого не сделает. При подготовке продукта к переводу следует помнить о простом правиле: желательная минимальная единица для языковой переменной — предложение (насколько это возможно). А лучше фраза целиком. Это может быть не очевидно, если архитектор системы знает только один язык или два грамматически близких (мне доводилось сталкиваться с такими на личном опыте, и в итоге разработчикам пришлось переделывать и переписывать большое количество текстовых сообщений в своём коде). Но язык в широком смысле — отражение образа жизни и культурных особенностей определённого народа.

    Например, все (или многие) из вас знают, что в английском есть строгий порядок частей речи. Насколько мне известно, в китайском тоже, кстати. А вот в русском порядок слов может либо вообще не иметь значения, либо менять значение («ты очень умный» звучит как похвала, а «ты умный очень» — как угроза). В арабском встречаются различия при общении с мужчинами и женщинами, в японском — между социальными слоями. В зависимости от того, насколько для Вас важна та или иная аудитория, Вам следует либо детально изучить подобные тонкости совместно с носителем языка, либо проигнорировать.
  • Дата и время по большей части отличаются именно форматированием даты. Разница в формате времени — в основном 12- или 24-часовой формат. А вот с датой вариантов куда больше. Форматов даты часто предполагается несколько. День и месяц; день, месяц, год в числовом формате; день, месяц, год в расширенном формате. И тут количество вариантов стремительно растёт. Где-то разделителем является точка, где-то — слэш, где-то в сокращённых форматах первым идёт день, где-то месяц. Ещё веселее дело с расширенным форматом. Возьмём для примера дату моего рождения (я скромняжка, ага). Итак, 5 сентября 1986 года появился на свет человек, пачкающий байты этим опусом. Поехали по локациям. Две англоязычные страны для начала.
    • США — September 5, 1986.
    • Великобритания — 5 September 1986.

    И это только начало. В английском языке нет падежей, но даже в начале нашего пути en_US и en_UK отличаются. Заглянем в языки стран поближе?
    • Россия — 5 сентября 1986. Вот и падежи появились. И уже тут могут начаться сюрпризы, т.к. стандартные средства форматирования даты Вашего языка программирования могут и не знать об именительном и родительном падежах.
    • Латвия — а Вы хотите просто назвать дату или сказать, что что-то произошло в эту дату? В русском (сегодня) 5 сентября и (родился) 5 сентября — всё родительный. А вот в латышском простое название даты — 1986 gada 5.septembris. А если «я родился» — 1986 gada 5.septembri. Год ставится первым, число — в местном падеже (грубый перевод — «в 5 сентябре»). А после всех порядковых числительных в латышском ставится точка.

    Таргетируетесь на весь мир? Подумайте о том, какие форматы дат использовать. Возможно, с расширенными лучше не связываться, вряд ли встроенные функции форматирования учитывают все упомянутые выше тонкости. А я прошёлся только по 4 из 195 стран — членов и наблюдателей ООН.
  • Формат чисел тоже хранит в себе немало мешанины. Мне известны только разделитель целой и дробной частей (обычно точка или запятая) и разделители внутри целой части (точно встречал варианты «нет разделителя», запятая, пробел, допускаю также использование точки и апострофа). Роль также играют позиции, где ставятся разделители. Скажем, мы (и не только) привыкли ставить разделители каждые 3 позиции (тысячи, миллионы и т.п.). Но вот упомянутые выше жители Индии и близлежащие страны живут своей жизнью. Первый разделитель в целочисленной части (считая от десятичного) идёт после 3 позиций (тысячи), а дальше — каждые две: лакх (100 тыс.), крор (10 млн.) и так далее. Таким образом, наши 42 000 000 в индийской системе записи будут выглядеть как 4,20,00,000. А ещё они там часто годовую зарплату в лакхах рупий измеряют. Впрочем, в вопросе форматирования чисел с большой степенью надёжности можно положиться на язык программирования.
  • Формат валюты по сути является отформатированным числом, сдобренным префиксом или суффиксом символа или кода валюты. Тут главное следить, чтобы не было приключений, как в самом начале статьи. На данный момент особенно касается стран ЕС, т.к. некоторые могут присоединиться в зону оборота евро.
  • Направление написания на самом деле кроет за собой чуть больше, чем просто написание всего текста в другую сторону в некоторых языках. Это кусок работы для верстальщика или UI дизайнера. При локализации интерфейса, созданного для языков «слева направо», его часто полностью отзеркаливают для языков «справа налево» (скажем, логотип и сайд-бар с меню сайта окажется справа).

Менее очевидное


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

  • Почтовый код. Угадайте, сколько стран не используют почтовый код вообще? Согласно статье на Великой и Всезнающей, 66! Справедливости ради отмечу, что 3 из них используют схожую с почтовым кодом систему, которая позволяет закодировать вплоть до улицы/группы домов/дома. Но остаётся ещё 63, в которых либо не используется почтовый код вообще, либо его внедрение планировалось или планируется. А это практически треть стран мира. А теперь вспомните, сколько Вы встречали сайтов, где почтовый код — обязательное поле? И прям ничего с этим нельзя поделать. Хотя правильным подходом было бы сделать его обязательным только для тех стран, где он вообще есть. В дополнение при желании можно сделать проверку ввода на стандарты выбранной пользователям страны. Благо, эта информация доступна (в том числе по ссылке выше).
  • Регион. Как варианты — штат, область… Ещё одно поле, которое любят делать обязательным, не учитывая реальную ситуацию с почтовой адресацией в стране. Да, даже в самых маленьких странах есть какое-то административное деление (подробности на той же вики), но вовсе не всегда стоит делать поле обязательным.
  • Телефонный номер. Он состоит из кода страны и национального идентификатора. И если список кодов стран достать не проблема, с валидацией национального идентификатора могут возникнуть нюансы. Например, какая минимальная длина номера зашита в Вашу верификацию? А реально существующая минимальная длина номера — 4 цифры. Да, это касается лишь двух миниатюрных территорий, одна из которых по населению на пятом с конце месте, другая — где-то тоже рядом. Но тут я хочу сделать скорее акцент на валидности, нежели на шансе получить в качестве пользователя одного из примерно 1600-1700 жителей Ниуэ. По ссылке можно получить представление о длине национальных идентификаторов по странам.
  • Имя и обращение (титул). Тут многим хватает обычного усреднения. Поля для имени и фамилии плюс уважительное обращение. Как и с другими пунктами этого раздела, тут всё зависит от того, насколько «своим» Вы хотите быть. Если в общих чертах, имя и фамилия обязательны (хотя в редких случаях законом может быть установлено только что-то одно из этого). Для удобства можно сделать поля для обращения, других имён и суффикса (всякие эти «младший», «третий»). Если вдаваться в частности, правила написания могут сильно варьироваться от культуры к культуре, от языка к языку.
    • Россия — всем нам известно, что полное имя состоит из фамилии, имени и отчества. В языке, как и в самой стране, порядок весьма условный, потому в обращении фамилия может быть на первом или последнем месте, а отчество может опускаться. Опционно может добавляться в начале обращение Г-н/Г-жа (господин/госпожа).
    • США — полное имя зачастую состоит из собственно имени (first name, «первое» имя), промежуточного имени или имён (middle name) либо инициала и фамилии. Записывается стандартно в таком порядке, промежуточные имена могут опускаться. Опционно может добавляться обращение (наиболее популярные: Mr, Ms, Mrs, Dr).
    • Латвия — полное имя состоит из имени и фамилии, всегда именно в таком порядке. Отчество как таковое существует только в свидетельстве о рождении, в других документах не используется. Существует форма вежливого обращения kungs/kundze (аналог русского господин/госпожа), которое ставится после фамилии (т.е. в конце, а не в начале, как в предыдущих вариантах). Фамилия при этом записывается в родительном платеже.
    • Китай — в оригинальной китайской записи фамилия всегда идёт первой, потом имя. Существует вежливая форма обращения, которая присоединяется к фамилии (сливается с ней, а не отдельным словом). Моя фамилия Василисков в китайской записи будет выглядеть как ??????. А китайский аналог «мистер Василисков» — ????????.
      Баловство с китайским языком
      Не относится к теме статьи, но может принести много лулзов. Если взять слово, перевести гугл переводчиком на китайский, а полученный результат разбить на 1-2 иероглифа и переводить назад, можно очень увлекательно провести время. Скажем, ??? он переводит как «Василий», ??? как «бухта», ?? как «Краков». Но тайный смысл древних знаний можно раскрыть на обычных словах. Скажем, телефон переводится в ??. При этом ? — «электричество», ? — «слова». Другие слова с электричеством: ?? — аккумулятор (? — бассейн), ?? — компьютер (? — мозг), ?? — фильм (? — тень). С настоящими китайцами по этой части не сверялся, но время провести таким образом можно очень неплохо. А вообще интересный язык. После латышского и польского надо бы заняться…
    • Филиппины — тут исторически смешалась американская и испанская системы написания имени. Взятая из времён испанской колонизации традиция записывать фамилии матери и отца смешалась с американской давать промежуточные имена. В текущем варианте данное при рождении имя или имена записываются в графу «имя», фамилией ребёнка становится фамилия отца, промежуточным именем — девичья фамилия матери.

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

Более редкие варианты


Аспекты i18n из этой категории большинству из Вас вряд ли когда-то понадобятся. Но всё же может быть полезно иметь их ввиду.

  • Система единиц. Ваши пользователи привыкли к метрам, килограммам, литрам и градусам Цельсия? Или футам, фунтам, галлонам и градусам Кельвина? Сам я в США пока не бывал, но те, кто бывал, рассказывали, что по прибытии туда попадаешь в Нарнию дивный мир «несистемных» единиц. А после определённого времени, проведённого там, начинаешь забывать системные.
  • Формат бумаги. Отчасти связан с предыдущим и очень полезен, если Вы генерируете какие-то счета, бумажные формы и что-то ещё, что потенциально может быть распечатано и сложено в папку для записей или подано кому-то. Большинство стран привыкли к формату А4. Но США, например, широко используют форматы Letter (8 1?2 х 11 дюймов, 216 х 279 мм) и Legal (8 1?2 х 14 дюймов, 216 х 356 мм).
  • Правила комбинированных строк. Один из аспектов, который на самом деле часто может стать полезен, и который сложно реализовать. Под правилами комбинированных строк я подразумеваю те случаи, когда Вам нужно сформировать фрагмент текста, а не просто выдать языковую переменную. Примеры включают, но не ограничиваются:
    • склонение слов, относящихся к числу (в Вашей корзине 3 товара / 5 товаров);
    • формирование полного имени из примера выше;
    • правильное использование грамматического рода в языках, где он существует (Уважаемый г-н Иванов / Уважаемая г-жа Иванова) и т.п.

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

Где черпать информацию?


В тексте статьи я давал ссылки на Википедию, но все мы знаем, что использовать её как серьёзный источник знаний лучше не стоит. К счастью, существует проект Common Locale Data Repository (Общий репозиторий данных о локалях), поддерживаемый Unicode Consortium. Мало того, что он содержит невероятное количество аспектов и параметров локалей и регулярно обновляется сообществом, данные доступны для свободной выгрузки в формате XML, что позволяет при правильной проработке архитектуры регулярно и безболезненно обновлять стандарты.

Я затронул только основные по моему мнению аспекты. Если Вы считаете, что я что-то упустил, напишите в комментариях, добавлю. Заодно делитесь своим опытом работы с локализированными продуктами.

Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас оформив заказ или порекомендовав знакомым, 30% скидка для пользователей Хабра на уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps от $20 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps до декабря бесплатно при оплате на срок от полугода, заказать можно тут.

Dell R730xd в 2 раза дешевле? Только у нас 2 х Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 ТВ от $249 в Нидерландах и США! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

Комментарии (9)


  1. RiseOfDeath
    08.11.2018 17:22

    Мне кажется в статье не хватает случаев перевода составных названий. В качеств епримера — система зельеварения в Minecraft — название состоят из нескольких слов, в зависимости от эффектов и т.п. Как только в игру добавили систему локалей почти сразу выяснилось что «обычная, очевидная» система делает перевод на арабский вообще невозможным (без надмозговости). Поскольку арабский не знаю не могу сказать что там конкретно было, но в итоге ребятам пришлось переделать всю систему именования зелий.


    1. Vasiliskov Автор
      08.11.2018 17:27

      В таких случаях так и хочется записать слово «зелье» в одну переменную, а «слепой ярости» в другую. И так делать не стоит, как я уже писал выше. Всё название в одну переменную, как бы нерационально это не казалось.


  1. ingumsky
    08.11.2018 17:41
    +2

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


    1. Vasiliskov Автор
      08.11.2018 18:35
      +1

      Спасибо за замечание, исправил.


  1. datacompboy
    09.11.2018 03:27
    +2

    Ещё важно: к любому тексту нужно контекст.
    "Name" легко и просто может означать разных пять и более вещей, Так что банальное _("Name") выдаст маразм в 4 из пяти этих мест.
    Особенно весело, если "исправили" самое редкое.


  1. smilyfox
    09.11.2018 08:34

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


  1. hard_sign
    09.11.2018 09:21

    А ещё интересный момент – шрифты. Если на сайте не используется «шрифт по умолчанию», то может оказаться, что в вашем шрифте просто нет символов нужного языка :)


  1. gban
    09.11.2018 11:37
    -1

    Потрачено.


  1. DuMMeR
    09.11.2018 11:57

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