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?

有帮助吗?

解决方案 3

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

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!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top