Sinatraのerbメソッドは標準ではContent negotiationをサポートしていません。そこで、ユーザエージェント(Webブラウザ)がリクエストに指定したAccept-Language
ヘッダの値をもとに、テンプレートを自動的に選択することができるメソッド(erb_l
)を新たに定義します。
多分、sinatra-r18nかSinatra本家がサポートするまでの間の暫定対応。
準備
以下のgemが必要です。適当にgem install
しておいて下さい。
- i18n
- rack-contrib
コード
アプリ
# coding: utf-8
require 'rack/contrib'
require 'sinatra/base'
class TestApp < Sinatra::Base
use Rack::Locale
helpers do
# erb with content negotiation support
def erb_l(template, options = {}, locals = {})
locale = request.env['rack.locale']
if locale.nil? or locale.to_s !~ /^\w+$/
erb(template, options, locals)
end
tmpl = "#{template.to_s}_#{locale}".to_sym
begin
erb(tmpl, options, locals)
rescue Errno::ENOENT
erb(template, options, locals)
end
end
end
get '/' do
erb_l :index
end
end
erb_l
メソッドは、Accept-Language
ヘッダの値に基いて、読み込むテンプレートのファイルを決定します。上記の例の場合、日本語を優先する設定のWebブラウザからのリクエストの場合にはindex_ja.erb
を、英語を優先するWebブラウザからのリクエストの場合にはindex_en.erb
をテンプレートとして使用します。これらのファイルが存在しない場合、index.erb
をテンプレートとして使用します。
テンプレートの例
<%# coding: utf-8 %>
<html>
<body>
<h1>Hello, world</h1>
</body>
</html>
<%# coding: utf-8 %>
<html>
<body>
<h1>こんにちは世界</h1>
</body>
</html>
config.ru
require 'rubygems'
require File.join(File.dirname(__FILE__), 'test_app.rb')
run TestApp
実行例
テストのため、上記のアプリを起動しておきます。
% rainbows -E production -p 8080 config.ru
Accept-Language
ヘッダを指定しない場合、標準のindex.erb
が使われます。
% wget -nv -4 -O - http://localhost:8080/
<html>
<body>
<h1>Hello, world</h1>
</body>
</html>
Accept-Language: en
の場合。index_en.erb
の利用を試みますが、これは存在しませんので、index.erb
が使われます。
% wget -nv -4 -O - --header='Accept-Language: en' http://localhost:8080/
<html>
<body>
<h1>Hello, world</h1>
</body>
</html>
Accept-Language: ja,en
の場合。index_ja.erb
が使われます。
% wget -nv -4 -O - --header='Accept-Language: ja,en' http://localhost:8080/
<html>
<body>
<h1>こんにちは世界</h1>
</body>
</html>
Accept-Language: fr
の場合。index_fr.erb
の利用を試みますが、これは存在しませんので、index.erb
が使われます。
% wget -nv -4 -O - --header='Accept-Language: fr' http://localhost:8080/
<html>
<body>
<h1>Hello, world</h1>
</body>
</html>