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 ...
随机推荐
- Java Swing界面编程(28)---复选框:JCheckBox
程序能够通过JRadioButton实现单选button的功能,那么要实现复选框的功能,则必须使用JCheckBox完毕. package com.beyole.util; import java.a ...
- About Unixstickers - Unixstickers - stickers on unix, programming, software, development and open source
About Unixstickers - Unixstickers - stickers on unix, programming, software, development and open so ...
- Raphaël 中文帮助文档(API)
http://html5css3webapp.com/raphaelApi.htm
- ASA failover应用
failover的条件: 1.硬件型号必须相同 2.系统版本必须一致 3.模式必须一致 4.相同的许可和许可的数量 步骤: step 1:配置failover interface,确保状态 up LZ ...
- 手机定位原理 - GPS/GLONASS/北斗 + WIFI + 基站(转)
卫星定位系统 - GPS/GLONASS/北斗: 关于GPS.GLONASS.北斗.伽利略系统的科普请自行谷歌. GPS是使用最广泛的全球定位网络,几乎是所有智能手机的标配.进几年,俄罗斯的GLONA ...
- 4、深入理解Bean
本节知识点: 1. Bean 的自己主动装配(了解) 2. bean 之间的关系:继承:依赖 3.Bean 的作用域:能够在 <bean> 元素的 scope 属性里设置 Bean 的作用 ...
- Gnu Linux下文件的字符编码及转换工具
/********************************************************************* * Author : Samson * Date ...
- 【从翻译mos文章】SGA_TARGET与SHMMAX关系
SGA_TARGET与SHMMAX关系 参考原始: Relationship Between SGA_TARGET and SHMMAX (文件 ID 1527109.1) 申请: Oracle Da ...
- H.O.T candy
candy是什么意思_candy在线翻译_英语_读音_用法_例句_海词词典 candy
- Redis在win7上的安装与可视化应用
Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...