2012-01-24 2 views
1

Контекст: Я хочу создать веб-приложение с использованием CakePhp, которое должно быть переводимым. Я хочу сохранить несколько переводов для одного и того же поля в одной форме.CakePhp TranslateBehavior, подтвердите и сохраните несколько локалей

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

Вопрос: Кто-нибудь знает лучший способ добиться того же результата?

Что я пробовал:

  • Придание формы поля имя, как «Model.fieldName.locale», что дает ему правильный формат имени атр входного элемента, а затем мой проверки не распознает имя поля. Но спасательные работы.

  • Придавая форме поля имя типа 'modelLocale' и передавайте имя attr 'data [Model] [field] [locale]', в этом случае проверка выполняется за исключением isUnique, но сохранение в базе данных не делает ' т работы.

  • Другие варианты этого, но не стоит упоминать.

Я добавлю вид и модель ниже: (если и хотят, чтобы увидеть больше кода или нужно больше информации просто спросите)

/App/View/Category/add.ctp

<?php echo $this->Form->create(); ?> 
<?php echo $this->Form->input('title|dut'); ?> 
<?php echo $this->Form->input('title|eng'); ?> 
<?php echo $this->Form->input('title|fre'); ?> 
<?php echo $this->Form->input('description|dut', array('type'=>'textarea')); ?> 
<?php echo $this->Form->input('description|eng', array('type'=>'textarea')); ?> 
<?php echo $this->Form->input('description|fre', array('type'=>'textarea')); ?> 
<?php echo $this->Form->end('add'); ?> 

/App/Model/AppModel.php

<?php 
App::uses('Model', 'Model'); 
class AppModel extends Model { 

    /** 
    * Check Unique 
    * 
    * Searches the i18n table to determine wetter a field is unique or not. 
    * Expects field name to be as following: "fieldname|locale". 
    * 
    * @param array $data  The data of the field, automatically passed trough by cakePhp. 
    * @param string $field The name of the field, which should match the one in the view. 
    * @returns boolean 
    */ 
    public function checkUnique($data, $field) { 
    // Seperate the field key and locale which are seperated by "|". 
    $a = preg_split('/[|]/', $field, 2); 
    // If field key and locale are found... 
    if (is_array($a) || count($a) === 2) { 
     $q = sprintf("SELECT * FROM i18n WHERE i18n.locale = '%s' AND i18n.model = '%s' AND i18n.field = '%s' AND i18n.content = '%s' LIMIT 1", 
     Sanitize::escape($a[1]), 
     Sanitize::escape(strtolower($this->name)), 
     Sanitize::escape($a[0]), 
     Sanitize::escape($data[$field]) 
    ); 
     if ($this->query($q)) { 
     return false; 
     } 
     return true; 
    } 
    } 

    /** 
    * Setup Translation 
    * 
    * Loops trough the fields. If a field is translatable 
    * (which it will know by it's structure [fieldname]|[locale]) 
    * and has the default locale. Then it's value will be stored 
    * in the array where cake expects it 
    * (data[Model][fieldname] instead of data[Model][fieldname|defaultLocale]) 
    * so that cake will save it to the database. 
    * 
    * In the afterSave method the translations will be saved, for then we know 
    * the lastInsertId which is also the foreign_key of the i18n table. 
    */ 
    public function _setupTranslations() { 
    foreach($this->data[$this->name] as $key => $value) { 
     $a = preg_split('/[|]/', $key, 2); 
     if (is_array($a) && count($a) === 2) { 
     $languages = Configure::read('Config.languages'); 
     if ($a[1] === $languages[Configure::read('Config.defaultLanguage')]['locale']) { 
      $this->data[$this->name][$a[0]] = $value; 
     } 
     } 
    } 
    } 

    /** 
    * Save Translations 
    * 
    * Saves the translations to the i18n database. 
    * Expects form fields with translations to have 
    * following structure: [fieldname]|[locale] (ex. title|eng, title|fre, ...). 
    */ 
    public function _saveTranslations() { 
    foreach($this->data[$this->name] as $key => $value) { 
     $a = preg_split('/[|]/', $key, 2); 
     if (is_array($a) && count($a) === 2) { 
     $q = sprintf("INSERT INTO i18n (locale, model, foreign_key, field, content) VALUES ('%s', '%s', '%s', '%s', '%s')", 
      Sanitize::escape($a[1]), 
      Sanitize::escape(strtolower($this->name)), 
      Sanitize::escape($this->id), 
      Sanitize::escape($a[0]), 
      Sanitize::escape($value) 
     ); 
     $this->query($q); 
     } 
    } 
    } 

    /** 
    * Before Save 
    */ 
    public function beforeSave() { 
    $this->_setupTranslations(); 
    return true; 
    } 

    /** 
    * After Save 
    */ 
    public function afterSave() { 
    $this->_saveTranslations(); 
    return true; 
    } 
} 

/App/Model/Category.php

<?php 
class Category extends AppModel { 
    public $name = 'Category'; 
    public $hasMany = array(
    'Item'=>array(
     'className'=>'Item', 
     'foreignKey'=>'category_id', 
     'order'=>'Item.title ASC' 
    ) 
); 
    var $actsAs = array(
    'Translate'=>array(
     'title', 
     'description' 
    ) 
); 
    public $validate = array(
    'title|dut'=>array(
     'required'=>array(
     'rule'=>'notEmpty', 
     'message'=>'Veld verplicht' 
    ), 
     'unique'=>array(
     'rule'=>array('checkUnique', 'title|dut'), 
     'message'=>'Titel reeds in gebruik' 
    ), 
    ), 
    'title|eng'=>array(
     'required'=>array(
     'rule'=>'notEmpty', 
     'message'=>'Veld verplicht' 
    ), 
     'unique'=>array(
     'rule'=>array('checkUnique', 'title|eng'), 
     'message'=>'Titel reeds in gebruik' 
    ), 
    ), 
    'title|fre'=>array(
     'required'=>array(
     'rule'=>'notEmpty', 
     'message'=>'Veld verplicht' 
    ), 
     'unique'=>array(
     'rule'=>array('checkUnique', 'title|fre'), 
     'message'=>'Titel reeds in gebruik' 
    ), 
    ), 
); 
} 
?> 

ПРИМЕЧАНИЕ: Существует не так много информации, там на эту тему ... У меня есть намного больше вопросов о поведении перевода, как получение рекурсивные результаты также в правильной локали, ... Кто-нибудь знает хорошую информацию или источник информации (поваренная книга весьма ограничена)

Спасибо за чтение !!

ответ

1

Возможно, вы создаете CRM-ролик, который позволяет пользователям устанавливать контент, который читается на сайте, на основе языка, который они установили. Я бы использовал встроенный в i18n and l10n. Это делает его очень простым, но это, вероятно, не является решением для динамического контента.

Сказав это, единственный способ, которым я могу это сделать, очень утомительно. Я бы построил один экран с раскрывающимся идентификатором языка. Поэтому вместо того, чтобы пытаться перерезать ВСЕ языки на одном экране с тестовым полем для каждого языка, я бы создал одну форму, а затем использовал раскрывающийся список для языка.

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

title 1 eng 
title 1 dut 
title 1 fre 
title 2 eng 
title 2 dut 
title 2 fre 
... 

Более того, если вы когда-нибудь, чтобы добавить новый язык, вы должны изменить проверки в модели и форма.

Однако, если вы настроили это так, измените | к _ и вы уходите. Но тогда вам нужно будет хранить все данные в одной записи. Поэтому, когда вы смотрите на индекс для записи, вы увидите:

title 1 end dut fre 
title 2 end dut fre 
... 

Мой совет:

1) Использование встроенного в i18n/l10n с помощью .po/.pot файлов.

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

Language: dropdown 
Title: text_field 
+0

Спасибо, я уже использую файлы .po для нединамического контента. И да, используя выбранный вход для языка, это обычный способ сделать это, но так как есть только два поля, которые нуждаются в переводе, и они всегда нуждаются в переводе, я настроен на выполнение одной формы. Я предполагаю, что использование двух пользовательских запросов - это не большая жертва ... Было просто интересно, есть ли лучшее решение. Я как бы ожидал большего от поведения Translate. –

 Смежные вопросы

  • Нет связанных вопросов^_^