Rails I18n活用術:すぐ使えるヒント3選と、常識破りの活用事例1つ
Railsのi18nライブラリは、見た目以上に強力です。翻訳のためだけに使う必要はありません。表示するテキストと、それを表示する場所を分離(デカップリング)したいあらゆる場面で役立ちます。
Avvoに在籍していた間、私たちはi18nを使ってさまざまな工夫を実現してきました。ここでは実際に役立った学びの数々と、一見「乱用」に見えながら結果的に素晴らしい成果をもたらした、ちょっとクレイジーな活用法を紹介します。
自動HTMLエスケープ
ビューにこんなコードを書いていませんか?
<%= raw(t('form.required_field_header')) %>
実はこのrawは不要です。翻訳キーの末尾が_htmlになっていれば、Railsが自動的にHTMLセーフとして扱ってくれるからです:
<%= t('form.required_field_header_html') %>
シンプルですし、他のt()呼び出しとも一貫性が保てます。
ロケールへのより便利なアクセス
ロケールファイルを作るとき、同じ親キーの下に複数のキーをグループ化することが多いでしょう:
en:
bugs:
index:
new_label: "File a new bug"
edit_label: "edit"
delete_label: "delete"
これらをまとめて参照するには、フルキーで指定することもできます:
<%= t('bugs.index.edit_label') %> | <%= t('bugs.index.delete_label') %>
でもこれはかなり面倒で冗長です。実はt()にはscopeオプションがあり、これを使うともっとスマートにキーを参照できます:
<% bugs_scope = 'bugs.index' -%>
<%= t('edit_label', scope: bugs_scope) %> | <%= t('delete_label', scope: bugs_scope) %>
さらに、パーシャル(部分テンプレート)のファイル名を適切に付けていれば、scopeの指定すら不要になります:
<%= t('.edit_label') %> | <%= t('.delete_label') %>
つまり、.edit_labelはbugs.index.edit_labelを参照します。今いるのがbugs/index.html.erbだからです。
ActiveRecordバックエンド
YAMLファイルに静的に翻訳を定義する方式では、プロジェクトによってはうまくいかないことがあります。そんなときは、代わりにActiveRecordのi18nバックエンドを使いましょう:
require 'i18n/backend/active_record'
I18n.backend = I18n::Backend::ActiveRecord.new
こうすると、データベースのtranslationsテーブルから翻訳を検索できるようになります。すべての翻訳を事前に定義しておく必要はなく、必要になった時点で新しい翻訳を追加できます。
translationsテーブルのセットアップには専用のマイグレーションが必要です。詳しくはi18n-active_recordリポジトリのREADMEに必要な情報がすべて載っています。
オブジェクトタイプ間でのパーシャル共有
Avvoでは、弁護士ディレクトリ、弁護士レビュー、法律相談サービスを運営しています。しかし数年前は、サイトに弁護士だけでなく、医師や歯科医師も在籍していました!
これらの職種間でUIの多くは共通していました。しかし、違いも十分にありました(例えば、弁護士が「practice areas=取扱分野」と呼ぶものを、医師は「specialties=専門分野」と呼ぶなど)。そのため、かなり無理のあるコードを書かない限り、同じビューやパーシャルを共有するのは困難でした。
やがて私たちは、この問題にi18nシステムを活用できないかと考え始めました。考えてみれば、弁護士英語は英語の一種の方言のようなものであり、医師英語も同じことです。将来的に他の言語へ対応できなくなるのは避けたかったため、en_jd(法務博士)とen_md(医学博士)という2つの新しいロケールを作ることにしました。
カスタムi18nバックエンドとして設定するのは簡単でした:
class AvvoI18nStore < I18n::Backend::Simple
def translate(locale, key, options = {})
begin
default = options.delete(:default)
super(locale, key, options)
rescue I18n::MissingTranslationData => e
# "en_jd"などで見つからない場合は"en"にフォールバック
fallback_locale = locale.to_s.split("_").first
super(fallback_locale, key, options.merge(:default => default))
end
end
end
I18n.backend = AvvoI18nStore.new
翻訳の定義も同じくらい簡単です:
en_jd:
practice_area: "practice area"
en_md:
practice_area: "specialty"
パーシャル全体の切り替えにも使えました(ファイル名に注目してください):
<!-- 弁護士向けバッジのHTML -->
<!-- 医師向けバッジのHTML -->
さらに、共有したい翻訳についてはenロケールへのフォールバックまで機能しました:
en:
leaderboard:
title: "Leaderboard"
サイトの「Doctors(医師)」セクションではデフォルトロケールを:en_mdに変更し、「Lawyers(弁護士)」セクションではその逆を行います:
I18n.locale = :en_md
そして、すべてが期待どおりに動作しました!
この手法をおすすめするかどうかは微妙なところです。職業ごとに異なる「言語」を持つという発想は、確かに少し突飛ですから。しかし実際に運用していた間は驚くほどうまく機能しました。i18nのようなシンプルなツールが、どれほど大きな力を発揮しうるかを示す好例だと思います。
こうした知識はどこで身につく?
先週、特定の技術について深く掘り下げることが、初心者からエキスパートへステップアップする方法だと話しました。今回のi18nの話もその一例です。私たちがi18nについて学んだことの大部分は、RailsガイドとAPIドキュメントを読んで得たものです。
だからこそ、もう一歩踏み込んでみてください。日頃頼りにしているツールをしっかり学ぶのです。生産性が上がるだけでなく、思いもよらなかったまったく新しい解決策の扉が開くかもしれません。
-
Redisを正しく使いこなすための10の実践テクニック
Redisは現在、技術コミュニティで非常に高い注目を集めています。Salvatore Sanfilippo(Antirez)氏の個人的な小さなプロジェクトとして始まったRedisは、今やインメモリデータストレージの業界標準へと成長しました。普及に伴い、Redisを適切に運用するためのベストプラクティスも確立されつつあります。本記事では、Redisを正しく活用するための10のヒントをわかりやすく解説します。 1. KEYS * の使用をやめる 冒頭から強い口調で申し訳ありませんが、これはおそらく最も重要なポイントです。Redisインスタンスのcommandstatsを確認すると、KEYSコマン
-
知らないと損!Gmailの生産性を高める10の便利なヒントとコツ
世界では約7人に1人がGmailを使用していますが、その多くはGmailが提供するさまざまな機能を十分に活用できていません。Gmailはメールの送受信だけでなく、重要なメールの強調表示、迷惑メールのフィルタリング、特定ユーザーのブロックなど、多彩な使い方ができるサービスです。 Gmailには数多くの便利な機能が備わっていますが、その多くが隠し機能となっているため、活用しきれていないユーザーも少なくありません。この記事では、そんな隠れた便利機能とその使い方をご紹介します。これらの機能を使えば、Gmailの整理・管理がしやすくなるだけでなく、楽しく快適なメールライフを実現できます。 1. 送信取り