參考:https://stackoverflow.com/questions/9416923/ios-how-to-change-app-language-programmatically-without-restarting-the-app
核心是使用
NSString *path = [[NSBundle mainBundle]pathForResource:currentLanguage ofType:@"lproj"];
if (path) {
localeBundle = [NSBundle bundleWithPath:path];
}else{
localeBundle= [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj" ]];
}
改變localeBundle的值
思路:
1.使用
NSLocalizedStringFromTableInBundle(@"TNC_title", nil, localeBundle] , @""),
可以實時變換不同的國際化檔案
*國際化檔案一般在檔案目錄系統是放在lproj字尾的檔案夾中的:形式如zh-Hant.lproj(繁體)zh-Hants.lproj(簡體)en.lproj(英文)
是以在上文的pathForResource:currentLanguage中也需要對應相應的檔案名。
2.再重新整理一遍UI的text擷取
基于項目的代碼示例:
建一個工具類.h:
#import <Foundation/Foundation.h>
@interface LanguageTool : NSObject
+(instancetype)getInstance;
- (NSBundle *)getLocaleBundle;
-(NSString *)getTap;
-(NSString *)getCurrentLanguage;
-(void)changeLanguage:(NSString*)language;
@end
.m:
#import "LanguageTool.h"
#import "SessionManager.h"
#define CNS @"zh"
#define EN @"en"
#define tap @"change_language"
static NSBundle *localeBundle = nil;
static NSString *currentLanguage = nil;
@interface LanguageTool()
@end
@implementation LanguageTool
//單例
+(instancetype)getInstance{
static LanguageTool *manager = nil;
static dispatch_once_t onceToken = 0;
dispatch_once(&onceToken, ^{
manager = [[LanguageTool alloc] init];
});
return manager;
}
-(void)changeLanguage:(NSString*)language{
currentLanguage = language;
NSString *path = [[NSBundle mainBundle]pathForResource:language ofType:@"lproj"];
if (path && ![@"en" isEqualToString:language]) {
localeBundle = [NSBundle bundleWithPath:path];
}else{
localeBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj" ]];
}
}
//這個方法的目的是,如果什麼都沒有選擇,就使用系統預設語言,否則使用使用者選擇的語言,并且不會因為關閉app而改變。
-(void)judgeLanguage{
//Get last change language
NSString *lastChangeLanguage = nil;
//使用一個持久化,保持上次的語言選擇
lastChangeLanguage = [SessionManager getSession:[SessionManager getLastLanguageTap]];
NSLog(@"last chage language: %@",lastChangeLanguage);
//語言優先級:currentLanguage > lastChangeLanguage > system default language
//user 沒有設定語言時:擷取系統預設語言
if (!lastChangeLanguage) {
if (!currentLanguage) {
//擷取系統預設語言:
//截取:zh-Hant-HK 去掉區域保留:zh-Hant
NSLog(@"-------system language:%@",[NSLocale preferredLanguages][0]);
currentLanguage = [[NSLocale preferredLanguages][0] substringToIndex:2];
if ([currentLanguage containsString:@"zh"]) {
currentLanguage = [NSString stringWithFormat:@"%@%@",currentLanguage,@"-Hant"];
}
}
}else if(!currentLanguage){
//目前沒有切換語言,app内有設定語言,優先app内語言
currentLanguage = lastChangeLanguage;
}
}
- (NSBundle *)getLocaleBundle{
[self judgeLanguage];
NSLog(@"------current language :%@",currentLanguage);
NSLog(@"-------system language:%@",[NSLocale preferredLanguages][0]);
NSString *path = [[NSBundle mainBundle]pathForResource:currentLanguage ofType:@"lproj"];
if (path) {
localeBundle = [NSBundle bundleWithPath:path];
}else{
localeBundle= [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj" ]];
}
return localeBundle;
}
//标記
-(NSString *)getTap{
return tap;
}
-(NSString *)getCurrentLanguage{
// if (!currentLanguage) {
// //截取:zh-Hant-HK 去掉區域保留:zh-Hant
// currentLanguage = [[NSLocale preferredLanguages][0] substringToIndex:2];
// }
[self judgeLanguage];
NSLog(@"current language:%@",currentLanguage);
return currentLanguage;
}
@end
使用在需要切換語言的地方點選後調用:
//如果目前是英語就切換成繁體
if ([@"en" isEqualToString:[[LanguageTool getInstance] getCurrentLanguage]]) {
[self changeLanguage:@"zh-Hant"];
} else {
[self changeLanguage:@"en"];
}
//通知其他頁面也切換語言
[self callLanguageChangeNotificationReceiver];
-(void)changeLanguage:(NSString*)language{
[[LanguageTool getInstance] changeLanguage:language];
//重新整理某些UI text
[self initTableResource];
[_tableView reloadData];
}
//例如這樣重新整理:
-(void)initTableResource{
_dataArray = @[NSLocalizedStringFromTableInBundle(@"Home", nil, [[LanguageTool getInstance] getLocaleBundle] , @""),
NSLocalizedStringFromTableInBundle(@"customization", nil, [[LanguageTool getInstance] getLocaleBundle] , @"")
,
NSLocalizedStringFromTableInBundle(@"TNC_title", nil, [[LanguageTool getInstance] getLocaleBundle] , @""),
NSLocalizedStringFromTableInBundle(@"localizable", nil, [[LanguageTool getInstance] getLocaleBundle] , @"")];
NSString *app_version = [[[NSBundle mainBundle]infoDictionary] objectForKey:@"CFBundleShortVersionString"];
_app_version_string = [NSString stringWithFormat:@"%@ %@",NSLocalizedStringFromTableInBundle(@"slider_version_info", nil, [[LanguageTool getInstance] getLocaleBundle] , @""),app_version];
if (_version_label) {
_version_label.text = _app_version_string;
}
[self initContentVersionLabel];
}
//設定通知:
-(void)callLanguageChangeNotificationReceiver{
[SessionManager setSession:[SessionManager getLastLanguageTap]
value:[[LanguageTool getInstance] getCurrentLanguage]];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:[[LanguageTool getInstance] getTap] object:nil];
}
被通知的頁面接收通知,并重新整理一下UI,操作并不複雜:
-(void)initNotification{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTextView) name:[[LanguageTool getInstance]getTap] object:nil];
}
-(void)refreshTextView{
_tncTextView.text = NSLocalizedStringFromTableInBundle(@"TNC_text", nil, [[LanguageTool getInstance] getLocaleBundle] , @"");
_navItem.title = NSLocalizedStringFromTableInBundle(@"TNC_title", nil, [[LanguageTool getInstance] getLocaleBundle] , @"");
}