Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Translate attributed string

I have a UILabel with an attributed string. Here is a printscreen of it:

enter image description here

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.

like image 311
BennoDual Avatar asked Apr 04 '14 06:04

BennoDual


2 Answers

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 ...".

like image 90
alex-i Avatar answered Oct 05 '22 06:10

alex-i


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;
}
like image 36
ZeMoon Avatar answered Oct 05 '22 05:10

ZeMoon