Ruby on Railsチュートリアル第6版が終わり、そこで作ったサンプルアプリケーションの修正や機能追加をやってます。
追加第4章では、日本語化(i18n対応)をします。
追加第4章 サンプルアプリの日本語化(i18n対応)
i18nがなぜi18nと呼ばれるのかは、確かRailsチュートリアル解説動画でも説明されてたような気がしますが、Wikipediaによると、
i18nは数略語であり、その「18」は、internationalizationの先頭のiと語尾のnの間にnternationalizatioの18文字があることに起因する。
国際化と地域化 – Wikipedia
ということのようです。今回はそんなi18n対応です。
i18n対応
何をどうすればいいのかわからない状態からのスタートだったため、とりあえずGoogle先生に聞いてみました。それで見つけたのが「[初学者]Railsのi18nによる日本語化対応」という記事です。
rails-i18nのインストールと設定変更
「[初学者]Railsのi18nによる日本語化対応」に書いてある通りに進めていきましたが、bundle installでエラーが出ました。
Bundler could not find compatible versions for gem "railties":
In snapshot (Gemfile.lock):
railties (= 6.0.0)
In Gemfile:
rails (= 6.0.0) was resolved to 6.0.0, which depends on
railties (= 6.0.0)
rails-i18n (~> 5.1) was resolved to 5.1.3, which depends on
railties (>= 5.0, < 6)
sass-rails (= 5.1.0) was resolved to 5.1.0, which depends on
railties (>= 5.2.0)
web-console (= 4.0.1) was resolved to 4.0.1, which depends on
railties (>= 6.0.0)
webpacker (= 4.0.7) was resolved to 4.0.7, which depends on
railties (>= 4.2)
Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
バージョンの問題があるようです。railtiesが何かよくわかりませんが。
記事をよく見てみると、Rails 5.0.7なんですよね。Railsチュートリアルは第6版でRails 6.0.0を使ってるのでたぶんここの問題だと思われます。
「Ruby on Rails 6.0によるWebアプリケーション開発16 バリデーションの日本語化」ではrails-i18nをバージョン指定なしでインストールする感じだったので、バージョン指定を外してbundle installしてみたらできました。
これでとりあえずエラーメッセージは日本語化されてるようです。ユーザー登録のエラーメッセージが日本語化されてるのを確認しました。
でも、ログインするとエラーが出ました。
nil can't be converted to a Time value
フィードのタイムスタンプのところでエラーが出てるようでした。記憶が正しければ、
time_ago_in_words(micropost.created_at)
ここに問題があるようです。
railsコンソールで確認してみると、created_atにはちゃんとデータが入ってました。db:seedでデータを入れたままなので当然といえば当然ですが。
そうなると、i18n対応で追加したところが問題と考えられます。さらにcreated_at関係らしいということで、追加したコードのタイムゾーンのところをコメントアウトしてみましたが、ダメでした。
(そういえば、Railsサーバーの再起動は試してなかったような)
とりあえず、データの問題だろうということで、データベースをリセットしてデータを入れ直してたら、
config.active_record.default_timezone = :local
と書くところが、
config.active_record.default_timezone = :locla
となってることに気づきました。db:seed中でしたが直して保存。db:seedが終わってRailsサーバーを立ち上げてみると、エラーがなくなり、表示させることができました。
タイムスタンプは「〇分前」というような表示に変更されてます。
「local」のスペルミスが問題なのか、db:seedのなり直しが必要だったのかはわかりません。
まだ日本語化されてないところもあるので、そこを修正していきます。
日本語化されないフォーム
「[初学者]Railsのi18nによる日本語化対応」などにある通りにja.ymlファイルを作り、フォームのラベルの日本語化をやってみました。
どこにファイルを置くかとかもあるようですが、「Railsでf.labelを日本語化する (i18n)」に従いました。実際に使ってるフォームに合わせて書き換えることで、ユーザー登録フォームのラベルは日本語化できました。
これで大丈夫かなと思ってましたが、ログインフォームのラベルは日本語化されてません。
「らくだ🐫にもできるRailsチュートリアル|番外編・I18n」の説明を読むと、モデル名を指定してることが問題なのかなと考えました。Userモデルのユーザー登録フォームは日本語化されて、他は日本語化されない、という感じです。
参考にしたサイトがどこかわからなくなってしまったんですが、
ja:
attributes:
name: 名前
みたいな感じにすると良さそうだったので試してみましたが、変化がありません。
「Railsでi18n」によると、コントローラとアクションを指定する方法もあるようなので試してみましたが、ダメでした。書き方が間違ってた可能性もありますが。
ちゃんと理解しようと思って、Railsガイドの「Rails 国際化 (i18n) API」を読んでみました。読んでも理解できないところが多かったんですが、
Model.model_name.humanメソッドとModel.human_attribute_name(attribute)メソッドを使うことで、モデル名と属性名を透過的に参照できるようになります。
4.5 Active Recordモデルで翻訳を行う – Rails国際化(i18n)API – Railsガイドv6.0
と書いてありました。
「[初学者]Railsのi18nによる日本語化対応」にもそのメソッドが使われてたので、試しに使ってみました。
<%= f.label :email, User.human_attribute_name(:email) %>
こんな感じです。これでログインフォームのラベルも日本語化できました。ただ、ja.ymlはモデルを指定してないので何が起こってるのかわからないままです。
ちなみに、ユーザー登録フォームの確認用パスワードのラベルは表示を指定してあって、そこを削除しないと設定が反映されないので注意が必要です。
日本語化できたようですし、調べてもわからなかったので、この先はレベルアップしてからにすることにしました。
最終的にはGitHubにあるファイルを使って日本語化しました。
デフォルトの言語とpluralizeメソッド
エラーメッセージとかが日本語化された関係で、テストに問題が出てないか確認したところ、REDになりました。
メッセージの内容チェックで引っかかってるのかなと思って見てみると、複数形になるはずのところが単数形になってたようです。複数形化はpluralizeメソッドを使ってるので、それが機能してないということですね。
試しにデフォルトの言語を英語に戻してみたところ、テストはGREENになりました。表示を確認してみると複数形になってました。
デフォルトの言語を日本語にすると複数形化されず、単数形のままです。
調べた感じだと、ロケールが英語のときだけ機能するようですね。なので、
config.i18n.default_locale = :ja
こんな感じでデフォルトの言語(ロケール)が日本語だと機能しないということなのでしょう。ということで、テストを書き直しておきました。
他のところの日本語化
Railsチュートリアルで作るアプリケーションは基本的に英語なので、メッセージとかいろんなものが英語になってます。おそらくこういうのもi18n対応できそうな気もしましたが、今回はやめておきました。
そこに時間をかけるとせっかく覚えたRailsの記憶が薄れていきそうだったからです。何気に時間かかりそうですしね。あとは、日本語以外を使ったアプリケーションを作る予定が今のところないので、優先順位としてはそんなに高くないというのもあります。
必要になったらやってみようと考えてます。
まとめ
i18n対応(日本語化)を始める前は、日本語のアプリケーションにしようと思ってましたが、現段階でそこに時間をかけるのはもったいないなと思い始めました。
i18n対応のイメージは何となく持てましたし、英語のところを日本語にするのはプログラムと関係ないところが多そうだったので、完全な日本語化をせず、途中で終了することにしました。
それよりもDeviseによるログイン/認証システムを優先した方がいいという判断です。
ということで、次はDeviseの導入です。