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

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