BK项目已完成7788,在项目的后期需要被翻译成多国语言版。为了适应全球多个国家使用多个存储。

应用本地化是分别对字符串、图片和 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”。这样做的目的是为了尽早发现问题。

(2)冻结UI  在应用开发的周期中必需要有一个明白的时间点来冻结UI。在此之后要坚决杜绝会影响本地化的资源变更。nib 文件能够在XCode中锁定。以防止改动可本地化的属性、不可本地化的属性或者是全部属性,如图所看到的。然后将需要翻译的文本发给翻译人员或者是本地化服务提供商去翻译即可了。

(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 <objc/runtime.h>
#import <UIKit/UIKit.h> 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<n; ++idx) {
[sc setTitle:localizedString([sc titleForSegmentAtIndex:idx]) forSegmentAtIndex:idx];
}
} static inline void localizeUITextField(UITextField* tf) {
tf.adjustsFontSizeToFitWidth = YES;
tf.text = localizedString(tf.text);
tf.placeholder = localizedString(tf.placeholder);
} static inline void localizeUITextView(UITextView* tv) {
tv.text = localizedString(tv.text);
} static inline void localizeUIViewController(UIViewController* vc) {
vc.title = localizedString(vc.title);
}

tips:本地化的时候还须要注意:

1、别忘了从右向左读的语言。

2、不要随便如果逗号就是千位分隔符以及句点就是小数点。在不同的语言中可能会有不同。

3、注意数字和日期的格式化(输入和输出都须要进行格式化)。

至此,,应用本地化的事儿就简单多了,剩下的事情就交给翻译人员去吧~

參考文章:

Apple官方文档:Localizing your APP

Apple官方文档:Internationalize Your App

Apple官方文档: Data Formatting Guide

Apple官方文档: Internationalization
Programming Topics

Apple官方文档: Internationalization and Localization

本地化协作工具:https://www.transifex.com/product/

https://crowdin.com/

版权声明:本文博客原创文章,博客,未经同意,不得转载。

IOS本地化应用的更多相关文章

  1. iOS本地化

    本地化与相机中显示英文  工程PROJECT -> info ->Localizations 添加相应的国际化语言  一.当你发现相机中显示英文,可以通过它设置 添加一项“Localize ...

  2. [IOS]本地化

    我们在IOS开发应用中,会碰到做好的一个应用,如何趋向国际化,也就是说支持多种语言?下面我就来简单演示一下,用一个Demo来实现中文和英文的实现. 实现步骤: 1.本地化项目中xib的view 1.在 ...

  3. IOS本地化。

    1,项目名本地化 点击项目,蓝色图标->info 最下面+号,添加chinese本地化. Supporting Files->infoPlist.strings 下会有两个文件,有一个是设 ...

  4. iOS 本地化应用程序(NSLocalizedString)

    App本地化的需要不用讲大家也都明白,本文将介绍一种简单的方法来实现字符串的本地化. 在不考虑本地化的情况下,我们如果在代码中给一个Button定义title,一般会这样写: btn.titleLab ...

  5. iOS本地化应用程序

    因为使用的是xcode4,应用程序本地化的问题跟以前的版本还是有些不同,在网上找了些资料对于xcode4以上的版本资料还是相对较少,有些最后要通过手动创建文件,这样操作实在是太麻烦,所以经过一个下午的 ...

  6. ios本地化多语言支持

    右键 -> new file -> resources -> strings file 一定要命名为: Localizable.strings 点击这个文件 -> xocde ...

  7. Xcode5和6上新建工程如何本地化启动页面

    建议阅读本篇文章前先具备iOS本地化的基本知识,Google中搜索“iOS本地化”,有成片的教程~~ 最近有个app需要支持英语.简体中文.繁体中文,由于启动页面上有文字,所以也不得不做下本地化处理. ...

  8. Xcode4.5 本地化,多语言设置

    网上已有很多关于ios本地化的博客和资料,由于部分原作者使用的Xcode版本较早,4.5以后的版本已不再支持该方法,后来也没有更新,因此在此写一点学习资料分享出来.废话不多说.     ios本地化主 ...

  9. 最全的iOS数据存储方法

    目的 项目准备运用的Core Data进行本地数据存储,本来打算只写一下Core Data的,不过既然说到了数据存储,干脆来个数据存储基础大总结!本文将对以下几个模块进行叙述. 沙盒 Plist Pr ...

随机推荐

  1. C++ 直方图匹配算法代码

    /*-------------------------------------------------------------------------*/ // 函数名称: histeq() // 传 ...

  2. [Android学习笔记]页面布局

    线性布局:LinearLayout 1.集成ViewGroup,故可容纳多个View 2.线性布局,可设置水平或者垂直方向 相对布局:RelativeLayout

  3. Java NIO 完全学习笔记(转)

    本篇博客依照 Java NIO Tutorial翻译,算是学习 Java NIO 的一个读书笔记.建议大家可以去阅读原文,相信你肯定会受益良多. 1. Java NIO Tutorial Java N ...

  4. POJ2112_Optimal Milking(网洛流最大流Dinic+最短路Flody+二分)

    解题报告 农场有k个挤奶机和c头牛,每头牛到每一台挤奶机距离不一样,每台挤奶机每天最多挤m头牛的奶. 寻找一个方案,安排每头牛到某一挤奶机挤奶,使得c头牛须要走的全部路程中的最大路程的最小值. 要使每 ...

  5. 使用FragmentTabhost取代Tabhost

       如今Fragment使用越来越广了,尽管Fragment寄生在Activity下.可是它的出现对于开发人员来说是一件很幸运的事,使开发的效率更高效了.好了以下就说说 FragmentTabhos ...

  6. curl订单具体解释

    为windows假设用户Cygwin模拟unix环境的话,不会有带curl命令,拥有设备,它建议使用Gow为了模拟,它已经自带curl工具,直接安装之后cmd使用环境curl命令可以,由于路径是自己主 ...

  7. nginx源代码分析--event事件驱动初始化

    1.在nginx.c中设置每一个核心模块的index ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]-> ...

  8. Xcode如何添加字体库--

    1.网上搜索字体文件(后缀名为.ttf,或.odf) 2.把字体库导入到工程的resouce中 3.在程序viewdidload中加载一下一段代码 NSArray *familyNames = [UI ...

  9. webapi Task

    webapi+Task并行请求不同接口实例 标题的名称定义不知道是否准确,不过我想表达的意思就是使用Task特性来同时请求多个不同的接口,然后合并数据:我想这种场景的开发对于对接过其他公司接口的人不会 ...

  10. Wix学习整理(4)——关于WiX文件格式和案例HelloWorld的分析

    原文:Wix学习整理(4)--关于WiX文件格式和案例HelloWorld的分析 关于WiX文件格式 .wxs是WiX的源文件扩展名..wxs文件以类XML文件的格式来指定了要构造Windows In ...