Interface BuilderでのiOSアプリケーションの便利なローカライズ





少し前に、GoogleスプレッドシートでAndroidおよびiOSアプリケーションをローカライズするユーティリティであるLocoLaserを使用するための詳細な手順を公​​開しました。 ローカリゼーションのトピックを継続し、iOSアプリケーションにもっと注意を払いたいと思います。 Androidとは異なり、iOS開発では、わずかではあるが不快な瞬間がいくつかあり、それらは全体として、完全に小さな問題につながる可能性があります。



今日、Interface Builderに特別な注意を払いたいと思います。 私たちは皆、それが完璧ではないことを知っています。 しかし、これは私たちが持っている唯一のものであり、私たちはそれに耐えなければなりません。 この記事では、Interface Builderでアプリケーションをローカライズする際に発生する可能性のある主な問題とその対処方法について説明します。



問題の本質



メインマークアップファイルに加えて、ストーリーボードまたはXIBファイルを翻訳すると、リソース文字列を含む追加のファイルが作成されます。 これらのリソースファイルを特別なテーブルにアップロードし、翻訳者に提供するのが一般的です。 問題は、このファイル内の文字列のキーがオブジェクトIDに基づいて構築され、オブジェクトIDが自動的に生成され、それらに影響を与える方法がないことです。 ビューをコピーまたは切り取りしてから貼り付けると、Interface Builderが新しい識別子を生成し、翻訳が失われます。



特定のビューの翻訳を修正できないことがわかりました。 移動しても、翻訳は移動しません。 たとえば、ストーリーボードにViewControllerがあり、それを分離することにします。 新しいXIBファイルを作成し、そこにViewControllerを移動しますが、翻訳は移動しません。 それだけでなく、ビューごとに新しい識別子が作成されるため、行識別子を手動で調整する必要があります。 翻訳をコピーするだけでは機能しません。



また、行識別子に影響を与える機能がないため、複数のプラットフォームで共通の行データベースを一度に使用することはできません。 これにより、異なるプラットフォーム用のリソースファイルを生成するユーティリティを使用できなくなります。



誰でもこの問題をできる限り解決しています。 2年前、モバイル会議で、大手企業の大手iOS開発者の1人に、インターフェイスのローカリゼーションの問題をどのように解決したかを聞いたことを覚えています。 当時、私はiOSを学び始めたばかりでしたが、すでにAndroid分野でかなり豊富な経験があり、比較するものがありました。 正直なところ、私はその答えに驚いた。 ViewControllerで、IBOutletを介して、Labelおよび他のViewへのリンクを受け取り、プログラムで翻訳しました。 コードでは、次のようになります。



class MainViewController: UIViewController { @IBOutlet var labelToTranslate: UILabel! override func viewDidLoad() { super.viewDidLoad() self.labelToTranslate.text = NSLocalizedString("scr_main_txt_example", comment: "Some Example text") ... } ... }
      
      





この場合、すべての行は同じLocalizable.stringsファイルにあります。 現在、同様の方法が最も一般的であり、ほぼ普遍的に使用されています。 それを認めて、それはあまりにもエレガントではないことが判明しました。 ここに属さない冗長なコードでViewControllerを散らかすだけでなく、ビューのコピーや移動の問題を解決できません。 より良いものを見つける時が来ました。



解決策



そして、ここに私があなたに提供できるものがあります。 実際、Interface Builderでは、Viewプロパティで、いわゆる「ユーザー定義のランタイム属性」を登録できます。 それらを使用します。 ただし、最初にUILabelの拡張機能を作成する必要があります。



 extension UILabel { public var lzText : String? { set { if newValue != nil { self.text = NSLocalizedString(newValue, comment: “”) } else { self.text = nil } } get { return self.text } } }
      
      





現在、すべてのUILabelにはlzTextプロパティがあり、変更されると、ローカライズされた文字列がtextプロパティに書き込まれます。 Interface Builderでこのプロパティを使用します。





  1. UILabelを選択して、「Identity Inspector」タブに移動します。
  2. ボタンをクリックして、「ユーザー定義のランタイム属性」に属性を追加します。
  3. 属性キー「lzText」、タイプ:「String」、値:「scr_main_txt_example」を指定します


そしてそれだけです。 余分なコードでコードが乱雑になることはもうありません。 別のコンテナにコピーまたは移動すると、ビューへの翻訳またはリンクが失われることを恐れることはできません。 属性はビューとともにコピーされます。 測定されない唯一のことは、すべての行を1つのLocalized.stringsファイルに保存することです。



UPD:

しかし、それだけではありません。 DjPhoeniXはさらに改善することを提案しました。 そして、ほとんど何も変更する必要はありません。 プロパティを宣言する前に@IBInspectable



を追加するだけです。

変更されたExtensions.swift
 extension UILabel { @IBInspectable public var lzText : String? { set { if newValue != nil { self.text = NSLocalizedString(newValue, comment: “”) } else { self.text = nil } } get { return self.text } } }
      
      







このプロパティは、[属性インスペクター]タブでも使用できるようになりました。







さらに便利なように、頻繁に使用されるビューに十分な数の拡張子を含むファイルを用意しました。各テキストプロパティには、接頭辞「lz」(「localized」の略)が付いたdoubleがあります。 このファイルは、LocoLaser: LocalizationExtensions.swiftを使用した例で見つけることができます。 プロジェクト全体はApache 2.0ライセンスの下で公開されています。このファイルを自分自身に安全にコピーして使用を開始できます。



Viewの拡張機能に加えて、LocalizationExtensions.swiftのStringクラスに拡張機能が追加されました。 ローカライズされた文字列を返す、計算されたローカライズされたプロパティを追加します。 翻訳が見つからない場合、NotificationCenterを介してアラートが送信されます。 これらのアラートをサブスクライブし、必要に応じて処理できます。 デバッグビルドでは、ログに書き込むか通知を表示できます。リリースビルドでは、レポートを分析システムに送信します。



その結果、上記のメソッドを適用した後、文字列のすべての作業はInterface Builderに残ります。 さらに、「壊れた」行をキャッチするための追加のメカニズムを取得します。



これで終わります。 ご清聴ありがとうございました。 健康のために使用してください!



All Articles