Про интернационализацию и локализацию
24/12/2009 20:29
Когда пользователь заходит на сайт, поддерживающий различные языки, то он должен выбрать тот язык, который подходит ему. В большинстве случаев язык, на котором отображается мультиязычный сайт определяется автоматически, на основе заголовка HTTP_ACCEPT_LANGUAGE, или на основе IP-адреса пользователя. Определять язык пользователя по его местоположению, при помощи IP-адреса неправильно, так как во-первых, правильно определить местоположение пользователя получится не всегда, а во-вторых, определять язык по местоположению это плохая идея.
Почему? Например, я могу находиться в Испании, и зайду на мультиязычный сайт из под локализованного на баскский язык браузера (я Баск), а страничка всё равно отобразится на Испанском языке, хотя я хотел именно баскский, который, к тому же, вообще не связан ни с одной известной языковой семьёй и по-испански я просто бы ничего не понял. Такое может случиться, если язык пользователя определяется по IP.
Итак, чтобы правильно определить язык пользователя, мы можем посмотреть только на HTTP_ACCEPT_LANGUAGE, кроме него мы можем узнать язык пользователя только если он сам его укажет.
Язык не связан со страной
Нам кажется, что язык конечно же связан со страной - в Италии говорят на итальянском, в России на русском, в США на английском. Но это если смотреть только на государственный язык. Внутри этих стран люди разных национальностей общаются на различных языках и хотят смотреть сайты в локализованных на свой родной язык браузерах.
Язык и локаль это разные вещи
Нужно их различать. Локаль определяет представление чисел, даты, времени, валют, принятую типографику в тексте, в то время как язык определяет сам текст, то есть то, на каком языке написан текст. Способность же сайта показать пользователю текст на его родном языке - это уже интернационализация (сокращенно - i18n). Чтобы мы могли показать сайт на родном языке пользователя, нам нужно узнать язык. Ранее мы уже разобрались, как это сделать. Но вот мы получили язык пользователя, теперь мы можем показать ему текст на сайте на этом языке, но как нам теперь определить локаль, чтобы мы могли правильно отформатировать в этом тексте даты, числа и все прочее?
На самом деле так же - из заголовка HTTP_ACCEPT_LANGUAGE. Например, значение этого заголовка в моем браузере выглядит так:
ru,en-us;q=0.7,en;q=0.3
Это значение может кодироваться в соответствии с несколькими стандартами, мы не будем их рассматривать. Для того, чтобы полученное значение использовать в Zend_Locale, нужно просто передать его в конструктор, Zend_Locale сам приведёт его к виду en_US:
$locale = new Zend_Locale('en-us');
Формат, которым определяется локаль такой:
<язык>_<ТЕРРИТОРИЯ>
Как видно из заголовка HTTP_ACCEPT_LANGUAGE, у языка, которому мы отдаём предпочтение (ru), не указан код территории. Это нормально, у локали не обязательно может быть указан код территории. Поэтому, в нашем случае, ru и будет названием локали.
А вдруг нам понадобится код территории? Откуда его взять в нашем случае? Ниоткуда, если пользователь не укажет его сам (например, в личном кабинете). А у тех, кому код территории действительно нужен - он почти всегда указан в заголовке HTTP_ACCEPT_LANGUAGE.
А если вы хотите сделать совсем приятно - сделайте инструмент выбора языка с территорией у себя на сайте (смотрите здесь).
Как составляется название локали
Список языков определяется в соответствии с IANA Language Subtag Registry. Код территории определяется в соответствии со стандартом ISO_3166-1. Эти же коды территорий можно найти и в реестре IANA Language Subtag Registry.
Таким образом, чтобы составить локаль для французского языка, используемого на территории Канады, нам нужно заглянуть в реестр IANA и найти там запись:
Type: language Subtag: fr Description: French Added: 2005-10-16 Suppress-Script: Latn
затем найти запись территории:
Type: region Subtag: CA Description: Canada Added: 2005-10-16
и, далее, просто составляем язык и территорию: fr_CA.
Оказывается, далеко не все языки локализованы, то есть не ко всем языкам составлены файлы с правилами для локализации. Вы можете посмотреть список всех существующих локалей на сегодняшний день. Но 99% разработчиков хватает и существующих локалей, не часто же вам приходится создавать сайты на языке Utarmbung (язык в Папуа-Новой Гвинее)?
Зачем нужна локаль
Как я уже говорил, локаль и язык это разные вещи. Локаль нужна нам прежде всего для интерфейса. Например, для каждой существующей локали мы можем сделать файл с переводом надписей интерфейса и, в зависимости от текущей локали, будем показывать пользователю надписи на его языке.
Но это только интерфейс сайта. Мы можем сделать интернационализацию, то есть вести сайт на нескольких языках, но мы, скорее всего, не имеем такой возможности, чтобы вести сайт на нескольких диалектах одного языка, например, английского. То есть, если у нас на сайте есть статья на американском английском (en_US), который сейчас использует большинство англоязычных людей, то вряд-ли мы будем делать локализацию этой статьи для пользователей из Австралии, которые тоже говорят на английском, но используют диалект этого языка (”страйн“), который имеет некоторые отличия и заимствованные слова у коренных жителей Австралии.
Поэтому, для всех англоязычных людей мы будем писать статьи на американском английском, не обращая внимания на диалекты. Это означает, что даже если к нам на сайт придет человек, для которого судя по заголовку HTTP_ACCEPT_LANGUAGE предпочтительным языком будет австралийский английский (en_AU), то мы все равно покажем ему статью на американском английском (теперь просто en, мы ведь не учитываем диалекты для контента сайта), а вот интерфейс сайта можем показать и локализованный на en_AU, так как такая локализация, скорее всего, отнимет немного сил.
В заключении
Я не стал обращать внимание на некоторые вещи, а постарался выделить главное, чтобы у вас сложилось понимание, как использовать локализацию и интернационализацию и как все это работает. Я мог упустить что-то, так что внимательных читателей прошу сообщать в комментах :)
Спасибо, отличная статья! Наконец-то я понял все эти фишки по локализации. На русском ничего не нашел хорошего, только эту вашу статью.
Еще раз спасибо)))
Дык, всегда пожалуйста)