I have a UILabel with an attributed string. Here is a printscreen of it:
Now, I have to translate this attributed string to english and italian. I am searching for a way to do this. Can I build this attributed string in code part by part? I have only found a solution where the whole string is set and then the attributes are set by range. But when I translate the string, I don't know the range anymore, because the words are longer or smaller.
Another option is to create localized .rtf files from which to create NSAttributedStrings
:
NSAttributedString *attributedStr = [[NSAttributedString alloc] initWithData:data options:@{NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType} documentAttributes:nil error:nil];
To use dynamic formatting (e.g. set colors, fonts specific to some app settings), I'm using some html-like formatting, with 1-char tags for which I afterwards apply the format from inside the app.
// NSMutableAttributedString category method
/**
* Updates the attributes of xml elements (where the xml tags are formed of 1 single char) with the passed attributes from param `tagsAttributes`
* Current version doesn't support recursive tags (tags in tags)
* All tags of form '<char>' or '</char>' will be used as formatting (the resulting string should not be expected to have any tags of this form)
* @param tagsAttributes - list of attribute dictionaries, where the key is the tag name */
-(void)formatCharXMLTagsUsingAttributes:(NSDictionary *)tagsAttributes {
int strippedLength = 0;
NSString *str = [[self string] copy];
NSScanner *scanner = [NSScanner scannerWithString:str];
while (![scanner isAtEnd]) {
NSString *tag = nil;
do {
[scanner scanUpToString:@"<" intoString:nil];
[scanner scanString:@"<" intoString:nil];
if (scanner.scanLocation + 2 < [str length] && [str characterAtIndex:scanner.scanLocation + 1] == '>') {
[scanner scanUpToString:@">" intoString:&tag];
[scanner scanString:@">" intoString:nil];
}
} while (!tag && ![scanner isAtEnd]);
if ([scanner isAtEnd]) {
break;
}
NSString *endTag = [NSString stringWithFormat:@"</%@>", tag];
NSString *tmpString;
[scanner scanUpToString:endTag intoString:&tmpString];
[scanner scanString:endTag intoString:nil];
NSRange range;
strippedLength += 7; // start tag + end tag length
range.location = scanner.scanLocation - [tmpString length] - strippedLength;
range.length = [tmpString length] + 7;
[self replaceCharactersInRange:range withString:tmpString];
range.length -= 7;
[self addAttributes:tagsAttributes[tag] range:range];
}
}
The method could afterwards be used like this:
NSDictionary* highlightAttributes = @{NSForegroundColorAttributeName: [UIColor blueColor],
NSFontAttributeName: [UIFont boldSystemFontOfSize:16]};
NSDictionary *xmlTagsAttributes = @{@"b": highlightAttributes};
[attrStr formatCharXMLTagsUsingAttributes:xmlTagsAttributes];
Where attrStr
may be @"Press <b>Next</b> button to ..."
.
Something like this method could work. It takes an NSAttributedString, extracts parts based on their attributes, translates each part, applies the same attributes and finally returns the complete translated attributed string.
-(NSAttributedString*)translateAttribString:(NSAttributedString*)attribString toLanguage:(NSString*)language
{
NSMutableAttributedString *returnString = [[NSMutableAttributedString alloc]init];
NSRange totalRange = NSMakeRange (0, attribString.length);
[attribString enumerateAttributesInRange: totalRange options: 0 usingBlock: ^(NSDictionary *attributes, NSRange range, BOOL *stop)
{
NSLog (@"range: %@ attributes: %@", NSStringFromRange(range), attributes);
NSString *string = [[attribString string] substringWithRange:range];
NSLog(@"string at range %@", string);
//Translate 'string' based on 'language' here.
NSString *trans; //This will hold the translated string.
NSAttributedString *translatedString = [[NSAttributedString alloc]initWithString:trans attributes:attributes];
[returnString appendAttributedString:translatedString];
}];
return returnString;
}
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