Blog

Unser Know-How teilen wir gerne...
Home/Blog/Softwareentwicklung/Swift 3: NSAttributedString – Mehrsprachigkeit/Übersetzen

Swift 3: NSAttributedString – Mehrsprachigkeit/Übersetzen

  • 27.11.2017

Wer mit XCode einen Attributed String übersetzen will, hat es nicht leicht.
Normale Strings lassen sich mit NSLocalizedString(key:comment) übersetzen.

Bei Attributed Strings gibt es aber ein Problem. Die Attribute müssen im String an
die richtige Stelle gesetzt werden und je nach Sprache kann das stark
variieren.

Einen Ansatz, den ich gefunden habe und welcher mich schlußendlich zu meiner Lösung
inspiriert hat, war das Anlegen einer RTF (Rich Text Format) Datei.
In dieser wurde der Text/String gestaltet und lokalisiert (im Utility Bereich).

Mit der Funktion NSAttributedString.init(url:options:documentAttributes)
habe ich versucht den Inhalt der RTF Datei zu laden. Leider ist es mir nicht gelungen
den Inhalt zu laden, obwohl die RTF Datei innerhalb des Bundles war.

Als Nächstes fand ich heraus, dass das Ganze auch mit HTML Dateien
funktioniert. Ich bin prinzipiell nach dem gleichen Schema wie mit RTF
Dateien vorgegangen. Und diesemal hat es geklappt.

Jedoch finde ich es entwas umständlich für jede Übersetzung eine eigene
HTML Datei anzulegen und da HTML in Gegensatz zu RTF eine Markup-Sprache
ist, war die Konsequenz, dass ich versucht habe die normalen Sprachdateien
um HTML Inhalte zu erweitern und daraus den Attributed String zu gewinnen.

Hierzu ein Beispiel:

"BUTTON_TERMS_OF_USE" = "
Hallo %1$@, durch die Registrierung akzeptierst du unsere
<u>Nutzerbedingungen&gt;</u>.";

Für die Übersetzung nutze ich selbst eine String Extension:

extension String {
  var localized: String {
    return NSLocalizedString(self, comment: "")
  }
}

Dies kann man einfach so nutzen: “BUTTON_TERMS_OF_USE”.localized.
Hat man auch noch Platzhalter im Text, kann man das auch wieder mit
einer String Extension lösen:

extension String {
  func formatted(_ arguments: CVarArg...) -&gt; String {
    return String(format: self, locale: Locale.current, arguments: arguments)
  }
}

Das würde dann jetzt so aussehen: “BUTTON_TERMS_OF_USE”.localized.formatted(“Franz”)

Jetzt zum Attributed String selbst:

extension String {
  var attributed: NSAttributedString {
    do {
      return try NSAttributedString.init(
        data: self.data(using: String.Encoding.utf8)!,
        options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue],
        documentAttributes: nil )
    } catch {
      return NSAttributedString.init(string: self)
    }
  }
}

Um diesen mittels HTML String korrekt zu übersetzen:
“BUTTON_TERMS_OF_USE”.localized.formatted(“Franz”).attributed

Hat man nun öfters Strings zu übersetzen und will nicht die Storyboard-eigene Übersetzung verwenden
oder man verwendet Attributed Strings, dann kann man View-Klassen erweitern:

class LocalizedButton : UIButton {
  @IBInspectable var localizedTitle : String = "" {
      didSet {
          self.setTitle(localizedTitle.localized, for: .normal)
      }
  }
  @IBInspectable var attributedTitle : String = "" {
      didSet {
          self.setAttributedTitle(attributedTitle.localized.attributed, for: .normal)
      }
  }
}

Jetzt kann man über den Utility-Editor die Übersetzungs-ID eingeben. Hat man Platzhalter im Text, muss die Übersetzung im Swiftcode selber stattfinden.

Leidenschaftlicher ITholicer und passionierter Informatiker mit Schwerpunkt Web-Programmierung.