2014-04-04 26 views
11

Ho un UILabel con una stringa attribuita. Ecco una printscreen di esso:Traduci stringa attribuita

enter image description here

Ora, devo tradurre questo attribuito stringa in inglese e italiano. Sto cercando un modo per farlo. Posso costruire questa stringa attribuita nel codice parte per parte? Ho trovato solo una soluzione in cui è impostata l'intera stringa e quindi gli attributi sono impostati per intervallo. Ma quando traduco la stringa, non conosco più l'intervallo, perché le parole sono più lunghe o più piccole.

+0

Provare a utilizzare il metodo NSAttributedString 'enumerateAttributesInRange: options: usingBlock:'. Questo restituisce ogni attributo con il suo intervallo. Puoi estrarre la stringa da quell'intervallo parte per parte e tradurla. – ZeMoon

risposta

6

Un'altra opzione è quella di creare file localizzati rtf da cui creare NSAttributedStrings:

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

Per utilizzare la formattazione dinamica (ad esempio impostare i colori, caratteri specifiche di alcune impostazioni di app), sto usando alcune formattazioni html, con tag 1-char per i quali successivamente applicherò il formato all'interno dell'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]; 
    } 
} 

Il metodo potrebbe poi essere usato così:

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

Dove attrStr possono essere @"Press <b>Next</b> button to ...".

0

Risolverei questo traducendo le singole parti della stringa. Questo funzionerà in questo caso perché la stringa attribuita è in realtà una versione concatenata di quattro stringhe.

Ma assicurati di salvare il formato in cui usi i numeri. In alcune lingue il testo potrebbe essere "3   Erweiterung". È possibile farlo utilizzando 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 

In questo modo si ottiene una bella stringhe di file è possibile utilizzare da tradurre:

/* '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

Non penso che funzioni per l'arabo, però. – OlivaresF

+1

Cosa funziona per l'arabo quando si tratta di localizzazione? :) – Lope

+1

@Lope Tutto funziona con la localizzazione, se sai come farlo. :) Per un antipasto: https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html – Manuel

2

Qualcosa di simile a questo metodo potrebbe funzionare. Prende una stringa NSAttributo, estrae parti in base ai loro attributi, traduce ogni parte, applica gli stessi attributi e infine restituisce la stringa attribuita tradotta completa.

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

Traduco solitamente parti evidenziate separatamente e aggiungo segnaposti unici al testo originale che è facile da trovare e sostituire.

Esempio: "Questo parola grassetto"

In localized.strings sarà
"BaseText" = "Questo -testo- è grassetto";
"HighlightedText" = "word";

Ora siamo in grado di prendere la stringa originale con il tasto "BaseText" e:
1. Trovare la gamma di "-testo-" stringa
2. Sostituirlo con stringa localizzata con il tasto "HighlightedText".
3. Utilizzando l'intervallo del segnaposto originale, la lunghezza del segnaposto originale e la lunghezza della traduzione, è possibile calcolare facilmente un nuovo intervallo e applicare ad esso attributi specifici.

Questo approccio è più flessibile della concatenazione e non dipende dall'ordine delle parole in una traduzione.

Si tratta di un'estensione per esso:

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

È possibile sostituire diversi segnaposti uno dopo l'altro, se necessario.