Ruby言語やLinuxのネタが多いです。
December 13, 2002
■ [Ruby-GNOME2] やること多すぎ
APIドキュメントの整備とかってとてつもなく大変な予感。量ありすぎ。
というわけで、Ruby-GNOME使ったことある人で誰か協力してくれませんか〜。
いつでもウェルカムですよ〜。
December 13, 2006
■ [Rails] act_as_translatable
指定したモデルのカラムを翻訳できるようにするプラグイン。Globalizeと同様にデータベース中に翻訳文字列を持たせる形態。
Ruby-GetTextを「アプリが提供する静的な文字列の国際化」、act_as_translatableを「アプリを使うユーザが入力する動的な文字列の国際化」、と棲み分けて使うことを想定しているようだ(上記サイトの例でもRuby-GetTextと連携する方法を書いてくれている)。
ちょっと使いかたがわかりづらかったので紹介がてら検証した方法をメモっておくことにする。mysqlとRailsを事前にインストールしておく。
■ まず、テスト用のプロジェクトを作る。
$ rails test -d mysql : : $ cd test
db/schema.rbというファイルを作る。内容は以下。articlesというのはRuby-GetTextのサンプルを持ってきただけなので特に意味は無い。念のため。
ActiveRecord::Schema.define(:version => 1) do
create_table "articles", :force => true do |t|
t.column "name", :string
end
end
config/database.ymlを適宜修正する。Fedora Core 6の場合はsocket/encodingの指定を追加する。以下のような感じかな。
development: adapter: mysql database: test_development username: root password: host: localhost socket: /var/lib/mysql/mysql.sock encoding: utf8
んで、DBとテーブル作成。
$ mysqladmin -u root create test_development #rootは環境に合わせて変更してね。 $ rake db:schema:load
ここまででDBの準備は終了。mysqlで内容を確認してみる。
$ mysql -u root test_development mysql> show tables; +----------------------------+ | Tables_in_test_development | +----------------------------+ | articles | | schema_info | +----------------------------+ 2 rows in set (0.00 sec) mysql> desc articles; +-------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | +-------+--------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
■ さて、前置きが長くなったけど、ここからはacts_as_translatableの説明。mysqlのコンソールは後で使うのでそのまま放置し、別のウインドウで以下を実行してほしい。
まずは、上であげたリンク先からacts_as_translatable-0.2.0.tar.gzをダウンロードして/vendor/pluginsに配置する。
$ cd vendor/plugins $ tar xvzf ~/acts_as_translatable-0.2.0.tar.gz -C .
おっと、モデルを作るのを忘れてた。
$ cd ../../ $ ruby script/generate model article
acts_as_translatableで日本語を使うためのおまじないをconfig/environment.rbの一番下に記述する。
$KCODE = "u" #これは上の方がベター
class TranslationLanguage
LANGUAGES.merge!({:ja => '日本語'})
end
TranslationLanguage.base = :en #デフォルトを英語とする。
app/models/article.rbに以下を追加。nameカラムを翻訳可能にする。
class Article < ActiveRecord::Base acts_as_translatable :fields => [:name] end
準備完了。以降はscript/consoleを使う。
$ ruby script/console
Loading development environment.
>> TranslationLanguage.current = :ja #現在の言語を指定
>> article = Article.new(:name => "English name")
=> #<Article:0x2aaaae544bc8 @new_record=true, @attributes={"name"=>"English name"}>
>> article.save
=> true
このタイミングでmysqlのウインドウに戻ってみると、以下のようにtranslation_articlesというテーブルが新規作成されていることがわかる。
mysql> show tables; +----------------------------+ | Tables_in_test_development | +----------------------------+ | articles | | schema_info | | translation_articles | +----------------------------+ 3 rows in set (0.00 sec) mysql> select * from articles; +----+--------------+ | id | name | +----+--------------+ | 1 | English name | +----+--------------+ 1 row in set (0.00 sec) mysql> desc translation_articles; +----------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | model_id | int(11) | NO | MUL | | | | language | varchar(2) | NO | | | | | name | text | YES | | NULL | | +----------+------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) mysql> select * from translation_articles; Empty set (0.00 sec)
当然、このタイミングではtranslation_articlesは空だ。
■ 引き続き、script/consoleを実行しているウインドウに戻り、以下を実行する。
>> article.name = "Japanese name" => "Japanese name" >> article.save => true
mysqlの内容を確認してみる。
mysql> select * from articles; +----+--------------+ | id | name | +----+--------------+ | 1 | English name | +----+--------------+ 1 row in set (0.00 sec) mysql> select * from translation_articles; +----+----------+----------+---------------+ | id | model_id | language | name | +----+----------+----------+---------------+ | 1 | 1 | ja | Japanese name | +----+----------+----------+---------------+ 1 row in set (0.00 sec)
あとは、これらを参照するときにどの言語で検索するかで結果が異なる。内容の方は@attributesのnameの値を確認してほしい。
>> Article.find :first
=> #<Article:0x2aaaae4ec4a0 @attributes={"name"=>"Japanese name", "id"=>"1"}>
>> TranslationLanguage.current = :en
=> :en
>> Article.find :first
=> #<Article:0x2aaaae4e3ff8 @attributes={"name"=>"English name", "id"=>"1"}>
>> TranslationLanguage.current = :de
=> :de
>> Article.find :first
=> #<Article:0x2aaaae4da700 @attributes={"name"=>"English name", "id"=>"1"}>
上記のポイントは、「一度登録したカラムに対し、新たにデータをセットすると、それが翻訳文字列として認識される。」ということ。最初に生成したものが翻訳対象(翻訳元文字列)という扱いである。実際はcontrollerで情報を保存していくんだろうけど、その際に最初に保存するオリジナル文字列が何で、これから登録しようとしている情報が翻訳文字列でというのをUI側でうまく区別しないとダメなんだろうな。管理系の登録画面でベース言語とユーザ言語の2種類の入力欄を用意する、みたいな感じで使うのかしら。あとはベース言語を入力して、その後、まったく別のタイミングでユーザ言語を追加する、みたいな感じか。
■ 実はGlobalizeを見たときもよくわからなかったんだけど、こういうのって具体的にはどのような時に使うんだろう。CMSなんかで、ユーザ自身がいろいろと国別に表示するような情報を作成する時には使うのかな。あるいは複数言語の同一内容の記事を提供するニュースサイトとか・・・。そっか、そういう用途なら結構アリかも。
■ 蛇足なんだけど、オレ的にはこのアプローチの他に、もう一つのacts_as_localized (?)みたいなものを考えてたりする。どういうものかというと、単に、ある言語で登録された情報はその言語の時にしか表示しない、というもの。acts_as_translatableは翻訳元があって翻訳先を作るわけだけど、こちらは単に登録された言語の情報しか表示しない。例えばローカライズされたWikiをURLの変更無しで見るようなイメージ。実装はきっとシンプルで、langというカラムをローカライズしたいテーブルに追加してwith_scopeで現在のlocaleに限定するって感じ。
■ ま、ともかく、今までGloblizeにしか無いとしてGlobalizeの利点としてあげられていた機能が単独でかつ、Ruby-GetTextと組み合わせて使うことができるというのは良いことだ。また一つピースが埋まった感じがするよ。うひ。

▲ たむら [Ruby/Gnome2試してみた-> ツッコミ入れた -> 引っ張られた なので、使ったことなくても興味あるだけでも..]
▲ むとぽん [そうですね。興味のある方ボシュー。今なら開発者みずから手取り足取り懇切丁寧フォロー付です(しつこい&コマカすぎるかも..]