Active Records

Active Records的国际化

Active Records通过使用locale命名的加前缀的列也许被国际化,然后使用一个AkActiveRecord功能来处理他们。这个部分将使用一个例子来提供详细的解释。这个例子将从一个没有被国际化的表中提取一个字段,然后将它的值写入 esimerkki 项目中一个国际化的表中(Finnish for example).

定义locales使之被识别

我们应该做得第一件事就是定义config/config.php中的AK_ACTIVE_RECORD_DEFAULT_LOCALES in config/config.php.最初,我的配置如下:

define('AK_ACTIVE_RECORD_DEFAULT_LOCALES', 'en,en_us');

I changed it to look like this:

define('AK_ACTIVE_RECORD_DEFAULT_LOCALES', 'en,fi,sv');

我说”should”是因为,如果AK_ACTIVE_RECORD_DEFAULT_LOCALES没有被定义,AkActiveRecord::getAvailableLocales()就不会从Ak::langs()得到值。

创建表

这个由[creating-and-running-migrations|creating and running a migration]]来完成。做这些的代码显示在连接部分。 运行migration将会给你创建两个表,mono_langs和 multi_langs。

创建models

我们需要为这两个表建立models: 转换到你的项目的根目录。

./script/generate model MonoLang
./script/generate model MultiLang

创建controller

我们将创建app/controllers/refmt_controller.php。为了访问他,然而,我们需要改变config/routes.php 的第一行来引用他。

$Map->connect('/:controller/:action/:id', array('controller' => 'refmt', 'action' => 'index'));

我们将要做的第一件事情是引用models,书写index方法,然后把这些代码写入到非国际化的mono_langs表中

<?php
 
class RefmtController extends ApplicationController
{
    var $models = 'mono_lang, multi_lang';
 
    function index()
    {
        if($this->MonoLang->count() == 0) {
          $this->populate_mono_lang();
        }
        $this->display_func_results();
        $this->populate_multi_lang();
        exit; // This is to keep from trying to access a view
    }

我们没有给怎样迁移这个表加备注,因为我们假设你已经知道怎样去做了。我们显示这些代码是为了让你知道输入到表中的内容。

    function populate_mono_lang()
    {
        $mono = new $this->MonoLang(array('lang' => 'en','name' => 'municipality'));
        $mono->save();
        $mono = new $this->MonoLang(array('lang' => 'fi','name' => 'kunta'));
        $mono->save();
        $mono = new $this->MonoLang(array('lang' => 'sv','name' => 'kommun'));
        $mono->save();
    }

为了使你明白我们拥有的Active Record思想,我们用显示页面源代码的方式,来展示”get”功能的locale的结果,显示页面源代码。(we'll display the results of locale related “get” functions as shown by Page Source.)

  function display_func_results()
  {
    $result = array();
    $result['available_locales']          = $this->MultiLang->getAvailableLocales();
    $result['internationalized_columns']  = $this->MultiLang->getInternationalizedColumns();
    $result['locales_for_name_attribute'] = $this->MultiLang->getAttributeLocales('name');
    $result['current_locale']             = $this->MultiLang->getCurrentLocale();
    print_r($result);
  }
Array
(
    [available_locales] => Array
        (
            [0] => en
            [1] => fi
            [2] => sv
        )

    [internationalized_columns] => Array
        (
            [name] => Array
                (
                    [0] => en
                    [1] => fi
                    [2] => sv
                )
        )

multi_langs表的字段有fields id, en_name, fi_name, sv_name, updated_at和created_at。在这里我们看到的是en_name, fi_name和sv_name,他们比理解为国际化的列。columns id, updated_at和created_at不会作为国际化的列被识别。注意到Active Record用数组存储相关的国际化的列。

    [locales_for_name_attribute] => Array
        (
            [en] => 
            [fi] => 
            [sv] => 
        )

    [current_locale] => en
)

这个功能是读取一个非国家化的表,然后把数据写入到国际化的表中。

  function populate_multi_lang()
  {
    $mono_langs = $this->MonoLang->find('all');   // $mono_langs is an array of objects
    $multi = $this->MultiLang;                    // $multi is an instance of the internationalized table
    foreach($mono_langs as $mono_lang) {
      $multi->setAttributeByLocale('name',  $mono_lang->name,  $mono_lang->lang);
    }
    $multi->save();
    // The following code shows that the data was written to the table.
    // The real reason for including it is to demonstrate the getAttributebyLocale function.
    $result = array();
    $result['name_by_locale-en'] = $multi->getAttributeByLocale('name','en');
    $result['name_by_locale-fi'] = $multi->getAttributeByLocale('name','fi');
    $result['name_by_locale-sv'] = $multi->getAttributeByLocale('name','sv');
    print_r($result);
  }
}
 
?>

下面的代码是在一个数据块中做这样的转换。注释和没有必要的代码已经被移除了。

<?php
 
class RefmtController extends ApplicationController
{
  var $models = 'mono_lang, multi_lang';
 
  function index()
  {
    if($this->MonoLang->count() == 0) {
      $this->populate_mono_lang();
    }
    $this->populate_multi_lang();
    exit;
  }
 
  function populate_mono_lang()
  {
    $mono = new $this->MonoLang(array('lang' => 'en','name' => 'municipality'));
    $mono->save();
    $mono = new $this->MonoLang(array('lang' => 'fi','name' => 'kunta'));
    $mono->save();
    $mono = new $this->MonoLang(array('lang' => 'sv','name' => 'kommun'));
    $mono->save();
  }
 
  function populate_multi_lang()
  {
    $mono_langs = $this->MonoLang->find('all');
    $multi = $this->MultiLang;
    foreach($mono_langs as $mono_lang) {
      $multi->setAttributeByLocale('name',  $mono_lang->name,  $mono_lang->lang);
    }
    $multi->save();
  }
}
 
?>

改变当前的locale

locale是在URL中把locale附加到项目的名字上而建立的。你可以打开一个非国际化的应用程序

  http://<host>/esimerkki

国际化的应用程序也许是这样打开

  http://<host>/esimerkki/en
  http://<host>/esimerkki/fi 或者
  http://<host>/esimerkki/sv

你也可以用非国际化的应用程序打开一个国际化的应用程序,并且在项目中设置语言,如下:

    Ak::lang('fi');
    $_SESSION['lang'] = 'fi';

'fi'是当前新的locale。第二行显然需要得到文本来反应新的语言。(I found this on the forum.)当然,如果你做了这些,那你不得不改变所有的locale changes programmatically;你不能够通过在URL上附加locale来访问不同的languages。

在这个例子中,这些代码放置在index() function的开头的右边。

ActiveRecord locale-related 功能在这里没有别讨论的是

setAttributeLocales($attribute [, $values = array()]);

我还没有试图去使用他,但是我认为他可能被用在installer中来创建i18n列。

让自己国际化吧(Go internationalize yourself.)。

 
activerecord_i18n_cn.txt · Last modified: 2011/04/22 16:47 by bermi
 

The Akelos Framework was created by Bermi Ferrer and other contributors.
Potions of the code and documentation have been ported from Ruby on Rails.

The Akelos Framework is released under the LGPL license.

"Akelos", "Akelos Framework", and the Akelos logo are trademarks of Bermi Labs All rights reserved.

Wiki driven by DokuWiki