Ruby-GetText-Packageを使ったCGI開発

ruby-gettext-howto-cgi

Ruby-GetText-PackageをCGIで使うヒントを書いてみました。

サンプルスクリプトがruby-gettext-x.x.x/samples/cgi/配下にありますのでそちらもご覧ください。

ここでは、

  • 単純にCGI使う
  • ERBから使う
  • 他のテンプレートエンジンや複数のHTMLファイルに分割して使う

の3つを説明します。

単純にCGIで使う

とっても簡単です。通常の開発手順と何ら変わりありません。

スクリプト例を以下に示します。ドメインはindexで/app/locale/#{lang}/LC_MESSAGES/ディレクトリにmoファイルを配置することとします。

require 'gettext/cgi'

include GetText

set_output_charset("UTF-8")
bindtextdomain("index", "/app/locale")

print "Content-type:text/html; charset=UTF-8\n\n"

puts %Q[<html><head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 <title>]
puts _("Sample script for CGI/ERB and Ruby-GetText-Package")
puts  "</title><body>"

puts "<h1>" + _("Hello World") + "</h1>"
puts "</body></html>"

このサンプルでは出力文字コードをUTF-8で固定としています。 もっとフレキシブルに対応したい!という方は、Locale.charsetを使って以下のように記述することも可能です。

require 'gettext/cgi'

include GetText

bindtextdomain("index", "/app/locale")

print "Content-type:text/html; charset=#{Locale.charset}\n\n"

puts %Q[<html><head>
 <meta http-equiv="content-type" content="text/html; charset=#{Locale.charset}">
 <title>]
puts _("Sample script for CGI/ERB and Ruby-GetText-Package")
puts  "</title><body>"

puts "<h1>" + _("Hello World") + "</h1>"
puts "</body></html>"

ただ、これを使う場合、WWWブラウザ側からきちんとHTTP_ACCEPT_CHARSETを返してくれないとUTF-8になってしまうし、FORM入力で受けた文字列をDBに保管するときにもうまく文字コードを変換する必要がある等、面倒なことが多いと思いますので、可能な限り前者のUTF-8固定を採用することをお奨めします。

どうやってロケール情報を取得するか

ロケール情報は、QUERY_STRINGのlangの値 > Cookieのlangの値 > WWWブラウザが返すHTTP_ACCEPT_LANGUAGE環境変数 > "en"(英語) の順番で決まります。QUERY_STRINGのlangの値とは、例えば、http://foo/?lang=ja という感じでURLの最後に追加する方法です。 QUERY_STRINGのlangの値やCookieのlangの値はアプリケーション側で適切に設定する必要があります。

ERBをテンプレートエンジンとして使う

ERBをテンプレートエンジンとして使う例をあげてみます。samples/cgi/helloerb1.cgiそのものです。

require 'gettext/cgi'
require 'gettext/erb'

class SimpleContainer1
  include GetText::ErbContainer

  def initialize(domainname, domainpath = nil, locale = nil, charset = nil)
    bindtextdomain(domainname, domainpath, locale)
  end

  def description
    _("Sample script for CGI/ERB (UTF-8).")
  end

  def to_html(path)
    eval_file(path)
  end
end

GetText.output_charset = "UTF-8"

print "Content-type:text/html; charset=UTF-8\n\n"

con = SimpleContainer1.new("helloerb1", "locale")

if GetText.cgi["other"] == "true"
  print con.to_html("other.rhtml")
else
  print con.to_html("helloerb.rhtml")
end

helloerb.rhtml/other.rhtmlがそれぞれのERBファイルです。実際にsamples/cgi/helloerb.rhtml, other.rhtmlを読めば、それぞれのrhtml(ERB)ファイル中でGetText.bindtextdomainを呼ばずにすんでいることがわかります。 これは、GetText::ErbContainerをインクルードしたクラスではそのクラスのインスタンス単位でテキストドメインを指定できるからです(通常のGetText.bindtextdomainでは、rhtmlファイル単位に呼び出さないといけない...ということになる)。

また、rhtmlファイル中から、SimpleContainer1クラスのインスタンス変数やメソッドをそのまま呼び出すことができます。descriptionはその一例です。

なお、rhtmlファイル側は以下のように書きます。ちょっと手間ですが、まぁ許容範囲ということで。

<h1><%= _("Hello World") %></h1>

このrhtmlファイルから翻訳文字列を取り出すにはrgettextを使うことができます。

$ rgettext foo.rhtml -o foo.pot

他のテンプレートエンジンや複数のHTMLファイルに分割して使う

他のテンプレートエンジンや、複数のHTMLファイルを分割して使う場合は、gettext/erb.rbのソースコードを参考にすると良いと思います。

更新日時:2005/04/30 21:29:30
キーワード:
参照:[Ruby-GetText-Package]