SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Zend Framework入門

Zend Framework入門(15):
多言語対応サイトの作成- Zend_Translate(後編)-

Zend Frameworkによる実践的なPHPアプリケーション開発 15

  • X ポスト
  • このエントリーをはてなブックマークに追加

Zend_Translateオブジェクトの生成

 Zend_Translateオブジェクトを生成します。

[リスト8]index.phpの一部
$translate = new Zend_Translate('Wings_Translate_Adapter_MySqlite',
                    '../languages/db/ja/trans_ja.db',
                    'ja');
$translate->addTranslation('../languages/db/en/trans_en.db', 'en');
$translate->addTranslation('../languages/db/fr/trans_fr.db', 'fr');

[1]第1引数

 第1引数において、自作アダプタを指定します。今回は「Wings_Translate_Adapter_MySqlite」としています。これはアダプタのクラス名であり、かつ、このクラスを記載しているphpファイル(/ZendFramework1.7.0/library/Wings/Translate/Adapter/MySqlite.php)の箇所も指定しています(「/ZendFramework1.7.0/library/」にinclude_pathが通っていることを前提としています)。

 また、先頭が「Zend」となるようなクラス名をつけることは禁止されています。先頭が「Zend」となるのを許しているのは、Zend Framework標準で提供されているもののみとなります。

[2]第2引数

 第2引数には翻訳ソースとなるファイルを指定します。前半で自動検出を学習したばかりですが、理解のためこちらの原始的な方法で行います。

[3]第3引数

 第2引数で指定した翻訳ソースに対応する言語情報(ロケール)となります。

[4]第4引数

 オプションを指定する箇所となります。今回は何も指定していませんが、前回の「多言語対応サイトの作成- Zend_Translate(前編)-」を参照し、必要なオプションを指定してください。また、実はオプション自体も自作することができますが、今回は触れません。

Zend_Translateクラスから自作アダプタ呼び出し

 次に、Zend_Translateクラス内で、生成時に引数「Wings_Translate_Adapter_Sqlite」を指定された場合に、Wings_Translate_Adapter_Sqliteオブジェクトをアダプタとして生成するように、改造を加えます。対象のファイルは「/ZendFramwork1.7.0/library/Zend/Translate/Translate.php」です。必ずバックアップをとりましょう。

[リスト9]Translate.phpの一部(太線部分を追加する)
class Zend_Translate {
    /**
     * Adapter names constants
     */
    const AN_ARRAY   = 'array';
    const AN_CSV     = 'csv';
    const AN_GETTEXT = 'gettext';
    const AN_INI     = 'ini';
    const AN_QT      = 'qt';
    const AN_TBX     = 'tbx';
    const AN_TMX     = 'tmx';
    const AN_XLIFF   = 'xliff';
    const AN_XMLTM   = 'xmltm';

    //[1]自作アダプタ用定数を定義する
    const AN_WINGS_SQLITE = 'Wings_Translate_Adapter_MySqlite';

    (省略)


    public function setAdapter($adapter, $data, $locale = null, array $options = array())
    {
        //[2]第1引数が自作アダプタ名だった場合、自作アダプタクラスをアダプタとして指定する
        if($adapter == AN_WINGS_SQLITE) {
            if(Zend_Loader::isReadable($adapter . '.php')) {
                $adapter = $adapter;
            }
        } else {
            if (Zend_Loader::isReadable('Zend/Translate/Adapter/' . ucfirst($adapter). '.php')) {
                $adapter = 'Zend_Translate_Adapter_' . ucfirst($adapter);
            }
        }

        //[3]アダプタ呼び出し
        Zend_Loader::loadClass($adapter);
        (省略)

[1]自作アダプタ用定数を定義する

 他のアダプタにならって、自作アダプタ用定数を定義します。前バージョンまでは、Zend_Translate生成時の第1引数がこれらのアダプタ名定数に当てはまる場合は、それに対応するアダプタクラスを呼び出す、という処理に使用されていました。1.7.0ではこの定数は実は使われていません。本稿では前バージョンのような場合分けをするために定数を定義しました。

[2]第1引数が自作アダプタ名だった場合、自作アダプタクラスをアダプタとして指定する

 setAdapterメソッドに改造を加えます。この関数はZend_Translateクラスのコンストラクタから呼び出されています。

 Zend_Translateオブジェクト生成時の第1引数$adapterが自作アダプタ名だったら、自作アダプタクラスの記載されているファイルの存在を確認してから$adapterを自作アダプタとします。もし自作アダプタ名以外が第1引数に指定されていたら、既存の処理を行います。

[3]アダプタ呼び出し

 $adapterに指定されたアダプタを呼び出します。loadClassメソッドでは引数に指定されたクラスを呼び出します。その際、クラス名の「_(アンダースコア)」をパスの区切りとして、最後に「.php」をつけたファイルがそのクラスの定義ファイルとして検索されます。

自作アダプタクラスを作成する

 いよいよ、自作アダプタクラスを作成します。自作アダプタはZend_Translate_Adapterのサブクラスとなりますが、Zend_Translate_Adapterは抽象クラスです。どのように定義されているのかソース(/ZendFramework1.7.0/library/Zend/Translate/Adapter.php)を見てみましょう。

[リスト10]Adapter.phpの一部
abstract class Zend_Translate_Adapter {

    (中略)

    /**
     * Translation table
     * @var array
     */
    protected $_translate = array();

    (中略)

     /**
     * Load translation data
     *
     * @param  mixed              $data
     * @param  string|Zend_Locale $locale

     * @param  array              $options (optional)
     * @return void
     */
    abstract protected function _loadTranslationData($data, $locale, array $options = array());

    (中略)

    /**
     * Returns the adapter name
     *
     * @return string
     */
    abstract public function toString();
}

 abstractのついているメソッド(抽象メソッド)が2つあると思います。1つは翻訳データをarray型の翻訳テーブル($_translate)に格納する動作を行う「_loadTranslationData」、もう1つがアダプタクラス名を返すtoString()です。要するにこれから作成する自作アダプタクラスでは、この2つのメソッドの定義のみ行えばよいということになります。

 今回作成した自作アダプタクラス「Wings_Translate_Adapter_MySqlite」は以下です。

[リスト11]MySqlite.php
<?php

/** Zend_Locale */
require_once 'Zend/Locale.php';

/** Zend_Translate_Adapter */
require_once 'Zend/Translate/Adapter.php';

//[1]DB接続するためZend_Dbを呼び出す
/** Zend_DB_Adapter_Sqlite */
require_once 'Zend/Db.php';

/* SQLite Adapter Class for Zend Translate */
class Wings_Translate_Adapter_MySqlite extends Zend_Translate_Adapter {

    /**
     * Generates the adapter
     *
     * @param  string              $data     Translation data
     * @param  string|Zend_Locale  $locale   OPTIONAL Locale/Language to set, identical with locale identifier,
     *                                       see Zend_Locale for more information
     * @param  array               $options  Options for this adapter
     */
    public function __construct($data, $locale = null, array $options = array())
    {
        // 独自のオプションを設定した場合はここに次のように記載
        // $this->_options['オプション名'] = デフォルト値;

        parent::__construct($data, $locale, $options);
    }

    /**
     * Load translation data
     *
     * @param  string|array  $filename  Filename and full path to the translation source
     * @param  string        $locale    Locale/Language to add data for, identical with locale identifier,
     *                                  see Zend_Locale for more information
     * @param  array         $option    OPTIONAL Options to use
     */
    //[2]_loadTranslationDataを定義する
    protected function _loadTranslationData($filename, $locale, array $options = array())
    {
        //オプションclearが指定されている、もしくは
        //翻訳データ格納arrayが初期化されていない場合
        //翻訳データ格納arrayを初期化する
        $options = $options + $this->_options;

        if ($options['clear']  ||  !isset($this->_translate[$locale])) {
            $this->_translate[$locale] = array();
        }

        //[3]データベースに接続する
        $db = Zend_DB::factory('Pdo_Sqlite', array('dbname' => $filename));
        try{
            $db->getConnection();
        } catch (Zend_Exception $e) {
            require_once 'Zend/Translate/Exception.php';
            throw new Zend_Translate_Exception($e->getMessage());
        }

        //[4]テーブル情報を取得する
        $strquery = 'select * from tbl_trans';
        $result = $db->fetchAll($strquery);

        //[5]取得したtrans_keyとtrans_wordを対にして_translateのarrayに格納する
        foreach ($result as $row){
            $key = $row['trans_key'];
            $word = $row['trans_word'];

            $this->_translate[$locale][$key] = $word;
        }
    }

    /**
     * returns the adapters name
     *
     * @return string
     */
    //[6]toStringメソッド定義
    public function toString()
    {
        return "Wings_Translate_Adapter_MySqlite";
    }
}

[1]DB接続するためZend_Dbを呼び出す

 データベースSQLiteを使用するため、Zend_Dbクラスを使用することを宣言します。

[2]_loadTranslationDataを定義する

 抽象メソッドである_loadTranslationDataを定義します。

[リスト12]_loadTranslationDataメソッド
_loadTranslationData(string/array $filename, string $locale, array $options = array())

 各々の引数については以下のとおりです。

_loadTranslationDataメソッドの引数
引数名 内容
$filename string / array 翻訳ソースファイルのパス
$local string 翻訳すべき言語(ロケール)
$options array オプション

[3]データベースに接続する

 まずはデータベースに接続します。データベースに接続する構文については「Zend Framework入門(6):抽象化レイヤによるデータベースアクセス手法 - Zend_Db(前編) -」を参考にしてください。

[リスト13]Adapter.phpの一部
$db = Zend_DB::factory('Pdo_Sqlite', array('dbname' => $filename));
try{
    $db->getConnection();
} catch (Zend_Exception $e) {
    require_once 'Zend/Translate/Exception.php';
    throw new Zend_Translate_Exception($e->getMessage());
}

[4]テーブル情報を取得する

 接続したデータベースのtbl_transの情報をすべて取得します。

[リスト14]Adapter.phpの一部
$strquery = 'select * from tbl_trans';
$result = $db->fetchAll($strquery);

[5]取得したtrans_keyとtrans_wordを対にして_translateのarrayに格納する

 $_translateが翻訳データを格納するarrayとなっています。

 SQLiteから取得したテーブルのデータを1行ずつ処理します。$locale(ロケール)とtrans_keyフィールドの値をインデックスとして、値がtrans_wordの値となるように$_translateに格納していきます。tbl_transにおいて、trans_keyフィールドはPRIMARY KEYとなっているため、翻訳キーインデックスが重複する心配はありません。

[リスト15]Adapter.phpの一部
foreach ($result as $row){
    $key = $row['trans_key'];
    $word = $row['trans_word'];

    $this->_translate[$locale][$key] = $word;
}

[6]toStringメソッド定義

 クラス名である「Wings_Translate_Adapter_MySqlite」を文字列として返します。

 以上で自作アダプタの作成は完了です。

次のページ
まとめ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Zend Framework入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 森山 絵美(モリヤマ エミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3435 2009/01/27 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング