LoginSignup
34
8

More than 1 year has passed since last update.

iOS 15.0+ではNSLocalizedStringよりString(localized:)を使おう(Swift)

Last updated at Posted at 2022-12-05

はじめに

本記事は Swift Advent Calendar 2022 の1日目の記事です。
遅くなりましたが、誰も埋めていなかったので埋めます。

ローカライズの文字列を取得する方法を紹介します。

環境

  • OS:macOS Ventura 13.0.1
  • Xcode:14.1 (14B47b)
  • Swift:5.7.1

今まで: NSLocalizedStringを使う

ローカライズの文字列を取得するとき、今までは NSLocalizedString(_:tableName:bundle:value:comment:) を使っていました。

func NSLocalizedString(
    _ key: String,
    tableName: String? = nil,
    bundle: Bundle = Bundle.main,
    value: String = "",
    comment: String
) -> String

引用: https://developer.apple.com/documentation/foundation/1418095-nslocalizedstring

Swift Packages上にあるSwiftUIのViewから呼び出す場合、以下のように使うことが多いと思います。

FooView.swift
import SwiftUI

struct FooView: View {
  var body: some View {
    Text("Foo")
      .navigationTitle(NSLocalizedString("Foo", bundle: .module, comment: ""))
  }
}

これから: String(localized:)を使う

たまたま apple/sample-food-truckのソースコード を見ていて、 String(localized:table:bundle:locale:comment:) なる String のイニシャライザがあることに気づきました。

init(
    localized keyAndValue: String.LocalizationValue,
    table: String? = nil,
    bundle: Bundle? = nil,
    locale: Locale = .current,
    comment: StaticString? = nil
)

引用: https://developer.apple.com/documentation/swift/string/init(localized:table:bundle:locale:comment:)

iOS 15.0+で使えること以外、公式ドキュメントには説明がありません。「No overview available.」すら書いてありません。

先ほどの NSLocalizedString を使った例を String(localized:) で置き換えてみます。

FooView.swift
import SwiftUI

struct FooView: View {
  var body: some View {
    Text("Foo")
-     .navigationTitle(NSLocalizedString("Foo", bundle: .module, comment: ""))
+     .navigationTitle(String(localized: "Foo", bundle: .module)
  }
}

いろいろ試したところ、iOS 15.0+からはこちらのAPIを使ったほうがいいと判断したので、この記事で紹介することにしました。

String(localized:)のメリット

String(localized:table:bundle:locale:comment:) のメリットを紹介します。

Stringを返すことがわかりやすい

定義を見るとわかりますが、 NSLocalizedString() の実態は String を返す関数です。
String のイニシャライザを使うことで、 String であることがわかりやすくなります。

commentを省略できる

NSLocalizedString では commentString 型なのに対し、 String(localized:) では StaticString? 型と、オプショナル型になっています。
しかもデフォルトで nil が指定されているので、呼び出しを省略できます。

今まで comment: "" と書くことが多かったので、省略できるとスッキリして嬉しいです。

String Interpolationに対応している

「String Interpolation(文字列補間)」とは、文字列リテラル内に埋め込まれたプレースホルダーを、実行時に実際の値へ置き換える処理のことです。

iOSのローカライズでは、以下のようにフォーマット指定子を使って実現できます。

Localizable.strings
"Set %lld" = "%lldセット目";

NSLocalizedString はString Interpolationに対応していないのに対し、 String(localized:) は対応しています。

FooView.swift
import SwiftUI

struct FooView: View {
  var body: some View {
    VStack {
      Text(NSLocalizedString("Set \(Int(3) + 1)", bundle: .module, comment: "")) // "Set 4"
      Text(String(localized: "Set \(Int(3) + 1)", bundle: .module)) // "4セット目"
    }
  }
}

これは String(localized:) に渡すキーの型が String でなく String.LocalizationValue になっているためです。

逆に言うと String を渡せないので、ローカライズしたい文字列がすでに String の場合は、何かしら工夫しないと使えません。

おまけ: Textはもっとスッキリ書ける

TextLocalizedStringKeyBundle の両方を渡せるイニシャライザが用意されているので、上記の記述はもっとスッキリ書けます。
詳細は以下の記事をご参照ください。

おわりに

String(localized:)NSLocalizedString の上位互換と言っても過言ではないので、ぜひ使っていきましょう :relaxed:
逆にデメリットがあればコメントなどで教えていただきたいです。

以上 Swift Advent Calendar 2022 の1日目の記事でした。
明日も私で LocalizedStringKeyの簡単な説明(Swift) です。

参考リンク

34
8
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
8