LoginSignup
6
2

More than 5 years have passed since last update.

[Swift Tips] 複数のLocalizable.stringsにアクセスする

Last updated at Posted at 2019-02-07

環境

  • Xcode 10.1
  • Swift 4.2.1

目的

分割されたEmbedded Framework毎にLocalizable.stringsを持ち、横断的に文字列を取得する。

課題

  • どうやってEmbedded Framework毎にLocalizable.stringsを持つのか?
  • Embedded Framework間で連動するNSLocalizedStringの使い方とは?

どうやってEmbedded Framework毎にLocalizable.stringsを持つのか?

単純に「File」メミューから「File...」を選んで、さらに「Strings File」を選んでプロジェクト(ターゲット)に追加してください。名前はスタンダードな「Localizable.strings」で構いません。
これはEmbedded Frameworkでは名前空間が異なるためです。

スクリーンショット 2019-02-07 9.39.07.png

スクリーンショット 2019-02-07 9.36.18.png

問題は、この新たな「Localizable.strings」をどうやって呼び出すかです。

下記の例ではCommonUtilクラス(クラス名は何でも良い)を、先ほどLocalizable.stringsを作成したEmbedded Framework内に作成します。

Swift

public class CommonUtil
{
    public static let shared = CommonUtil()
    private init(){
        bundle = Bundle(for: type(of: self))
    }
    public let bundle: Bundle
}

上記のコードで、Embedded FrameworkのBundleを取得できるようになります。

そして、Bundleがとファイル名(Localizable.strings)が分かればNSLocalizedString()を使うことができます。

Swift
extension String
{
    public var localized: String
    {
        let bundle = CommonUtil.shared.bundle
        let result = NSLocalizedString(self, tableName: "Localizable", bundle: bundle, value: "", comment: self)
        return result
    }
}

上記のコードは、Stringクラスのextension内でlocalizedプロパティを定義しています。
このlocalizedプロパティは先ほどの CommonUtil.shared.bundle を使ってEmbedded FrameworkのBundleを取得し、Localizable.stringsを指定しています。

Embedded Framework間で連動するNSLocalizedStringの使い方とは?

ところで、NSLocalizedString()は非常に使いにくい関数です。それは、Localizable.stringsにキーがない場合は、キーを返り値として戻してくることです。
例えば、

/* 
  Localizable.strings
*/

"確定" = "確定";
"キャンセル" = "キャンセル";

というようなLocalizable.stringsがあったとして、

Swift
let val = NSLocalizedString("もどる")

とすると、"もどる"が返ってきてしまいます。
つまり、Localizable.stringsにそのキーが無いことが判定できません。

この場合、複数のLocalizable.stringsから単語を検索できなくなり、大変不便です。

そこで、Localizable.stringsにあるルールを付加することでこれを解決します。

/* 
  Localizable.strings
*/

"_確定" = "確定";
"_キャンセル" = "キャンセル";

上記のアンスコは例ですが、取得する単語とキーは一致させない、というルールです。
これによって、

Swift
extension String
{
    public var localized: String
    {
        let result = NSLocalizedString(self, value: "", comment: "")
        if result == self
        {
            // 無かった
        }
        return result
    }
}

というように書くことができます。

結論

まとめると、下記のように書くことで、Mainバンドルに無かったキーを、Embedded FrameworkのLocalizable.stringsから検索して取得することができるようになります。

Swift

import Foundation

extension String
{
    public var localized: String
    {
        let result = NSLocalizedString(self, value: "", comment: "")
        if result == self
        {
            return embedded_localized
        }
        return result
    }

    public var embedded_localized: String
    {
        let bundle = CommonUtil.shared.bundle
        let result = NSLocalizedString(self, tableName: "Localizable", bundle: bundle, value: "", comment: self)
        return result
    }
}

基本的な単語で、どのプロジェクトでも変わらないような物は、こちらに集めることで、少し便利かもしれません。また、Embedded Framework内でLocalizable.stringsを使ってUIViewを表示したりする場合も有効かもしれません。

6
2
0

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
6
2