Swift 3: NSAttributedString – localization/translation
- 11.01.2018
If you want to translate an attributed string with XCode, it is not easy.
Normal strings can be translated with NSLocalizedString(key: comment).
However, there is a problem with attributed strings. The attributes must be placed in the correct place in the string and this can vary greatly depending on the language.
One approach I found and which inspired me to my solution was the creation of an RTF (Rich Text Format) file.
The text/string has been designed and localized (in the utility area).
With the function NSAttributedString.init(url: options: documentAttributes) I tried to load the contents of the RTF file. Unfortunately I was not able to load the content, although the RTF file was inside the bundle.
Next I found out that it works with HTML files, too. In principle, I used the same scheme as with RTF files. And this time it worked.
However, I find it difficult to create a separate HTML file for each translation and since HTML is a markup language in contrast to RTF, the consequence was that I tried to extend the normal language files with HTML content and to gain the attributed string from it.
Here is an example:
"BUTTON_TERMS_OF_USE" = "Hello %1$@, by registering you accept our <u>Terms of use> </u>.".; |
For the translation I use a string extension myself:
extension String { var localized: String { return NSLocalizedString(self, comment: "") } } |
This can be used like this: “BUTTON_TERMS_OF_USE”.localized.
If you also have placeholders in the text, you can do this again with
of a string extension:
extension String { func formatted(_ arguments: CVarArg...) -> String { return String(format: self, locale: Locale.current, arguments: arguments) } } |
That would look like this now: “BUTTON_TERMS_OF_USE”.localized.formatted(“Tom”)
Now to the attributed string itself:
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) } } } |
To translate it correctly using HTML string:
“BUTTON_TERMS_OF_USE”.localized.formatted(“Tom”).attributed
If you now have to translate strings more often and don’t want to use the storyboard’s own translation or you use attributed strings, then you can extend view classes:
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) } } } |
Now you can use the utility editor to enter the translation ID. If there are placeholders in the text, the translation must take place in the swiftcode itself.
Leidenschaftlicher ITholicer und passionierter Informatiker mit Schwerpunkt Web-Programmierung.