2010-05-15 148 views
7

我有一個本地化的字符串需要採取一些變量。但是,在本地化中,重要的是變量的順序可以從語言變爲語言。如何創建格式化的本地化字符串?

因此,這不是一個好主意:

NSString *text = NSLocalizedString(@"My birthday is at %@ %@ in %@", nil); 

在某些語言中一些詞語來在別人面前,而在其他的反向。我目前缺乏一個很好的例子。

我該如何在格式化字符串中提供NAMED變量?有沒有辦法做到這一點,沒有一些重自制的字符串替換?甚至像{%@ 1},{%@ 2}等一些編號變量就足夠了......是否有解決方案?

回答

12

這就是爲什麼NSLocalizedString有兩個參數。使用第二個參數來包含描述變量本地語言含義的註釋。然後,翻譯人員可以使用$ +編號構造對其進行重新排序。請參閱Apple的Notes for Localizers

但是,您不能跳過一種語言的參數。例如,如果您有3個英文參數和4個法文參數,並且您不需要英文第三個參數,則不能像%[email protected] %[email protected] and %[email protected]那樣格式化。你只能跳過最後一個。

3

我在幾個星期後通過構建我自己的簡單模板系統NSScanner解決了這個問題。該方法使用模板系統來查找語法爲${name}的變量。變量通過NSDictionary提供給方法。

- (NSString *)localizedStringFromTemplateString:(NSString *)string variables:(NSDictionary *)variables { 
    NSMutableString *result = [NSMutableString string]; 
    // Create scanner with the localized string 
    NSScanner *scanner = [[NSScanner alloc] initWithString:NSLocalizedString(string, nil)]; 
    [scanner setCharactersToBeSkipped:nil]; 

    NSString *output; 

    while (![scanner isAtEnd]) { 
     output = NULL; 
     // Find ${variable} templates 
     if ([scanner scanUpToString:@"${" intoString:&output]) { 
      [result appendString:output]; 

      // Skip syntax 
      [scanner scanString:@"${" intoString:NULL]; 

      output = NULL; 

      if ([scanner scanUpToString:@"}" intoString:&output]) { 
       id variable = nil; 
       // Check for the variable 
       if ((variable = [variables objectForKey:output])) { 
        if ([variable isKindOfClass:[NSString class]]) { 
         // NSString, append 
         [result appendString:variable]; 
        } else if ([variable respondsToSelector:@selector(description)]) { 
         // Not a NSString, but can handle description, append 
         [result appendString:[variable description]]; 
        } 
       } else { 
        // Not found, localize the template key and append 
        [result appendString:NSLocalizedString(output, nil)]; 
       } 
       // Skip syntax 
       [scanner scanString:@"}" intoString:NULL]; 
      } 
     } 
    } 

    [scanner release]; 

    return result; 
} 

憑藉本地化文件看起來像這樣:

"born message" = "I was born in ${birthYear} on a ${birthWeekDay}. ${byebye}"; 
"byebye"  = "Cheers!"; 

我們可以實現以下結果...

NSDictionary *variables = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1986], @"birthYear", @"monday", @"birthWeekDay", nil]; 
NSString *finalString [self localizedStringFromTemplateString:@"born message" variables:variables]; 
NSLog(@"%@", finalString); // "I was born in 1986 on a monday. Cheers!" 

正如你所看到的,我已經添加了一些額外的功能太。首先,找不到任何變量(我的例子中的${byebye})將被本地化並附加到結果中。我這樣做是因爲我從我的應用程序包加載HTML文件,並通過localize方法運行它們(當這樣做時,我不會在創建掃描儀時本地化輸入字符串)。此外,我增加了發送其他內容的能力,而不僅僅是NSString對象,因爲它具有一些額外的靈活性。

這個代碼也許不是最好的表演或漂亮編寫的,但它的工作沒有任何明顯的性能影響:)

10

格式化的本地化字符串例如:

NSString *today = [MyHandWatch today]; 
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Today is %@", @""), today]; 

genstrings將產生在Localizable.strings文件中這一行:

"Today is %@" = "Today is %@"; 
+0

它根本不起作用,它returnes相同的字符串 – user2159978 2014-03-20 11:21:43

+0

@ user2159978難道你真的只是複製最後一行? OF COURSE它會返回相同的字符串... – 2016-02-03 14:37:08