事实之后应用CakePHP的翻译行为

时间:2009-04-13 17:58:38

标签: cakephp internationalization

我正在慢慢学习如何应用CakePHP的翻译行为,我想我已经掌握了基础知识,但我正在研究现有数据的现有项目。 Cake会为我插入新记录,这很棒,但我需要手动(我假设)为一些现有数据插入一些翻译。我的第一个问题:

如果这是我的默认语言和核心表中使用的语言,我是否必须在i18n表中为en_us创建一条记录?例如,如果categories.name ='Entertainment',我真的需要在i18n中创建一个“重复”记录来指示指定“娱乐”的英文翻译吗?经验证据似乎是肯定的,但这似乎是一项额外的工作,所以我希望有人可以告诉我,我错过了一些东西。

第二,是否有一种“简单”的方式将翻译记录导入数据库?随着在项目过程中添加语言,返回并为遗留数据创建i18n记录将非常痛苦。

感谢。

4 个答案:

答案 0 :(得分:3)

我知道这已经过时了,但是因为它没有得到答复而我在解决这个问题时遇到了一些麻烦,这是我的两分钱:

范围,Cakephp 1.3。

首先,您需要为每个字段提供i18n记录 - >记录 - >您的应用中的模型,当然只有具有Translate行为且仅适用于指定字段的模型,所以是的,您最终会在实际模型字段和i18n表中找到重复的内容。

此外,您需要为指定的任何语言提供现有翻译,以便返回任何内容。这让我感到困惑,因为我还将翻译行为添加到已经开发的项目中,包含大量数据。基本上我所做的是创建一个同步方法,以便为每个具有翻译行为的模型的每个字段创建每个翻译。我将来是否应该添加一种新语言,我将不得不再次运行它。

这是代码:

$locales = array( 'spa', 'eng', 'por' );
$models = array( 'Event', 'News', 'Promotion', 'Shop', 'ShopCategory' );

foreach ( $models as $model )
{
    $this->loadModel( $model );
    $records = $this->{$model}->find( 'all', array(
                                                  'fields' => array( "*" ),
                                                  'contain' => FALSE
                                             ) );

    $fields = $this->{$model}->actsAs['Translate'];
    foreach ( $records as $record )
    {
        foreach ( $fields as $field )
        {
            foreach ( $locales as $locale )
            {
                $content = mysql_real_escape_string( $record[$model][$field] );
                $this->{$model}->query( "INSERT INTO `i18n` (`locale`, `model`, `foreign_key`, `field`, `content`) VALUES('{$locale}', '{$model}', '{$record[$model]['id']}', '{$field}', '{$content}');" );
            }
        }
    }
}

提示:使用locale,model,foreign_key和field键在i18n表中创建唯一索引。

所以,既然我已经在所有语言中复制了原始数据,我需要能够使用给定语言创建新记录。问题是,如果我用英语创建一个新记录,我应该能够用西班牙语更新它,但由于没有西班牙语的i18n记录,我在CMS中看不到记录,我无法编辑它。 我解决这个问题的方法是在创建新记录时为每种语言创建i18n记录,但只能在编辑记录时使用当前语言进行编辑。

我将此修改用于翻译行为: http://bin.cakephp.org/view/1939852942

但是大多数使用此修改的示例都表示您必须在表单中创建表单输入:     echo $ this-> Form-> input('name.eng');     echo $ this-> Form-> input('name.spa');     echo $ this-> Form-> input('description.eng');     echo $ this-> Form-> input('description.spa');

我发现这很烦人,所以我基本上在app_controller中创建了一个帮助函数,将可翻译字段转换为这个数据结构:

function _expandLocalizations( $data )
{
    foreach ( $data as $modelName => $modelData )
    {
        if ( !isset( $modelData[$this->{$modelName}->primaryKey] ) )
        {
            foreach ( $this->{$modelName}->actsAs['Translate'] as $field )
            {
                $translations = array();
                foreach ( $this->languages as $language )
                {
                    $translations[$language] = $this->data[$modelName][$field];
                }
                $data[$modelName][$field] = $translations;
            }
        }
    }
    return $data;
}

并在每个添加方法中:

if ( !empty( $this->data ) )
    {
        $this->News->set( $this->data );
        if ( $this->News->validates() )
        {
            $this->News->create();
            $data = $this->_expandLocalizations( $this->data );
            $saved = $this->News->save( $data );
            if ( $saved )
            {

这样我可以使用传统表单,如果添加新语言,我不需要更改视图。 我需要修改传统的烘焙添加方法,因为我需要提交的数据进行验证,但修改后的数据需要保存。

最后,我按照以下步骤更改了网站/ admin中的语言:http://nuts-and-bolts-of-cakephp.com/2008/11/28/cakephp-url-based-language-switching-for-i18n-and-l10n-internationalization-and-localization/

所以基本就是这样。 1.您为数据库中已有的每个数据创建翻译,每个数据都复制到每种语言。 2.为create上的新记录创建每个翻译,所有翻译都具有相同的课程价值。 3.编辑所选翻译中的每条记录。

答案 1 :(得分:0)

我对第二个问题没有答案,但第一个问题的答案似乎是“是”。在挖掘源代码之后,看起来生成的查询的where子句将结果限制为那些被检索的字段名称具有当前语言环境的语言环境值的结果。这是非常有限的。

这有一个existing ticket(或类似的东西)。

答案 2 :(得分:0)

至于第一个问题,答案是否定的。 即使我最初也这么认为,也不需要重复数据。

我写了一篇关于它的博客文章,以帮助你在那里失去灵魂。 http://kristofferdarj.se/2012/05/cakephp-how-to-actually-use-i18n/

答案 3 :(得分:0)

使用包含许多列的翻译行为会大大减慢您的网站速度。 我能找到加速它的最简单方法是添加这个索引。 这个索引在cakephp/app/Config/Schema/i18n.sql中被注释掉了,我不明白为什么。

ALTER TABLE rabotvins_i18n
ADD UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field);