2014-04-04 39 views
11

Mam UILabel z przypisanym ciągiem znaków. Oto PrintScreen go:Tłumaczenie przypisanego ciągu znaków

enter image description here

Teraz muszę tłumaczyć to przypisać ciąg angielski i włoski. Szukam sposobu na zrobienie tego. Czy mogę utworzyć ten przypisany ciąg w kodzie części po części? Znalazłem tylko rozwiązanie, w którym ustawiony jest cały ciąg znaków, a następnie atrybuty są ustawione według zakresu. Ale kiedy tłumaczę ciąg, już nie znam zakresu, ponieważ słowa są dłuższe lub mniejsze.

+0

Spróbuj użyć metody NSAttributedString 'enumerateAttributesInRange: options: usingBlock:'. Zwraca każdy atrybut z jego zakresem. Możesz wyodrębnić ciąg z tego zakresu części po części i przetłumaczyć go. – ZeMoon

Odpowiedz

6

Inną opcją jest stworzenie zlokalizowanych rtf plików, z którego można tworzyć NSAttributedStrings:

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

Aby skorzystać z dynamicznego formatowania (np ustawić kolory, czcionki specyficzne dla niektórych ustawieniach aplikacji), używam trochę formatowania podobnego do html, z tagami 1-char, dla których potem zastosuję format z wnętrza aplikacji.

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

Metoda może być potem wykorzystywane tak:

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

Gdzie attrStr może być @"Press <b>Next</b> button to ...".

0

Rozwiązałbym to przez tłumaczenie poszczególnych części napisu. To zadziała w tym przypadku, ponieważ twój przypisany ciąg naprawdę jest połączoną wersją czterech ciągów znaków.

Ale upewnij się, że zapisałeś format, w którym używasz liczb. W niektórych językach tekst może brzmieć "3   Erweiterung". Możesz to zrobić, używając 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 

W ten sposób można uzyskać ładne ciągi pliku można użyć do przetłumaczenia:

/* '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"; 
+0

Nie sądzę, że to działa na arabski. – OlivaresF

+1

Co działa dla arabskiego, jeśli chodzi o lokalizację? :) – Lope

+1

@Lope Wszystko działa z lokalizacją, jeśli wiesz jak to zrobić. :) Na początek: https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html – Manuel

2

Coś w tej metodzie może pracować. Wymaga NSAttributedString, wyodrębnia części na podstawie ich atrybutów, tłumaczy każdą część, stosuje te same atrybuty i ostatecznie zwraca kompletny przetłumaczony łańcuch atrybutu.

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

Zazwyczaj tłumaczy osobno wyróżnione części i dodaje unikalne elementy zastępcze do oryginalnego tekstu, który można łatwo znaleźć i zamienić.

Przykład „tego słowa pogrubienie”

W localized.strings będzie
„BaseText” = „ten -Word- pogrubienie”;
"HighlightedText" = "word";

Teraz możemy wziąć oryginalny łańcuch z kluczem „BaseText” oraz:
1. Znajdź wachlarz „-Word-” podciągu
2. Wymień go zlokalizowanego łańcucha z kluczem „PodświetlonyTekst”.
3. Korzystając z oryginalnego zakresu zastępczego, oryginalnej długości zastępczej i długości tłumaczenia, można łatwo obliczyć nowy zakres i zastosować do niego określone atrybuty.

To podejście jest bardziej elastyczne niż konkatenacja i nie zależy od kolejności słów w tłumaczeniu.

Jest to rozszerzenie do niego:

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

Można wymienić kilka elementów zastępczych jeden po drugim razie potrzeby.