IOS本地化应用

IOS本地化应用

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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

应用本地化是分别对字符串、图片和 xib 或 storyboard 文件本地化,而传统的做法是对 xib 上的字符串(包含UILabel和UIButton、UITextField等)关联一个变量,通过NSLocalizedString这个函数去查找 Localizeable .strings 文件里的key值进行本地化操作,或者是生成同一个xib文件的不同语言版本号。如 MainVC.xib(German) 和 MainVC.xib(English)。但这样做未免过于繁杂,像人们常说的 tedious and useless.

IOS本地化应用

还是先介绍一下本地化的一般流程:

                                         IOS本地化应用

(1)伪本地化伪本地化是将字符串本地化为无意义语言的过程。

即将须要翻译的字符串替换成其它如果已经是翻译过的“译文”,能够用谷歌翻译替换一下或者是将全部元音字母替换成x。比如:“Press here to continue” 会变成 “Prxss hxrx tx cxntxnxx”。这样做的目的是为了尽早发现问题。

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

                                             IOS本地化应用

(3)本地化将资源发给本地化服务提供商之后,他们会发回翻译完毕的文件。依据翻译的文本进行本地化工作。

(4)版本号控制用版本号控制系统记录下你的每一次变更。

(5)測试不用怎么说,必需要的步骤。

(6a)合并逻辑变更逻辑变更一般不会影响到nib文件和本地化的工作。多人协作的项目还是须要合并一些变更的逻辑的。

(6b)本地化变更假设你做了一些本地化变更,比方改变了已本地化的文本,那么就须要从头開始这个过程。并将这些变更发给本地化人员。能够重用之前的字符串翻译,这么做会大大提高效率,但仍然非常麻烦。所以,应尽量避免在开发后期引入这类变更。

应用本地化的文章之前已经就有非常多大牛写过了。这里就不在赘述了,直接贴出本人读过的认为还不错的文章:

1、MJ 的应用程序本地化,2013年写的,对于XCode5,有些操作界面已经不一样了,但思想是不变的。

2、IOS应用国际化教程(2014版),这个比較新,并且是使用 storyboard 的。

3、RAYWENDERLICH 上的 Internationalization Tutorial for iOS [2014 Edition] 这上面的文章都非常不错,非常值得一读,强烈推荐。

另外。重点是要讲我在 github 上找到的一个类,很棒,优雅的代码一直感动到我眼泪哗哗直流~~IOS本地化应用

这是github上的项目地址:HERE ,假设有找到很多其它更好的优秀代码,请知会一声。

就像作者所说的那样:

       IOS本地化应用

       IOS本地化应用

下面是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] = {
		,
		,
		,
		
	};
	
    ;
	) forState:UIControlStateNormal];
	if (title[1] == )
		) forState:UIControlStateHighlighted];
	if (title[2] == )
		) forState:UIControlStateDisabled];
	if (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/

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117691.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Stairway to SQLCLR Level 5: Development (Using .NET within SQL Server)

    Stairway to SQLCLR Level 5: Development (Using .NET within SQL Server)原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/119429/BySolomonRutzky,2015/03/11TheSeriesThisarticleispartoftheStairwaySeries:StairwaytoSQLCLRThepossibil

    2022年7月20日
    12
  • phpmyadmin端口多少(iis配置改端口号)

    当前使用phpmyadmin版本号为phpMyAdmin-4.7.5mysql默认端口3306,如果你当前mysql不是3306,则如何通过phpmyadmin连接呢?网上文章都是要修改phpmyadmin目录下libraries下配置文件config.default.php文件的$cfg[‘Servers’][$i][‘port’]=”参数,…

    2022年4月10日
    47
  • git下载安装教程

    git下载安装教程git下载安装教程前言:因为最近突然对使用github搭建一个自己的网站并绑定域名特别着迷,但是前提条件是必须得安装git,于是便把安装过程记录下来,便利自己,帮助他人。1.访问git官网下载最新版本git官方网页:https://git-scm.com/download/win在git官网中,有不同操作系统下的git,选择符合自己电脑版本的进行下载就可以了这里我选择的windows,然后根据自己电脑是32位还是64位,在下面两个选项中选择选择好了静待其下好就好了或许会有下载缓慢或无法下

    2022年6月11日
    31
  • 扒一扒使用boostrap-fileinput上传插件遇到的坑,Bootstrap-fileinput上传插件的使用详解,「建议收藏」

    扒一扒使用boostrap-fileinput上传插件遇到的坑,Bootstrap-fileinput上传插件的使用详解,「建议收藏」由于公司项目的需求,需要实现动植物名录的添加,包括姓名等信息和图片等,需要使用bootstrap-fileinput的上传插件,在提交添加界面表单数据的同时上传一张或者多张图片,并将上传的图片保存到本地磁盘中(本文是f:盘的目录下),在在实现的时候,不适用bootstrap-fileinput上传插件本身的上传按钮(因为本身的按钮只能上传图片),需要点击提交,将表单的其他信息和图片一起提交到后台。

    2022年6月7日
    149
  • Mac OS使用技巧之十六:系统失去响应怎么办?[通俗易懂]

    Mac OS使用技巧之十六:系统失去响应怎么办?

    2022年2月2日
    58
  • 西门子plc scl语言很少人用_西门子plc的scl语言

    西门子plc scl语言很少人用_西门子plc的scl语言原标题:为什么说SCL将成为西门子PLC的主流编程语言接触S7-1200的时间不是很长,但个人感觉TIAPROTAL中的SCL编程语言还不错,下面是我写的一个传送带的启停程序:bnnyygysaid:我献丑来一个,半成品,给设备改造的,用的欧姆龙CP1L,ST语言功能块,部分节选。wenpiansaid:还是梯形图适合逻辑。ljj977said:程序写的不错。tiaprotal中可以…

    2025年11月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号