Sử dụng bản địa hóa và mã ngôn ngữ trong Android SDK

Tại sao điều này quan trọng

Mã ngôn ngữ (locale code) được dùng khi Adapty chọn bản địa hóa cho một flow, và khi bạn đọc Remote Config cho một paywall tùy chỉnh.

Mã ngôn ngữ khá phức tạp và có thể khác nhau tùy nền tảng, vì vậy Adapty dùng một tiêu chuẩn nội bộ thống nhất trên mọi nền tảng được hỗ trợ. Hiểu rõ tiêu chuẩn đó giúp bạn dự đoán được bản địa hóa nào người dùng sẽ nhận được.

Chuẩn locale code tại Adapty

Đối với locale codes, Adapty sử dụng phiên bản điều chỉnh nhẹ của chuẩn BCP 47: mỗi code gồm các subtag viết thường, phân cách bằng dấu gạch ngang. Một số ví dụ: en (tiếng Anh), pt-br (tiếng Bồ Đào Nha (Brazil)), zh (tiếng Trung giản thể), zh-hant (tiếng Trung phồn thể).

Khớp mã ngôn ngữ

Khi Adapty tìm kiếm bản dịch phù hợp với ngôn ngữ của người dùng, quá trình diễn ra như sau:

  1. Chuỗi ngôn ngữ được chuyển thành chữ thường và tất cả dấu gạch dưới (_) được thay thế bằng dấu gạch ngang (-)
  2. Adapty tìm kiếm bản dịch có mã ngôn ngữ khớp hoàn toàn
  3. Nếu không tìm thấy, Adapty lấy chuỗi con trước dấu gạch ngang đầu tiên (pt từ pt-br) và tìm kiếm bản dịch phù hợp
  4. Nếu vẫn không tìm thấy, Adapty trả về nội dung theo ngôn ngữ mặc định của flow

Bằng cách này, 'pt_BR', pt-BR, và pt-br đều được phân giải về cùng một bản địa hóa.

Triển khai bản địa hóa

Trong SDK v4, bạn không cần truyền mã ngôn ngữ khi tải một flow — getFlow trả về flow cùng với tất cả các bản địa hóa của nó.

  • Flow được xây dựng trong builder: SDK không tự đọc ngôn ngữ của thiết bị, vì vậy hãy xác định ngôn ngữ trong ứng dụng của bạn và truyền nó vào tham số locale của AdaptyUI.getFlowConfiguration. Tham số này không bắt buộc — bỏ qua nó và flow sẽ hiển thị bằng en, hoặc theo ngôn ngữ mặc định khi flow không có bản dịch en. Khi bạn yêu cầu một ngôn ngữ mà flow không hỗ trợ, giao diện sẽ tự động dùng ngôn ngữ mặc định của flow mà không báo lỗi, và các chuỗi văn bản thiếu trong ngôn ngữ đã chọn sẽ được lấy từ ngôn ngữ mặc định.

Rendering trong en theo mặc định yêu cầu Android SDK 4.0.1. Trong 4.0.0, bỏ qua locale sẽ render bản địa hóa mặc định của flow.

  • Paywall tùy chỉnh (remote config): getFlow trả về tất cả bản địa hóa đã cấu hình trong flow.remoteConfigs. Mỗi entry có mã locale và nội dung config (jsonString, hoặc dataMap đã được parse). Chọn entry phù hợp với người dùng, kết hợp với logic fallback của riêng bạn:
Adapty.getFlow("YOUR_PLACEMENT_ID") { result ->
    when (result) {
        is AdaptyResult.Success -> {
            val flow = result.value
            val config = flow.remoteConfigs.firstOrNull { it.locale == "en" }
                ?: flow.remoteConfigs.firstOrNull()
            // read your values from config?.dataMap
        }
        is AdaptyResult.Error -> {
            // handle the error
        }
    }
}

Các quy tắc khớp mã ngôn ngữ ở trên mô tả cách Adapty chuẩn hóa các mã locale được lưu trữ trên mỗi Remote Config.

Tại sao điều này quan trọng

Có một vài trường hợp mà mã ngôn ngữ (locale code) có vai trò quan trọng — ví dụ, khi bạn cần lấy đúng paywall cho ngôn ngữ hiện tại của ứng dụng.

Vì mã ngôn ngữ khá phức tạp và có thể khác nhau giữa các nền tảng, chúng tôi sử dụng một tiêu chuẩn nội bộ thống nhất cho tất cả các nền tảng được hỗ trợ. Tuy nhiên, chính vì sự phức tạp đó, bạn cần hiểu rõ mình đang gửi gì lên server để nhận đúng bản ngôn ngữ mong muốn — và điều gì sẽ xảy ra tiếp theo.

Tiêu chuẩn mã ngôn ngữ tại Adapty

Đối với mã ngôn ngữ, Adapty sử dụng phiên bản được điều chỉnh nhẹ của tiêu chuẩn BCP 47: mỗi mã gồm các subtag viết thường, ngăn cách nhau bằng dấu gạch ngang. Ví dụ: en (tiếng Anh), pt-br (tiếng Bồ Đào Nha (Brazil)), zh (tiếng Trung giản thể), zh-hant (tiếng Trung phồn thể).

Khớp mã ngôn ngữ

Khi Adapty nhận được lệnh gọi từ SDK phía client kèm mã ngôn ngữ và bắt đầu tìm kiếm bản localization tương ứng của một paywall, quá trình diễn ra như sau:

  1. Chuỗi locale đầu vào được chuyển thành chữ thường và tất cả dấu gạch dưới (_) được thay bằng dấu gạch ngang (-)
  2. Hệ thống tìm kiếm bản localization có mã locale khớp hoàn toàn
  3. Nếu không tìm thấy, hệ thống lấy chuỗi con trước dấu gạch ngang đầu tiên (pt từ pt-br) và tiếp tục tìm kiếm bản localization khớp
  4. Nếu vẫn không tìm thấy, hệ thống trả về nội dung theo ngôn ngữ mặc định của paywall

Nhờ đó, một thiết bị iOS gửi 'pt_BR', một thiết bị Android gửi pt-BR, và một thiết bị khác gửi pt-br đều nhận được kết quả giống nhau.

Nếu bạn đang quan tâm đến localizations, rất có thể bạn đã làm việc với các file chuỗi đã được dịch trong dự án. Trong trường hợp đó, chúng tôi khuyến nghị bạn thêm một cặp key-value chứa Adapty locale code tương ứng vào từng file localization. Sau đó, trích xuất giá trị của key đó khi gọi SDK, như sau:

// 1. Modify your strings.xml files

/*
strings.xml - Spanish
*/
<string name="adapty_paywalls_locale">es</string>

/*
strings.xml - Portuguese (Brazil)
*/
<string name="adapty_paywalls_locale">pt-br</string>

// 2. Extract and use the locale code

val localeCode = context.getString(R.string.adapty_paywalls_locale)
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

Cách này giúp bạn kiểm soát hoàn toàn localization nào sẽ được tải về cho từng người dùng trong ứng dụng của bạn.

Cách triển khai localizations khác

Bạn cũng có thể đạt được kết quả tương tự (nhưng không hoàn toàn giống) mà không cần định nghĩa tường minh locale codes cho từng localization. Cách này có nghĩa là trích xuất locale code từ các đối tượng mà nền tảng của bạn cung cấp, như sau:

val locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
    context.resources.configuration.locales[0]
else
    context.resources.configuration.locale

val localeCode = locale.toLanguageTag()
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method

Lưu ý rằng chúng tôi không khuyến nghị cách tiếp cận này vì khó dự đoán chính xác máy chủ của Adapty sẽ nhận được gì.

Nếu bạn vẫn quyết định sử dụng cách này — hãy đảm bảo rằng bạn đã xử lý tất cả các trường hợp sử dụng liên quan.