翻译属性字符串

时间:2014-04-04 06:14:05

标签: ios xcode localization nsattributedstring nslocalizedstring

我有一个带有属性字符串的UILabel。这是它的打印屏幕:

enter image description here

现在,我必须将此属性字符串翻译为英语和意大利语。 我正在寻找一种方法来做到这一点。我可以逐个代码地在代码中构建这个属性字符串吗?我只找到了一个解决方案,其中设置了整个字符串,然后通过范围设置属性。但是当我翻译字符串时,我不再知道范围,因为这些字词更长或更小。

5 个答案:

答案 0 :(得分:6)

另一种选择是创建本地化的.rtf文件,从中创建NSAttributedStrings

NSAttributedString *attributedStr = [[NSAttributedString alloc] initWithData:data options:@{NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType} documentAttributes:nil error:nil];

要使用动态格式设置(例如设置颜色,特定于某些应用设置的字体),我使用一些类似html的格式,使用1-char标签,然后我会在应用内部应用格式。

// 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];
    }
}

之后可以像这样使用该方法:

NSDictionary* highlightAttributes = @{NSForegroundColorAttributeName: [UIColor blueColor],
                                 NSFontAttributeName: [UIFont boldSystemFontOfSize:16]};
NSDictionary *xmlTagsAttributes = @{@"b": highlightAttributes};
[attrStr formatCharXMLTagsUsingAttributes:xmlTagsAttributes];

attrStr可能是@"Press <b>Next</b> button to ..."

答案 1 :(得分:2)

像这种方法可以起作用。它需要NSAttributedString,根据属性提取部分,翻译每个部分,应用相同的属性,最后返回完整的翻译属性字符串。

-(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;
}

答案 2 :(得分:1)

您可以利用可以从HTML数据构造属性字符串的事实。因此,将带有嵌入式HTML属性的字符串写在Localized.string中:

MY_STRING = "some <b>bold</b> string";

然后您可以像这样检索它

    let htmlTitle = NSLocalizedString("MY_STRING", comment: "")
    let data = htmlTitle.data(using: .utf8)!
    let attributedTitle = NSAttributedString(html: data, options:[:], documentAttributes: nil)
    myLabel.attributedText = attributedTitle!

请注意,您将需要对属性做更多的工作来设置正确的字体,因为它将使用默认字体显示html(Helvetica吗?)。

答案 3 :(得分:0)

我会通过翻译字符串的各个部分来解决这个问题。这将适用于这种情况,因为您的属性字符串确实是四个字符串的连接版本。

但请确保保存使用数字的格式。在某些语言中,文本可能是“3 Erweiterung”。您可以使用NSLocalizedStringWithDefaultValue执行此操作。

NSString *stepFormat = NSLocalizedStringWithDefaultValue(@"AttributedStringStepFormat", @"main", [NSBundle mainBundle], @"Step %ld", @"'Step 4' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft'");
NSString *step = [NSString stringWithFormat:stepFormat, (long)4];

NSString *erweiterungFormat = NSLocalizedStringWithDefaultValue(@"AttributedStringErweiterungFormat", @"main", [NSBundle mainBundle], @"Erweiterung %ld", @"'Erweiterung 3' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft'");
NSString *erweiterung = [NSString stringWithFormat:erweiterungFormat, (long)3];

NSString *erhalten = NSLocalizedStringWithDefaultValue(@"AttributedStringErhalten", @"main", [NSBundle mainBundle], @"erhalten", @"'erhalten' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft'");
NSString *dauerhaft = NSLocalizedStringWithDefaultValue(@"AttributedStringDauerhaft", @"main", [NSBundle mainBundle], @"dauerhaft", @"'dauerhaft' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft'");

NSString *result = [NSString stringWithFormat:@"%@ - %@ - %@\n%@", step, erweiterung, erhalten, dauerhaft];

NSRange stepRange = [result rangeOfString:step];
NSRange erweiterungRange = [result rangeOfString:erweiterung];
NSRange erhaltenRange = [result rangeOfString:erhalten];
NSRange dauerhaftRange = [result rangeOfString:dauerhaft];

// Create attributed string

通过这种方式,您可以获得可用于翻译的精美字符串文件:

/* 'dauerhaft' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft' */
"AttributedStringDauerhaft" = "dauerhaft";

/* 'erhalten' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft' */
"AttributedStringErhalten" = "erhalten";

/* 'Erweiterung 3' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft' */
"AttributedStringErweiterungFormat" = "Erweiterung %ld";

/* 'Step 4' in 'Step 4 - Erweiterung 3 - erhalten\ndauerhaft' */
"AttributedStringStepFormat" = "Step %ld";

答案 4 :(得分:0)

我通常会单独翻译突出显示的部分,并在原始文本中添加独特的占位符,以便于查找和替换。

示例:&#34;此为粗体&#34;

在localized.strings中,它将是
&#34; BaseText&#34; =&#34;这个-Word-是粗体&#34;;
&#34; HighlightedText&#34; =&#34;字&#34 ;;

现在我们可以使用&#34; BaseText&#34;键和:
1.找到&#34; -Word - &#34;的范围。子
2.将其替换为带有&#34; HighlightedText&#34;的本地化字符串。键。
3.使用原始占位符的范围,原始占位符的长度和翻译长度,您可以轻松计算新范围并应用特定属性。

这种方法比连接更灵活,不依赖于翻译中的单词顺序。

这是它的延伸:

extension NSMutableAttributedString {
    func replacePlaceholder(_ placeholder: String, with translation: String, attributes: [String: Any]) {

        // find the placeholder
        var range = (string as NSString).range(of: placeholder)

        // nothing to replace
        if range.location == NSNotFound {
            return
        }

        // replace it with the translation
        mutableString.replaceCharacters(in: range, with: translation)

        // adjust range according to changes
        range.length = range.length + translation.length - placeholder.length

        // apply attributes
        self.setAttributes(attributes, range: range)
    }
}

如果需要,您可以一个接一个地替换多个占位符。