CakePHP 2.4 и локаль timeAgoInWords от Timehelper

Недавно я обновил CakePHP с 2.3.9 до 2.4.4. Насколько я помню (сейчас не могу проверить) Timehelper::timeAgoInWords хорошо работал в старом CakePHP. Но после этого обновления у меня возникла проблема с локалью. Я меняю язык на английский, но время назад все равно приходит на турецком языке.

В core.php я уже установил язык по умолчанию на турецкий:

Configure::write('Config.language', 'tur');

Внутри моего файла просмотра я использую это:

$d = "2012-05-02 20:17:30"
$myString = $this->Time->timeAgoInWords($d, array('end' => '+10 year')); 

Я получаю результат на турецком языке следующим образом:

1 yıl, 8 ay, 4 hafta önce

Я хочу такой результат:

1 year, 8 months, 4 weeks ago

Мои переменные сеанса такие:

[Config] => Array
        (
            [userAgent] => 35db889a82essb4e57b540d52e8a766d
            [time] => 1391121684
            [countdown] => 10
            [language] => eng
        )

Хотя я установил свой язык как английский, результат пришел на турецком языке. Как я могу отладить/исправить это?

Изменить:
Я проверил значения языка настройки. Результаты такие:

echo Configure::read( 'Config.language' );
result: tur

Но

echo $this->Session->read('Config.language');
result: eng

Как я уже отметил в начале своего вопроса, я уже установил Configure::language внутри своего файла core.php. core.php переопределяет значение моего сеанса?

Edit2:
Странно то, что хотя Config.language выглядит как «tur» и «eng», другие части моего файла представления работают хорошо. Например, это хорошо работает:

__("string")

Edit3: Относительно этой страницы: http://book.cakephp.org/2.0/en/core-libraries/internationalization-and-localization.html

Я добавил это:

class AppController extends Controller {
    public function beforeFilter() {
        if ($this->Session->check('Config.language')) {
            Configure::write('Config.language', $this->Session->read('Config.language'));
        }
    }
}

После этого изменения языка конфигурации результаты выглядят следующим образом:

echo Configure::read( 'Config.language' );
result: eng

echo $this->Session->read('Config.language');
result: eng

Но я все еще вижу результат timeAgo на турецком языке..
На прошлой неделе я мигрировал на новый сервер, может быть, какие-то настройки отсутствуют для английского языка и т. д.? Я не могу понять, почему timeAgo не работает, а __("string") работает.

Edit4:
я даже изменил core.php вот так:

Configure::write('Config.language', 'eng');
setlocale( LC_TIME, 'en_US.utf8', 'eng', 'en', 'en_US', 'en_UK' );

Похоже, в моей конфигурации ничего не меняет язык timeAgoInWords. Я переопределяю каждый фильтр beforeFilter, чтобы изменить Config.language на английский, но слова по-прежнему турецкие. Обратите внимание, что в моем часовом поясе php.ini это так:

date.timezone = Europe/Istanbul

Edit5:
Похоже, проблема в переводах. Я проверил исходный код timeago, вот его копия: https://github.com/cakephp/cakephp/blob/2.4.4/lib/Cake/Utility/CakeTime.php#L738

Похоже, что этот метод использует __d и __dn, поэтому я проверил результаты в своем коде. «az önce» в переводе с турецкого означает «только что».

Я уверен, что Config.language — «eng». Так:

echo __d('cake', 'just now', 'just now'); // results: "az önce"
echo __('just now');                      // results: "just now"
echo __('az önce');                       // results: "az önce"
$days=12; 
echo __dn('cake', '%d day', '%d days', $days, $days); // results: "12 gün"
echo __('gün');                       // results: "days"

person trante    schedule 30.01.2014    source источник


Ответы (3)


Для отладки echo Configure::read( 'Config.language' ); прямо перед вашим timeAgo вызовом. Если вы обнаружите, что это не «eng», значит, вы устанавливаете английский язык после того, как timeAgo уже был вызван.

ЕСЛИ это не сработает, возможно, вам также придется вызвать setlocale

Я использую это для английских дат:

setlocale( LC_TIME, 'en_US.utf8', 'eng', 'en', 'en_US', 'en_UK' );

И я думаю, это будет призыв к турецкому

setlocale(LC_TIME, 'tr_TR.UTF-8', 'tr_TR', 'tr', 'turkish');

PS: Глядя на историю TimeHelper, ничего не изменилось, чтобы повлиять на локаль, но, возможно, была изменена зависимость.

person Ilie Pandia    schedule 30.01.2014
comment
Спасибо Илие, как раз перед timeAgo я проверил Config.language. Я знаю и английский, и турецкий. Я добавил результаты в конец вопроса. - person trante; 01.02.2014
comment
ОК, в вашем фильтре перед замените ваш код просто этим: Configure::write( 'Config.language', 'eng'), чтобы принудительно использовать английский язык везде и проверить, как ведет себя timeAgo(). Если это работает, значит, где-то в вашем коде вы переключаетесь на турецкий язык. - person Ilie Pandia; 01.02.2014
comment
Я добавил Configure::write( 'Config.language', 'eng') в beforeFilters контроллеров. Я даже написал это прямо перед строкой timeAgoInWords внутри моих файлов представления. Когда я проверяю, я вижу, что Config.language установлен на eng. - person trante; 01.02.2014
comment
Когда я пишу строки, это работает: __("word"). Но timeAgoInWords по-прежнему показывалось на турецком языке. - person trante; 01.02.2014
comment
Попробуйте и это setlocale(LC_TIME, 'tr_TR.UTF-8', 'tr_TR', 'tr', 'turkish'); (до вызова timeAgo). Возможно, timeAgo просматривает языковой стандарт системы, чтобы перевести вашу строку. - person Ilie Pandia; 01.02.2014

Обычно я меняю текущий язык следующим образом:

$this->Session->write('Config.language', $lang);

Я устанавливаю такой язык по умолчанию в каждом запросе в core.php:

Configure::write('Config.language', 'tur');

Что касается документов CakePHP Я должен добавить этот код в свой AppController:

class AppController extends Controller {
    public function beforeFilter() {
        if ($this->Session->check('Config.language')) {
            Configure::write('Config.language', $this->Session->read('Config.language'));
        }
    }
}

После добавления приведенного выше кода в beforeFilter() AppController я обновил папку /tmp/cache/persistent/, и все работает нормально.

Изменить:
Это решение хорошо работало для английского, но не для других языков.
Почему? Как указано в этом вопросе, cake ищет cake.po файлов в папке Locale.
Например. если вы хотите видеть сообщения торта на французском языке, вам нужно создать этот файл:

/app/Locale/fra/LC_MESSAGES/cake.po

Где CakePHP использует записи cake.po? Например: этот метод


Вы можете создать po-файлы по умолчанию следующим образом: учебник по оболочке i18n
После создания файла оболочки вы можете отредактировать файл cake.po для вашего языка.


Для некоторых языков готовы файлы cake.po. Например: французский файл
Вы можете найти отдых оттуда: https://github.com/cakephp/localized

person trante    schedule 21.02.2014

Для русского языка необходимо установить кодировку файла cake.po в utf-8, иначе вы увидите пустые опции вместо переведенных названий месяцев.

Мое решение: 1. Поместите файл cake.po в каталог \app\Locale\rus\LC_MESSAGES и установите 2. в файл AppController

public function beforeFilter()
    {
        Configure::write('Config.language', 'rus');
    }

Файл перевода для вашего языка вы можете найти в файлах плагина CakePHP Localized https://github.com/cakephp/localized

person Nick Yakubina    schedule 12.01.2016