[cakephp]多言語展開CMS
グローバル化の影響なのか、多言語展開CMSの需要が伸びています。
n-style;でも複数の事例を扱うようになってきました。CakePHPはけっこう前からi18n対応していました。php4で動作しかつi18n対応のフレームワークは、数年前はCakePHPしかなかったように思います。
手順としては、
- アプリケーションを普通に作成。メッセージは
__(’english message’);
のようにしておき、英語で記述すること。
動的に変化させる必要のある部分はsprintfなどを用いて記述するとよい。 - コンソールから
cake i18n -app /path/to/your/app
とコマンドを叩いて、 英語のメッセージ文を抽出する。 - poeditを使って翻訳する。
- 翻訳後、書き出しを行う。
- 日本語の翻訳ファイルを
/app/locale/jpn/LC_MESSAGES/default.po
に配置する。
ざっと上記のような感じになります。
プログラマーとしては、メッセージの作り方、UIの作り方に注意すればよいと思います。
テンプレートの読み込み分けとか、画像ファイルの読み込み分けなども必要になってきますよね。
意外と、画像の中にテキストが含まれるもの—例えば、ボタンのグラフィック、スローガン入りバナーなど—を「多言語仕様」で作るのを忘れる、なんていうことが起きます。
別途デザイナーさんがいらっしゃるようなプロジェクトでは要検討事項になるでしょう。
Webアプリケーションの多言語展開をお考えでしたら、どうぞn-style;にご用命ください。
[cakephp]Windows Apache + PHP5.2.11 + SQLServer2005
DB接続で文字化けし、UTF-8でのデータ取得でハマったのでメモ。
データをUTF-8で取得するには、SQL Server Driver for PHP 1.1をインストールする必要があり、バージョンの整合性の関係上SQL Server 2008 Native Clientをインストール。(SQLServer自体は2005だけど、下位互換ありのためこちらを使用する)。
SQL Server Driver for PHP 1.1をダウンロードすると、複数のdllがあるので、phpのバージョンとVisual C(コンパイラのバージョンが影響しているのか?不明。。。)を合うようにマニュアルのマトリックスから選択。
選択したdllをphp/extに入れておき、php.iniのextensionコーナーに記述。
このサイトにあるスクリプトを参考にする。
<?php uses(‘model‘ . DS . ‘datasources‘ . DS . ‘dbo‘ . DS . ‘dbo_mssql‘); class DboSqlsrv extends DboMssql { var $description = "SQL Server 2005 Driver for PHP"; var $_baseConfig = array( ‘persistent‘ => true, ‘host‘ => ‘localhost‘, ‘login‘ => ‘root‘, ‘password‘ => ”, ‘database‘ => ‘cake‘, ); function __construct($config) { if (!function_exists(‘sqlsrv_connect‘)) { trigger_error($this->description . " is not installed, cannot continue.", E_USER_ERROR); } return DboSource::__construct($config); } function connect() { $this->connection = sqlsrv_connect($this->config[‘host‘], array( ‘Database‘ => $this->config[‘database‘], ‘ConnectionPooling‘ => $this->config[‘persistent‘] ? 1 : 0, ‘UID‘ => $this->config[‘login‘], ‘PWD‘ => $this->config[‘password‘], )); $this->connected = false; if ($this->connection !== false){// && sqlsrv_query($this->connection, ‘USE ‘ . $this->config[’database’])) { $this->connected = true; } } function disconnect() { @sqlsrv_free_stmt($this->results); $this->connected = !@sqlsrv_close($this->connection); return !$this->connected; } function _execute($sql) { return sqlsrv_query($this->connection, $sql); } function begin(&$model) { if (parent::begin($model)) { if (sqlsrv_begin_transaction($this->connection)) { $this->_transactionStarted = true; return true; } } return false; } function commit(&$model) { if (parent::commit($model)) { $this->_transactionStarted = false; return sqlsrv_commit($this->connection); } return false; } function rollback(&$model) { if (parent::rollback($model)) { return sqlsrv_rollback($this->connection); } return false; } function lastError() { if (($errors = sqlsrv_errors()) != null) { $msg = ”; foreach($errors as $e) { $msg .= "SQLSTATE: " . $e[‘SQLSTATE‘] . " "; $msg .= "CODE: " . $e[‘code‘] . " "; $msg .= "MESSAGE: " . $e[‘message‘] . " "; break; } return $msg; } return null; } function lastAffected() { if ($this->_result) { $cnt = sqlsrv_rows_affected($this->_result); if ($cnt < 0) $cnt = 0; return $cnt; } return null; } function lastNumRows() { if (is_resource($this->_result)) { $cnt = -1; $stmt = sqlsrv_query($this->connection, ‘SELECT @@ROWCOUNT AS cnt‘); if (sqlsrv_fetch($stmt)) { $cnt = sqlsrv_get_field($stmt, 0); } return $cnt; } return null; } function resultSet(&$results) { $this->results =& $results; $this->map = array(); $meta = sqlsrv_field_metadata($results); $num_fields = count($meta); $index = 0; $j = 0; while ($j < $num_fields) { $column = $meta[$j][‘Name‘]; if (strpos($column, ‘__‘)) { if (isset($this->__fieldMappings[$column]) && strpos($this->__fieldMappings[$column], ‘.‘)) { $map = explode(‘.‘, $this->__fieldMappings[$column]); } elseif (isset($this->__fieldMappings[$column])) { $map = array(0, $this->__fieldMappings[$column]); } else { $map = array(0, $column); } $this->map[$index++] = $map; } else { $this->map[$index++] = array(0, $column); } $j++; } } function fetchResult() { if (sqlsrv_fetch($this->results)) { $resultRow = array(); foreach (sqlsrv_field_metadata($this->results) as $index => $field) { list($table, $column) = $this->map[$index]; $resultRow[$table][$column] = sqlsrv_get_field($this->results, $index); } return $resultRow; } else { return false; } } } ?>
[MySQL]トランザクション
トランザクションを有効にするには、InnoDBにする必要がある。
デフォルトはMyISAM。
[cakephp] CakePHPカンファレンス東京!
CakePHPのカンファレンスが開催されるようです。
待ちに待った感がありまして、7日はPCに張り付いて申込しました。
http://events.php.gr.jp/events/show/55
楽しみです。久々の東京・・・
[cakephp1.2.x.x][php]CakePHPで作成したアプリケーションの文字コード
CakePHPで作成したアプリケーションを、Shift-JISで表示させたいときには。。。
DB:mysqlをUTF8で作成。
.htaccess:以下のように設定しました。
php_flag output_buffering On
php_value output_handler mb_output_handler
php_value default_charset Shift_JIS
php_value mbstring.language japanese
php_flag mbstring.encoding_translation On
php_value mbstring.http_input auto
php_value mbstring.http_output SJIS
php_value mbstring.internal_encoding UTF-8
php_value mbstring.substitute_character none
[実験][SimplePie][RSS]複数のRSSを取得して表示する
SimplePieの実験で作ってみました。
こちら。
サーバーサイドでphpを実行し、Javascriptの形式で返却、といってもdocument.writeの嵐です。
ちょっと重いかな。。。キャッシュしている間は早いです。
配置するサーバによって、faviconが表示できたりできなかったりするなぞの現象あり。要調査。
[cakephp][1.2.x.x]キャッシュ
■キャッシュを使うには:
var $helpers = array(’Cache’);
ヘルパーにCacheを設定
■$cacheActionで、アクション単位でキャッシュを指定
var $cacheAction = array(’display’ => ‘1 hour’);
adminルーティングを使用したアプリケーションで、キャッシュを使用した途端にログインできなくなってしまったので、原因を調査していたところ、ログイン画面もキャッシュされていたことが原因と判明。特定のアクションではキャッシュしない設定に変更することで回避できました。
[cakephp][ajax][jQuery]ファイルアップロード
http://cakephp.jp/modules/newbb/viewtopic.php?post_id=1870&topic_id=965&forum=12
[cakephp][1.2.x.x]URLで言語を切り替える方法
$bits = explode('/', $_GET['url']); foreach($bits as $strUrl){ if($strUrl === 'ja' || $strUrl === 'en'){ Configure::write('Config.language', $strUrl); Router::connect("/$strUrl/admin/:controller/:action/*", array( 'controller' => ':controller', 'prefix' => 'admin',
'action' => ':action' ) );
break; } }
Googleのデザインガイドライン
Googleのデザインガイドライン
http://googlesystem.blogspot.com/2008/03/googles-design-guidelines.html
1. Useful: focus on people - their lives, their work, their dreams.
2. Fast: every millisecond counts.
3. Simple: simplicity is powerful.
4. Engaging: engage beginners and attract experts.
5. Innovative: dare to be innovative.
6. Universal: design for the world.
7. Profitable: plan for today’s and tomorrow’s business.
8. Beautiful: delight the eye without distracting the mind.
9. Trustworthy: be worthy of people’s trust.
10. Personable: add a human touch.
こういうことを考慮に入れた開発を心がけたいですね。
