はじめに
SwiftUI で多言語対応をする際、以下のように表示したいとします
英語
Apples are 1,000 yen each.
日本語
りんごは一つ1,000円です
金額が固定であれば View 側で LocalizedStringKey を指定し、 各Stringsファイルに対応する文言を書いておけば問題ありません
Swift
Text("apple")
英語
"apple" = "Apples are 1,000 yen each.";
日本語
"apple" = "りんごは一つ1,000円です";
しかし、実際には金額が変動する場合、どうすべきでしょうか
文字列
まず先に、変数が文字列の場合を見てみましょう
英語
Hello World!!
日本語
こんにちは世界!!
let target = "World"
とすると、例えばこのようになります
-
Swift
Text("hello\(target)")
-
英語
"hello%@" = "Hello %@!!";
-
日本語
"hello%@" = "こんにちは%@!!";
プレビュー結果(多言語プレビューモジュールを使用)
Strings ファイルの方で %@
としていた部分に \(target)
とすることで、変数が展開されました
ただし、当然この方法では World
は翻訳されません
翻訳したければ、 World
の方も Strings ファイルに定義しておかねばなりません
また、 NSLocalizedString
で先に翻訳してから埋め込むことになります
-
Swift
Text("hello\(NSLocalizedString(target, comment: ""))")
-
英語
"hello%@" = "Hello %@!!"; "world" = "World";
-
日本語
"hello%@" = "こんにちは%@!!"; "world" = "世界";
ただし、 NSLocalizedString
の引数に変数を渡す行為は swiftlint にエラーを出されるため、おすすめできません
TestView.swift:8:45: error: NSLocalizedString Key Violation: Static strings should be used as key/comment in NSLocalizedString in order for genstrings to work. (nslocalizedstring_key)
また、実機で動かしたときは問題ありませんが、プレビュー上は日本語の方も こんにちはWorld!!
になってしまいます
以下のようにすれば、あまりキレイではありませんが、 swiftlint もエラーにならず、プレビューも機能します
-
Swift
Text("hello") + Text(LocalizedStringKey(target)) + Text("!!")
-
英語
"hello" = "Hello "; "world" = "World";
-
日本語
"hello" = "こんにちは"; "world" = "世界";
整数
整数の場合、文字列と同じようにしてもうまくいきません
-
Swift
Text("price\(price)")
-
英語
"price%@" = "Apples are %@ yen each.";
-
日本語
"price%@" = "りんごは一つ%@円です";
これだと翻訳されないまま展開されるだけです
%@
はオブジェクト(文字列含む)を指定するのに使われます
整数の場合は型の桁数に応じて指定が異なります(互換性はありません)
- Int 、 Int64 の場合、
%lld
で指定します - Int8 、 Int16 、 Int32 の場合、
%d
を指定します
したがって、 let price = 1000
というように Int 型を使っている場合は Strings ファイルを以下のように変更します
-
英語
"price%lld" = "Apples are %lld yen each.";
-
日本語
"price%lld" = "りんごは一つ%lld円です";
また、もう一つの方法として、文字列にしておいてから展開する方法もあります
この方法だと %d
でも %lld
でも問題ありません
-
Swift
Text("price\(String(format: "%lld", price))")
-
英語
"price%@" = "Apples are %@ yen each.";
-
日本語
"price%@" = "りんごは一つ%@円です";
ただし、カンマ区切りはしてくれないので、おすすめしません
小数
小数の場合も型の桁数に応じて指定が異なります
また、展開先( Strings ファイルの右辺)で桁数を指定します
- CGFloat 、 Float64 、 Double の場合、
%lf
を指定します - Float 、 Float32 の場合、
%f
を指定します
実装例は以下のようになります
-
Swift
Text("pi\(CGFloat.pi)")
-
英語
"pi%lf" = "Pi: %.2lf";
-
日本語
"pi%lf" = "円周率: %.2lf";
まとめ
Strings ファイル内で以下の指定子を使うことで翻訳しつつ変数を展開することができます
型の桁数で変わることに注意しましょう
型 | 指定子 |
---|---|
String | %@ |
Int | %lld |
Int8 | %d |
Int16 | %d |
Int32 | %d |
Int64 | %lld |
Float | %f |
Float32 | %f |
Float64 | %lf |
CGFloat | %lf |
Double | %lf |