NSLocalizedString이 특정 언어를 사용하도록하는 방법


답변:


261

NSLocalizedString()(및 그 변형) "AppleLanguages"키에 액세스하여 NSUserDefaults원하는 언어에 대한 사용자 설정을 확인하십시오. 언어 코드 배열을 반환합니다. 첫 번째 언어는 사용자가 전화로 설정 한 언어이며, 이후 언어는 기본 언어로 리소스를 사용할 수없는 경우 대체로 사용됩니다. (데스크톱에서 사용자는 시스템 환경 설정에서 사용자 정의 순서로 여러 언어를 지정할 수 있습니다)

원하는 경우 setObject : forKey : 메소드를 사용하여 사용자 고유의 언어 목록을 설정하여 사용자 고유의 애플리케이션에 대한 글로벌 설정을 대체 할 수 있습니다. 전역 설정 값보다 우선하며 지역화를 수행하는 응용 프로그램의 모든 코드로 반환됩니다. 이에 대한 코드는 다음과 같습니다.

[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:@"de", @"en", @"fr", nil] forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize]; //to make the change immediate

이렇게하면 영어와 프랑스어를 대체 언어로 사용하여 독일어를 응용 프로그램에서 선호하는 언어로 만들 수 있습니다. 응용 프로그램을 시작할 때 언젠가이를 호출하려고합니다. 언어 / 로캘 기본 설정에 대한 자세한 내용은 다음을 참조하십시오. 국제화 프로그래밍 주제 : 현재 언어 및 로캘 얻기


4
이것은 나를 위해 작동하지 않습니다. 무엇이든 기본 언어를 사용합니다.
quano

50
데니스; 앱을 시작 하기 전에 언어 기본 설정을 설정하면 더 잘 작동하는 것 같습니다 . UIApplicationMain ()이 호출되기 전에 main () 함수에서 수행합니다. 실제로 실행되면 사용 된 언어가 변경되지 않고 다음에 기본 설정을 설정합니다.
geon

3
UIKit을 초기화하기 전에 언어를 설정해야하며 완전한 언어 + 지역 로케일을 지정해야합니다. 완전한 예제를 보려면이를 확인하십시오. blog.federicomestrone.com/2010/09/15/…
fedmest

18
main ()에서 수행하면 AppleLanguages를 설정하면 런타임에 언어가 변경됩니다. 그러나 ... 응용 프로그램을 처음 설치하면 nsuserdefaults가 초기화 된 후 초기화됩니다 .UIApplicationMain ()이 호출되면 이전에 설정된 AppleLanguages를 무시하고 원하는 언어를 보려면 응용 프로그램을 강제로 다시 시작해야합니다.
JohnPayne

3
Localizable.stringsdict에 정의 된 복수 항목에서는 작동하지 않습니다. 가능한 해결책이 있는지 아십니까?
Mihai Fratu

147

최근에 같은 문제가 발생하여 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)
    }
}

7
안녕하세요 @Wirsing, 이것은 지금까지 훌륭하게 작동합니다. 스토어에 하나의 앱을 업로드했는데 Apple이 불평하지 않습니다.
Gilad Novik

7
이것은 훌륭한 해결책입니다. 나는 이것을 여기에서도 참조했습니다. medium.com/ios-apprentice/905e4052b9de
James Tang

1
안녕하세요 @JamesTang, 참조 및 게시물 주셔서 감사합니다-현지화에 관한 유용한 정보가 많이 있습니다.
Gilad Novik

3
@Gilad 방법은 동적 문자열 (localizable.strings에 정의 된 문자열)에는 완벽하지만 스토리 보드 버튼 및 레이블은 기본 방법에서만 작동합니다. UI 컨트롤 현지화를 포함하도록 답변을 확장 할 수 있습니까? [NSBundle setLanguage : @ "??"];를 호출 한 후 스토리 보드를 새로 고침하지 않고 닫는 방법을 의미합니다.
Jawad Al Shaikh

2
XIB / 스토리 보드의 경우 : 뷰를로드하기 전에이 메소드를 호출해야합니다. 뷰가 업데이트되는 한 내 경우에는 단순히 뷰 컨트롤러를 다시로드했습니다 (탐색 컨트롤러에 넣고 컨트롤러를 교체했습니다. 다시로드하면 새로운 번역 된 문자열이 나타납니다). 나는 그것을 위해 cocoapod에서 일하고 있습니다. 아마도 예제를 포함시킬 것입니다. 지켜봐 주시기 바랍니다 ...
Gilad Novik

137

나는 보통 이런 식으로이 작업을 수행하지만 프로젝트에 모든 지역화 파일이 있어야합니다.

@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

1
+1. 이것은 다른 곳에서는 보지 못한 정말 좋은 트릭입니다. 로컬라이제이션 폴더 중 하나에서 "하위 번들"을 생성하면 NSLocalizedString을 우회하는 것으로 래핑하는 한 문자열이 제대로 작동 할 수 있습니다.
Ben Zotto

4
훌륭한 마우로. 프로젝트 외부의 파일에서도 작동 할 수 있음을 알았습니다. 어떤 이유로 든 (내 경우와 같이) 네트워크에서 문자열 파일을 다운로드하여 'Documents'디렉토리에 저장해야합니다 (Documents / en.lproj / Localizable.strings, Documents / fr.lproj / 지역화 가능. 문자열, ...). NSBundle을 만들 수도 있습니다. 경로에이 코드를 사용하십시오. NSString * path = [NSHomeDirectory () stringByAppendingPathComponent : [NSString stringWithFormat : @ "/ Documents / % @. lproj", l, nil]];
arnaud del.

1
아래의 Alessandro의 기여와 함께 이것이 최선의 접근법이라고 생각합니다. 너무 관입 적이 지 않으므로 다시 시작할 필요가 없습니다.
PKCLsoft

1
내가 뭘 잘못하고 있죠? NSObject를 상속하는 Language 클래스를 만들었고 이것을 구현에 넣고 메서드 이름을 .h에 넣은 다음 [Language setLanguage : @ "es"]; 내 언어 변경 버튼에서 코드 실행 (버튼 메서드가 호출되고 언어 클래스로 이동)하지만 아무것도하지 않습니다. localizable.strings (Spanish)도 설정했습니다. 그러나 그것은 많은 다른 사람들을 위해 일하는 것 같습니다. 누군가 나를 위해 바보를 제발하십시오.
SirRupertIII

1
@KKendall 당신은 이것을 다음과 같이 부릅니다 : [Language setLanguage : @ "es"]; NSString * stringToUse = [언어 get : @ "텍스트"alter : nil];
Mikrasya

41

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, @""));

2
@ powerj1984 : 아니요, 소스 파일의 문자열 만 변경합니다. xib 언어를 변경하려면 선택한 언어 번들에서 xib를 수동으로 다시로드해야합니다.
gklka

@gklka Tudozier가 제공 한 단계를 따르지만 XIB를 수동으로 다시로드한다고 말한 것처럼 XIB가 언어를 변경하지 않습니다. 실제로 XIB를 다시로드한다는 의미는 무엇입니까?
Dk Kumar

@DkKumar : 이와 비슷한 것을해야합니다 : stackoverflow.com/questions/21304988/…
gklka

@gklka 귀하의 답변이 정확하고 귀하의 답변에 설명 된 것과 동일한 단계를 수행했지만 문제는 번들 경로를 변경하면 번들에서 모든 리소스 (예 : XIB에서 사용되는 .png 파일)를 찾는 것보다 동일한 번들이므로 en.lproj, es.lproj 등과 같은 모든 번들의 이미지 폴더를 복사해야합니다. IPA 크기를 늘리는 데 영향을 미치므로이 문제를 극복 할 수있는 방법이 있습니까? 당신이 게시물에 말했듯이, 내가 이것을 시도하고 같은 저를 도와 더 많은이 덕분에 당신을하자,
DK 쿠마

1
이것은 iOS 9에서 끔찍하게 손상되어 모든 문자열에 대해 null을 반환합니다.
Alex Zavatone

32

앞서 말했듯이 다음과 같이하십시오.

[[NSUserDefaults standardUserDefaults] setObject: [NSArray arrayWithObjects:@"el", nil] forKey:@"AppleLanguages"];

그러나 앱을 다시 시작하지 않으려면 (...) main.m직전 의 주요 메소드에 줄을 넣으십시오 UIApplicationMain.


2
매우 유용한 답변! PS 초보자가 아닌 사람에게는 분명하게 들릴 수 있지만 자동 NSAutoreleasePool * pool ..릴리스 된 객체가 몇 개나 누출 된 후에 해당 라인을 삽입해야합니다 .
pt2ph8

1
중요 : 전화를 걸면 작동하지 않습니다 [[NSBundle mainBundle] URLForResource:withExtension:].
Kof

3
Swift를 사용하면 main.m이없는 것은 어떻습니까?
turingtest에

@turingtested 신속하고 스토리 보드를 사용해 보셨습니까?
iDevAmit

안녕하세요, 서버에서 오는 동적 텍스트를 현지화하는 방법, 응용 프로그램에서 모든 텍스트를 중국어 간체로 표시해야하지만 영어로 오는 중국어로 텍스트를 표시하는 방법. 도와 줘요.
Mahesh Narla

31

앱에서 특정 언어를 선택하여 사용하는 요령 NSLocalizedString은 선택한 언어에 따라 특정 번들을 사용 하도록 강요하는 것입니다.

다음은 iOS 학습 앱 에서이 학습 고급 현지화를 위해 작성한 게시물입니다.

다음은 iOS 앱에서 하나의 샘플 앱 고급 지역화 코드입니다.


iOS7에서도 작동합니다 .Brian의 솔루션에서 iOS로 언어 옵션을 다시 무시하는 것처럼 보이기 때문에 처음으로 언어 설정을 고수 한 것처럼 보입니다. 당신의 솔루션은 매력처럼 작동합니다!
haxpor

14

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.

안녕하세요, 서버에서 오는 동적 텍스트를 현지화하는 방법, 응용 프로그램에서 모든 텍스트를 중국어 간체로 표시해야하지만 영어로 오는 중국어로 텍스트를 표시하는 방법. 도와 줘요.
Mahesh Narla

이것은 훌륭한 답변입니다.)
Bartłomiej Semańczyk

좋은 날 answer.helped
딜립 Tiwari 보낸 사람을

13

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;
}

이에 대한 의견을 부탁드립니다.


내 구현에는 사용자 설정 가능한 것입니다 - 나는 그냥 알려주는 대화 상자가 나타 그래서 그들이 다시 시작해야합니다 :)
윌리엄 Denniss

현지화 된 Default.png 이미지를 제외하고 거의 모든 경우에 작동합니다.
Lukasz

2
사용자가 언어를 설정하도록하고 앱을 다시 시작하라고하면 NSUserDefaults가 너무 빨리 다시 시작되면 저장되지 않을 수 있습니다. 대부분의 사용자는 그렇게 빠르지는 않지만 앱을 테스트 할 때 너무 빠를 수 있으며 결과적으로 일관성이없는 동작을 볼 수 있습니다. 언어 전환이 때때로 작동하고 때로는 작동하지 않는 이유를 이해하는 데 몇 시간이 걸렸습니다.
arlomedia

3
즉 문제, 바로 사용이 아니다 [[NSUserDefaults standardUserDefaults] synchronize];호출 한 후setObject:forKey:
벤 남작을

11

마우로 델리오의 방법이 가장 좋습니다. 또한 Project_Prefix.pch에 다음을 추가했습니다.

#import "Language.h"    
#define MyLocalizedString(key, alt) [Language get:key alter:alt]

따라서 NSLocalizedString을 사용하는 표준 메소드를 사용하려는 경우 모든 파일에서 빠른 구문 대체를 수행 할 수 있습니다.


1
또한 그의 방법을 좋아하고 png 이미지를로드하는 방법을 추가합니다. + (UIImage ) imageNamed : (NSString *) imageFileName {NSString fullPath = [번들 pathForResource : imageFileName ofType : @ "png"]; UIImage * imageObj = [[UIImage alloc] initWithContentsOfFile : fullPath]; [imageObj 자동 릴리스]를 반환합니다. }
Jagie

11

NSLocalizedString()AppleLanguages표준 사용자 기본값 ( [NSUserDefaults standardUserDefaults]) 에서 키 값을 읽습니다 . 이 값을 사용하여 런타임시 기존의 모든 현지화 중에서 적절한 현지화를 선택합니다. Apple은 앱을 시작할 때 사용자 기본 사전을 빌드 할 때 시스템 환경 설정에서 원하는 언어 키를 찾아 그 값을 복사합니다. 예를 들어 OS X에서 언어 설정을 변경해도 앱 실행에 영향을 미치지 않는 이유는 그 이후에 시작된 앱에만 해당됩니다. 복사 한 후에는 설정이 변경되어 값이 업데이트되지 않습니다. 그렇기 때문에 언어를 변경하면 iOS가 모든 앱을 다시 시작합니다.

그러나 사용자 기본값 사전의 모든 값 은 명령 행 인수로 겹쳐 쓸 수 있습니다. 의 NSUserDefaults설명서를 참조하십시오 NSArgumentDomain. 여기에는 앱 환경 설정 (.plist) 파일에서로드 된 값도 포함됩니다. 테스트를 위해 한 번만 값을 변경하려는 경우이 방법을 사용하는 것이 좋습니다 .

따라서 테스트를 위해 언어를 변경하려면 코드를 변경하고 싶지 않을 것입니다 (나중에이 코드를 제거하는 것을 잊어 버린 경우 ...) 대신 Xcode에게 명령 줄 매개 변수 ( 예 : 스페인어 현지화 사용) :

여기에 이미지 설명을 입력하십시오

코드를 전혀 만질 필요가 없습니다. 다른 언어에 대해 다른 체계를 만들기 만하면 체계를 전환하여 한 언어로 한 번, 다른 언어로 한 번만 앱을 시작할 수 있습니다.


장치 pref.에 다시로드 된 후 처음으로 만 작동합니다. language ..
Aks

@Aks 나를 위해 매번 작동합니다. 올바른 구성표를 시작했는지 확인하고 Xcode 내에서 시작했는지 확인하십시오 (다시 시작, 포크 등은 인수를 얻지 못합니다). OptionsApple이 제공하는 최신 Xcode 버전과 마찬가지로 언어를 재정의하지 마십시오 게다가.
Mecki

귀하의 답변에 감사드립니다. @Mecki .. xcode에서 작동하지 않지만 코드에서 언급 할 때 작동합니다. 그러나 여전히 다른 선호 언어로 장치를 설정 한 경우 선호하는 언어로로드하려면 앱을 다시 시작해야합니다 내가 논쟁에서 전달하는 언어 ....
Aks

@Aks 기기에서 사용하면 Xcode에서 직접 시작할 때만 작동하며 일부 기기에서 아이콘을 탭하여 앱을 다시 시작하면 작동하지 않으며 앱이 종료되면 작동하지 않습니다 (예 : 백그라운드로 이동하여 시스템에 의해 다시 시작되기 때문에 (이 다시 시작은 Xcode에 의해 다시 시작되지 않기 때문에) iOS가 사이에서 앱을 종료해야하는 경우 다른 앱으로 전환하거나 다시 작동하지 않을 수 있습니다 (예 : 메모리가 필요합니다).
Mecki

10

나는 당신이 사용할 수있는 솔루션을 생각해 냈습니다 NSLocalizedString. NSBundlecall 카테고리를 작성합니다 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마르코가 재정의 했다는 경고입니다 . 아마도 누군가 가이 부분을 고치도록 도울 수 있습니다.


1
경고를 비활성화 #undef NSLocalizedString하기 직전 #define에 추가하십시오
beryllium

이것은 xib 파일의 현지화에서 작동합니까? UI 이름을 특정 언어로 번역하기 위해 .xib 파일과 .strings가 있습니다. 시도했지만 XIB에서는 작동하지 않지만 올바르게 작업했는지 확실하지 않습니다.
Kong Hantrakool

응답이 지연되어 죄송합니다. NSLocalizedString을 사용하는 모든 곳에서 작동합니다. 따라서 XIB에서 직접 작동하지 않습니다. XIB의 문자열에 대한 IBOutlet이 필요하며 코드에서 문자열 값을 프로그래밍 방식으로 설정해야합니다.
qman64

이 방법은 저에게 효과적이며 언어를 즉석에서 변경할 수있었습니다. "es", fr "및"en "과 같은 언어 코드는 제대로 작동하지만"zh "(중국어 간체의 경우)는 실패하고 null 문자열을 반환했습니다. 시스템에서"es.lproj "에 대한 전역 검색을 수행했습니다. 내가 액세스 한 파일의 위치를 ​​확인한 후 "zh.lproj"가 실제로 "zh-Hans.lproj"라는 것을 발견했습니다.
Gallymon

9

스위프트 버전 :

NSUserDefaults.standardUserDefaults().setObject(["fr"], forKey: "AppleLanguages")
NSUserDefaults.standardUserDefaults().synchronize()

8

간단히 말해서 :

응용 프로그램 현지화

가장 먼저해야 할 일은 두 가지 언어 (이 예에서는 영어와 프랑스어)로 앱을 현지화하는 것입니다.

NSLocalizedString 재정의

코드에서을 NSLocalizedString(key, comment)사용하는 대신 MYLocalizedString(key, comment)다음과 같이 정의 된 매크로를 사용 하십시오. #define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];

MYLocalizationSystem싱글 톤은 :

  • 현지화 된 NSBundle 사용자가 요구 하는 올바른 언어 를 설정하여 언어 설정
  • 이전에 설정 한 언어에 따라 지역화 된 NSString을 반환합니다.

사용자 언어 설정

사용자가 프랑스어로 응용 프로그램 언어를 변경 한 경우 전화 [[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 에서 자세한 내용을 확인할 수 있습니다.


우리는 당신이 단지 당신의 답변에서 해결책으로 연결되는 것이 아니라고 요청합니다; 링크가 언젠가 작동을 멈출 수 있습니다. 답변에서 링크를 제거 할 필요는 없지만 링크 된 기사의 관련 섹션에 대한 요약을 포함하도록 답변을 편집하도록 요청합니다.
Oblivious Sage

7

스위프트 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

감사. 잘 작동합니다.
Krunal Nagvadia

5

.pch 파일 에서 다음을 정의하십시오.

#define currentLanguageBundle [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[[NSLocale preferredLanguages] objectAtIndex:0] ofType:@"lproj"]]


#define NSLocalizedString(str,nil) NSLocalizedStringFromTableInBundle(str, nil, currentLanguageBundle, @"")

'ovverride ...'경고를 없애려면 어떻게해야합니까?
Idan Moshe

1
간단한 솔루션은 필요한 모든 것을 수행합니다. 이 문제를 가이드로 사용하여 문제를 해결할 수있었습니다. 현지화 파일이 없기 때문에 pathForResource가 nil을 반환하면 pathForResource : @ "Base"를 사용합니다. 감사합니다.
GRW

이것은 해키 (다른 모든 답변도 마찬가지)이며, 내가 쓰고있는 단위 테스트에서 구현하는 것이 가장 쉬웠습니다.
Max

4

어쩌면 당신은 이것을 보완해야합니다 (#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]

/Users/pwang/Desktop/Myshinesvn/Myshine/viewController/OrientationReadyPagesView.m:193:31 : 선언되지 않은 식별자 'bundle'사용
pengwang

4

스위프트 3 솔루션 :

let languages = ["bs", "zh-Hant", "en", "fi", "ko", "lv", "ms", "pl", "pt-BR", "ru", "sr-Latn", "sk", "es", "tr"]
UserDefaults.standard.set([languages[0]], forKey: "AppleLanguages")

사용할 수있는 언어 코드의 예를 제공하십시오. 도움이 되었기를 바랍니다


3

이 작업을 수행하려는 현지화 된 문자열 세트로 하위 번들을 빌드 한 다음이를 사용 NSLocalizedStringFromTableInBundle()하여로드 할 수 있습니다. (이것은 앱에서 수행 할 수있는 일반적인 UI 현지화와는 별도의 내용이라고 가정합니다.)


3

내 경우에는 현지화 된 두 파일 인 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]));


    }


}

감사합니다 @ chings228 나에게 유용하지만 각 언어마다 다른 스플래시가있는 앱의 기본 시작 이미지 (스플래시)는 변경되지 않습니다. 당신은 이것을 신청하는 방법을 알고 있습니까 ??
JERC

내가 메인 프로그램 전에 시작 실행은 내가 그것을 재정의하는 방법을 알고하지 않도록 PLIST 깡통 도움이 될 수있다, 실행을 시작 생각하지만 앱이 열립니다 다음 시간 동안 작동 할 수
chings228

2

다음과 같이 할 수 있습니다 :

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"es"];


NSBundle *spanishBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];

NSLocalizedStringFromTableInBundle(@"House", nil, spanishBundle, nil):

2

응용 프로그램 을 종료하거나 다시 시작 하지 않고 언어를 변경 하려는 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"];

2

신속한 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

그것이 가장 좋은 방법인지는 모르겠지만 매우 간단하다는 것을 알았습니다. 그것이 도움이되기를 바랍니다.


1

이 함수는 현재 언어에 대한 지역화 된 문자열을 얻으려고 시도하며 찾을 수 없으면 영어를 사용하여 가져옵니다.

- (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;
}

1

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 페이지 링크 참조).


나는 당신이 슬로베니아 언어에 문제가 있다는 것을 안다 :) iOS에서 지원하지 않는 언어에 대한이 답변을 개선하기 위해 앱에서 시스템 제어에 사용될 사용자 정의 현지화 가능 문자열을 설정할 수 있는지 알아 냈습니다 (편집, 완료, 기타, ...)?
miham

1

이 문제에 대한 적절한 해결책이 있으며 응용 프로그램을 다시 시작할 필요가 없습니다.

https://github.com/cmaftuleac/BundleLocalization

이 구현은 NSBundle 내부를 조정하여 작동합니다. NSBundle 객체의 인스턴스에서 localizedStringForKey 메서드를 재정의 한 다음 다른 언어의 다른 번들에서이 메서드를 호출하는 것이 좋습니다. 모든 유형의 리소스와 완벽하게 호환되는 단순하고 우아합니다.


프로젝트 의이 코드는 많은 도움이되었습니다. 특정 언어 코드를위한 번들을 찾는 방법 ---NSString *path = [[NSBundle mainBundle] pathForResource:lang ofType:@"lproj" ];
Eonil

이 수업은 잘 진행되고 있지만 언어를 다른 언어로 바꾼 후에는 효과가 없습니다.
Anilkumar iOS ReactNative8

0

당신이 무엇이든간에, 가장 좋은 방법은 지정된 언어에 대해 short_name을 가져 오는 것입니다 : 예 : fr, en, nl, de, it 등 ... 그리고 전역 값에 동일하게 할당하십시오.

선택 도구보기가 드롭 다운 메뉴처럼 팝업되도록하고 (선택 목록이 아래에서 언어 목록과 함께 표시되는 단추 조합) 원하는 언어를 선택하십시오. 짧은 이름을 내부에 저장하십시오. LocalisedString이라는 .h + .m 파일을 만듭니다.

short_name의 글로벌 값을 LocalisedString.m에서 확보 한 값과 동일하게 설정하십시오. 필요한 언어가 선택되면 필요한 언어에 대한 프로젝트 서브 디렉토리를 작성하도록 NSBundlePath를 지정하십시오. 예를 들어, nl.proj, en.proj.

특정 proj 폴더가 선택되면 해당 언어의 현지화 된 문자열을 호출하고 언어를 동적으로 변경하십시오.

규칙이 깨지지 않았습니다.


0

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.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.