[iOS] 런타임에 언어 바꾸기

iOS 프로젝트에서 Localizable.string 파일을 만들어 앱의 다양한 언어를 지원할 수 있다. 기본적으로 유저가 사용하고 있는 OS 세팅에 적용되어 있는 언어를 앱은 받아드리고 보여주게 될 것이다. 하지만 필자 같이 영문 OS 버전을 사용하면서 특정 앱에 한에서 한국어를 사용하고 싶을 때가 있다. 하지만 CocoaTouch에 선언되어 있는 NSLocalizedString 매크로를 통해서 앱의 언어를 바꾸려면 앱을 메모리에서 한번 지우고 다시 앱을 열어야지만 새 언어를 적용할 수 있다는 특징이 있다. 꽨 번거로운 일이다. 그래서 필자는 런타임에 언어를 바꿀수 있는 방법을 찾아보다가 괜찮은 방법을 찾았기에 소개하고자 한다.

본 글은 stackoverflow에서 찾은 솔루션이다.

링크

기본적인 아이디어는 애플에서 적용되어 있는 NSLocalizedString 매크로를 재정의 하여 사용하는 것이다.

  1. NSBundle의 카테고리를 만든다.
  2. AppDelegate에 language 코드를 알려주는 인스턴스 메서드를 만든다.
  3. NSLocalizedString 매크로를 사용하는 파일에 카테코리 파일을 임포트 한다.

NSBundle의 카테고리 만들기

  1. //
  2. //  NSBundle+RunTimeLanguage.h
  3. //  Copyright © 2016 bartysways. All rights reserved.
  4. //
  5.  
  6. @import Foundation;
  7.  
  8. #undef NSLocalizedString
  9. #define NSLocalizedString(key, comment) [[NSBundle mainBundle] runTimeLocalizedStringForKey:(key) value:@"" table:nil]
  10.  
  11. @interface NSBundle (RunTimeLanguage)
  12.  
  13. - (NSString *)runTimeLocalizedStringForKey:(NSString *)key
  14.                                      value:(NSString *)value
  15.                                      table:(NSString *)tableName;
  16.  
  17. @end
  18.  
  19. //
  20. //  NSBundle+RunTimeLanguage.m
  21. //  Copyright © 2016 bartysways. All rights reserved.
  22. //
  23.  
  24. #import "NSBundle+RunTimeLanguage.h"
  25. #import "AppDelegate.h"
  26.  
  27. @implementation NSBundle (RunTimeLanguage)
  28.  
  29. - (NSString *)runTimeLocalizedStringForKey:(NSString *)key
  30.                                      value:(NSString *)value
  31.                                      table:(NSString *)tableName
  32. {
  33.     AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
  34.     NSString *path = [[NSBundle mainBundle] pathForResource:appDelegate.languageCode
  35.                                                      ofType:@"lproj"];
  36.     NSBundle *languageBundle = [NSBundle bundleWithPath:path];
  37.     NSString *localizedString= [languageBundle localizedStringForKey:key value:key table:nil];
  38.  
  39.     return localizedString;
  40. }
  41.  
  42. @end

AppDelegate에 인스턴스 메서드 만들기

  1. //
  2. //  AppDelegate.h
  3. //  Copyright © 2015 bartysways. All rights reserved.
  4. //
  5.  
  6. @import UIKit;
  7.  
  8. @interface AppDelegate : UIResponder
  9. <
  10. UIApplicationDelegate
  11. >
  12.  
  13. @property(nonatomic, strong) UIWindow *window;
  14. @property(nonatomic, strong, readonly) NSString *languageCode;
  15.  
  16. @end
  17.  
  18. //
  19. //  AppDelegate.m
  20. //  Copyright © 2015 bartysways. All rights reserved.
  21. //
  22.  
  23. @import UserNotifications;
  24.  
  25. #import "AppDelegate.h"
  26.  
  27. @implementation AppDelegate
  28.  
  29. - (NSString *)languageCode
  30. {
  31.     NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  32.     NSString *languageCode = ((NSArray *)[userDefaults objectForKey:@"AppleLanguages"]).firstObject;
  33.     return languageCode != nil ? languageCode : @"en";
  34. }
  35. @end

카테코리 파일을 임포트하기

  1. //
  2. //  HeaderCollectionReusableView.m
  3. //  Copyright © 2016 bartysways. All rights reserved.
  4. //
  5.  
  6. #import "HeaderCollectionReusableView.h"
  7. #import "NSBundle+RunTimeLanguage.h"
  8.  
  9. @implementation HeaderCollectionReusableView
  10. @end