Try   HackMD

[快速理解 - Android 多國語系翻譯]
大家都知道 strings.xml中可指定帶怎樣的變數顯示怎樣的字串,這個大家都通就不用多解釋,但當產品面對多國多語言多地區一起來,到底原理是什麼呢,這篇就是來帶大家快速理解,以便你日後能制定自己的產品翻譯策略及優先順序。

Android 多國語系字串翻譯注意事項

1. 當不同語系、地區的交疊,會讀哪個檔?

範例1 - 通用 -> 語系 -> 地區 的套用優先順序

  • 我的 Android App 有以下翻譯檔
    • strings.xml
    • strings-en.xml
    • strings-en-rIN.xml
  • 翻譯狀況
    • 在strings.xml 中 app_name 翻譯為 "我的APP"
    • 在 strings-en.xml 中 app_name 翻譯為 "My App"
    • 在 strings-en-rIN.xml 中 app_name 翻譯為 "My Lovely App"

這個時候,在Android 系統的環境設定中, 哪些情況下我的 app_name 最終顯示為 "我的APP" 而哪些情況下會顯示"My App" 又有哪些情況下會顯示為 "My Lovely App" 呢?

在 Android 中,不同的 strings.xml 檔案用於支援不同的語言和地區設定。系統會根據用戶的裝置語言和地區設定來選擇適當的翻譯檔案。以下是你提供的例子中不同情況下 app_name 的顯示規則:

1. 何時顯示為 "我的APP"

當裝置的語言設定不是英語(English),或者是英語但沒有特定的地區設定與 strings-en.xmlstrings-en-rIN.xml 匹配時,將使用 strings.xml 中的翻譯。例如:

  • 裝置語言設定為中文(無論是簡體還是繁體中文)。
  • 裝置語言設定為英語,但沒有對應的地區設定(例如設定為英語但不是印度)。

2. 何時顯示為 "My App"

當裝置的語言設定為英語(English),但沒有更具體的地區設定匹配 strings-en-rIN.xml 時,將使用 strings-en.xml 中的翻譯。例如:

  • 裝置語言設定為英語(美國)、英語(英國)等,但不是英語(印度)。

3. 何時顯示為 "My Lovely App"

當裝置的語言設定為英語(English)且地區設定為印度(India)時,將使用 strings-en-rIN.xml 中的翻譯。例如:

  • 裝置語言設定為英語(印度)。

總結

Android 系統會根據用戶裝置的語言和地區設定選擇相應的翻譯檔案。如果沒有匹配特定語言和地區的檔案,系統會回退到使用默認的 strings.xml。这种机制支持了应用的国际化和本地化,确保用户在不同的语言和地区设置下获得适当的翻译。

範例2 若設置印度班牙文,但無通用西班牙文時,選西班牙文能否套用?

  • 我的 Android App 全部就只有以下4個翻譯檔,
    • strings.xml
    • strings-en.xml
    • strings-en-rIN.xml
    • strings-es-rIN.xml
  • 然後翻譯狀況是
    • 在strings.xml 中 app_name 翻譯為 "我的APP"
    • 在 strings-en.xml 中 app_name 翻譯為 "My App"
    • 在 strings-en-rIN.xml 中 app_name 翻譯為 "My Lovely App"
    • 在 strings-es-rIN.xml 中的 app_name 翻譯為 "班牙App"

請問一下,當系統選擇西班牙語,但沒有設定地區時,這時候app_name 會出現的是什麼?

在上述提供的情況中,如果系統設定為西班牙語(Spanish)但沒有指定地區(Region),則會發生以下情況:

由於你的應用沒有一個專門針對非特定地區的西班牙語(例如 strings-es.xml)的翻譯文件,Android 系統將會使用默認的翻譯文件 strings.xml。因此,在這種情況下,app_name 將顯示為 "我的APP"。

語言和地區匹配的回退機制

Android 的資源管理系統會嘗試找到最匹配用戶設備語言和地區設定的翻譯文件。如果找不到完全匹配的文件,它會回退到下一個最接近的匹配。在你的例子中,由於沒有對應非特定地區的西班牙語翻譯文件,系統將回退到默認的 strings.xml 文件。

如何解決這個問題

為了避免這種情況,建議為主要支持的語言提供一個不帶地區碼的翻譯文件。例如,你可以創建一個 strings-es.xml 文件來專門處理西班牙語的翻譯,而不論用戶的地區設定為何。這樣,當用戶選擇西班牙語但沒有設定特定地區時,系統將會使用 strings-es.xml 中的翻譯。

2. 特殊字符帶參數

請問 Android 字串翻譯中

<string name="abc\_action\_bar\_home\_description\_format">%1$s, %2$s</string> 
<string name="abc\_action\_bar\_home\_subtitle\_description\_format">%1$s, %2$s, %3$s</string> 
<string name="abc\_shareactionprovider\_share\_with_application">Share with %s</string>

這些特殊符號有特別用途嗎? 程式上會怎麼使用呢?

在 Android 的字串資源文件中,提到的這些特殊符號 %1$s, %2$s, %3$s 等,是格式化字串的佔位符。它們用於在運行時將動態值插入到字串中。這種做法在多語言支持和動態內容顯示中非常有用。

特殊符號的用途

  • %s:表示一個字串佔位符。
  • %1$s%2$s%3$s 等:這些是帶有序號的字串佔位符。序號(如 1, 2, 3)指定了傳遞給字串的參數的順序。這在需要將多個參數插入到同一個字串中時特別有用,並且可以控制這些參數的順序。

程式中的使用

在 Android 程式中,這些佔位符主要是通過 getString 方法來使用的。以下是一些例子:

`// 獲取資源 Resources res = getResources(); // 無參數的情況 String actionBarHome = res.getString(R.string.abc_action_bar_home_description_format); // 帶一個參數的情況 String shareWithApp = res.getString(R.string.abc_shareactionprovider_share_with_application, "Facebook"); // 帶多個參數的情況 String actionBarHomeSubtitle = res.getString(R.string.abc_action_bar_home_subtitle_description_format, "Item1", "Item2", "Item3");`

在上面的例子中:

  • getString(R.string.abc_shareactionprovider_share_with_application, "Facebook") 會將 Share with Facebook 這個字串返回。
  • getString(R.string.abc_action_bar_home_subtitle_description_format, "Item1", "Item2", "Item3") 會將 Item1, Item2, Item3 這樣格式化的字串返回,其中 %1$sItem1 替換,%2$sItem2 替換,%3$sItem3 替換。

這種格式化方法使得字串資源更加靈活,並且便於本地化和國際化,因為你可以為不同的語言提供相同結構的字串,但具有不同的文本內容。