你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> IOS本地化應用程序

IOS本地化應用程序

編輯:IOS開發綜合

BK項目已經完成得七七八八了,在項目的後期需要將其翻譯成多國語言版本,以適應全球多個國家多個店面的使用。

應用本地化是分別對字符串、圖片和 xib 或 storyboard 文件本地化,而傳統的做法是對 xib 上的字符串(包括UILabel和UIButton、UITextField等)關聯一個變量,通過NSLocalizedString這個函數去查找 Localizeable .strings 文件中的key值進行本地化操作,或者是生成同一個xib文件的不同語言版本,如 MainVC.xib(German) 和 MainVC.xib(English),但這樣做未免過於繁雜,像人們常說的 tedious and useless.

\

還是先介紹一下本地化的一般流程:

\

(1)偽本地化 偽本地化是將字符串本地化為無意義語言的過程。即將需要翻譯的字符串替換成其他假設已經是翻譯過的“譯文”,可以用谷歌翻譯替換一下或者是將所有元音字母替換成x,例如:“Press here to continue” 會變成 “Prxss hxrx tx cxntxnxx”。這樣做的目的是為了盡早發現問題。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PHN0cm9uZz6jqDKjqbazveFVSTwvc3Ryb25nPgogINTa06bTw7+qt6K1xNbcxtrW0LHY0OvSqtPQ0ru49sP3yLe1xMqxvOS148C0trO94VVJoaPU2rTL1q6689KqvOG+9rbFvvi74dOwz+yxvrXYu6+1xNfK1LSx5Lj8o6xuaWIgzsS8/r/J0tTU2lhDb2Rl1tDL+Laoo6zS1LfA1rnQ3rjEv8mxvrXYu6+1xMr00NShorK7v8mxvrXYu6+1xMr00NS78tXfysfL+dPQyvTQ1KOsyOfNvMv5yr6jrMi7uvO9q9Do0qq3rdLrtcTOxLG+t6K4+Let0uvIy9Sxu/LV38rHsb612Luvt/7O8czhuanJzMilt63S677N0NDBy6GjPC9wPgo8cD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW1nIHNyYz0="/uploadfile/Collfiles/20140718/2014071809451874.png" alt="\">

(3)本地化 將資源發給本地化服務提供商之後,他們會發回翻譯完成的文件。根據翻譯的文本進行本地化工作。

(4)版本控制 用版本控制系統記錄下你的每一次變更。

(5)測試 不用怎麼說,必須要的步驟。

(6a)合並邏輯變更 邏輯變更一般不會影響到nib文件和本地化的工作,多人協作的項目還是需要合並一些變更的邏輯的。

(6b)本地化變更 如果你做了一些本地化變更,比如改變了已本地化的文本,那麼就需要從頭開始這個過程,並將這些變更發給本地化人員。可以重用之前的字符串翻譯,這麼做會大大提高效率,但仍然很麻煩。所以,應盡量避免在開發後期引入這類變更。

應用本地化的文章之前已經就有很多大牛寫過了,這裡就不在贅述了,直接貼出本人讀過的覺得還不錯的文章:

1、MJ 的應用程序本地化,2013年寫的,對於XCode5,有些操作界面已經不一樣了,但思想是不變的。

2、IOS應用國際化教程(2014版),這個比較新,而且是使用 storyboard 的。

3、RAYWENDERLICH 上的 Internationalization Tutorial for iOS [2014 Edition] 這上面的文章都很不錯,很值得一讀,強烈推薦。

另外,重點是要講我在 github 上找到的一個類,非常棒,優雅的代碼一直感動到我眼淚嘩嘩直流~~\

這是github上的項目地址:HERE ,如果有找到更多更好的優秀代碼,請知會一聲。

就像作者所說的那樣:

\

\

以下是OHAutoNIBi18n.m類,做了一下小修改,在不改變 frame 的情況下,對 UILabel、UIButton、UITextField 的字體大小做了一下自適應。

//
//  OHAutoNIBi18n.m
//
//  Created by Olivier on 03/11/10.
//  Copyright 2010 FoodReporter. All rights reserved.
//

#import 
#import 

static inline NSString* localizedString(NSString* aString);

static inline void localizeUIBarButtonItem(UIBarButtonItem* bbi);
static inline void localizeUIBarItem(UIBarItem* bi);
static inline void localizeUIButton(UIButton* btn);
static inline void localizeUILabel(UILabel* lbl);
static inline void localizeUINavigationItem(UINavigationItem* ni);
static inline void localizeUISearchBar(UISearchBar* sb);
static inline void localizeUISegmentedControl(UISegmentedControl* sc);
static inline void localizeUITextField(UITextField* tf);
static inline void localizeUITextView(UITextView* tv);
static inline void localizeUIViewController(UIViewController* vc);


// ------------------------------------------------------------------------------------------------

@interface NSObject(OHAutoNIBi18n)
-(void)localizeNibObject;
@end


@implementation NSObject(OHAutoNIBi18n)

#define LocalizeIfClass(Cls) if ([self isKindOfClass:[Cls class]]) localize##Cls((Cls*)self)
-(void)localizeNibObject
{
	LocalizeIfClass(UIBarButtonItem);
	else LocalizeIfClass(UIBarItem);
	else LocalizeIfClass(UIButton);
	else LocalizeIfClass(UILabel);
	else LocalizeIfClass(UINavigationItem);
	else LocalizeIfClass(UISearchBar);
	else LocalizeIfClass(UISegmentedControl);
	else LocalizeIfClass(UITextField);
	else LocalizeIfClass(UITextView);
	else LocalizeIfClass(UIViewController);
    
    if (self.isAccessibilityElement == YES)
    {
        self.accessibilityLabel = localizedString(self.accessibilityLabel);
        self.accessibilityHint = localizedString(self.accessibilityHint);
    }
	
    // Call the original awakeFromNib method
	[self localizeNibObject]; // this actually calls the original awakeFromNib (and not localizeNibObject) because we did some method swizzling
}

+(void)load
{
    // Autoload : swizzle -awakeFromNib with -localizeNibObject as soon as the app (and thus this class) is loaded
	Method localizeNibObject = class_getInstanceMethod([NSObject class], @selector(localizeNibObject));
	Method awakeFromNib = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));
	method_exchangeImplementations(awakeFromNib, localizeNibObject);
}

@end

/////////////////////////////////////////////////////////////////////////////

static inline NSString* localizedString(NSString* aString)
{
	if (aString == nil || [aString length] == 0)
		return aString;
    
    // Don't translate strings starting with a digit
	if ([[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[aString characterAtIndex:0]])
		return aString;
	
#if OHAutoNIBi18n_DEBUG
#warning Debug mode for i18n is active
    static NSString* const kNoTranslation = @"$!";
	NSString* tr = [[NSBundle mainBundle] localizedStringForKey:aString value:kNoTranslation table:nil];
	if ([tr isEqualToString:kNoTranslation])
    {
		if ([aString hasPrefix:@"."])
        {
			// strings in XIB starting with '.' are typically used as temporary placeholder for design
            // and will be replaced by code later, so don't warn about them
			return aString;
		}
		NSLog(@"No translation for string '%@'",aString);
		tr = [NSString stringWithFormat:@"$%@$",aString];
	}
	return tr;
#else
	return [[NSBundle mainBundle] localizedStringForKey:aString value:nil table:nil];
#endif
}


// ------------------------------------------------------------------------------------------------


static inline void localizeUIBarButtonItem(UIBarButtonItem* bbi) {
	localizeUIBarItem(bbi); /* inheritence */
	
	NSMutableSet* locTitles = [[NSMutableSet alloc] initWithCapacity:[bbi.possibleTitles count]];
	for(NSString* str in bbi.possibleTitles) {
		[locTitles addObject:localizedString(str)];
	}
	bbi.possibleTitles = [NSSet setWithSet:locTitles];
#if ! __has_feature(objc_arc)
	[locTitles release];
#endif
}

static inline void localizeUIBarItem(UIBarItem* bi) {
	bi.title = localizedString(bi.title);
}

static inline void localizeUIButton(UIButton* btn) {
	NSString* title[4] = {
		[btn titleForState:UIControlStateNormal],
		[btn titleForState:UIControlStateHighlighted],
		[btn titleForState:UIControlStateDisabled],
		[btn titleForState:UIControlStateSelected]
	};
	
    [btn.titleLabel setAdjustsFontSizeToFitWidth:YES];
	[btn setTitle:localizedString(title[0]) forState:UIControlStateNormal];
	if (title[1] == [btn titleForState:UIControlStateHighlighted])
		[btn setTitle:localizedString(title[1]) forState:UIControlStateHighlighted];
	if (title[2] == [btn titleForState:UIControlStateDisabled])
		[btn setTitle:localizedString(title[2]) forState:UIControlStateDisabled];
	if (title[3] == [btn titleForState:UIControlStateSelected])
		[btn setTitle:localizedString(title[3]) forState:UIControlStateSelected];
}

static inline void localizeUILabel(UILabel* lbl) {
    lbl.adjustsFontSizeToFitWidth = YES;
//    lbl.minimumScaleFactor = 6.0f;
	lbl.text = localizedString(lbl.text);
}

static inline void localizeUINavigationItem(UINavigationItem* ni) {
	ni.title = localizedString(ni.title);
	ni.prompt = localizedString(ni.prompt);
}

static inline void localizeUISearchBar(UISearchBar* sb) {
	sb.placeholder = localizedString(sb.placeholder);
	sb.prompt = localizedString(sb.prompt);
	sb.text = localizedString(sb.text);
	
	NSMutableArray* locScopesTitles = [[NSMutableArray alloc] initWithCapacity:[sb.scopeButtonTitles count]];
	for(NSString* str in sb.scopeButtonTitles) {
		[locScopesTitles addObject:localizedString(str)];
	}
	sb.scopeButtonTitles = [NSArray arrayWithArray:locScopesTitles];
#if ! __has_feature(objc_arc)
	[locScopesTitles release];
#endif
}

static inline void localizeUISegmentedControl(UISegmentedControl* sc) {
	NSUInteger n = sc.numberOfSegments;
	for(NSUInteger idx = 0; idx

tips:本地化的時候還需要注意:

1、別忘了從右向左讀的語言。

2、不要隨便假設逗號就是千位分隔符以及句點就是小數點。在不同的語言中可能會有不同。

3、注意數字和日期的格式化(輸入和輸出都需要進行格式化)。

至此,,應用本地化的事兒就簡單多了,剩下的事情就交給翻譯人員去吧~


參考文章:

Apple官方文檔:Localizing your APP

Apple官方文檔:Internationalize Your App

Apple官方文檔: Data Formatting Guide

Apple官方文檔: Internationalization Programming Topics

Apple官方文檔: Internationalization and Localization




  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved