Sinatraでi18nする

sinatra-r18nというgemを使うと、Sinatraアプリを簡単にi18n(国際化)できるようになるので、NekostagramInustagramに英語版のテキストも用意して、ブラウザーの言語設定で日本語or英語に分岐するようにした時の備忘録。ただし、このやり方だと後述するクローラー関連の問題がある。

sinatra-r18nのインストール

普通にgemをインストールする。

$ gem install sinatra-r18n

または、Bundlerを使っている場合は、Gemfileファイルにsinatra-r18nを追加する。

gem 'sinatra-r18n'

i18n用のYAMLファイルの作成

プロジェクトフォルダ直下にi18nフォルダを作成して、ja.ymlen.ymlを用意する。ファイル名からお察しのとおり、それぞれ日本語版でのテキストと、英語版でのテキストを書いておく。例えば以下のような感じ。

site:
  title: 'Nekostagram - ねこ大好き専用Instagram'
site:
  title: 'Nekostagram - Cat Lovers Instagram Viewer'

上記のsite:とかtitle:は自分で勝手に付けた属性名なので、特に決まりはなく適当でおk Nekostagramでは、それぞれja.ymlen.ymlがこの部分に該当する。

使い方

まずrequireする。ハイフンじゃなくてスラッシュなので注意。

require 'sinatra/r18n'

sinatra/r18nrequireしてあれば、tオブジェクトから上記で設定した情報を参照できる。以下は、実際にNekostagramのソースコード内で使われているSlimコードの断片を簡略化したもの。r18n.locale.codeは現在表示している言語を取得でき、下記のコードでは日本語ならlogo.gif、それ以外ならlogo_en.gifのロゴ画像を読み込むように分岐している。img srcの文字列内での変数展開で、波カッコが二重になっているのは、Slimで変数展開する値をHTMLエンコードしない時の記法。

h1
  a href='/'
    - image_name = (r18n.locale.code == 'ja') ? 'logo' : 'logo_en'
    img src="images/#{{image_name}}.gif" title="#{{t.site.title}}" alt="#{{t.site.title}}"

また、その後のtitle属性・alt属性でtオブジェクトから、上述のYAMLで指定した属性を経由して、現在の言語の文字列を取得している。この分岐は自動でしてくれるので、単に参照するだけでおk

クローラー関連の問題

詳しくはこの記事にまとめてあって、まだ解決もしていないんだけど、推測では「クローラーのブラウザーの言語設定が英語になっているから」が原因だと思っている。なぜなら、最初は日本語版しかなかったNekostagramも、今は上記ライブラリを使用したi18n化が済んでおり、今GoogleでNekostagramを検索すると英語版のタイトルが表示されるようになっている。最初は日本語タイトルだったけど、時間経過で更新され、その時には既にi18n化していたことにより、英語版タイトルに更新されたものと思われる。はてブの場合も同様に、タイトルを取得するサーバーの言語設定が英語になっているからなんじゃないかなぁと。自動で分岐させる場合は、これは仕方ないのかもしれないと半ば諦めている。


Sinatra – R18n