среда, 12 мая 2010 г.

Symfony: храним i18n-фразы в mysql

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

Предполагается, что i18n уже включен, и плагин mgI18n вам по каким-то причинам не подошел (в моем случае он просто не завелся - ни с первого, ни с третьего раза).

Поиск документации дал только этот старенький документ и это несколько мутное описание решение проблемы.

Итак, начнем.

Для хранения фраз нам потребуется две таблицы (их структура дана в первом найденном документе, а также в файле symfony/lib/i18n/sfMessageSource_MySQL.class.php. Поскольку мы работаем с Doctrine, нарисуем схему для этих таблиц:
Catalogue:
  columns:
    cat_id: { type: integer, notnull: true, autoincrement: true, primary: true }
    name: { type: string(100), notnull: true, default: '' }
    source_lang: { type: string(100), notnull: true, default: '' }
    target_lang: { type: string(100), notnull: true, default: '' }
    date_created: { type: integer, notnull: true, default: 0 }
    date_modified: { type: integer, notnull: true, default: 0 }
    author: { type: string(255), notnull: true, default: '' }
    
trans_unit:
  columns:
    msg_id: { type: integer, notnull: true, autoincrement: true, primary: true }
    cat_id: { type: integer, notnull: true}
    source: { type: clob(65532), notnull: true }
    target: { type: clob(65532), notnull: true }
    comments: { type: clob(65532) }
    date_added: { type: integer, notnull: true }
    date_modified: { type: integer, notnull: true }
    author: { type: string(255), notnull: true, default: ''}
    translated: { type: boolean, notnull: true, default: false }    
  relations:
    Catalogue:
      local: cat_id
      foreign: cat_id
      foreignAlias: Units

И немножечко фикстур

catalogue:
  ru:
    name: messages.ru_RU
    source_lang: en_US
    target_lang: ru_RU
    author: ''
    
  en:
    name: messages.en_US
    source_lang: en_US
    target_lang: en_US
    author: ''
    
  jp:
    name: messages.jp
    source_lang: en_US
    target_lang: jp
    author: ''
    
trans_unit:
  u1:
    Catalogue: ru
    source: hello
    target: Привет
    translated: true

Здесь следует обратить внимание на следующие важные моменты:
- поле name должно содержать значение вида "каталог.вариант", где каталог - это название каталога фраз (messages по умолчанию), а вариант - это вариант написания локали (ru_RU,RU,ru). В ходе поиска перевода перебираются все варианты локалей, поэтому лучше писать сразу ru_RU - он идет первым.
- можно переводить с английского на английский. Зачем это надо? Чтобы в шаблонах вставлять "токены" фраз, а полнотекстовые переводы делать уже в админке (актуально для длинных фраз, например, для шаблонов писем).

Затем небольшие настройки в factories.yml:
all:
  #...
  i18n:
    class: sfI18N
    param:
      source:               MySQL
      database:             mysql://user:pass@localhost/your_db
      debug:                true
      untranslated_prefix:  "[T]"
      untranslated_suffix:  "[/T]"
      cache:
        class: sfNoCache


В общем-то, готово. Потестируем? Напишем где-нибудь в шаблоне
echo __('hello')

Следующий абзац предназначен для тех, у кого выскочили ромбики или всякие кракозябры вместо русского перевода. Если это случилось, значит mysql-сервер выдает по умолчанию результат в кодировке, отличной от UTF8. Что ж, придется допиливать класс, который коннектится к БД и выбирает переводы фраз. Создаем новый файл sfMessageSource_MySQL_utf8.class.php с содержимым
class sfMessageSource_MySQL_utf8 extends sfMessageSource_MySQL
{
  protected function connect()
  {
    $conn=parent::connect();
    mysql_query('SET  NAMES \'UTF8\'',$conn);
    return $conn;
  }
}
Теперь нам следует поменять source в factories.yml на MySQL_utf8. Готово.

Осталось сгенерировать админку для каталогов и фраз. Это уж сами :)

И да, не пытайтесь увидеть на веб-панели mysql-запросы, которые делает подсистема i18n: она делает их не через доктрину.

Еще одна полезная ссылка, на которую натолкнулся, пока искал решение - презентация на тему i18n в симфонии (PDF)

1 комментарий:

  1. и так грабли с которыми вы встретитесь так как тут куча ошибок в этой статье да и не полная она, но все же спасибо за что есть.
    1.
    date_added: { type: integer, notnull: true, default: 0 }
    date_modified: { type: integer, notnull: true, default: 0 }

    2. (пропущено важное поле)
    trans_unit:
    columns:
    id: { type: string(255), notnull: true, default: '' }
    3.
    что бы проверить hello
    надо сменить культуру, ставим дефолтное
    заходим в frontend/config/setings.yml
    i18n: true
    standard_helpers: [Partial, Cache, I18N]
    default_culture: ru_RU
    чистим кэш, а также кэш браузера!!

    Думаю я вам сэкономил немного времени и нервов

    added by Skynet

    ОтветитьУдалить