携手创作,一起生长!这是我参加「日新计划 8 月更文挑战」的第9天,点击查看活动概况
前语
原理:
- 从指定的表和包中回来字符串的本地化版别:
NSLocalizedStringFromTableInBundle(key, table, _bundle, nil)
- 切换言语收效方法:采用毁掉根控制器,从头进入一次
- 本地化字符串指定参数次第
从CSDN下载【iOS APP 内的国际化切换】demo源码:download.csdn.net/download/u0…
I 字符串的本地化
1.1 用法
- 创立字符串资源文件Localizable.strings
- 为Localizable.strings添加多言语支撑
选 make Localize代表会将Localizable.strings加入到英语的本地化文件夹en.lproj中去
Localizable.strings(English)对应en.lproj文件夹中的Localizable.strings文件 Localizable.strings(Chinese)对应zh-Hans.lproj文件夹中的Localizable.strings文件
- 在资源文件Localizable.strings配备字符串对应的key和value。
en.lproj/Localizable.strings
static NSString * const kSystem = @"SystemDefault";
static NSString * const kCH = @"zh-Hans";
static NSString * const kEN = @"en";
static NSString * const kProj = @"lproj";
static NSString * const kLanguageSet = @"kLanguageSet";
"Connected" = "Connected";
"Tip"="Tip";
zh-Hans.lproj/Localizable.strings
"Connected" = "已衔接";
"Tip"="提示";
- 在代码中运用NSLocalizedString(key, comment)来读取本地化字符串,key是Localizable.strings文件中等号左面的字符串,comment纯粹是注释
#define NSLocalizedString(key, comment) \
[NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
[NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \
[bundle localizedStringForKey:(key) value:(val) table:(tbl)]
1.2 言语的切换
//程序的本地化,引用国际化的文件
#define QCTLocal(x, ...) HZLocalizedString(x, nil)
#define HZLocalizedString(key, comment) HZLocalizedStringFromTable(key, @"Localizable", nil)
#define HZLocalizedStringFromTable(key, tbl, comment) [[HZLanguageManager defaultManager] stringWithKey:key table:tbl]
/**
@param key <#key description#>
@param table Localizable
@return <#return value description#>
*/
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
//假定为随从系统
if (self.languageType==HZLanguageTypeSystem) {
return NSLocalizedString(key, nil);
}
//回来对应国际化文字
if (_bundle) {
return NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
}
return NSLocalizedStringFromTable(key, table, nil);
}
// 运用QCTLocal读取本地化字符串
[LBAlertController showAlertTitle:QCTLocal(@"tips") content:QCTLocal(@"str_cann_printer") cancelString:QCTLocal(@"cancel") cancleBlock:nil sureString:QCTLocal(@"sure") sureBlock:^{
假定没有对字符串进行本地化 或者 找不到key对应的值,NSLocalizedString将直接回来key这个字符串
重置TableBundle
- (void)resetBundle{
NSLog(@"resetBundle:%@",_languageString);
if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
self.bundle = [NSBundle bundleWithPath:path];
}
}
1.3 强制为中文
因为审理时境外IP无法访问,抉择去掉英文版别。
blog.csdn.net/z929118967/…
// 因为审理时,境外IP无法访问,抉择去掉英文版别
- (void)setLanguageType:(HZLanguageType)languageType{
//HZLanguageTypeChineseSimple
languageType =HZLanguageTypeChineseSimple;
_languageString = kCH;//强制为中文
_languageType =languageType;
}
// 中英文切换
- (void)changeLanguageType:(HZLanguageType)type;
{
if (self.currentLanguageType == type) {
return;
}
self.languageType = type;
switch (self.languageType) {
case HZLanguageTypeSystem:
self.languageString=kSystem;
break;
case HZLanguageTypeEnglish:
self.languageString = kEN;
break;
case HZLanguageTypeChineseSimple:
self.languageString = kCH;
break;
}
//bundle 设置
[self resetBundle];
//设置言语,并作记载保存
[[NSUserDefaults standardUserDefaults] setObject:_languageString forKey:kLanguageSet];
[[NSUserDefaults standardUserDefaults] synchronize];
//运用告知更改文字 [[NSNotificationCenter defaultCenter] postNotificationName:kNoticeLanguageChange object:nil];
}
1.4 本地化字符串指定参数次第
关于在中英文语法的差异,在本地化字符串的时分,我们常常需求调整stringWithFormat的参数次第
- iOS本地化字符串指定参数次第:运用场景:app内的多言语切换
文章:kunnan.blog.csdn.net/article/det… 原理:在%和@中心加上数值(1(1,2$),数字代表参数的次第
"FORMAT" = "I am %2$@ from '%1$@'";
II 自定义解析本地化字符串的东西类LanguageManager
2.1 代码完成
- LanguageManager
从CSDN下载【iOS APP 内的国际化切换】demo源码:download.csdn.net/download/u0…
#import <Foundation/Foundation.h>
#define HZLocalizedString(key, comment) HZLocalizedStringFromTable(key, @"Localizable", nil)
#define HZLocalizedStringFromTable(key, tbl, comment) [[HZLanguageManager defaultManager] stringWithKey:key table:tbl]
static NSString * const kNoticeLanguageChange = @"kNoticeLanguageChange";
typedef NS_ENUM(NSUInteger, HZLanguageType) {
HZLanguageTypeSystem,
HZLanguageTypeEnglish,
HZLanguageTypeChineseSimple,
};
@interface HZLanguageManager : NSObject
@property (nonatomic, assign, getter=currentLanguageType) HZLanguageType languageType;
+ (instancetype)defaultManager;
- (void)changeLanguageType:(HZLanguageType)type;
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table;
- (HZLanguageType)currentLanguage;
+ (BOOL )isEN;
- LanguageManager.h .m
static NSString * const kSystem = @"SystemDefault";
static NSString * const kCH = @"zh-Hans";
static NSString * const kEN = @"en";
static NSString * const kProj = @"lproj";
static NSString * const kLanguageSet = @"kLanguageSet";
@interface HZLanguageManager()
@property (nonatomic, strong) NSBundle *bundle;
@property (nonatomic, strong) NSString *languageString;
@end
@implementation HZLanguageManager
+ (instancetype)defaultManager
{
static dispatch_once_t onceToken;
static HZLanguageManager *manager;
dispatch_once(&onceToken, ^{
if (!manager) {
manager = [[HZLanguageManager alloc] init];
}
});
return manager;
}
- (instancetype)init
{
self = [super init];
if (!self) {
return nil;
}
//取字段看是哪种言语
NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:kLanguageSet];
// NSString *path;
//假定用户没有设置过言语
if (!tempStr) {
tempStr=kSystem;
}
self.languageString = tempStr;
if ([self.languageString isEqualToString:kCH]) {//为中文
self.languageType = HZLanguageTypeChineseSimple;
}else if ([self.languageString isEqualToString:kEN]) {//为英文
self.languageType = HZLanguageTypeEnglish;
}else if([self.languageString isEqualToString:kSystem]){//为系统默许
self.languageType= HZLanguageTypeSystem;
if([self isENLanguage]){//HZLanguageManager
self.languageType = HZLanguageTypeEnglish;
}else{
self.languageType = HZLanguageTypeChineseSimple;
}
}
if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
self.bundle = [NSBundle bundleWithPath:path];
}
NSLog(@"其时的言语 HZLanguageTypeSystem HZLanguageTypeEnglish HZLanguageTypeChineseSimple:%lu",(unsigned long)self.languageType);
return self;
}
- (void)changeLanguageType:(HZLanguageType)type;
{
if (self.currentLanguageType == type) {
return;
}
_languageType = type;
switch (type) {
case HZLanguageTypeSystem:
self.languageString=kSystem;
break;
case HZLanguageTypeEnglish:
self.languageString = kEN;
break;
case HZLanguageTypeChineseSimple:
self.languageString = kCH;
break;
}
//bundle 设置
[self resetBundle];
//设置言语,并作记载保存
[[NSUserDefaults standardUserDefaults] setObject:_languageString forKey:kLanguageSet];
[[NSUserDefaults standardUserDefaults] synchronize];
//运用告知更改文字 [[NSNotificationCenter defaultCenter] postNotificationName:kNoticeLanguageChange object:nil];
}
- (void)resetBundle{
if ([_languageString isEqualToString:kEN] || [_languageString isEqualToString:kCH]) {
NSString *path = [[NSBundle mainBundle] pathForResource:_languageString ofType:kProj];
self.bundle = [NSBundle bundleWithPath:path];
}
}
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
//假定为随从系统
if (self.languageType==HZLanguageTypeSystem) {
return NSLocalizedString(key, nil);
}
//回来对应国际化文字
if (_bundle) {
return NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
}
return NSLocalizedStringFromTable(key, table, nil);
}
-(HZLanguageType)currentLanguage{
//获取其时言语
// NSString *tempStr = [[NSUserDefaults standardUserDefaults] objectForKey:kLanguageSet];
// if ([tempStr rangeOfString:@"zh"].length) {
//// tempStr = kCH;
// return HZLanguageTypeChineseSimple;
// }else if([tempStr isEqualToString:kEN]){
//// tempStr = kEN;
// return HZLanguageTypeEnglish;
// }else {//if([tempStr isEqualToString:kSystem])
//
// return HZLanguageTypeSystem;
// }
return self.languageType;
}
+ (NSArray *)english {
return @[@"en", @"en-CN"];
}
+ (NSArray *)chineseHans {
return @[@"zh-Hans", @"zh-Hans-CN"];
}
+ (NSArray *)chineseHant {
return @[@"zh-Hant", @"zh-Hant-CN"];
}
/**
(lldb) po [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]
<__NSCFArray 0x2833357a0>(
zh-Hans-AM,
en-AM,
en-GB,
ru-AM,
zh-Hant-AM,
zh-Hant-HK
)
第一个就是用户设置的言语
@return
*/
- (BOOL )isENLanguage {
// NSString *language = [[NSUserDefaults standardUserDefaults] objectForKey:GHLLanguageKey];
// if (){
// if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeEnglish) {
if (self.currentLanguage == HZLanguageTypeEnglish) {
return YES;
}
// if () {
NSArray *languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];
NSString *language = languages.firstObject;
// }
// if([[HZLanguageManager chineseHans] containsObject:language] || [[HZLanguageManager chineseHant] containsObject:language] ){
if([language containsString:@"zh-Hans"] || [language containsString:@"zh-Hant"] ){
return NO;
}else{
return YES;
}
}
+ (BOOL )isEN{
if([HZLanguageManager defaultManager].currentLanguage == HZLanguageTypeEnglish ){
// make.width.mas_equalTo(kAdjustRatio(73 * 3));
return YES;
}else{
// make.width.mas_equalTo(kAdjustRatio(50 * 3));
// make.left.equalTo(weakSelf.contentView).offset(kAdjustRatio(20));
// make.right.equalTo(weakSelf.contentView).offset(- kAdjustRatio(20));
//
return NO;
}
}
@end
2.2 strings文件的文本内容过长导致key 失效的解决计划
/consts/Localizable/en.lproj/Localizable.strings
文本内容太长了。 会导致key 失效。
- 解决计划
新增一个table来存储,解析的时分从两个文件查找。
new file: retail/retail/class/consts/Localizable/en.lproj/Localizable1.strings
new file: retail/retail/class/consts/Localizable/zh-Hans.lproj/Localizable1.strings
- 读取本地字符串的代码:
假定你的字符串资源文件名不是Localizable.strings,如KN.strings,那么你就得运用NSLocalizedStringFromTable()、NSLocalizedStringFromTableInBundle来读取本地化字符串:
- (NSString *)stringWithKey:(NSString *)key table:(NSString *)table
{
//假定为随从系统
if (self.languageType==HZLanguageTypeSystem) {
return NSLocalizedString(key, nil);
}
//回来对应国际化文字
if (_bundle) {// 批改成为,从别的一个文件找,先从文件找,假定找不到就从文件二找。
//NSLocalizedStringFromTableInBundleWithKey
return [self NSLocalizedStringFromTableInBundleWithKey:key table:table];
return NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
}
return NSLocalizedStringFromTable(key, table, nil);
}
/**
假定你的字符串资源文件名不是Localizable.strings,如KN.strings,那么你就得运用NSLocalizedStringFromTable()来读取本地化字符串:
*/
//{// 批改成为,从别的一个文件找,先从文件找,假定找不到就从文件二找。
- (NSString*)NSLocalizedStringFromTableInBundleWithKey:(NSString *)key table:(NSString *)table{
NSString* tmp = key;
if(_bundle){
tmp =NSLocalizedStringFromTableInBundle(key, table, _bundle, nil);
if([tmp isEqualToString:key]){
// 继续从备份表查找
NSLog(@"开端从Localizable1 找key:%@", tmp);
tmp =NSLocalizedStringFromTableInBundle(key, @"Localizable1", _bundle, nil);
// NSLog([NSString stringWithFormat:@"完毕从Localizable1 找key:%@",tmp]);
NSLog(@"完毕从Localizable1 找key:%@", tmp);
}
}
return tmp;
}
III info.plist 的国际化
- 新建一个 .strings文件,叫做InfoPlist.strings(文件名必须是这个)
- 新建往后,点击右侧的 localized 才有含义。
- 要害的过程来了,这时分,点击我们的info.plist,右键选择open as source code 查看我们所要获取权限的原始 key
Info.plist中的CFBundleDisplayName的key抉择了运用程序的称号
"NSMicrophoneUsageDescription" = "Allow this app to use your microphone for decibel detection and sound recording; audio is recorded locally only and is not sent to anyone, only for decibel detection and sound variation.";
IV 事例
4.1 《用户协议及隐私方针》弹框(包含超链接特色)【本文包含无缺demo源码,demo支撑中英文切换】
iOS《用户协议及隐私方针》弹框(包含超链接特色)【本文包含无缺demo源码,demo支撑中英文切换】 | 蓄力计划
kunnan.blog.csdn.net/article/det…
4.2 登录界面切换中英文
- AppDelegate: 设置默许的言语
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if([LanguageManager isEN] ){
// _titleLab.font = kPingFangFont(10);
[[LanguageManager defaultManager] changeLanguageType: HZLanguageTypeEnglish];
NSLog(@"其时位英文版别");
}else{
// _titleLab.font = kPingFangFont(12);
NSLog(@"其时位中文版别");
[[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeChineseSimple];
}
}
github.com/zhangkn/Lan…
- 建立切换按钮:languageLab
处理切换中英文言语的动作事情
- (UILabel *)languageLab{
if (!_languageLab) {
_languageLab = [[UILabel alloc]init];
_languageLab.textColor = rgb(51,51,51);
_languageLab.font = kBoldFont(15);
_languageLab.textAlignment = NSTextAlignmentRight;
// 依据配备进行显现
// typedef NS_ENUM(NSUInteger, HZLanguageType) {
// HZLanguageTypeSystem,
// HZLanguageTypeEnglish,
// HZLanguageTypeChineseSimple,
// };
// 获取配备信息
//设置选中的言语
if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeSystem) {
// self.seletedIndex=@0;
}
else if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeChineseSimple) {
// self.seletedIndex=@1;
// _languageLab.text = @"";
_languageLab.text = @"English";
}
else if ([HZLanguageManager defaultManager].currentLanguage==HZLanguageTypeEnglish) {
// self.seletedIndex=@2;
_languageLab.text = @"简体中文";
}else{
// _languageLab.text = @"简体中文";
}
//
// ti ti阿佳
//
_languageLab.userInteractionEnabled = YES;
[self addSubview:_languageLab];
__weak __typeof__(self) weakSelf = self;
[_languageLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(weakSelf).offset(36);
make.right.equalTo(weakSelf).offset(-kAdjustRatio(16));
make.size.mas_equalTo(CGSizeMake(kAdjustRatio(100), kAdjustRatio(40)));
}];
UITapGestureRecognizer *cutTap = [[UITapGestureRecognizer alloc] init];
// __weak __typeof__(self) weakSelf = self;
[[cutTap rac_gestureSignal] subscribeNext:^(id x) {
switch ([HZLanguageManager defaultManager].currentLanguage) {
case HZLanguageTypeSystem:
{
}
break;
case HZLanguageTypeEnglish:
{
[[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeChineseSimple];
weakSelf.languageLab.text = @"简体中文";
}
break;
case HZLanguageTypeChineseSimple:
{
[[HZLanguageManager defaultManager] changeLanguageType: HZLanguageTypeEnglish];
weakSelf.languageLab.text = @"English";
}
break;
default:
{
}
break;
}
[ AccountLoginView rootViewController4nil];
}];
[_languageLab addGestureRecognizer:cutTap];
}
return _languageLab;
}
+ (void) rootViewController4nil{
//毁掉 root
UIWindow *oldWindow=[UIApplication sharedApplication].keyWindow;
oldWindow.rootViewController=nil;
//新 root
UIWindow *newWindow = [UIApplication sharedApplication].keyWindow;
AccountLoginViewController *VC = [[AccountLoginViewController alloc]init];
HWNavigationController *NA = [[HWNavigationController alloc]initWithRootViewController:VC];
[AccountLoginView restoreRootViewController:NA newWindow:newWindow];
}
/**
UIModalTransitionStyleCoverVertical = 0, //从下到上盖上进入
UIModalTransitionStyleFlipHorizontal, //水平翻转
UIModalTransitionStyleCrossDissolve, //渐变出现
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_2
UIModalTransitionStylePartialCurl, //相似翻页的曲折
@param rootViewController <#rootViewController description#>
@param newWindow <#newWindow description#>
https://github.com/codeRiding/CRProject/blob/165886b8426fa43b52e76e659b8e18496e2fa8c8/CRProject/Classes/Expand/Tool/CRChangeVC.m
*/
+ (void)restoreRootViewController:(UIViewController *)rootViewController newWindow:(UIWindow*)newWindow
{
typedef void (^Animation)(void);
UIWindow* window = newWindow;
//
rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
//UIModalPresentationPopover
//UIModalPresentationNone
// rootViewController.modalPresentationStyle = UIModalPresentationOverFullScreen;//UIModalPresentationOverFullScreen
// UIModalTransitionStyleCoverVertical = 0,
// UIModalTransitionStyleFlipHorizontal __TVOS_PROHIBITED,
// UIModalTransitionStyleCrossDissolve,
// UIModalTransitionStylePartialCurl
// rootViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Animation animation = ^{
BOOL oldState = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
// [UIApplication sharedApplication].keyWindow.rootViewController = rootViewController;
[newWindow switchWithRootViewController:rootViewController];
[UIView setAnimationsEnabled:oldState];
};
//
[UIView transitionWithView:window
duration:0.5f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:animation
completion:nil];
}
4.3 本地化字符串指定参数次第
关于在中英文语法的差异,在本地化字符串的时分,我们常常需求调整stringWithFormat的参数次第
原理:在%和@中心加上数值(1(1,2$),数字代表参数的次第 文章:blog.csdn.net/z929118967/…
see also
- iOS精品资源汇总:(继续更新)
kunnan.blog.csdn.net/article/det…
- 合并develop到master,并打版别tag
blog.csdn.net/z929118967/…
更多内容请重视#小程序:iOS逆向
,只为你出现有价值的信息,专心于移动端技术研究领域。