12/08/2018, 14:05

Thay đổi ngôn ngữ của ứng dụng bằng Localization.

Sau khi tạo ra một ứng dụng iOS tuyệt vời với thiết kế tuyệt đẹp và tương tác trực quan đưa lên store. Để leo lên bảng xếp hạng App Store đòi hỏi phải tiếp thị sản phẩm đúng lúc, khả năng mở rộng quy mô người dùng, và sử dụng các công cụ và kỹ thuật để có được càng nhiều người dùng càng tốt. Thị ...

Sau khi tạo ra một ứng dụng iOS tuyệt vời với thiết kế tuyệt đẹp và tương tác trực quan đưa lên store. Để leo lên bảng xếp hạng App Store đòi hỏi phải tiếp thị sản phẩm đúng lúc, khả năng mở rộng quy mô người dùng, và sử dụng các công cụ và kỹ thuật để có được càng nhiều người dùng càng tốt.

Thị trường nước ngoài là một suy nghĩ cho rất nhiều nhà phát triển, bất kỳ dev iOS nào cũng có thể phát hành ứng dụng của họ trên hơn 150 quốc gia. Nhưng để tận dụng tiềm năng thị trường toàn cầu của các ứng dụng của bạn, bạn sẽ cần hỗ trợ nhiều loại ngôn ngữ khác nhau.

Trong bài này sẽ hướng dẫn bạn thay đổi ngôn ngữ của ứng dụng một cách nhanh nhất bằng Localization.

Simulator Screen Shot Oct 25, 2016, 6.09.08 PM.png

Đây là một ví dụ nhỏ trên ViewController có chứa các button, label và một textview.

Trong xcode sử dụng các tệp tin với phần mở rộng ".strings" để lưu trữ và lấy tất cả các chuỗi được sử dụng trong ứng dụng cho mỗi ngôn ngữ được hỗ trợ. Khi ngôn ngữ thay đổi ứng dụng sẽ tra cứu và trả lại chuỗi yêu cầu dựa trên các tệp tin ngôn ngữ đã được khai báo trong ứng dụng.

Để tạo các file .strings. Bạn vào File > New > File. Chọn Strings File như hình bên dưới.

Screen Shot 2016-10-25 at 10.29.57 PM.png

Trong Project Editor. Phần list project and target settings chọn project. Tab info các bạn chọn localizations click dấu + để thêm ngôn ngữ mà ứng dụng của bạn hỗ trợ. Trong ví dụ này mình chọn ngôn ngữ là Việt Nam, English, Japanese, Indo và Thái Lan.

Sau đó bạn chọn file Localizable.strings mà bạn đã thêm trước đó. Bên phần file inspector chọn các Localization mà bạn đã thêm vào.

Screen Shot 2016-10-25 at 7.10.11 PM.png

Tiếp theo bạn cần hardcoded tất cả các dòng text có trong ứng dụng của bạn vào trong các file Localization.

Ví dụ:

Screen Shot 2016-10-25 at 10.27.58 PM.png

Các ngôn ngữ khác làm tương tự.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //Ở đây mình hardcod list danh sách các ngôn ngữ hỗ trợ trong ứng dụng.
    language = [[NSArray alloc] initWithObjects:@"English",@"Japanese",@"Thái Lan",@"Indonesia",@"Việt Nam", nil];
}

Thêm action cho button chọn ngôn ngữ

- (IBAction)changeLanguage:(id)sender {
    UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"Language" message:@"Select language" preferredStyle:UIAlertControllerStyleActionSheet];
    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Huỷ" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        // Cancel button tappped.
        [self dismissViewControllerAnimated:YES completion:^{
        }];
    }]];
    for (NSString * item in language) {
        [actionSheet addAction:[UIAlertAction actionWithTitle:item
                                                        style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction *action)
        {
            // Set language

            //
            [NSNotification notificationWithName:@"Did selected language"
                                          object:nil
                                        userInfo:nil];
            [self dismissViewControllerAnimated:YES completion:nil];
        }]];
    }

    [self presentViewController:actionSheet animated:YES completion:nil];

}

Tạo một file NSObject ở đây mình đặt tên là Language. Trong file Language sẽ quản lý toàn bộ các thao tác liên quan đến ngôn ngữ của ứng dụng

+(void)initialize {
    NSString *current = [self getCurrentLanguage];
    [self setLanguage:current];
}

+(void)setLanguage:(NSString *)language {
    [[NSUserDefaults standardUserDefaults] setObject:language forKey:@"curren_language"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    NSString *filePath = [NSString stringWithFormat:@"%@/%@.lproj", [self appDocumentDirectory], language];
    BOOL isDir;
    BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDir];
    if (!exists)
        filePath = [[NSBundle mainBundle] pathForResource:language ofType:@"lproj"];
    bundle = [NSBundle bundleWithPath:filePath];
}

+(NSString*)getCurrentLanguage {
    NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
    NSString *lang = [defs objectForKey:@"curren_language"];
    if (lang) return lang;
    else return @"vi";
}

+(NSString *)get:(NSString *)key {
    NSString *result = [bundle localizedStringForKey:key value:nil table:nil];
    if (!result) result = key;
    return result;
}

+ (NSString*) appDocumentDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
}

+ (NSString *)getLanguageCode:(NSString *)language{
    if([language isEqualToString:@"Indonesia"]){
        return @"id";
    }else if([language isEqualToString:@"English"]){
        return @"en";
    }else if([language isEqualToString:@"Japanese"]){
        return @"ja";
    }else if([language isEqualToString:@"Thái Lan"]){
        return @"th";
    }
    return @"vi";
}

Trong AppDelegate gọi class funtion initialize để set language cho ứng dụng với ngôn ngữ đã được thay đổi gần nhất.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [Language initialize];
    return YES;
}

Selected Language

- (IBAction)changeLanguage:(id)sender {
    .....
        [actionSheet addAction:[UIAlertAction actionWithTitle:item
                                                        style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction *action)
        {
            //Get language code
            NSString *langCode = [Language getLanguageCode:action.title];
            //Update current Language
            [Language setLanguage:langCode];
            //
            ....
            [self dismissViewControllerAnimated:YES completion:nil];
        }]];
}

Về cơ bản là xong. Bây giờ bạn có thể get một chuỗi text theo ngôn ngữ mà bạn đang lựa chọn như sau.

Ví Dụ:

lbTitle.text = [Language get:@"Developed by"];

Nhưng làm như vậy là hết sức cơ bắp và mình không khuyến khích các bạn làm như vậy, tuy nhiên nhiều trường hợp vấn có thể dùng. Tiếp đây mình sẽ đưa ra một cách giúp các bạn thực hiện thay đổi, cập nhật ngôn như đơn giản hơn (Có thể có cách khác tốt hơn mà mình không biết =))).

Trước tiên bạn tạo một object kiểu UIView có thể là Category cũng được nhưng ở đây mình viết riêng 1 file kế thừa của UIView.

#import "BaseUIView.h"
#import "Language.h"

@interface BaseUIView () {
    NSMutableArray *listLanguageView, *listLanguageText;
}

@end

@implementation BaseUIView

- (void) awakeFromNib {
    [super awakeFromNib];
    [self setupLanguage];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(observerDidChangeLanguage:) name:@"Did selected language" object:nil];
}

- (void) observerDidChangeLanguage:(NSNotification*)notification {
    [self setupLanguage];
}

- (void) dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void) getLanguageForView:(UIView *)parentView {
    for (UIView *view in parentView.subviews) {
        if ([view isKindOfClass:[UILabel class]]) {
            [listLanguageView addObject:view];
            NSString *text = [(UILabel*)view text];
            if (!text) text = @"";
            [listLanguageText addObject:text];
        }
        else if ([view isKindOfClass:[UITextField class]]) {
            UITextField *textField = (UITextField*)view;
            [listLanguageView addObject:view];
            NSString *text = textField.placeholder;
            if (!text) text = @"";
            [listLanguageText addObject:text];
        }
        else if ([view isKindOfClass:[UIButton class]]) {
            UIButton *button = (UIButton *)view;
            [listLanguageView addObject:view];
            NSString *text = [button titleForState:UIControlStateNormal];
            if (!text) text = @"";
            [listLanguageText addObject:text];
        }
        else
            [self getLanguageForView:view];
    }
}

- (void) setupLanguage {
    // Lấy danh sách các View và text. Chỉ gọi lần đầu. Các lần sau dùng luôn list trước đó.
    if (!listLanguageView) {
        listLanguageView = [NSMutableArray array];
        listLanguageText = [NSMutableArray array];

        [self getLanguageForView:self];
    }
    for (int i=0; i<listLanguageView.count; i++) {
        UIView *view = listLanguageView[i];
        if ([view isKindOfClass:[UILabel class]]) {
            [(UILabel *)view setText:[Language get:listLanguageText[i]]];
        }
        else if ([view isKindOfClass:[UITextField class]]) {
            UITextField *textField = (UITextField*)view;
            textField.placeholder = [Language get:listLanguageText[i]];
        }
        else if ([view isKindOfClass:[UIButton class]]) {
            UIButton *button = (UIButton *)view;
            [button setTitle:[Language get:listLanguageText[i]] forState:UIControlStateNormal];
        }
    }
}

@end

Tiếp theo trong mục custom class bạn khai báo class là BaseUIView.

Screen Shot 2016-10-26 at 10.16.03 AM.png

Bây giờ tất cả các view nào kế thừa BaseUIView của bạn sẽ tự động cập nhật ngôn ngữ mỗi khi bạn thay đổi ngôn ngữ. Việc duy nhất của các bạn là hardcode tất cả các chuỗi text trên view đó ở các file .strings.

Kết luận: Trong ví dụ này mình đã đưa ra một cách giúp úng dụng của bạn hỗ trợ nhiều ngôn ngữ khác nhau tiết kiệm thời gian khai báo, update khi thay đổi ngôn ngữ của ứng dụng.

Download Final Project

Tham khảo thêm : Internationalization Tutorial for iOS

0