IOS本地化应用
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/
版权声明:本文博客原创文章,博客,未经同意,不得转载。
IOS本地化应用的更多相关文章
- iOS本地化
本地化与相机中显示英文 工程PROJECT -> info ->Localizations 添加相应的国际化语言 一.当你发现相机中显示英文,可以通过它设置 添加一项“Localize ...
- [IOS]本地化
我们在IOS开发应用中,会碰到做好的一个应用,如何趋向国际化,也就是说支持多种语言?下面我就来简单演示一下,用一个Demo来实现中文和英文的实现. 实现步骤: 1.本地化项目中xib的view 1.在 ...
- IOS本地化。
1,项目名本地化 点击项目,蓝色图标->info 最下面+号,添加chinese本地化. Supporting Files->infoPlist.strings 下会有两个文件,有一个是设 ...
- iOS 本地化应用程序(NSLocalizedString)
App本地化的需要不用讲大家也都明白,本文将介绍一种简单的方法来实现字符串的本地化. 在不考虑本地化的情况下,我们如果在代码中给一个Button定义title,一般会这样写: btn.titleLab ...
- iOS本地化应用程序
因为使用的是xcode4,应用程序本地化的问题跟以前的版本还是有些不同,在网上找了些资料对于xcode4以上的版本资料还是相对较少,有些最后要通过手动创建文件,这样操作实在是太麻烦,所以经过一个下午的 ...
- ios本地化多语言支持
右键 -> new file -> resources -> strings file 一定要命名为: Localizable.strings 点击这个文件 -> xocde ...
- Xcode5和6上新建工程如何本地化启动页面
建议阅读本篇文章前先具备iOS本地化的基本知识,Google中搜索“iOS本地化”,有成片的教程~~ 最近有个app需要支持英语.简体中文.繁体中文,由于启动页面上有文字,所以也不得不做下本地化处理. ...
- Xcode4.5 本地化,多语言设置
网上已有很多关于ios本地化的博客和资料,由于部分原作者使用的Xcode版本较早,4.5以后的版本已不再支持该方法,后来也没有更新,因此在此写一点学习资料分享出来.废话不多说. ios本地化主 ...
- 最全的iOS数据存储方法
目的 项目准备运用的Core Data进行本地数据存储,本来打算只写一下Core Data的,不过既然说到了数据存储,干脆来个数据存储基础大总结!本文将对以下几个模块进行叙述. 沙盒 Plist Pr ...
随机推荐
- QTableView 固定列宽度(鼠标拖动后,仍可固定)
QTableView 提供一个函数: void QTableView::setColumnWidth ( int column, int width ) 用于设置column指定的列的宽度 但setC ...
- ogre sample分析(一)
ogre自带了一些例子,逐个过一遍并自己动手做一些调整 1 Sample_BezierPatch:这个例子直接用数值来构造顶点缓存并创建entity,这种方法一般只能创建简单对象,本人以为复杂对象顶点 ...
- Struts工作机制图+OGNL+EL+值栈(Map,对象栈)
struts 值栈 通过get set方法 方便的获取,设置属性值 比如从jsp页面传来的參数...从Action设置jsp所要回显的内容 注意EL表达式,struts2对request进 ...
- VSTO学习笔记(八)向 Word 2010 中写入表结构
原文:VSTO学习笔记(八)向 Word 2010 中写入表结构 前几天公司在做CMMI 3级认证,需要提交一系列的Word文档,其中有一种文档要求添加公司几个系统的数据库中的表结构.我临时接到了这项 ...
- TBDR缺点
TBDR全称Tile-based Deferred Rendering.它是Power VR独特的TBR技术的一种延伸实现手段.TBR/TBDR通过将每一帧画面划分成多个矩形区域,并对区域内的全部像素 ...
- 浅谈SQL之主键、外键约束
约束:顾名思义就是一种限制,在表或列的层次设置约束,确保数据的有效性和完整性. SQL server中约束的主要分类: UNIQUE约束(唯一性约束) 防止一个特定的列中两个记录具有相同的值.可设置多 ...
- java与c/c++进行socket通信
比如Server端只接收一个结构Employee,定义如下: struct UserInfo { char UserName[20]; int UserId; }; struct Employ ...
- 伪教练技术培训之殇-2013年9月江西IDC拓行榜与综述
纠集几个人,然后培训所谓的教练技术培训. 培训的人一期又一期的参与,国学.佛学.超能量,无所不用其极,然后就是疯狂的拿人头,邀请朋友加盟. 有甚者还披上“科技”的外衣,用“水知道答案”这种早被公知指出 ...
- WPF动态改变主题颜色
原文:WPF动态改变主题颜色 国内的WPF技术先行者周银辉曾介绍过如何动态改变应用程序的主题样式,今天我们来介绍一种轻量级的改变界面风格的方式--动态改变主题色. 程序允许用户根据自己的喜好来对界面进 ...
- Xamarin 安装步骤
原文:Xamarin 安装步骤 1.下载并解压吾乐吧软件站提供的“Mono for Android 离线包” 安装:jdk-6u45-windows-i586.exe (就算你是64位系统,也要安装i ...