Thymeleafで言語別フィールドをカッコよく表示する
日本語名カラムと英語名カラムを持つテーブルってよくあるじゃないですか。…よくありますよね?まぁよくあるとして、それを画面表示する際にユーザのロケールによって切り替えたい。カッコよく。そんな試行錯誤のメモです。
TL;DR
|
|
やっていき
Spring Boot 2.1.x です。
こういうクラスがあったとします。名前フィールドがnameEn
とnameJa
に別れてます。これをうまいことユーザのロケールによって切り替えて画面に表示させたいわけです。
ちなみに、私は「そもそも」と言われるとしんでしまいます。
|
|
普通に考えると、条件分岐でしょうか。
|
|
でも、私はif文を書くとしんでしまう体質だし、三項演算子書いたら三項演算子警察にころされるじゃないですか。
ていうか、こんな事やってて別のロケールフィールドが増えたらどうすんじゃいって感じだし、固定のフィールドと言えどもResourceBundleであるところのメッセージプロパティと同じように扱いたい。
で、ちょっと思ったんですけど、Thymeleafってオブジェクトのフィールドを${item.nameEn}
のようにドットを使った記法で取得する他に${item['nameEn']}
のように角括弧を使って取得することもできるんですよね。角括弧の引数は文字列なので、これを変数で渡してやれば取得するフィールドを動的に切り替えることができるはずです。
余談ですが、対象のオブジェクトがMapの場合も${map['key1']}
でも${map.key1}
でも取れますね。GetterでのアクセスなのかMap#get()
なのかView側では意識することなく扱えるってことですねー。Rubyっぽいっていうか。よく知りませんが、最近のテンプレートエンジンはみんなこんな感じなんですかね?
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html#%E5%A4%89%E6%95%B0
結局やりたいのは固定フィールドもメッセージプロパティと同じように取り回ししたいということなので、じゃあ角括弧の引数はメッセージプロパティから取ればいいじゃんと思いました。
messages_en.properties
|
|
messages_ja.properties
|
|
通常Thymeleafでメッセージを表示する場合は#{i18nfields.name}
のような構文で記述しますが、#messages
オブジェクトを使って${#messages.msg('i18nfields.name')}
のように記述することも可能です。角括弧の引数に直接メッセージを渡す場合は#messages
オブジェクトを使う必要があります。
|
|
#{i18nfields.name}
構文で書きたければ、一旦変数に入れてから渡します。
|
|
また余談ですが、ドットを使った記法だと、${item?.nameJa}
のようにオブジェクトの後ろに?
を付けることで、対象オブジェクトがNullでない場合のみGetterを呼び出す…というかメソッドチェーンを実行することが可能ですが(Null安全?)、角括弧を使った記法だとこれはできません。オブジェクトがNullになる可能性がある場合は愚直にNullチェックする必要があります。
…
これがスマートかって言われるとそうではない気がしますし、みんなどうやってるのか知りませんが、多少は格好がついたのではないかと思います。カッコなだけに。
プリプロセッシングを使う(2020/08/30追記)
そもそもこの問題の解決策がチュートリアルに提示されていました。Thymeleafには通常の式より先に評価される「プリプロセッシング」という機能があります。プリプロセッシング式は2重のアンダースコアで囲みます。
プリプロセッシングでメッセージプロパティに定義したフィールド名を取得することで動的に参照フィールドを切り替えることができます。
|
|