Xcode
iOS
Swift
swift4

【Swift4】(国際化対応) Int型の数値を各国のフォーマットで文字列に変換する

VASILYさんのブログに素敵な記事が掲載されていましたので、少し自己流にアレンジした実装を紹介したいと思います。
参考にさせていただいたのは、
モダンなSwiftのExtensionについて - Targeted Extensions

新しいアプリを作るときによく使うSwift Extension集
です。ありがとうございます。
自分の経験値では結構難解な実装でした^^;

この二つのブログを読んでいて、こんな実装もありかな、と考えました。

こんな感じで使用します。

        let value: Int = 1_000_000

        print("ja.currency = "+value.ja.currency) // ja.currency = ¥1,000,000
        print("en.currency = "+value.en.currency) // en.currency = $1,000,000.00
        print("ja.decimal = "+value.ja.decimal) // ja.decimal = 1,000,000
        print("en.decimal = "+value.en.decimal) // en.decimal = 1,000,000

この手法を用いることでRxSwiftなどで採用された記述方法(.rx.xxxx)を取り入れることができます。
このメリットはブログにもしっかり書いてありますので気になる方はリンクを辿ってください。

あえてOSの設定に反して貨幣単位などを切り替えることは少ないかもしれませんが、このような書き方もできるということで・・・

ちなみにOS設定の貨幣単位を使う場合は

        let value: Int = 1_000_000
        print("current.currency = "+value.cur.currency)

となります。

実装ですが、
前述のブログにある手法をほぼそのまま用いてます。

下記のプロトコル定義でcur、ja、enなどが定義されていきます。

// プロトコル
protocol LanguageProtocol
{
    associatedtype LanguageType

    var ja: LanguageType { get }
    var en: LanguageType { get }
}

// プロトコル・エクステンション
extension LanguageProtocol
{
    var cur: Language<Self>
    {
        // static let identifier = (Locale.current as NSLocale).object(forKey: .identifier) as? String
        return Language(self, CommonUtil.identifier!)
    }

    var ja: Language<Self>
    {
        return Language(self, "ja_JP")
    }

    var en: Language<Self>
    {
        return Language(self, "en_US")
    }
}

// 言語別のクラス
final class Language<Base>
{
    let base: Base
    let identifier: String
    init(_ base: Base, _ identifier: String)
    {
        self.base = base
        self.identifier = identifier
    }
}

CommonUtil.identifierはコメントにあるように

static let identifier = (Locale.current as NSLocale).object(forKey: .identifier) as? String

を実装しておきます。

詳細はここでは書きませんが、Base型に対してLanguage型のcur、ja、enの変数をもたせています。Base型をInt型にすると、Int型にcur、ja、enを持たせることができます。

Int型に上記のプロトコルを適用します。

extension Int: LanguageProtocol { }

関数を実装します。

private let formatter: NumberFormatter = NumberFormatter()

extension Int
{
    func formattedString(style: NumberFormatter.Style, localeIdentifier: String) -> String
    {
        formatter.numberStyle = style
        formatter.locale = Locale(identifier: localeIdentifier)
        return formatter.string(from: self as NSNumber) ?? ""
    }
}

// 関数の実装
extension Language where Base == Int
{
    // 通貨表示
    var currency: String
    {
        return self.base.formattedString(style: .currency, localeIdentifier: identifier)
    }

    // カンマ区切り表示
    var decimal: String
    {
        return self.base.formattedString(style: .decimal, localeIdentifier: identifier)
    }
}

ほぼパクりです^_^;