IOS開發入門(8)-本地化(1)

  在大多數國家,英語不是母語,當然我們漢語也不是母語。即使在某個國家,有些人使用漢語或英語,最好的方式還是用客戶的母語來展現應用程序。用戶如果選擇漢語,那沒別的了。但如果選擇英語,這時候英語又會有英式英語、美式英語、澳大利亞英語、加拿大英語等,它們各有差異。

  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-你們好啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章