サーバーサイドエンジニアの趙(じゃお)です。
PlanBのフロントエンドとサーバーサイドを担当しています。
PlanBは「あなたの時間を最高にするCtoCのダイニングコンシェルジュサービス」です。
アレンジの価格帯は500円~で、街をよく知るコンシェルジュたちが飲食店選びから予約までを行い、ゲストのシチュエーションにあったアレンジをすることで唯一の体験を提供します。
このPlanBですが、リリース当初は日本語のみに対応していました。
しかし、海外市場やインバウンド市場への展開を視野に入れ、国際化対応版をリリースしました。
この記事では、PlanBの国際化にあたり行なった対応をまとめています。
言語ごとにURLを分ける
URLの分け方はplnb.jp/(:locale)/path/to
にしました。
この分け方を選んだ理由は、
- SEOフレンドリーである
- ユーザーはURLからどの言語を使っているか判断できる
Route
コンフィグファイルだけを変更すれば簡単に実現できる
の3つです。
ユーザーのロケール設定
ユーザーに表示する言語を決定する順番は以下の通りです。
- URLの中の
locale
変数 Cookie
で保存された言語- ブラウザーの
Accept-Language
設定 - デフォルトロケール(日本語)
Railsのdefault_url_options
メソッドで、サイト内すべてのリンクにロケール変数を入れました。
def default_url_options(options = {}) {locale: I18n.locale}.merge(options) end
そのため、locale
変数の順位を最優先にします。
また、ユーザーが言語を変える時、その言語をCookie
に保存します。
目的はユーザーがplnb.jp/path/to
のようなURL(特にホームのplnb.jp
)を訪問する時、もともと使っていた言語で表示させるためです。そのためCookie
を第二順位にしました。
次のAccept-Language
による設定は、ユーザーが初めてplnb.jp
を訪問するための仕組みです。
もしAccept-Language
の検出が失敗したらデフォルトロケールである日本語で表示します。
データベースの翻訳
コンシェルジュの自己紹介、得意料理ジャンル名など、データベースに保存するデータの多言語化はGlobalizeというgemを使いました。
翻訳テーブルを作るマイグレーションファイルは以下の通りです。
class TranslateAreas < ActiveRecord::Migration def up Area.create_translation_table!({ name: :string }, { migrate_data: true }) end def down Area.drop_translation_table!(migrate_data: true) end end
ActiveRecordクラスは以下の通りです。
class Area < ActiveRecord::Base translates :name default_scope { eager_load(:translations) } # ... end
default_scope { eager_load(:translations) }
により、翻訳テーブルのN+1
ロードを回避することができます。
レビューの自動翻訳
レビューの自動翻訳にMicrosoftのTranslator APIを使いました。
このAPIは2,000,000文字/月までは無料で使うことが出来ます。
ユーザーがレビューを書くとき、ユーザーが使う言語以外の言語に自動翻訳を行います。
class Review < ActiveRecord::Base translates :content globalize_accessors default_scope { eager_load(:translations) } before_validation :translate_content #... def translate_content self.origin_language = I18n.locale (I18n.available_locales - [I18n.locale]).each do |trans_to| # APIにより自動翻訳 self.send("content_#{trans_to}=", translation) end end end
タイムゾーンに沿った時刻の表示
PlanBは、コンシェルジュがユーザーの要望によってレストランを提案し、予約してくれるサービスです。
ユーザーとコンシェルジュのやり取りはメッセージで行います。
各メッセージには送信時間が表示されるため、この時間はユーザーがいる場所のタイムゾーンに沿って表示する必要があります。
タイムゾーンを判断する方法はいくつかありますが、PlanBではユーザーのIPアドレスによりタイムゾーンを判断しています。
具体的にはgeoipというgemと、無料のGeoLiteデーターベースを使っています。
GEO_IP = GeoIP.new(Rails.root.join("db", "GeoLiteCity.dat")) @timezone = GEO_IP.city(request.remote_ip).try(:timezone) || "Unknown"
現地通貨での価格表示
PlanBの決済は日本円ですが、参考価格としてユーザーロケールに沿った現地の通貨を表示しています。
実装は以下の通りです。
まず、前述のgeoip
で国を判定します。
country = GEO_IP.country(request.remote_ip).country_code2
次に、geoip
で判定した国により、通貨を判定します。
currency = Settings.country_currency[country]
最後に、Redisに保存する変換レートをOpen Exchange Ratesを使って取得しています。
rate = REDIS.hget("country_currency_rate", country).to_f
まとめ
PlanBの国際化対応にあたり、下記に挙げる実装を行ないました。
- 言語ごとにURLを分ける
- ユーザーのロケール設定
- データベースの翻訳
- レビューの自動翻訳
- タイムゾーンに沿った時刻の表示
- 現地通貨での価格表示
国際化対応には様々な方法があり、その時々で最適な方法は異なりますが、PlanBで行った対応方法が何かの参考になれば幸いです。
PlanBは、あなたの時間を最高にするダイニングコンシェルジュです。
記念日や会食はもちろん、普段とちょっと違う時間を過ごしたい時にご活用ください。
TwitterやFacebook、オフィシャルブログも要チェックです。