xcode 翻译属性字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22854922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Translate attributed string
提问by BennoDual
I have a UILabel with an attributed string. Here is a printscreen of it:
我有一个带有属性字符串的 UILabel。这是它的打印屏幕:
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.
现在,我必须将这个属性字符串翻译成英语和意大利语。我正在寻找一种方法来做到这一点。我可以部分地在代码中构建这个属性字符串吗?我只找到了一个解决方案,其中设置了整个字符串,然后按范围设置了属性。但是当我翻译字符串时,我不再知道范围,因为单词更长或更小。
采纳答案by alex-i
Another option is to create localized .rtf files from which to create NSAttributedStrings
:
另一种选择是创建本地化的 .rtf 文件,从中创建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.
要使用动态格式(例如设置颜色、特定于某些应用程序设置的字体),我使用了一些类似 html 的格式,带有 1 个字符的标签,然后我从应用程序内部应用格式。
// 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 ..."
.
attrStr
可能在哪里@"Press <b>Next</b> button to ..."
。
回答by ZeMoon
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,根据它们的属性提取部分,翻译每个部分,应用相同的属性,最后返回完整的翻译属性字符串。
-(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;
}
回答by Guillaume Laurent
You can take advantage of the fact that you can construct an attributed string from HTML data. So write your string with embedded HTML attributes in Localized.string :
您可以利用可以从 HTML 数据构造属性字符串这一事实。因此,在 Localized.string 中使用嵌入的 HTML 属性编写字符串:
MY_STRING = "some <b>bold</b> string";
then you can retrieve it like this
然后你可以像这样检索它
let htmlTitle = NSLocalizedString("MY_STRING", comment: "")
let data = htmlTitle.data(using: .utf8)!
let attributedTitle = NSAttributedString(html: data, options:[:], documentAttributes: nil)
myLabel.attributedText = attributedTitle!
Note that you'll have to do a bit more work with the attributes to set the proper font, as it will use the default font for html display (Helvetica ?).
请注意,您必须对属性做更多的工作来设置正确的字体,因为它将使用默认字体进行 html 显示(Helvetica ?)。
回答by Michael Krutoyarskiy
I usually translate highlighted parts separately and add unique placeholders to the original text which is easy to find and replace.
Example for: "This wordis bold"
我通常单独翻译突出显示的部分,并在原始文本中添加独特的占位符,以便于查找和替换。
例如:“这个词是粗体”
In localized.strings it will be
"BaseText" = "This -Word- is bold";
"HighlightedText" = "word";
在 localized.strings 中,它将是
"BaseText" = "This -Word- is bold";
"HighlightedText" = "word";
Now we can take the original string with "BaseText" key and:
1. Find the range of "-Word-" substring
2. Replace it with localized string with "HighlightedText" key.
3. Using the original placeholder's range, original placeholder's length and the translation length you can easily calculate new range and apply specific attributes to it.
现在我们可以使用带有“BaseText”键的原始字符串和:
1. 找到“-Word-”子字符串的范围
2. 用带有“HighlightedText”键的本地化字符串替换它。
3. 使用原始占位符的范围、原始占位符的长度和翻译长度,您可以轻松计算新范围并将特定属性应用于它。
This approach is more flexible than concatenation and does not depend on the words order in a translation.
这种方法比串联更灵活,并且不依赖于翻译中的词序。
This is an extension for it:
这是它的扩展:
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)
}
}
You can replace several placeholders one after another if needed.
如果需要,您可以一个接一个地替换多个占位符。
回答by Matthias Bauch
I would solve this by translating the individual parts of the string. This will work in this case because your attributed string really is a concatenated version of four strings.
我会通过翻译字符串的各个部分来解决这个问题。这将在这种情况下起作用,因为您的属性字符串实际上是四个字符串的串联版本。
But make sure that you save the format where you use numbers. In some language the text might be "3 Erweiterung". You can do this by using NSLocalizedStringWithDefaultValue
.
但请确保保存使用数字的格式。在某些语言中,文本可能是“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
This way you get a nice strings file you can use to translate:
这样你就可以得到一个很好的字符串文件,你可以用它来翻译:
/* '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";