iPhone에서 iPhone NSLocalizedString
의 언어로 문자열을 반환합니다. NSLocalizedString
앱을 기기와 다른 언어로 사용하기 위해 특정 언어 를 강제 로 사용할 수 있습니까?
iPhone에서 iPhone NSLocalizedString
의 언어로 문자열을 반환합니다. NSLocalizedString
앱을 기기와 다른 언어로 사용하기 위해 특정 언어 를 강제 로 사용할 수 있습니까?
답변:
NSLocalizedString()
(및 그 변형) "AppleLanguages"키에 액세스하여 NSUserDefaults
원하는 언어에 대한 사용자 설정을 확인하십시오. 언어 코드 배열을 반환합니다. 첫 번째 언어는 사용자가 전화로 설정 한 언어이며, 이후 언어는 기본 언어로 리소스를 사용할 수없는 경우 대체로 사용됩니다. (데스크톱에서 사용자는 시스템 환경 설정에서 사용자 정의 순서로 여러 언어를 지정할 수 있습니다)
원하는 경우 setObject : forKey : 메소드를 사용하여 사용자 고유의 언어 목록을 설정하여 사용자 고유의 애플리케이션에 대한 글로벌 설정을 대체 할 수 있습니다. 전역 설정 값보다 우선하며 지역화를 수행하는 응용 프로그램의 모든 코드로 반환됩니다. 이에 대한 코드는 다음과 같습니다.
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate
이렇게하면 영어와 프랑스어를 대체 언어로 사용하여 독일어를 응용 프로그램에서 선호하는 언어로 만들 수 있습니다. 응용 프로그램을 시작할 때 언젠가이를 호출하려고합니다. 언어 / 로캘 기본 설정에 대한 자세한 내용은 다음을 참조하십시오. 국제화 프로그래밍 주제 : 현재 언어 및 로캘 얻기
최근에 같은 문제가 발생하여 NSLocalizedString 전체를 시작하고 패치 하거나 새 언어가 작동하도록 앱을 강제로 다시 시작하고 싶지 않았습니다 . 나는 모든 것이 그대로 작동하기를 원했습니다.
내 솔루션은 기본 번들의 클래스를 동적으로 변경하고 적절한 번들을로드하는 것입니다.
헤더 파일
@interface NSBundle (Language)
+(void)setLanguage:(NSString*)language;
@end
이행
#import <objc/runtime.h>
static const char _bundle=0;
@interface BundleEx : NSBundle
@end
@implementation BundleEx
-(NSString*)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
NSBundle* bundle=objc_getAssociatedObject(self, &_bundle);
return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end
@implementation NSBundle (Language)
+(void)setLanguage:(NSString*)language
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
object_setClass([NSBundle mainBundle],[BundleEx class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
따라서 기본적으로 앱이 시작되고 첫 번째 컨트롤러를로드하기 전에 다음을 호출하십시오.
[NSBundle setLanguage:@"en"];
사용자가 설정 화면에서 원하는 언어를 변경하면 다시 전화하십시오.
[NSBundle setLanguage:@"fr"];
시스템 기본값으로 다시 설정하려면 nil을 전달하면됩니다.
[NSBundle setLanguage:nil];
즐겨...
스위프트 버전이 필요한 분들 :
var bundleKey: UInt8 = 0
class AnyLanguageBundle: Bundle {
override func localizedString(forKey key: String,
value: String?,
table tableName: String?) -> String {
guard let path = objc_getAssociatedObject(self, &bundleKey) as? String,
let bundle = Bundle(path: path) else {
return super.localizedString(forKey: key, value: value, table: tableName)
}
return bundle.localizedString(forKey: key, value: value, table: tableName)
}
}
extension Bundle {
class func setLanguage(_ language: String) {
defer {
object_setClass(Bundle.main, AnyLanguageBundle.self)
}
objc_setAssociatedObject(Bundle.main, &bundleKey, Bundle.main.path(forResource: language, ofType: "lproj"), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
나는 보통 이런 식으로이 작업을 수행하지만 프로젝트에 모든 지역화 파일이 있어야합니다.
@implementation Language
static NSBundle *bundle = nil;
+(void)initialize
{
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString *current = [[languages objectAtIndex:0] retain];
[self setLanguage:current];
}
/*
example calls:
[Language setLanguage:@"it"];
[Language setLanguage:@"de"];
*/
+(void)setLanguage:(NSString *)l
{
NSLog(@"preferredLang: %@", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
bundle = [[NSBundle bundleWithPath:path] retain];
}
+(NSString *)get:(NSString *)key alter:(NSString *)alternate
{
return [bundle localizedStringForKey:key value:alternate table:nil];
}
@end
iOS 9에서는 사용하지 마십시오. 전달 된 모든 문자열에 대해 nil을 반환합니다.
앱을 다시 시작하지 않고 genstring과 호환되는 언어 문자열을 업데이트 할 수있는 또 다른 솔루션을 찾았습니다.
이 매크로를 Prefix.pch에 넣으십시오.
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
지역화 된 문자열 사용이 필요한 곳 :
NSLocalizedStringFromTableInBundle(@"GalleryTitleKey", nil, currentLanguageBundle, @"")
언어 사용을 설정하려면 :
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
다음과 같은 연속 언어 호핑에서도 작동합니다.
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"fr"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"it"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:@"de"] forKey:@"AppleLanguages"];
NSLog(@"test %@", NSLocalizedStringFromTableInBundle(@"NewKey", nil, currentLanguageBundle, @""));
앞서 말했듯이 다음과 같이하십시오.
[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];
그러나 앱을 다시 시작하지 않으려면 (...) main.m
직전 의 주요 메소드에 줄을 넣으십시오 UIApplicationMain
.
NSAutoreleasePool * pool ..
릴리스 된 객체가 몇 개나 누출 된 후에 해당 라인을 삽입해야합니다 .
[[NSBundle mainBundle] URLForResource:withExtension:]
.
Swift 3의이 솔루션에 대해 어떻게 생각하십니까?
extension String {
func localized(forLanguage language: String = Locale.preferredLanguages.first!.components(separatedBy: "-").first!) -> String {
guard let path = Bundle.main.path(forResource: language == "en" ? "Base" : language, ofType: "lproj") else {
let basePath = Bundle.main.path(forResource: "Base", ofType: "lproj")!
return Bundle(path: basePath)!.localizedString(forKey: self, value: "", table: nil)
}
return Bundle(path: path)!.localizedString(forKey: self, value: "", table: nil)
}
}
간단한 사용법 :
"report".localized(forLanguage: "pl") //forced language
"report".localized() //default language selected by user in settings, in case when your app doesnt support selected lanaguage, the default one is selected, here is an english.
Brian Webster가 언급했듯이, 언어는 "언제나 응용 프로그램 시작시"설정해야합니다. 나는 생각 applicationDidFinishLaunching:
의 AppDelegate
나는 다른 모든 초기화를 할 곳이기 때문에, 그것을 할 수있는 적당한 장소이어야한다.
그러나 윌리엄 데니스 (William Denniss)가 언급했듯이 앱을 다시 시작한 후에 만 효과가있는 것 같습니다 .
그래도 코드를 주요 기능에 넣으면 정상적으로 작동하는 것 같습니다.
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Force language to Swedish.
[[NSUserDefaults standardUserDefaults]
setObject:[NSArray arrayWithObject:@"sv"]
forKey:@"AppleLanguages"];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
이에 대한 의견을 부탁드립니다.
[[NSUserDefaults standardUserDefaults] synchronize];
호출 한 후setObject:forKey:
마우로 델리오의 방법이 가장 좋습니다. 또한 Project_Prefix.pch에 다음을 추가했습니다.
#import "Language.h"
#define MyLocalizedString(key, alt) [Language get:key alter:alt]
따라서 NSLocalizedString을 사용하는 표준 메소드를 사용하려는 경우 모든 파일에서 빠른 구문 대체를 수행 할 수 있습니다.
NSLocalizedString()
AppleLanguages
표준 사용자 기본값 ( [NSUserDefaults standardUserDefaults]
) 에서 키 값을 읽습니다 . 이 값을 사용하여 런타임시 기존의 모든 현지화 중에서 적절한 현지화를 선택합니다. Apple은 앱을 시작할 때 사용자 기본 사전을 빌드 할 때 시스템 환경 설정에서 원하는 언어 키를 찾아 그 값을 복사합니다. 예를 들어 OS X에서 언어 설정을 변경해도 앱 실행에 영향을 미치지 않는 이유는 그 이후에 시작된 앱에만 해당됩니다. 복사 한 후에는 설정이 변경되어 값이 업데이트되지 않습니다. 그렇기 때문에 언어를 변경하면 iOS가 모든 앱을 다시 시작합니다.
그러나 사용자 기본값 사전의 모든 값 은 명령 행 인수로 겹쳐 쓸 수 있습니다. 의 NSUserDefaults
설명서를 참조하십시오 NSArgumentDomain
. 여기에는 앱 환경 설정 (.plist) 파일에서로드 된 값도 포함됩니다. 테스트를 위해 한 번만 값을 변경하려는 경우이 방법을 사용하는 것이 좋습니다 .
따라서 테스트를 위해 언어를 변경하려면 코드를 변경하고 싶지 않을 것입니다 (나중에이 코드를 제거하는 것을 잊어 버린 경우 ...) 대신 Xcode에게 명령 줄 매개 변수 ( 예 : 스페인어 현지화 사용) :
코드를 전혀 만질 필요가 없습니다. 다른 언어에 대해 다른 체계를 만들기 만하면 체계를 전환하여 한 언어로 한 번, 다른 언어로 한 번만 앱을 시작할 수 있습니다.
Options
Apple이 제공하는 최신 Xcode 버전과 마찬가지로 언어를 재정의하지 마십시오 게다가.
나는 당신이 사용할 수있는 솔루션을 생각해 냈습니다 NSLocalizedString
. NSBundle
call 카테고리를 작성합니다 NSBundle+RunTimeLanguage
. 인터페이스는 이렇습니다.
// NSBundle+RunTimeLanguage.h
#import <Foundation/Foundation.h>
@interface NSBundle (RunTimeLanguage)
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName;
@end
구현은 다음과 같습니다.
// NSBundle+RunTimeLanguage.m
#import "NSBundle+RunTimeLanguage.h"
#import "AppDelegate.h"
@implementation NSBundle (RunTimeLanguage)
- (NSString *)runTimeLocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString *path= [[NSBundle mainBundle] pathForResource:[appDelegate languageCode] ofType:@"lproj"];
NSBundle *languageBundle = [NSBundle bundleWithPath:path];
NSString *localizedString=[languageBundle localizedStringForKey:key value:key table:nil];
return localizedString;
}
@end
NSBundle+RunTimeLanguage.h
를 사용하는 파일로 가져 오기 를 추가하는 것보다 NSLocalizedString
.
보시다시피 내 languageCode를의 속성에 저장 AppDelegate
합니다. 원하는 곳에 저장할 수 있습니다.
내가 싫어하는 것은 NSLocalizedString
마르코가 재정의 했다는 경고입니다 . 아마도 누군가 가이 부분을 고치도록 도울 수 있습니다.
#undef NSLocalizedString
하기 직전 #define
에 추가하십시오
가장 먼저해야 할 일은 두 가지 언어 (이 예에서는 영어와 프랑스어)로 앱을 현지화하는 것입니다.
코드에서을 NSLocalizedString(key, comment)
사용하는 대신 MYLocalizedString(key, comment)
다음과 같이 정의 된 매크로를 사용 하십시오.
#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
이 MYLocalizationSystem
싱글 톤은 :
사용자가 프랑스어로 응용 프로그램 언어를 변경 한 경우 전화 [[MYLocalizationSystem sharedInstance] setLanguage:@"fr"];
- (void)setLanguage:(NSString *)lang
{
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"];
if (!path)
{
_bundle = [NSBundle mainBundle];
NSLog(@"Warning: No lproj for %@, system default set instead !", lang);
return;
}
_bundle = [NSBundle bundleWithPath:path];
}
이 예제 에서이 메소드는 현지화 된 번들을 fr.lproj로 설정합니다.
현지화 된 번들을 설정 한 후에는이 방법을 사용하여 현지화 된 올바른 문자열을 얻을 수 있습니다.
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
{
// bundle was initialized with [NSBundle mainBundle] as default and modified in setLanguage method
return [self.bundle localizedStringForKey:key value:value table:nil];
}
이것이 도움이되기를 바랍니다.
이 기사에서는 NSWinery.io 에서 자세한 내용을 확인할 수 있습니다.
스위프트 3 확장 :
extension Locale {
static var preferredLanguage: String {
get {
return self.preferredLanguages.first ?? "en"
}
set {
UserDefaults.standard.set([newValue], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
}
}
}
extension String {
var localized: String {
var result: String
let languageCode = Locale.preferredLanguage //en-US
var path = Bundle.main.path(forResource: languageCode, ofType: "lproj")
if path == nil, let hyphenRange = languageCode.range(of: "-") {
let languageCodeShort = languageCode.substring(to: hyphenRange.lowerBound) // en
path = Bundle.main.path(forResource: languageCodeShort, ofType: "lproj")
}
if let path = path, let locBundle = Bundle(path: path) {
result = locBundle.localizedString(forKey: self, value: nil, table: nil)
} else {
result = NSLocalizedString(self, comment: "")
}
return result
}
}
용법:
Locale.preferredLanguage = "uk"
label.text = "localizedKey".localized
.pch 파일 에서 다음을 정의하십시오.
#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]
#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")
어쩌면 당신은 이것을 보완해야합니다 (#import 후 .pch 파일에서) :
extern NSBundle* bundle; // Declared on Language.m
#ifdef NSLocalizedString
#undef NSLocalizedString
// Delete this line to avoid warning
#warning "Undefining NSLocalizedString"
#endif
#define NSLocalizedString(key, comment) \
[bundle localizedStringForKey:(key) value:@"" table:nil]
이 작업을 수행하려는 현지화 된 문자열 세트로 하위 번들을 빌드 한 다음이를 사용 NSLocalizedStringFromTableInBundle()
하여로드 할 수 있습니다. (이것은 앱에서 수행 할 수있는 일반적인 UI 현지화와는 별도의 내용이라고 가정합니다.)
내 경우에는 현지화 된 두 파일 인 ja와 en이 있습니다.
그리고 나는 시스템에서 선호하는 언어가 en 또는 ja가 아닌 경우 en으로 강제하고 싶습니다.
main.m 파일을 편집하겠습니다
첫 번째 기본 설정이 en인지 ja인지 확인하고, 그렇지 않은 경우 두 번째 기본 설정 언어를 en으로 변경합니다.
int main(int argc, char *argv[])
{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString *lang = [[NSLocale preferredLanguages] objectAtIndex:0];
if (![lang isEqualToString:@"en"] && ![lang isEqualToString:@"ja"]){
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[NSLocale preferredLanguages]];
[array replaceObjectAtIndex:1 withObject:@"en"];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
다음과 같이 할 수 있습니다 :
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];
NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):
응용 프로그램 을 종료하거나 다시 시작 하지 않고 언어를 변경 하려는 Tudorizer의 답변을 기반으로 합니다.
매크로 대신 특정 언어 코드가 있는지 확인하기 위해 선호하는 언어에 액세스하기위한 클래스를 사용하십시오.
다음은 iOS 9에서 작동하는 현재 언어 번들을 얻는 데 사용되는 클래스입니다.
@implementation OSLocalization
+ (NSBundle *)currentLanguageBundle
{
// Default language incase an unsupported language is found
NSString *language = @"en";
if ([NSLocale preferredLanguages].count) {
// Check first object to be of type "en","es" etc
// Codes seen by my eyes: "en-US","en","es-US","es" etc
NSString *letterCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([letterCode rangeOfString:@"en"].location != NSNotFound) {
// English
language = @"en";
} else if ([letterCode rangeOfString:@"es"].location != NSNotFound) {
// Spanish
language = @"es";
} else if ([letterCode rangeOfString:@"fr"].location != NSNotFound) {
// French
language = @"fr";
} // Add more if needed
}
return [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]];
}
/// Check if preferred language is English
+ (BOOL)isCurrentLanguageEnglish
{
if (![NSLocale preferredLanguages].count) {
// Just incase check for no items in array
return YES;
}
if ([[[NSLocale preferredLanguages] objectAtIndex:0] rangeOfString:@"en"].location == NSNotFound) {
// No letter code for english found
return NO;
} else {
// Tis English
return YES;
}
}
/* Swap language between English & Spanish
* Could send a string argument to directly pass the new language
*/
+ (void)changeCurrentLanguage
{
if ([self isCurrentLanguageEnglish]) {
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
} else {
[[NSUserDefaults standardUserDefaults] setObject:@[@"en"] forKey:@"AppleLanguages"];
}
}
@end
위의 클래스를 사용하여 문자열 파일 / 이미지 / 비디오 등을 참조하십시오.
// Access a localized image
[[OSLocalization currentLanguageBundle] pathForResource:@"my_image_name.png" ofType:nil]
// Access a localized string from Localizable.strings file
NSLocalizedStringFromTableInBundle(@"StringKey", nil, [OSLocalization currentLanguageBundle], @"comment")
아래처럼 인라인으로 언어를 변경하거나 위 클래스에서 "changeCurrentLanguage"메소드를 업데이트하여 새 언어를 참조하는 문자열 매개 변수를 가져 오십시오.
[[NSUserDefaults standardUserDefaults] setObject:@[@"es"] forKey:@"AppleLanguages"];
신속한 4에서는 라이브러리를 다시 시작하거나 사용할 필요없이 해결했습니다.
많은 옵션을 시도한 후 번역하려는 LocalTo.String (문자열 파일)의 stringToLocalize와 번역하려는 언어를 전달하는이 함수를 찾았습니다. Strings 파일에있는 String :
func localizeString (stringToLocalize: String, language: String) -> String
{
let path = Bundle.main.path (forResource: language, ofType: "lproj")
let languageBundle = Bundle (path: path!)
return languageBundle! .localizedString (forKey: stringToLocalize, value: "", table: nil)
}
이 기능을 고려하여 Swift 파일에서이 기능을 만들었습니다.
struct CustomLanguage {
func createBundlePath () -> Bundle {
let selectedLanguage = //recover the language chosen by the user (in my case, from UserDefaults)
let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
return Bundle(path: path!)!
}
}
전체 앱과 나머지 ViewController의 각 문자열에서 액세스하는 대신 다음을 수행하십시오.
NSLocalizedString ("StringToLocalize", comment: “")
나는 그것을 대체했다
let customLang = CustomLanguage() //declare at top
let bundleLanguage = customLang.createBundle()
NSLocalizedString("StringToLocalize", tableName: nil, bundle: bundleLanguage, value: "", comment: “”) //use in each String
그것이 가장 좋은 방법인지는 모르겠지만 매우 간단하다는 것을 알았습니다. 그것이 도움이되기를 바랍니다.
이 함수는 현재 언어에 대한 지역화 된 문자열을 얻으려고 시도하며 찾을 수 없으면 영어를 사용하여 가져옵니다.
- (NSString*)L:(NSString*)key
{
static NSString* valueNotFound = @"VALUE_NOT_FOUND";
static NSBundle* enBundle = nil;
NSString* pl = [NSLocale preferredLanguages][0];
NSString* bp = [[NSBundle mainBundle] pathForResource:pl ofType:@"lproj"];
NSBundle* b = [NSBundle bundleWithPath:bp];
NSString* s = [b localizedStringForKey:key value:valueNotFound table:nil];
if ( [s isEqualToString:valueNotFound] ) {
if ( !enBundle ) {
bp = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
enBundle = [NSBundle bundleWithPath:bp];
}
s = [enBundle localizedStringForKey:key value:key table:nil];
}
return s;
}
iOS에서 공식적으로 지원하지 않는 언어 (시스템 설정의 언어 섹션에 나열되지 않은 언어)에 대한 지원을 추가하고 싶었습니다. Brian Webster와 geon 이 Apple의 Internationalization Tutorial 과 몇 가지 힌트를 따르면이 코드를 만들었습니다 (main.m에 넣습니다).
int main(int argc, char * argv[]) {
@autoreleasepool {
// Grab regional settings locale, for Slovenian this is either sl_SI or en_SI
NSLocale *locale = [NSLocale currentLocale];
NSString *ll = [locale localeIdentifier]; // sl_SI
// Grab the first part of language identifier
NSArray *comp = [ll componentsSeparatedByString:@"_"];
NSString *ll1 = @"en";
if (comp.count > 0) {
ll1 = comp[0]; // sl, en, ...
}
// Check if we already saved language (user can manually change it inside app for example)
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"]) {
// Slovenian (Slovenia), Slovenia
if ([ll isEqualToString:@"sl_SI"] || [ll isEqualToString:@"en_SI"]) {
ll1 = @"sl-SI"; // This is the part of localized path for Slovenian language that Xcode generates
}
// Add more unsupported languages here...
[[NSUserDefaults standardUserDefaults] setObject:ll1 forKey:@"SelectedLanguage"]; // Save language
}
else {
// Restore language as we have previously saved it
ll1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"SelectedLanguage"];
}
// Overwrite NSLocalizedString and StoryBoard language preference
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:ll1, @"en", @"fr", nil] forKey:@"AppleLanguages"];
// Make sure settings are stored to disk
[[NSUserDefaults standardUserDefaults] synchronize];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
이것은 스토리 보드 및 NSLocalizedString 코드 모두에 잘 작동합니다. 이 코드는 사용자가 나중에 앱 내부에서 언어를 수동으로 변경할 수있는 옵션이 있다고 가정합니다.
물론 적절한 스토리 보드 번역과 Localizable.strings 번역을 추가하는 것을 잊지 마십시오 (해당 방법은 위의 Apple 페이지 링크 참조).
이 문제에 대한 적절한 해결책이 있으며 응용 프로그램을 다시 시작할 필요가 없습니다.
https://github.com/cmaftuleac/BundleLocalization
이 구현은 NSBundle 내부를 조정하여 작동합니다. NSBundle 객체의 인스턴스에서 localizedStringForKey 메서드를 재정의 한 다음 다른 언어의 다른 번들에서이 메서드를 호출하는 것이 좋습니다. 모든 유형의 리소스와 완벽하게 호환되는 단순하고 우아합니다.
NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
당신이 무엇이든간에, 가장 좋은 방법은 지정된 언어에 대해 short_name을 가져 오는 것입니다 : 예 : fr, en, nl, de, it 등 ... 그리고 전역 값에 동일하게 할당하십시오.
선택 도구보기가 드롭 다운 메뉴처럼 팝업되도록하고 (선택 목록이 아래에서 언어 목록과 함께 표시되는 단추 조합) 원하는 언어를 선택하십시오. 짧은 이름을 내부에 저장하십시오. LocalisedString이라는 .h + .m 파일을 만듭니다.
short_name의 글로벌 값을 LocalisedString.m에서 확보 한 값과 동일하게 설정하십시오. 필요한 언어가 선택되면 필요한 언어에 대한 프로젝트 서브 디렉토리를 작성하도록 NSBundlePath를 지정하십시오. 예를 들어, nl.proj, en.proj.
특정 proj 폴더가 선택되면 해당 언어의 현지화 된 문자열을 호출하고 언어를 동적으로 변경하십시오.
규칙이 깨지지 않았습니다.
Swift의 main.swift
경우 앱을 실행하기 전에 파일을 재정의하고 UserDefaults 문자열을 설정할 수 있습니다 . 이렇게하면 원하는 효과를보기 위해 앱을 다시 시작할 필요가 없습니다.
import Foundation
import UIKit
// Your initialisation code here
let langCultureCode: String = "LANGUAGE_CODE"
UserDefaults.standard.set([langCultureCode], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
파일 @UIApplicationMain
에서 제거와 함께 쌍을 이룹니다 AppDelegate.swift
.