ラベル gettext の投稿を表示しています。 すべての投稿を表示
ラベル gettext の投稿を表示しています。 すべての投稿を表示

2009年11月28日土曜日

CakePHPの GetText (i18n)で複数形の翻訳をする

はまったのでメモ。最初からリファレンスや参考サイトを見ながらやれば書いてあったんだろうけど。


CakePHPで単数と複数で異なる翻訳を付けようとした。

__n(' person', ' people', $count);
poファイルも書いた。
msgid " person"
msgid_plural " people"
msgstr[0] "人"
msgstr[1] "人"

するとエラー(Warning)が表示された。
Warning (2): strlen() expects parameter 1 to be string, array given ...


該当箇所はCORE/cake/libs/i18n.phpのtranslate()。
if (is_array($trans)) {
if (isset($trans[$plurals])) {
$trans = $trans[$plurals];
}
}
if (strlen($trans)) {
$singular = $trans;
return $singular;
}
strlen()に配列を渡しているようだ。
でもその上で$transが配列の場合は文字列に入れ替えてるはず。(変数の使いまわしは良くないと思う。)それが効いてないのは「isset($trans[$plurals])」がfalseになっているということか。

この$pluralsをセットしているところを追うと、今回の場合は同じファイル内の__pluralGuess()によりセットしているようだ。
__pluralGuess()の中を追うと、$headerの中身で判断してるようだ。
if (strpos($header, "plurals=3")) {
if (strpos($header, "100!=11")) {
if (strpos($header, "10<=4")) {
return $n % 10 === 1 && $n % 100 !== 11 ? 0 : (略)

$headerを出力してみる。
nplurals=INTEGER;plural=EXPRESSION;

ん?さっきのif文の条件と似ても似つかない。
これは...poファイルで何か設定不足?

poファイルの最初の方を見てみる。
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
まさにこれだ。

こうしてみる。(キャッシュの削除も忘れずに。)
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

動いた!

以上。

2009年9月24日木曜日

Rails ActiveRecord::Validationsのエラーメッセージを多国語対応するメモ

RailsでActiveRecordのValidationによって生成されるエラーメッセージを翻訳するためのメモ。


方法その1:I18nを使う

所定のYAMLに翻訳部分を記述しておく方法。現在はこれが一番スマートなようだ。
(フィールド名とその後のメッセージの間に半角スペースが入ってしまう?)

参考:
 Rails 2.2.2でエラーメッセージを日本語化する。|WEBデザイン Tips
 Rails 2.2 の ActiveRecord::Validations#add のソースコードを読む - Ruby on Rails 研究 - Ruby on Rails with OIAX



方法その2:GetTextを使う

ActiveRecord::Errorsのdefault_error_messagesをゴリゴリ書き換える方法。
例えば、基本となるModelを作ってその中でメッセージをセットし、他のモデルはそれを継承する方法でもよいと思う。

class BaseModel < ActiveRecord::Base
 ActiveRecord::Errors.default_error_messages[:invalid] = _("がおかしいよ!")
 ActiveRecord::Errors.default_error_messages[:empty] = _("を入力してね!")
 ・
 ・
end
ただし最新のRailsではDeprecation::warnの対象

個々のエラー内容の前に出てくる文(デフォルトでは「<n> errors prohibited this object from being saved」と「There were problems with the following fields:」)は、Module: ActionView::Helpers::ActiveRecordHelperにあるとおり、:header_messageと:messageを指定することにより変えられる。
(2009/10/14追記:Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.3.2以降) - よたらぼ 保管庫に書いてある、「エラーメッセージのタイトル部分をカスタマイズ」のやり方なら、個々のformごとに:header_messageと:messageを指定しなくてすむようだ。)


参考:
 エラーメッセージからフィールド名を取り除く
 ActiveRecord::Errorsあたりのローカライズ - ハードコアシステム開発
 validationのエラーメッセージ(error_messages_for)の日本語化 - Slow Dance
(2009/10/14追加:最新のRails/GetTextについての説明になっていた)
 Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.3.2以降) - よたらぼ 保管庫

2009年8月12日水曜日

Railsの GetText 2.0でサーバが起動しないエラーの対応メモ

レアなケースだろうけど一応メモ。


(参考:RailsでGetText)
Rails のためのものぐさな Web アプリケーションの国際化手法 - 川o・-・)<2nd lifeが参考になる。
ただしGetText 2.0からはenvironment.rbで読み込むgemが変わったので注意。

config.gem "locale_rails"
config.gem "gettext_activerecord"
config.gem "gettext_rails"



ActiveRecordもActionMailerも使わないので、config/environment.rbで不使用にしていた。
config.frameworks -= [ :active_record, :action_mailer ]

gettext(2.0)を使うために、下記をgemでインストール。
locale
locale_rails
gettext
gettext_rails
ActiveRecordは使わないのでgettext_activerecordは入れなかった。

アプリケーションにgettextを使う設定を入れて、mongrelを起動しようとしたがエラーになって起動できない。
ruby server/script

.../lib/active_support/core_ext/module/aliasing.rb:33:in `alias_method': undefined method `create!' for class `ActionMailer::Base' (NameError)

ActionMailer?使ってないけど?
しょうがないから不使用指定を外す。
config.frameworks -= [ :active_record, :action_mailer ]

config.frameworks -= [ :active_record ]

これでも駄目。
試しにgettext_activerecordをインストール。
これで起動したら起動できた。

もう1つ試しにgettext_activerecordのrequireをコメントアウトしたら起動しなかった。


結論:RailsでGetTextを使う場合、不要でもActionMailerを外しては駄目。かつ、不使用でもgettext_activerecordが必要。

2008年9月15日月曜日

CakePHP 1.2 で多国語対応(GetText)調査メモ

PHPでは _() または gettext() でgettextできるが、CakePHPではそれをラップして __() でgettextできる。

//PHPの例
echo _('We love PHP');
//CakePHPの例
__('You love CakePHP'); //第2引数でtrueを指定すればechoせずに戻り値を返すこともできる
CakePHPではCakeコンソールからi18nできて便利そう。
CakePHPでのgettextについては、CakePHP 1.2 の多言語対応メモ - miau's blog?が、参考サイトへのリンクも多く、よくまとまっていて参考になる。


あとはひっかかりそうなところについてのメモ。


複数形
英語など単数と複数でメッセージが変わる場合、__n() を使う。
//例
__n('cat', 'cats', $catCount);
echo __n('mouse', 'mice', $mouseCount, true); //第4引数は戻り値を返すかどうか
詳しくは、1.2系の多言語対応メモ(2) - Writing Some Codeを参照。
Rubyよりも使いやすいと思う。

(2008/09/17 追記)
__n()の第3引数は、シンプルな変数でないと機能しないようだ。sprintfとかの関係だろうか?
//NG

__n('cat', 'cats', $cat['count']);


//OK
$count = $cat['count'];
__n('cat', 'cats', $count);
(追記終わり)


言語によってメッセージ内のパラメータの順番が違う場合
翻訳メッセージの複数個所に穴埋めで項目名などを入れる場合で、言語によって順番が違う場合の対応方法。
1.2系の多言語対応メモ(3) - Writing Some Codeの後半を参照。

ブログ アーカイブ

tags