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: 2008/07/18 10:32 by liyh