接續前一篇,我們來聊聊 errors 的 I18n 翻譯規則。
這可以分兩個部分,因應 errors.add
可以傳入兩個 argument ,第一個是 attribute,第二個是 message。
今天先講第一部分,attribute,或者 method。
首先在完全沒有規劃 I18n 檔案的情況下,除了 EN 的其他語言應該都會顯示 translation missing: ...
在你的翻譯結果裡面。
所以我們還是先從 EN 英文開始比較單純。
一樣,我們先做出一個範例 class:
class MyCls
include ActiveModel::Model
attr_accessor :name
attr_accessor :target_id
validates_presence_of :name
validates_presence_of :target_id
end
在完全沒有規劃翻譯檔的情況下,我們新建一個物件,並且觀察他的 error message:
obj = MyCls.new
obj.validate
obj.errors.to_a
=> ["Name can't be blank", "Target can't be blank"]
從第一個我們可以觀察到,attribute 翻譯的部分,就只是把該欄位第一個字母轉大寫而已,
但看到第二個的時候,不對呀!我的欄位明明叫做 target_id
為什麼他只顯示 Target
呢?
這是因為,翻譯欄位的時候,他事實上會去使用 self.class.human_attribute_name
以進行翻譯。而當我們沒有規劃翻譯檔的時候,這個 method 最後會直接把 attribute 先 .to_s
再接 .humanize
以順利翻出人類易讀的樣子。
然而,string.humanize
這個方法他背後其實會很雞婆的幫你去掉結尾的 _id
,再把第一個字母大寫。
於是,就變成上面看到的樣子了...。
那應該如何規劃翻譯檔呢?
在您的 conig/locales/
資料夾裡加上 en.yml
並且寫入:
en:
activemodel:
attributes:
my_cls:
name: Name
target_id: Target ID
然後上面的在跑一次:
obj = MyCls.new
obj.validate
obj.errors.to_a
=> ["Name can't be blank", "Target ID can't be blank"]
你看,就完整翻譯出 Target ID
惹~。
注意!上面翻譯檔裡面的 activemodel
其實是根據您的 class method i18n_scope
來決定的,預設長這樣
def i18n_scope
:activemodel
end
所以如果你想要,你完全可以覆寫掉這個 i18n_scope
的 method,像是:
def i18n_scope
:my_scope
end
然後你的翻譯檔就要配合規劃,像這樣:
en:
my_scope:
attributes:
my_cls:
name: Name
target_id: Target ID
今天大致介紹過了 attribute 的翻譯規則,下一篇再來介紹 message 的。