Suppose there is this string in English and its a requirement to bold or color etc. to a particular part of a string of text:
"word1 word2 WORD3 word4"
That can be accomplished by setting the attribute for the appropriate range.
The range could be hardcoded to (13,5) but then of course that wouldn't be localizable.
So alternatively the range could be dynamically determined by knowing that its the 3rd word that has to have the bold applied to it.
But that too isn't localizable. Suppose once that sentence is translated to language N it only contains 2 words, or contains 5 words in language M?
So my question is how can you use attributes strings in combination with localization without lots of hardcoding?
Harry's answer for Swift 4
extension NSAttributedString {
convenience init?(withLocalizedHTMLString: String) {
guard let stringData = withLocalizedHTMLString.data(using: String.Encoding.utf8) else {
return nil
}
let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html as Any,
NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue
]
try? self.init(data: stringData, options: options, documentAttributes: nil)
}
}
Taken from Bens answer, I created an extension to help me do this in Swift.
extension NSAttributedString {
convenience init?(withLocalizedHTMLString: String) {
guard let stringData = withLocalizedHTMLString.data(using: String.Encoding.utf8) else {
return nil
}
let options: [String : Any] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType as AnyObject,
NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue
]
try? self.init(data: stringData, options: options, documentAttributes: nil)
}
}
Use this initialiser with your HTML tagged string e.g:
NSAttributedString(withLocalizedHTMLString: NSLocalizedString("By signing up, you agree to our <u><b>Terms & Privacy Policy</b></u>", comment: "terms and conditions"))
and it should do all of the work for you!
You could use some notation to signify which words should be bolded, and then have a transformer that would find ranges to bold and add appropriate attributes.
word •word• word word
מילה מילה •מילה• מילה מילה
In these two sentences, I use the character •
to signify that the word in between should be bold. I can then use rangeOfString:options:range:
to iterate and find all ranges to bold and insert an attribute accordingly.
The approach I'm taking with my latest project is to use HTML in the Localizable.strings
file, and then use something like this to generate the NSAttributedString
:
NSString *htmlString = NSLocalizedString(key, comment);
[[NSAttributedString alloc] initWithData:
[htmlString dataUsingEncoding:NSUTF8StringEncoding]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
documentAttributes:nil
error:nil]]
(As a personal preference, I wrap this all up into a #define LocalizedHTMLForKey(key)
, so hopefully I've not added any typos into this answer by making it legible…)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With