【SwiftUI】引数から渡されたStringではTextはローカライズしてくれない
SwiftUIで多言語対応の際に、引数で渡されたStringからではText
はローカライズしてくれないという現象になった為、もう少しTextに寄り添ってみることにしました。
環境
- Xcode 14
はじめに
今回は多言語対応のためにLocalizable.strings
を作成したりする方法は説明していません。すでに日本語対応用のLocalizable.strings
がある前提で進めていきます。
Text
SwiftUIのText
はUIKitのUILabel
に相当するコンポーネントで、表示したい文字列をText
に渡すだけでいい感じに表示してくれます。
import SwiftUI struct ContentView: View { var body: some View { Text("Hello, world!") } }
Textのここが素晴らしい
Text
は、渡された値がLocalizable.strings
内にあるキーと一致する場合は、そのキーに紐づく値を表示して、一致しない場合は渡された値をそのまま表示するという挙動をしてくれます。
自ら先回りして動いてくれて、本当に素晴らしい。いつもありがとうという気持ちをここに表明します。
素晴らしさを実感
Localizable.strings
まず、日本語用のLocalizable.strings
を用意しました。
/* Localizable.strings Localization(Japanese) */ "Hello, world!" = "こんにちは、世界!";
ContentView
実際にText
にLocalizable.strings
のキーと一致するものがあるText
とキーが存在しないText
を配置してみます。
import SwiftUI struct ContentView: View { var body: some View { VStack(spacing: 16) { Text("Hello, world!") Text("Goodbye, world!") } } }
Preview
今回は日本語ローカルでローカライズが反映されるか確認したいので、Locale(identifier: "ja")
に設定しています。
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .environment(\.locale, Locale(identifier: "ja")) } }
出力結果
Localizable.strings
にキーが存在するものはその値が表示され、そうではない場合にはそのままの文字列が表示されました!
引数で渡されたStringからはローカライズしてくれない
String型としてText
に設定する値を受け取るカスタムViewを作成して検証してみます。
CustomText
struct CustomText: View { let text: String var body: some View { Text(text) } }
ContentView
import SwiftUI struct ContentView: View { var body: some View { CustomText(text: "Hello, world!") } }
出力結果
Localizable.strings
に該当するキーがあるはずなのに、Hello, world!
という文字列がそのまま表示されています。
解決策
Apple 公式ドキュメント Textに下記の記載がありました。
変数値でText viewを初期化する場合、Viewは文字列をローカライズしないinit()になります。ただし、最初にLocalizedStringKeyインスタンスを作成することでローカライズをリクエストできます。これにより、代わりにinit(_:tableName:bundle:comment:)がトリガーされます。
// 文字列変数をローカライズしない... Text(writingImplement) // ローカライズされた文字列キーに明示的に変換すると、ローカライズされます Text(LocalizedStringKey(writingImplement))
ということで、変数(定数) :String
を渡す際には、LocalizedStringKey
に変換する必要があるようです。
TextにLocalizedStringKeyを渡す
作成したCustomText
のText
に渡す値をLocalizedStringKey
に変更しました。
struct CustomText: View { let text: String var body: some View { Text(LocalizedStringKey(text)) } }
出力結果
実際にビルドをしてみると、無事にローカライズされたものが表示されました。
おわりに
普段は何も言わなくても自分で気づいて良い感じに振る舞ってくれるテキストくん。そんなテキストくんに甘えていたようです。当たり前だった日常が当たり前ではなくなった時に初めてTextくんへの感謝の気持ちが溢れました。
いつもありがとうテキストくん。