Форум → Программирование → PHP для идиотов → Локализация - кто будет говорить?
Локализация - кто будет говорить?
Страницы: ← Следующая страница →
-
Предлагаю взглянуть на задачу локализации веб-приложения с такой точки зрения: надо ли объявлять язык свойством приложения? Может быть это атрибут объекта Пользователь? В системе всегда присутствует "текущий пользователь" и у него есть языковые предпочтения.
$app->t('Say cheese')
или
$user->t('Say cheese')
Казалось бы, какая разница если и Пользователь и Приложение всегда присутствуют. А разница есть.
Пример: мы взялись за рассылку писем. Если язык - свойство приложения, то все письма будут на языке по-умолчанию или на языке инициатора рассылки. Или нам придется использовать какие-то хаки, чтобы постоянно переключать "текущий язык приложения".
Но если сделаем так, что класс пользователь "умеет говорить на своем языке", то достаточно просто перебирать пользователей по списку и подставлять объект в шаблонизатор.ιιlllιlllι унц-унц -
11 мая 2010 г. 9:42, спустя 2 часа 4 минуты 41 секунду
о, ахуеть какая клевая тема, сам сейчас занят подобной проблемой. Ща расскажу о своем видении ситуации. Приготовьтесь господа, текста будет много
Есть файл application/languages формата<?php
return array(
'avalible' => array('ru_RU', 'en_UK', 'et_EE'),
'default' => 'ru_RU'
);
И ежу понятно: мы теперь знаем, какие языки доступны в приложении и какой язык по умолчанию.
У каждого пользователя есть поле lang_code (или locale?). Именно в базе: id, name, passhash, locale, … . Когда пользователь залогинен под своей учеткой - в сессии хранится информация об его языковых предпочтениях. Ессно когда делаем рассылку ему, то берем язык из этого поля.
Теперь самое интересное: а на каком же языке показывать пользователю сайт? на том же, который прописан в базе для него? а вот хуй! Ниже представлена цепочка:
1) если указан GET-параметр (или субдомен с языком) ?lang_code и значение этого параметра есть в languages.avalible - показываем сайт на этом языке. Опционально можно записать в сессию данные о языке. В противном случае - идем дальше.
2) если в сессии есть данные о языке - показываем сайт на этом языке. В противном случае - идем дальше.
3) получаем request-параметр HTTP_ACCET_LANGUAGES, парсим его. Берем первый язык из него. Он есть в languages.avalible? отлично, записываем эту информацию в сессию, показываем сайт на этом языке. Если нету - берем следующий язык, проверяем. И так далее. Если ни один язык не подошел - идем дальше.
4) а что тут думать? берем язык, который прописан в languages.default. Записываем эти данные в сессию. И покажем пользователю список доступных языков
по поводу "свойств" приложения и пользователя. Есть объект Locale, который сам занимается вышеописанным дрочем. Объект Translate имеет доступ к Locale и все переводы делаются на том языке, который в Locale. А когда мы делаем рассылку - язык будет принудительно перегружен.public function tr($string, $args = array(), $escape = NULL, $namespace = NULL, $locale = NULL)
// вот когда здесь принудительно указываем $locale - это и есть перегрузка -
11 мая 2010 г. 10:00, спустя 18 минут 5 секунд
кстати, $tr->tr('переведи меня') - это i18n а не l10n. l10n - это форматирование даты, чисел, валюты.
Что вы посоветуете для этого? Я пока колеблюсь в выборе между sfCulture и Zend_Locale. Может что-то полегче есть? -
11 мая 2010 г. 10:15, спустя 14 минут 46 секунд
ну пусть "интернационализация", согласен.
то есть в твоих В.Б. для рассылки «придется использовать какие-то хаки, чтобы постоянно переключать "текущий язык приложения""»
рассуждения о выборе предпочтительного языка понравились.ιιlllιlllι унц-унц -
11 мая 2010 г. 10:22, спустя 7 минут 29 секунд
кое что про оптимизацию
public function tr($string, $args = array(), $escape = NULL, $namespace = NULL, $locale = NULL)
функция-супермаркет :)
по твоим значениям-по-умолчанию видно, что как правило нужен только первый параметр. на сотню вызовов будет 95 вызовов с одним параметром.
не лучше ли сделать отдельные методы для множественного числа, экранирование выкинуть нахуй, потому, что это отдельная задача, а локаль настраивать один раз отдельным свойством/методом???ιιlllιlllι унц-унц -
11 мая 2010 г. 10:46, спустя 23 минуты 16 секунд
то есть в твоих В.Б. для рассылки «придется использовать какие-то хаки, чтобы постоянно переключать "текущий язык приложения""»
это не совсем хак, да и текущий язык по сути не переключается$tr = BL_Translate::instance('modules.backend.news') // указали неймспейс
->setLanguage('en'); // и язык (вообще он сам из Locale укажется). Метод может принять как экземпляр BL_Locale так и строку (ru, ru_RU)
$tr->tr('apple'); // apple
$tr->tr('apple', false, false, false, 'ru'); // яблоко
$tr->tr('apple'); // apple. То есть язык остался прежнимне лучше ли сделать отдельные методы для множественного числа
так и естьpublic function ntr($string, $count, $args = array(), $escape = NULL, $namespace = NULL, $locale = NULL)
экранирование выкинуть нахуй, потому, что это отдельная задача
я подумаю над этим.а локаль настраивать один раз отдельным свойством/методом???
так и естьСпустя 117 сек.экранирование может быть выкину когда сделаю интеграцию с Twig и там будет Twig'овское экранирование использоваться -
11 мая 2010 г. 10:55, спустя 8 минут 57 секунд
во, еще про такую хуйню нужно помнить: в админке необходимо кроме локали где-то в сессии хранить язык сайта, который редактируется. (ну то есть язык интерфейса - русский, а редактируем англ. версию сайта) -
11 мая 2010 г. 15:25, спустя 4 часа 30 минут 10 секунд
я у себя устанавливаю язык приблизительно в том порядке что и уАбырвалг
но вроде у меня заполняется сперва по умолчанию, а потом ищется, не помню порядок но если очень интересно кому, могу вечером позырять.
Еще такая штука, допустим пользователь оставил коммент в статье, я сразу отправляю всем пользователям, подписанным на рассылку в статье уведомления (то что это не отложено сейчас не обсуждается), но уведомление мне надо отправить на языке пользователя, которому оно отправляется. При этом с помощью обычной фабрики я получаю инстанс языка обрабатываемого пользователя - Translate::SetLanguage($user->lang) - фактически переключая язык в синглтоне Translate. Причём я немного лукавлю и не перключаю язык к исходному состоянию, так как после этих действий идёт переадресация.
Я категорически против языка у приложения, потому что язык это свойство пользователя, раз уж приложение многоязычное! -
14 мая 2010 г. 2:00, спустя 2 дня 10 часов 35 минут
Я для себя решил все-таки держать переводы вне User. При необходимости делать типа
$old = Qb::setLanguage($user->language);
// …
Qb::setLanguage($old);
Небольшая фишка: при переключении на другой язык не потребуется "руками" подгружать все необходимые разделы. Список нужных разделов у нас уже есть. setLanguage() подгрузит всё, что надо для нового языка.
Переводы буду хранить в структуре:
'languageA' => array(
'domain1' => array(…),
'domain2' => array(…),
),
'languageB' => array(
'domain1' => array(…),
'domain2' => array(…),
),
На диске храню отдельные файлы для каждой секции (domain) перевода в сериализованном виде. Для каждого языка отдельная папочка.
Типично при инициализации приложения будет грузиться секция 'common'
$user = new User() // загрузка пользователя, в т.ч. его предпочтительного языка
Qb::set('user', $user); // сохраним в реестр на будущее
Qb::setLanguage($user->language);
Qb::useTranslation('common');
В контроллере подгружаются разделы перевода по необходимости
class XyzController
{
public function __construct()
{
Qb::useTranslation('forum');
Qb::useTranslation('topic');
}
public function actionFoo()
{
echo Qb::t('Listen to me, banderlogies');
echo Qb::t('Fuck you all', 'topic');
}
Кто будет грузить файл с примером, сначала запустите lang/revive.php чтобы создать serialized переводыιιlllιlllι унц-унц -
12 мая 2010 г. 12:16, спустя 10 часов 16 минут 7 секунд
ох ты наш любитель статики) А где plural forms?Qb::setLanguage('Russian'); // мне западло писать имя полостью, лучше ru, et, ua
сериализацию можно б сделать опциональной. Мне кажется, что если на сервере будет APC то инклюд файла с переводом будет быстро работать. -
12 мая 2010 г. 13:54, спустя 1 час 37 минут 38 секунд
1. пример хорош пока он прост. это — пример. он иллюстрирует ОДНУ вещь: переключение языков
2. конечно статика. она доступна отовсюду без онанизма вроде $this->$a->$b->t()
3. непринципиально какие имена. абсолютно!
4. хуй там. даже с байт-код кешерами сериализованные данные читаются быстрееιιlllιlllι унц-унц -
12 мая 2010 г. 12:37, спустя 22 часа 43 минуты 24 секунды
кстати, блин, нашел у себя кучу проблем
1)BL_Translate::instance('modules.backend.news', 'array'); // драйвер массива
BL_Translate::instance('modules.backend.news', 'database'); // а вот хуй! опять драйвер массива. Так как в self::$instances['modules.backend.news'] уже есть данные
2) местами у меня может быть двойной расход памяти
3) и еще я в instance могу передать настройки драйвера, но не могу передать настройки всего Translate (они через BL_Settings получаются)Спустя 73 сек.зато в статике нельзя
one::thre::fourСпустя 32 сек.если даже с опкод кешерами сериализация быстрее - надо б и мне ее сделать тогда -
12 мая 2010 г. 14:46, спустя 2 часа 8 минут 19 секунд
вот любишь ты влезть со своим самоваром, непонятным никому кроме тебя, в чужую тему.
offtopic: Д. Котеров в известном примере показал, что эффективность кешеров сильно падает, когда php-файлов много.
конечно редактировать сериализованный массив нереально. поэтому в моем примере (в архиве) исходные переводы даются как php, но есть "транслятор-сериализатор"
в статике можно делать one::too()->three() и т.д. есть статический глобально видимый корень, дальше танцуешь как хочешь.
и лучше, если не one, two, three, four, а только one, two ))) — юзабельнее )))ιιlllιlllι унц-унц -
22 мая 2010 г. 13:36, спустя 9 дней 22 часа 50 минут
Теперь самое интересное: а на каком же языке показывать пользователю сайт? на том же, который прописан в базе для него? а вот хуй! Ниже представлена цепочка:
в этой цепочке я забыл про определение языка на основе geoip… -
22 мая 2010 г. 18:09, спустя 4 часа 33 минуты 8 секунд
Абырвалг, считаю для себя такой подход (язык по геоАйПи) одним из говенных методов (кроме исключений для очень редких проектов).
Причины: если у нас сайт русский, то для того же Гугля по сути "главный" сайт будет инглишем, а русский только вариацией. А нам нужно чтоб русский сайт был "русским". Но это так, образно.
В целом считаю что дефолтным (если у юзера не указано иного) нужно показывать тот язык, по которому "географически" находится сайт. Тот, которым имеет наибольшую аудиторию. А дальше юзер сам себе выберет "свой" язык если это ему понадобится.
Все ИМХО.
Страницы: ← Следующая страница →
Пожалуйста, авторизуйтесь, чтобы написать комментарий!