在大多數國家,英語不是母語,當然我們漢語也不是母語。即使在某個國家,有些人使用漢語或英語,最好的方式還是用客戶的母語來展現應用程序。用戶如果選擇漢語,那沒別的了。但如果選擇英語,這時候英語又會有英式英語、美式英語、澳大利亞英語、加拿大英語等,它們各有差異。
IOS提供了一些方法來本地化整個屏幕、一些或全部字符串,甚至只是一幅單獨的圖像。歸因於自動佈局,大多數應用程序可以專注於字符串或更新一些佈局約束。
在接下來的章節裏,我們將嘗試向CarValet應用程序再添加兩種語言,並尋找其中的約束可能需要修改的地方。
正文開始
首先先練練手,在ViewController.m中進行如下修改
- (void)displayCurrentCarInfo {
Car *currentCar;
currentCar = [arrayOfCars objectAtIndex:displayedCarIndex];
self.CarInfoLabel.text = currentCar.carInfo;
[self updateLabel:self.CarNumberLabel withBaseString:NSLocalizedString(@"Car Number",@"Label for the total number of current car")
count:displayedCarIndex +1];
}
- (IBAction)newCar:(id)sender {
Car *newCar = [[Car alloc] init];
[arrayOfCars addObject:newCar];
[self updateLabel:self.totalCarsLabel withBaseString:NSLocalizedString(@"Total Cars", @"Label for the total number of cars")
count:[arrayOfCars count]];
}
在終端中快速打開
然後輸入genstrings -o Base.lproj *.m
會出現Localizable.strings的一個文件,現在把他拉到項目中。如圖(PS 你們的應該是沒有倒三角的,我這是之後添加其他東西的圖)
Localizable.strings文件內容如下:
Localizable.strings文件中的每一條對應一個唯一的用NSlocalizedString定義的字符串。鍵與第一個參數相同,並且註釋也與第二個參數一致。這個文件中有一些結果字符串竟然和鍵相同,這可能看起來很奇怪,但那時因爲這是英語本地化的結果。對於漢語的話,應該是這個樣子的
"Car Number" = "車輛數目";
在這裏我們最好使用描述性的鍵。作如下修改
- (void)displayCurrentCarInfo {
Car *currentCar;
currentCar = [arrayOfCars objectAtIndex:displayedCarIndex];
self.CarInfoLabel.text = currentCar.carInfo;
[self updateLabel:self.CarNumberLabel withBaseString:NSLocalizedStringWithDefaultValue(@"CarNumberLabel",nil,[NSBundle mainBundle],@"Car Number",@"Label for the total number of current car") count:displayedCarIndex +1];
}
- (IBAction)newCar:(id)sender {
Car *newCar = [[Car alloc] init];
[arrayOfCars addObject:newCar];
[self updateLabel:self.totalCarsLabel withBaseString:NSLocalizedStringWithDefaultValue(@"TotalCarsLabel",nil,[NSBundle mainBundle],@"Total Cars",@"Label for the total number of cars") count:[arrayOfCars count]];
}
這時候再genstrings -o Base.lproj *.m
變成下面的圖
可以試着改一下變成"CarNumberLabel" = "Car Numberasdasd"
你會發現在模擬器中他變了。
接下來我們要本地化其他的標籤或按鈕
首先爲New Car按鈕
命名爲addCarButton
使用同樣的方法創建previousCarButton/nextCarButton和editCarButton
完成之後,修改ViewController.m文件中的viewDidLoad方法中的變化
- (void)viewDidLoad {
[super viewDidLoad];
NSString *local;//爲當前的本地化標題設置臨時字符串引用
//將這個臨時字符串設置爲Add Car按鈕的本地化標題
local = NSLocalizedStringWithDefaultValue(@"NewCarButton", nil, [NSBundle mainBundle], @"New Car", @"Button to create and add a new car");
[self.addCarButton setTitle:local forState:UIControlStateNormal];//將Add Car按鈕在默認狀態下的標題設置爲這個本地化字符串
local = NSLocalizedStringWithDefaultValue(@"PreviousCarButton", nil, [NSBundle mainBundle], @"Previous", @"Title for button to go to the previous car");
[self.previousCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"NextCarButton", nil, [NSBundle mainBundle], @"Next", @"Title for button to go to the next car");
[self.nextCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"EditCarButton", nil, [NSBundle mainBundle], @"Edit", @"Title for button to edit the current car");
[self.editCarButton setTitle:local forState:UIControlStateNormal];
arrayOfCars = [[NSMutableArray alloc] init];//初始化汽車的數組爲空數組
displayedCarIndex = 0;//顯示創建的第一輛汽車
[self setupLandscapeConstraints];
UIInterfaceOrientation currOrientation = [[UIApplication sharedApplication]statusBarOrientation];
isShowingPortrait = UIInterfaceOrientationIsPortrait(currOrientation);
}
然後再次genstrings -o Base.lproj *.m
Car對象從carInfo方法返回用於顯示的字符串。該方法目前基於一個簡單的格式字符串,其中的標題、分隔符、類別、佔位符值和年份都是硬編碼值。現在,可以向各市字符串添加元素來進行本地化了。
Car.m文件中新的carInfo:方法
- (NSString *)carInfo {
NSString *infoLabel = NSLocalizedStringWithDefaultValue(@"CarInfoLabel", nil, [NSBundle mainBundle], @"Car Info", @"Label for the information of one car");
NSString *makeLabel = NSLocalizedStringWithDefaultValue(@"CarInfoMakeLabel", nil, [NSBundle mainBundle], @"Make ", @"Make Label for the make of one car");
NSString *modelLabel = NSLocalizedStringWithDefaultValue(@"CarInfoModelLabel", nil, [NSBundle mainBundle], @"Model", @"Model label for the model of one car");
NSString *yearLabel = NSLocalizedStringWithDefaultValue(@"CarInfoYearLabel", nil, [NSBundle mainBundle], @"Year", @"Year label for one car");
NSString *unknownMake = NSLocalizedStringWithDefaultValue(@"UnknownMakePlaceholder", nil, [NSBundle mainBundle], @"Unknown Make", @"Placeholder string for an unknown car make");
NSString *unknownModel = NSLocalizedStringWithDefaultValue(@"UnknownModelPlaceholder", nil, [NSBundle mainBundle], @"Unknown Model", @"Placeholder string for an unknown car model");
return [NSString stringWithFormat:@"%@\n %@: %@\n %@: %@\n %@: %d",
infoLabel,makeLabel,
self.make ? self.make : unknownMake,
modelLabel,
self.model ? self.model : unknownModel,
yearLabel,self.year];
}
再次genstrings -o Base.lproj *.m
最後,我們要爲編輯汽車場景設置本地化:
屬性名稱 | 文本框 |
---|---|
CarMakeFieldLabel | Make文本框旁邊的標籤 |
CarModelFieldLabel | Model文本框旁邊的標籤 |
CarYearFieldLabel | Year文本框旁邊的標籤 |
CarFuelFieldLabel | Fuel文本框旁邊的標籤 |
上表是我們將編輯汽車場景中的四個標籤拉到CarEditViewController.h中的名稱,方法就不再細說了。最後代碼應該如下
#import <UIKit/UIKit.h>
#import "CarEditViewControllerProtocol.h"
@class Car;
@interface CarEditViewController : UIViewController
//
//@property (nonatomic) NSInteger carNumber;
@property (weak, nonatomic) id <CarEditViewControllerProtocol> delegate;
@property (strong,nonatomic) Car *currentCar;
@property (weak, nonatomic) IBOutlet UILabel *carNumberLabel;
@property (weak, nonatomic) IBOutlet UILabel *CarMakeFieldLabel;
@property (weak, nonatomic) IBOutlet UILabel *CarModelFieldLabel;
@property (weak, nonatomic) IBOutlet UILabel *CarYearFieldLabel;
@property (weak, nonatomic) IBOutlet UILabel *CarFuelFieldLabel;
@property (weak, nonatomic) IBOutlet UITextField *makeField;
@property (weak, nonatomic) IBOutlet UITextField *modelField;
@property (weak, nonatomic) IBOutlet UITextField *yearField;
@property (weak, nonatomic) IBOutlet UITextField *fuelField;
@end
現在修改CarEditViewController.m文件中viewDidLoad方法
- (void)viewDidLoad {
[super viewDidLoad];
NSString *labelFormat = @"%@:";//爲標籤設置默認的格式字符串,其中包含分隔符。這允許後續使用NSlocalizedString宏來對格式字符串進行本地化
NSString *local;//設置一個臨時變量,用於存儲指向每一個本地化字符串對象的指針,然後設置UI元素要顯示的字符串。可以跳過使用變量,將接賣弄字符串設置爲調用NSLocalizedStringWithDefaultValue的返回值
//格式化所有標籤
local = NSLocalizedStringWithDefaultValue(@"CarMakeFieldLabel", nil, [NSBundle mainBundle], @"Make", "Label for the line to enter or edit the Make of a car");
self.CarMakeFieldLabel.text = [NSString stringWithFormat:labelFormat,local];
local = NSLocalizedStringWithDefaultValue(@"CarModelFieldLabel", nil, [NSBundle mainBundle], @"Model", @"Label for the line to enter or edit the Model of a car");
self.CarModelFieldLabel.text = [NSString stringWithFormat:labelFormat,local];
local = NSLocalizedStringWithDefaultValue(@"CarYearFieldLabel", nil, [NSBundle mainBundle], @"Year", @"Label for the line to enter or edit the Year of a car");
self.CarYearFieldLabel.text = [NSString stringWithFormat:labelFormat,local];
local = NSLocalizedStringWithDefaultValue(@"CarFuelFieldLabel", nil, [NSBundle mainBundle], @"Fuel", @"Label for the line to enter or edit the Fuel of a car");
self.CarFuelFieldLabel.text = [NSString stringWithFormat:labelFormat,local];
NSString *carNumberText;
//格式化Car Number標籤。與Add/View場景使用相同的鍵
carNumberText = [NSString stringWithFormat:@"%@: %ld",
NSLocalizedString(@"CarNumberLabel", @"Label for the index number of the current car"),(long)[self.delegate carNumber]];
self.carNumberLabel.text = carNumberText;
self.currentCar = [self.delegate carToEdit];
self.makeField.text = self.currentCar.make;
self.modelField.text = self.currentCar.model;
self.yearField.text = [NSString stringWithFormat:@"%d",self.currentCar.year];
self.fuelField.text = [NSString stringWithFormat:@"%0.2f",self.currentCar.fuelAmount];
}
再次genstrings -o Base.lproj *.m
PS可能出現的問題是Localizable.strings文件沒有變化,我是出現這種情況了,找半天沒辦法,只能手動輸入,親測也是可以的,下面給出最後的Localizable.strings代碼
/* Label for the information of one car */
"CarInfoLabel" = "Car Info";
/* Make Label for the make of one car */
"CarInfoMakeLabel" = "Make ";
/* Model label for the model of one car */
"CarInfoModelLabel" = "Model";
/* Year label for one car */
"CarInfoYearLabel" = "Year";
/* Label for the total number of current car */
"CarNumberLabel" = "Car Number";
/* Title for button to edit the current car */
"EditCarButton" = "Edit";
/* Button to create and add a new car */
"NewCarButton" = "New Car";
/* Title for button to go to the next car */
"NextCarButton" = "Next";
/* Title for button to go to the previous car */
"PreviousCarButton" = "Previous";
/* Label for the total number of cars */
"TotalCarsLabel" = "Total Cars";
/* Placeholder string for an unknown car make */
"UnknownMakePlaceholder" = "Unknown Make";
/* Placeholder string for an unknown car model */
"UnknownModelPlaceholder" = "Unknown Model";
/* Label for the line to enter or edit the Make of a car */
"CarMakeFieldLabel" = "Make";
/* Label for the line to enter or edit the Model of a car */
"CarModelFieldLabel" = "Model";
/* Label for the line to enter or edit the Year of a car */
"CarYearFieldLabel" = "Year";
/* Label for the line to enter or edit the Fuel of a car */
"CarFuelFieldLabel" = "Fuel";
好了,現在我們把要變的名稱都設好鍵了。開始添加新的語言區域。我們首先當然是添加中文區域。先添加一個簡體中文。
(PS:你可能會發現並沒有InfoPlist.Strings,沒關係,我們可以自己創建一個)
首先創建一個文件
選中Strings File 並命名爲InfoPlist.strings,然後拉到文件中(或本來就在裏面了)
這邊我又創建一個文件來說明一下(上面那個是最後結果)
先假裝左邊的圈圈是InfoPlist.strings,然後點右邊的圈圈,會出現
選擇Chinese
然後會如下圖(出現三角形了)
將旁邊那些除了base都選上。在中文的那個文件裏面(就是寫了Chinese的那個文件,輸入CFBundleDisplayName = "汽車管理程序";
然後你把手機調成中文或模擬器的設置裏面調成中文。運行,回到桌面
變成中文了。所以這裏的CFBundleDisplayName
表示的是桌面的名稱。
現在我們來修改裏面的內容
Localizable.strings中選中中文的那個文件
不想敲代碼的話可以複製下面的內容:
/* Label for the information of one car */
"CarInfoLabel" = "車輛信息";
/* Make Label for the make of one car */
"CarInfoMakeLabel" = "品牌";
/* Model label for the model of one car */
"CarInfoModelLabel" = "型號";
/* Year label for one car */
"CarInfoYearLabel" = "生產日期";
/* Label for the total number of current car */
"CarNumberLabel" = "當前車號";
/* Title for button to edit the current car */
"EditCarButton" = "編輯";
/* Button to create and add a new car */
"NewCarButton" = "新添一輛車";
/* Title for button to go to the next car */
"NextCarButton" = "下一輛";
/* Title for button to go to the previous car */
"PreviousCarButton" = "上一輛";
/* Label for the total number of cars */
"TotalCarsLabel" = "總車數";
/* Placeholder string for an unknown car make */
"UnknownMakePlaceholder" = "未知品牌";
/* Placeholder string for an unknown car model */
"UnknownModelPlaceholder" = "未知型號";
/* Label for the line to enter or edit the Make of a car */
"CarMakeFieldLabel" = "品牌";
/* Label for the line to enter or edit the Model of a car */
"CarModelFieldLabel" = "型號";
/* Label for the line to enter or edit the Year of a car */
"CarYearFieldLabel" = "生產日期";
/* Label for the line to enter or edit the Fuel of a car */
"CarFuelFieldLabel" = "耗油量";
這時候在運行。貼上四張圖
發現一開始是沒有全會中文的,還有一些英文在搗亂,而且編輯汽車的時候,發現標籤沒有完全顯示出來。這不是我夢想要的,所以接下來我們還得改。
(PS當然你還可以在試着添加幾門語言進去玩一下)
好了,言歸正傳,現在開始修改主頁的英文,修改ViewController.m的ViewDidLoad方法
- (void)viewDidLoad {
[super viewDidLoad];
self.title = NSLocalizedStringWithDefaultValue(@"AddViewScreenTitle", nil, [NSBundle mainBundle], @"CarValet", "Title for the main app screen");
NSString *local;//爲當前的本地化標題設置臨時字符串引用
//將這個臨時字符串設置爲Add Car按鈕的本地化標題
local = NSLocalizedStringWithDefaultValue(@"NewCarButton", nil, [NSBundle mainBundle], @"New Car", @"Button to create and add a new car");
[self.addCarButton setTitle:local forState:UIControlStateNormal];//將Add Car按鈕在默認狀態下的標題設置爲這個本地化字符串
local = NSLocalizedStringWithDefaultValue(@"PreviousCarButton", nil, [NSBundle mainBundle], @"Previous", @"Title for button to go to the previous car");
[self.previousCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"NextCarButton", nil, [NSBundle mainBundle], @"Next", @"Title for button to go to the next car");
[self.nextCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"EditCarButton", nil, [NSBundle mainBundle], @"Edit", @"Title for button to edit the current car");
[self.editCarButton setTitle:local forState:UIControlStateNormal];
arrayOfCars = [[NSMutableArray alloc] init];//初始化汽車的數組爲空數組
displayedCarIndex = 0;//顯示創建的第一輛汽車
[self setupLandscapeConstraints];
UIInterfaceOrientation currOrientation = [[UIApplication sharedApplication]statusBarOrientation];
isShowingPortrait = UIInterfaceOrientationIsPortrait(currOrientation);
}
對CarEditViewController.m進行同樣的操作,使用鍵EditViewScreenTitle,默認值爲”Edit Car”,在中文的那個文件裏面寫”編輯汽車”(或隨便啦)
其餘的兩個車輛信息跟車輛總數和當前車輛,那個就交給你們自己試一下吧。(如果沒有試出來可以在下面看到代碼,記得要加鍵)
- (void)viewDidLoad {
[super viewDidLoad];
self.title = NSLocalizedStringWithDefaultValue(@"AddViewScreenTitle", nil, [NSBundle mainBundle], @"CarValet", "Title for the main app screen");
NSString *local;//爲當前的本地化標題設置臨時字符串引用
//將這個臨時字符串設置爲Add Car按鈕的本地化標題
local = NSLocalizedStringWithDefaultValue(@"NewCarButton", nil, [NSBundle mainBundle], @"New Car", @"Button to create and add a new car");
[self.addCarButton setTitle:local forState:UIControlStateNormal];//將Add Car按鈕在默認狀態下的標題設置爲這個本地化字符串
local = NSLocalizedStringWithDefaultValue(@"PreviousCarButton", nil, [NSBundle mainBundle], @"Previous", @"Title for button to go to the previous car");
[self.previousCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"NextCarButton", nil, [NSBundle mainBundle], @"Next", @"Title for button to go to the next car");
[self.nextCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"EditCarButton", nil, [NSBundle mainBundle], @"Edit", @"Title for button to edit the current car");
[self.editCarButton setTitle:local forState:UIControlStateNormal];
local = NSLocalizedStringWithDefaultValue(@"TotalNumber", nil, [NSBundle mainBundle], @"Total Car", @"total car");
self.totalCarsLabel.text = local;
local = NSLocalizedStringWithDefaultValue(@"CurrentNumber", nil, [NSBundle mainBundle], @"Current Car", @"Current car");
self.CarNumberLabel.text = local;
local = NSLocalizedStringWithDefaultValue(@"CarInfor", nil, [NSBundle mainBundle], @"CarInfor", @"CarInfor");
self.CarInfoLabel.text = local;
arrayOfCars = [[NSMutableArray alloc] init];//初始化汽車的數組爲空數組
displayedCarIndex = 0;//顯示創建的第一輛汽車
[self setupLandscapeConstraints];
UIInterfaceOrientation currOrientation = [[UIApplication sharedApplication]statusBarOrientation];
isShowingPortrait = UIInterfaceOrientationIsPortrait(currOrientation);
}
對齊問題偷了個懶,修改如圖,如果有精力的話,可以按照第6、7節的方法去進行約束。記得會有一行放不下所有信息的情況,這時候要考慮換行的問題,這就交給你們自己去查咯
今天的介紹就到這裏咯
我的另一個博客站點:Arnold-你們好啊