DbHelp.ru
Маленький Yii блог
Комментарии
Гость: комент
Гость: wahaha
zolter: Друпал на Yii? ))
nastia: http://drupal.org/
JB: Да там просто ад)) мне всего 3 значения нужно чтобы выпадало, все равно спасибо)...



Сервер Ultima Online - Forest Wars (от создателя данного блога)

Урок 5 : Многоязычность

Рубрика: Создаем блог вместе

Оцените эту статью:

Рейтинг: 0.00 (0)
10 Июн. 2009
Опубликовать в Twitter Написать в Facebook Опубликовать в своем блоге livejournal.com

Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут возникнуть ошибки из-за несовместимости. Обычно ответы на все вопросы работы на 1.1.х были описаны в комментариях ниже статьи.

Yii Framework Blog img http://dbhelp.ruselectlang Я надеюсь вы согласитесь со мной что каждый серьезный сайт (проект) должен поддерживать многоязычность. Мы с вами не имеем право навязывать пользователю язык на котором он должен смотреть наш сайт. Пока наш блог проект не зашел слишком далеко - стоит оглянуться и заняться интернационализацией...

---

А вы уже читали "Урок 4 : Создаем отдельную страницу для постов (тем)"? Если нет, тогда дальше читать не стоит :)

Хочу обратить внимание что Yii отлично поддерживает интернационализацию (I18N) и что перевести проект на другие языки проблем не составит.

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

Заходим в protected/config/main.php и добавляем две строчки:

<?php
return array(
...
    'sourceLanguage' => 'ru',
    'language' => 'en',
...

  • sourceLanguage - язык скриптов.
  • language - язык нашего сайта по умолчанию

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

Теперь заходим в protected и создаем там папку messages. В папке messages создаем папку en, а в папке en создаем файл main.php:

<?php
    return array(
        'русский вариант' => 'английский вариант',
    );

В этом самом файле мы и делаем все переводы нашего сайта на английский язык. К примеру сюда же кидаются переводы для кнопочек, элементов форм и прочей фигни. В народе файл messages/en/main.php называют словарём. Таких словарей у нас может быть много и использовать их будем в зависимости от ситуации.

Я взял на себя смелость немного перевести элементы блога и файл messages/en/main.php у меня теперь выглядит следующим образом:

<?php
    return array(
        'Перейти к странице:' => 'Select page:',
    );

Так получилось что в тех скриптах блога что мы с вами уже написали - только одна русская фраза фигурирует в отображении (post/index.php), её я и перевёл. Все остальные наши данные выводятся с базы данных и в переводе на данном этапе не нуждаются.

Теперь давайте откроем файл views/post/index.php и укажем там что фразу "Перейти к странице" надо переводить (если язык пользователя не русский).

Все переводы осуществляются одной командой:

Yii::t("словарь", "что_переводим")

Как вы понимаете что б перевести фразу "Перейти к странице:" нам достаточно указать:

Yii::t("main", "Перейти к странице:");

  • Первым параметром мы указали название нашего рабочего словаря (messages/en/main.php)
  • Второй параметр - это фраза которую надо переводить.

Теперь после небольшой теории - переходим к практике.

Файл views/post/index.php до интернационализации:

 <table border="0" width="100%" cellpadding="10" cellspacing="10">
    <?php
    if (!empty($posts))
        foreach ($posts as $key => $val) {
            $this->renderPartial('_list',array(
                'post'=>$val,
            ));
        }
    ?>
</table>

<?php $this->widget('CLinkPager',array(
            'pages'=>$pages,
            'maxButtonCount' => 5,
            'header' => '<b>Перейти к странице:</b><br><br>',
    )); ?>

Файл views/post/index.php после интернационализации:
 <table border="0" width="100%" cellpadding="10" cellspacing="10">
    <?php
    if (!empty($posts))
        foreach ($posts as $key => $val) {
            $this->renderPartial('_list',array(
                'post'=>$val,
            ));
        }
    ?>
</table>

<?php $this->widget('CLinkPager',array(
            'pages'=>$pages,
            'maxButtonCount' => 5,
            'header' => '<b>'.Yii::t("main", "Перейти к странице:").'</b><br><br>',
    )); ?>

Изменилась всего одна строчка. Старая фраза просто обернулась методом Yii::t.

На этом наше с вами участие заканчивается. Дальше Yii сама проверяет какой язык пользователем был выбран на сайте.
Давайте рассмотрим как работает на простых примерах

  • Если язык пользователя совпадает с языком скриптов (указанно в config/main.php) - тогда перевод не осуществляется. Т.е. на экран выводиться просто фраза которая указана вторым параметром в Yii::t.
  • Если язык пользователя английский - Yii открывает словарь main (messages/en/main.php) и ищет в нём фразу указанную вторым параметром. Если такой фразы не найдено - выводиться оригинальное название на родном языке. Если фраза найдена - значит она и подставляется при выводе.
  • Если у пользователя выбран язык для которого мы не писали перевода (к примеру язык "ua", а папки messages/ua нет) тогда на экран будет выведена фраза на оригинальном языке скриптов

Вот в принципе и все премудрости которые надо знать.
В дальнейшем при разработке я сразу буду использовать Yii::t, так что больше к тому "откуда растут ноги" мы возвращаться не будем.

Вкратце про интернационализацию я уже писал тут, но еще больше вы можете прочитать в официальной документации на русском языке!



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

  1. Поздравляю всех с выходом Yii Framework 1.1 beta next Список изменений Загрузить версию 1.1 beta ... "Yii PHP framework 1.1 beta"

  2. Вот и порадовали нас новой версией любимого фреймворка. Хотелось бы отметить что на этот раз исправлений ошибок оказалось меньше чем ... "Yii PHP framework 1.0.9"

  3. Сегодня обнаружил что Sam Dark как и обещал перевел интерисующюю практически всех часть документации про RBAC. next Благодаря таким людям  - ... "Перевод : Аутентификация и авторизация (RBAC)"

[guest] corpix

Было сказано: Четверг, 11 Июнь 2009

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

[adm] zolter

Было сказано: Четверг, 11 Июнь 2009

Тут вы не правы. Если переводом занимаеться не разработчик (так и должно быть) тогда переводчику врядли будет удобно получить в качестве материала исходники всех вьюх и искать в них текст что б переводить. Мне кажеться намного удобнее переводчику кинуть обычный практически текстовый файл словаря где он без каких либо знаний html-а поймет где надо переводить и куда что вставлять :)

[guest] Гость

Было сказано: Четверг, 11 Июнь 2009

Как считаете оправдано использование пространств имен в этой функции (Yii::t)?
Я сейчас склоняюсь к тому, чтобы написать враппер с простым именем, например "__" для замены
<?php echo Yii::t('main',
И "_" для использования без echo.

[adm] zolter

Было сказано: Четверг, 11 Июнь 2009

А есть ли в этом смысл? Только в том чтобы визуально было красивее? Мне кажется это лишняя затрата своего времени, хотя кому как нравится :) Плюс к этому, судя по вашему примеру - вы лишитесь такой возможности как использовать любое кол-во словарей, а не только main.

В самой работе использование словарей очень полезно.

[guest] Гость

Было сказано: Четверг, 11 Июнь 2009

я не очень понял, как быть с большими статичными текстами на страницах ?
их тоже в словарь совать ?

[adm] zolter

Было сказано: Четверг, 11 Июнь 2009

Нет. Словари используются только для перевода статических элементов на странице (название кнопок, колонок в таблицах, всякие системные ошибки и сообщения, поля в формах и тп).

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

corpix

Было сказано: Пятница, 12 Июнь 2009

2 zolter
Да, если передавать тексты переводчику, то словари безусловно удобней =)

Zzz

Было сказано: Вторник, 16 Июнь 2009

Yii::t("словарь", "что_перево<u>О</u>м")

[guest] zolter

Было сказано: Вторник, 16 Июнь 2009

сенк

[guest] kaiser Zaido

Было сказано: Воскресенье, 12 Июль 2009

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

[adm] zolter

Было сказано: Воскресенье, 12 Июль 2009

По этой теме просто уже написана статья в кукбуку. Скорее всего скоро просто займусь её переводом и опубликую ссылку в уроке на неё. Спасибо что напомнили!

Кстати ссылка на неё - http://www.yiiframework.com/doc/cookbook/26/ (англ.)

[guest] Гость

Было сказано: Вторник, 13 Октябрь 2009

Скажите, пожалуйста, а что делать, если мне приходят данные в виде ключей массива, а мне надо получить "перевод" этих ключей согласно файлам в каталогах messages/ru messages/en.
Вот у меня есть такой массив грубо говоря
array("key1", "key2", "key3");

и переводы:

ru:
"key1" => "Русский key1",
"key2" => "Русский key2",
"key3" => "Русский key3"

en:
"key1" => "English key1",
"key2" => "English key2",
"key3" => "English key3"

если я пишу просто Yii::t("main", $key) - то он так и выводит "key1", так как считает что это написано уже на русском. Можно ли как-нибудь сфорсировать перевод?

[guest] Maxx

Было сказано: Вторник, 13 Октябрь 2009

Для англ.рус перевода надо всего 1 словарь делать. ненадо два отдельных. Первое значение - текущее название, второе - которое должно быть в случае выбора англ. языка.

Посмотрите еще раз урок, там об этом говорится. Некаких key1,key2 ненадо

[guest] Гость

Было сказано: Среда, 14 Октябрь 2009

Я бы рад от них избавиться, но они приходят из внешней среды.

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

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

Может ли Yii помочь мне в этом?

[guest] Нянька

Было сказано: Суббота, 31 Октябрь 2009

>> [guest] Гость
ну ни Сукин ли ты сын??
нет конечно...

[guest] Гость

Было сказано: Суббота, 13 Март 2010

Не получается вывести русский язык.
Беру стандартный testdrive - заменяю там английские слова на русские - буквы вообще не выводятся. Если просто добавляю русскую букву к английскому слову - все слово пропадает.
Что я делаю не так?

[guest] Гость

Было сказано: Суббота, 13 Март 2010

спасибо за урок, появился один вопрос, у меня модуль news как сделать перевод если у меня словарный файл хранится тут
\protected\modules\news\messages\main.php

как мне прописать в строчке
Yii::t("main", "Перейти к странице:");

в первом параметре что нужно указать чтобы со слаться в модуль?

как я понимаю сейчас он ищит тут
\protected\messages\main.php

[guest] Гость

Было сказано: Суббота, 13 Март 2010

ой, забыл указать директорию ru/

вот так
\protected\modules\news\messages\ru\main.php
\protected\messages\ru\main.php

просто при написании комментария забыл прописать ru/
В файлах всё в порядке.

[guest] Гость

Было сказано: Суббота, 13 Март 2010

вопрос ещё открытый подскажите как прописать тут
Yii::t("main", "Перейти к странице:");

чтобы файл читался отсюда
\protected\modules\news\messages\ru\main.php

?

[guest] zolter

Было сказано: Суббота, 13 Март 2010

Сори, но по модулям не подскажу. не пробовал

[guest] Гость

Было сказано: Воскресенье, 14 Март 2010

всё разобрался, подсказали на другом форуме

http://www.yiiframework.com/forum/index.php?/topic/7443-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b8/page__view__findpost__p__39721

просто нужно было указать название модуля

Yii::t('NewsModule.news', 'title');

[guest] Гость

Было сказано: Воскресенье, 14 Март 2010

и ещё вот, немного поискав на основном форуме Yii

http://www.yiiframework.com/forum/index.php?/topic/6623-failed-to-get-i18n-working-please-help/page__hl__/messages/__fromsearch__1

[guest] zolter

Было сказано: Воскресенье, 14 Март 2010

Спасибо! Думаю многим будет полезно

[guest] Гость

Было сказано: Воскресенье, 14 Март 2010

ага, для этого выложил ссылки. А вопрос у меня появился только тогда как решил сделать модули, до этого даже как-то и не задумывался. Теперь остаётся сделать плагин под смарти, так чтобы было удобно просто и понятно. Что то вроде этого

{t lang="news.title"}

где news модуль а следом за точкой словарное слово что нужно перевести. Но это пока обдумываю как лучше)

[guest] alex3d

Было сказано: Воскресенье, 14 Март 2010

> [guest] Гость
> Было сказано: Суббота, 13 Март 2010
> Не получается вывести русский язык.
> Беру стандартный testdrive - заменяю там английские слова на > русские - буквы вообще не выводятся.

У меня была таже фигня - ниче понять не мог... погуглил и нашел что надо вставить в config/main.php например после:

'name'=>'My Demo App...',

вот это:
'charset'=>'windows-1251',

[guest] Гость

Было сказано: Воскресенье, 14 Март 2010

сразу е понял о чём речь)
вообщем проблема та же самая была, исправил след. образом, в файле .htaccess прописал такую строчку
AddDefaultCharset utf-8

и всё стало в порядке

[guest] alex3d

Было сказано: Понедельник, 15 Март 2010

Захотел вставить комбо-бокс переключения языков как в статье из cookbook/26, но там очень сжато написано - даже не показано как виджет вставить - из комментов только понял. Там же в комментариях прочитал что компонент "MyController" (который я поместил в папку components) лучше запихнуть в "аутолоад" - чтоб ненадо было каждый раз все компоненты вызывать через "extends MyController". окошко с языками показывается, параменты сессии не передаются и не присваиваются переменной app()->language. Такое ощущение что init() от MyController не вызывается вообще... Но ведь должен? если в конфиге у меня

'import'=>array(
'application.models.*',
'application.components.*',
),

значит всё файлы что в папке components будут автоматом вызыватся? т.е. init() обязательно исполнится? Или я неправильно понял что такое поставить в "аутолоад"?
И второй вопрос - все что присваивается в конфиге (main.php) исполняется только 1 раз при входе на сайт? я к тому что
'sourceLanguage' => 'ru',
'language' => 'en',

не будет ли каждый раз сбрасывать параметр app()->language на "en"?

[guest] Artem

Было сказано: Четверг, 25 Март 2010

А как локализовать стандартные сообщения?
Например которые выводятся при валидации формы.

У Вас такие есть :)

Please fix the following input errors:
* Логин содержит недопустимые символы.

[adm] zolter

Было сказано: Четверг, 25 Март 2010

Свое сообщение указывается параметром 'message'. Т.е. в rules мое правило выглядит вот так:

array('login', 'match', 'pattern' => '/^[A-Za-z0-9А-Яа-я\_\-\s,]+$/u','message' => 'Логин содержит недопустимые символы.'),

[guest] Artem

Было сказано: Пятница, 26 Март 2010

Вы меня не поняли. Я имел ввиду другой текст. Как локализовать его?

Please fix the following input errors: - вот этот текст не переведён.

[adm] zolter

Было сказано: Пятница, 26 Март 2010

А 'sourceLanguage' => 'ru', в конфиге не помогает?

[guest] Artem

Было сказано: Пятница, 26 Март 2010

К сожалению нет...

[guest] Гость

Было сказано: Вторник, 13 Апрель 2010

Добрый день, а кто нибудь использовал gettext в качестве источника сообщений? не могу разобраться в какую директорию подкладывать файлы перевода.. с пом poedit сгенерировал файл category1.po и category1.mo.
В конфигах
'components'=>array(
...
'messages'=>array(
'class'=>'CGettextMessageSource',
'useMoFile'=>1,
),...

вызываю $test = Yii::t('category1', 'some key');
файлы перевода лежат тут protected\messages\en\category1.mo
и protected\messages\ru\category1.mo
в результате перевода не получаю(, другие источники сообщений отрабатывают отлично.

[guest] almix

Было сказано: Четверг, 15 Апрель 2010

решил проблему,(слегка некорректно по моему правда).
в файле CGettextMoFile.php
function load()
...
закоментил
//if(($pos=strpos($id,chr(4)))!==false && substr($id,0,$pos)===$context)
// {
// $id=substr($id,$pos+1);

$message=$this->readString($fr,$targetLengths[$i],$targetOffsets[$i]);
$messages[$id]=$message;
// }
по всей видимости тут проблема с utf-8.

и прописал в main.php -> 'catalog'=>'category1'
'messages'=> array(
'class'=> 'CGettextMessageSource',
'catalog'=>'category1'
),
после этого переводы из mo файлов стали отрабатывать корректно. Если у кого то есть более корректный способ решения, отпишите плиз.

[adm] zolter

Было сказано: Четверг, 15 Апрель 2010

вместо substr нужно mb_substr поставить и думаю заработает

[guest] yolf

Было сказано: Понедельник, 14 Июнь 2010

Как по мне - не удобно хранить текст во вьюхах. Проще сделать как в хотел человек в комменте за прошлый год - юзать ключи.
Потому сделал следующий костыль:
в конфиге sourceLanguage присваивается какая ни будь левая локаль, например abc, в словарях пишем:
en/main.php - 'key1'=>'hello world'
ru - 'key1' => 'привет мир'

И в переопределенном контроллере в init_e проверяем Пост, сессию. Если там языка нет - то запихиваем в сессию и в app->language тот - который хотим юзать по умолчанию.

Метод несколько кривой, но лично мне проще во вьюхе написать:
Yii::t('main', 'btnSaveText');
чем вместо btnSaveTest печатать готовый текст.

[guest] Гость

Было сказано: Четверг, 03 Февраль 2011

Товарищи, а от куда ж берётся этот язык пользователя?
Нигде не указано о том как его устанавливать, как его передавать, например, в урле.
Он просто где-то есть... Но где?
Да, например, браузер передаёт желаемый язык пользователя соответственно настройкам - это ли то, о чём идёт речь?
А что, если пользователь хочет изменить язык?

[guest] zolter

Было сказано: Пятница, 04 Февраль 2011

Язык один раз выбираем на странице. Затем уже сохраняем в сессию к пример и берем оттуда, если он небыл отдельно передан в URL страницы. Тут уже дело фантазии как бы.

[guest] V1dun

Было сказано: Суббота, 25 Июнь 2011

Автоматический перевод сообщений из ядра Yii будет при выставлении опций:


'language'=>'ru',
'components'=>array(
'coreMessages'=>array(
'language'=>'en',
),
),

[guest] Гость

Было сказано: Четверг, 11 Август 2011

Здравствуйте, хочу построить мультиязычность через gettext и столкнулся с проблемой, что POedit при сканировании проекта выберает для перевода не текст, а словарь, т.е Yii::t('словарь','текст') выберает только первый аргумент функции.
В Poedit во вкладке Ключевые слова добавил t.
Буду очень благодарен за помошь!!!

[guest] Гость

Было сказано: Пятница, 09 Декабрь 2011

Все очень просто: используйте как ключевое слово t:2
(2 указывает на использование второго параметра)

Оставить комментарий


Код:
Имя: