iOS/Swift/Localization: Cách tách Localizable.strings thành nhiều file theo từng màn hình

by DaoNM2
142 views

Xin chào, trong số chúng ta hẳn không ít developer đã từng gặp tình trạng phải ngồi sửa các conflict file localizable strings khi làm việc, nhất là khi dự án của bạn có nhiều người tham gia lúc này file localizable.strings sẽ như là một đấu trường hỗn loạn với rất nhiều developer xâu xé, thi nhau chiếm đất. Người này sửa lên text người kia, người này sửa bug của mình lại tạo thành các bug của người khác. Khi dự án có thêm nhiều tính năng, file Localizable.strings sẽ càng ngày càng phình to ra, khi nó quá lớn thì một số máy MAC của anh em sẽ gặp tình trạng lag, chậm khi sửa file này.

Câu hỏi đặt ra là để giải quyết bài toán này thì chúng ta cần phải làm gì?

Chia để trị là cách mình giải quyết vấn đề này.


Nếu bạn chưa làm ứng dụng có tính năng đa ngôn ngữ bao giờ thì quay lại đọc bài của mình trước rồi quay lại nhé!
HƯỚNG DẪN THỰC HIỆN ỨNG DỤNG MOBILE HỖ TRỢ ĐA NGÔN NGỮ

Ưu điểm của việc tách file Localizable.strings theo từng màn hình

  • Mỗi màn hình có một file .strings quản lý riêng vì vậy không bị conflict khi merge code
  • Không bị bug khi fix string màn hình A lại lỗi màn hình B, C, D …
  • Dễ dàng quản lý, dễ dàng maintain
  • Không bị vì lỗi format trên file Localizable.strings mà cả ứng dụng không chạy được đa ngôn ngữ

Ý tưởng

Theo cách kiến trúc lập trình phần mềm, chúng ta luôn tìm cách phân tách các thành phần riêng để xử lí các tác vụ, và giảm tải cho các phần càng ngày càng lớn lên khi ứng dụng có nhiều tính năng hơn. Vậy tại sao chúng ta lại để file Localization của mình đến hàng nghìn dòng đến vạn dòng. Không thể chịu được cảnh mở file localizable giật lag, cuộn mỏi tay. Mình đã suy nghĩ đến giải pháp chia ra để trị, mỗi màn hình sẽ có một file .strings riêng để thực hiện Localization.

Cách thực hiện

Từ rất lâu Apple đã cung cấp cho chúng ta cách thức để làm được việc này.

Nếu bạn muốn thực hành luôn thì có thể tài project bắt đầu ở đây nhé.

Bước 1: Tạo 2 màn hình tương ứng với 2 tính năng của ứng dụng.

Bước 2: Tạo 2 file .strings tương ứng với 2 màn hình là FirstScreen.strings và SecondScreen.strings như hình dưới, bạn copy nội dung từ File Localizable.strings rồi xoá file đi như hình.

Bước 3: Sửa lại extension String file LanguageManager.swift như sau

extension String {
    var localized: String {
        // default language of device
        let currentLanguage = LanguageManager.shared.getAppLanguage().rawValue
        guard let bundlePath = Bundle.main.path(forResource: currentLanguage, ofType: "lproj"),
              let bundle = Bundle(path: bundlePath),
              let tableName = self.split(separator: ".").first// lấy table name từ string
        else {
            return self
        }
        
        return NSLocalizedString(self, tableName: String(tableName), bundle: bundle, value: "", comment: "")
    }
}

Để sử dụng chúng ta code như sau:

lbHeaderTitle.text = Localization.SecondScreen.title.localized

NOTE: Để hàm này hoạt động đúng thì tất cả thành viên trong dự án sẽ phải tuân thủ cách đặt tên nằm trong .strings.
Ví Dụ: Feature1.strings, thì nội dung bên trong phải là Feature1.xxxx, xxxx ở đây là key string của bạn.

Nếu bạn cảm thấy việc tuân thủ luật này quá cứng nhắc dễ mắc sai lầm thì chúng ta có một hàm mới như sau:

// Định nghĩa các table Name, lưu ý đặt tên phải trùng với tên file .strings
enum LocalizationTableName: String {
    case firstScreen = "FirstScreen"//FirstScreen.strings
    case secondScreen = "SecondScreen"//SecondScreen.strings
}

extension String {
    func localized(tableName: LocalizationTableName) -> String {
        // default language of device
        let currentLanguage = LanguageManager.shared.getAppLanguage().rawValue
        guard let bundlePath = Bundle.main.path(forResource: currentLanguage, ofType: "lproj"),
              let bundle = Bundle(path: bundlePath)
        else {
            return self
        }
        
        return NSLocalizedString(self, tableName: tableName.rawValue, bundle: bundle, value: "", comment: "")
    }
}

Khi sử dụng chúng ta sẽ code như sau:

lbHeaderTitle.text = Localization.SecondScreen.title.localized(tableName: .secondScreen)

Vậy là chúng ta đã thành công tạo localization cho từng màn hình. Mình hi vọng bài viết sẽ giúp ích cho các bạn ở các dự án sau này.

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

You may also like