Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there approaches for using attributed strings in combination with localization?

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?

like image 647
Gruntcakes Avatar asked Mar 13 '14 18:03

Gruntcakes


4 Answers

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)
    }
}
like image 106
protspace Avatar answered Sep 30 '22 19:09

protspace


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!

like image 24
Harry Bloom Avatar answered Sep 30 '22 20:09

Harry Bloom


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.

like image 40
Léo Natan Avatar answered Sep 30 '22 20:09

Léo Natan


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…)

like image 44
BenRW Avatar answered Sep 30 '22 20:09

BenRW