鴻蒙Next應用國際化:語言與區域設定

SameX發表於2024-11-02

本文旨在深入探討華為鴻蒙HarmonyOS Next系統(截止目前API12)在應用國際化中語言與區域設定方面的技術細節,基於實際開發實踐進行總結。主要作為技術分享與交流載體,難免錯漏,歡迎各位同仁提出寶貴意見和問題,以便共同進步。本文為原創內容,任何形式的轉載必須註明出處及原作者。

在當今全球化的應用開發中,提供多語言支援和靈活的區域設定功能是滿足不同使用者需求的關鍵。鴻蒙Next系統為開發者提供了豐富的工具和介面,用於處理應用中的語言與區域設定。本文將詳細介紹如何獲取系統語言和區域資訊、設定應用偏好語言、支援多語言切換,以及處理語言與區域設定相關的問題,拋磚引玉。

一、獲取系統語言和區域資訊

(一)獲取系統語言

  1. 使用 i18n.System.getSystemLanguage() 方法
    • 該方法返回當前系統設定的語言程式碼,例如“zh”表示中文,“en”表示英文等。在應用啟動時,可以呼叫此方法獲取系統語言,以便根據使用者的語言偏好進行相應的介面顯示和資源載入。例如:
import { i18n } from '@kit.LocalizationKit';

let systemLanguage = i18n.System.getSystemLanguage();
console.log("當前系統語言:", systemLanguage);
  1. 語言程式碼的意義和用途
    • 語言程式碼遵循一定的標準(如ISO - 639標準),它是應用進行語言相關處理的重要依據。透過獲取系統語言程式碼,應用可以確定使用哪種語言資原始檔,載入相應的介面文字、音訊等內容,實現語言的本地化顯示。例如,如果系統語言為“zh - Hans”(中文簡體),應用可以載入簡體中文的資原始檔,顯示中文介面給使用者。

(二)獲取系統區域

  1. 使用 i18n.System.getSystemRegion() 方法
    • 此方法用於獲取當前系統設定的區域程式碼,如“CN”表示中國,“US”表示美國等。區域程式碼依據ISO - 3166標準,它不僅可以幫助應用確定使用者所在的地理區域,還能用於進一步的區域特定設定,如日期格式、數字格式、度量衡單位等的適配。例如:
import { i18n } from '@kit.LocalizationKit';

let systemRegion = i18n.System.getSystemRegion();
console.log("當前系統區域:", systemRegion);
  1. 區域資訊對應用的影響
    • 不同區域可能有不同的文化習慣和格式規範。例如,在日期格式方面,某些區域習慣使用“MM/DD/YYYY”,而其他區域可能使用“DD/MM/YYYY”。獲取系統區域資訊後,應用可以根據區域特點進行相應的格式設定,確保使用者看到的日期、時間、數字等資訊符合當地習慣。同時,區域資訊還可以用於提供本地化的服務和內容推薦,如根據使用者所在區域顯示當地的天氣資訊、新聞資訊等。

(三)獲取系統區域標識(Locale)

  1. 使用 i18n.System.getSystemLocale() 方法
    • 該方法返回當前系統的區域標識,它是語言和區域資訊的組合,例如“zh - Hans - CN”表示中文簡體、中國地區。區域標識在應用國際化中具有重要作用,它是資源匹配和載入的關鍵依據。例如:
import { i18n } from '@kit.LocalizationKit';

let systemLocale = i18n.System.getSystemLocale();
console.log("當前系統區域標識:", systemLocale);
  1. 區域標識與資源載入的關係
    • 應用通常會根據區域標識來查詢和載入對應的資原始檔。在資源目錄結構中,會按照區域標識建立不同的子目錄,存放相應語言和地區的資源。當獲取到系統區域標識後,應用可以準確地定位並載入最適合使用者的資源,如介面佈局檔案、字串資源、圖片資源等,實現全面的本地化。例如,如果系統區域標識為“en - US”,應用會在“resources/en - US”目錄下查詢和載入資源,以提供英文(美國)版本的介面和內容。

二、設定應用偏好語言

(一)設定應用偏好語言的方法

  1. 使用 i18n.System.setAppPreferredLanguage() 方法
    • 開發者可以透過此方法為應用設定特定的偏好語言。例如,將應用偏好語言設定為中文簡體:
import { i18n } from '@kit.LocalizationKit';
import {BusinessError } from '@kit.BasicServicesKit';

try {
    i18n.System.setAppPreferredLanguage("zh - Hans");
} catch(error) {
    let err: BusinessError = error as BusinessError;
    console.error(`設定應用偏好語言失敗,錯誤碼: ${err.code}, 訊息: ${err.message}.`);
}
  1. 注意事項
    • 設定應用偏好語言僅影響應用本身,不會改變系統語言設定。這使得使用者可以在系統語言為一種語言的情況下,為特定應用選擇另一種語言。例如,使用者系統語言為英文,但希望某個應用顯示中文介面,就可以在該應用中設定偏好語言為中文。同時,設定偏好語言後,應用應立即響應並載入相應的語言資源,更新介面顯示,以提供無縫的語言切換體驗。

(二)應用偏好語言對應用的影響

  1. 資源載入與介面顯示
    • 一旦設定了應用偏好語言,應用在啟動或執行過程中,會優先根據偏好語言載入資源。這包括介面文字、圖片、音訊等所有與語言相關的資源。例如,如果偏好語言為法語,應用會從“resources/fr - FR”目錄(假設存在)載入法語資源,顯示法語介面給使用者。如果找不到與偏好語言完全匹配的資源,應用應根據一定的規則(如回退到系統語言或預設語言)進行資源載入,確保應用能夠正常執行,而不會因為語言資源缺失而崩潰。
  2. 功能適配與使用者體驗
    • 根據偏好語言,應用還可以進行功能適配。例如,在某些語言環境下,可能需要調整輸入方法、鍵盤佈局、日期和時間格式等功能。對於支援語音輸入的應用,還可以根據偏好語言選擇相應的語音識別模型,提高語音輸入的準確性。透過這些適配措施,應用能夠為使用者提供更加符合其語言習慣和使用場景的功能體驗,增強使用者對應用的滿意度和忠誠度。

三、支援多語言切換

(一)多語言切換的實現方式

  1. 介面互動設計
    • 在應用的設定介面或其他合適的位置,提供語言切換選項。例如,可以建立一個下拉選單或列表,顯示應用支援的所有語言,讓使用者能夠方便地選擇自己想要的語言。當使用者選擇一種新語言時,應用應觸發語言切換邏輯。
  2. 語言切換邏輯處理
    • 當使用者選擇新語言後,應用呼叫 i18n.System.setAppPreferredLanguage() 方法設定新的偏好語言。然後,重新載入當前介面或整個應用,以應用新的語言設定。在重新載入過程中,應用根據新的偏好語言重新獲取和顯示資源,更新介面文字、圖片等內容。例如:
// 假設在一個語言設定頁面的函式中處理語言切換
function changeLanguage(languageCode: string) {
    try {
        i18n.System.setAppPreferredLanguage(languageCode);
        // 重新載入當前頁面或整個應用(這裡假設透過重新導航到當前頁面來實現重新載入,實際情況可能更復雜)
        window.location.reload();
    } catch(error) {
        let err: BusinessError = error as BusinessError;
        console.error(`語言切換失敗,錯誤碼: ${err.code}, 訊息: ${err.message}.`);
    }
}

(二)多語言切換的使用者體驗最佳化

  1. 實時反饋與過渡效果
    • 在使用者選擇語言後,立即給予反饋,如顯示一個短暫的提示資訊,告知使用者語言切換正在進行。同時,可以新增一些過渡效果,如漸變動畫,使介面切換更加自然流暢,減少使用者的等待感和不適感。例如,當使用者點選語言切換選項後,在螢幕中央顯示一個“正在切換語言,請稍候...”的提示框,同時介面逐漸淡化為白色,在新語言介面載入完成後再淡入顯示。
  2. 儲存使用者語言偏好
    • 應用應記住使用者選擇的語言偏好,下次啟動時自動應用該語言設定。可以將使用者選擇的語言偏好儲存在本地儲存(如應用內的資料庫或檔案)中,在應用啟動時讀取並設定偏好語言。這樣,使用者無需每次啟動應用都進行語言選擇,提高了使用便利性。例如:
// 儲存語言偏好
function saveLanguagePreference(languageCode: string) {
    // 這裡假設使用本地儲存的簡單方法,實際可能需要更復雜的儲存機制
    localStorage.setItem("preferredLanguage", languageCode);
}

// 讀取語言偏好並設定
function loadLanguagePreference() {
    let languageCode = localStorage.getItem("preferredLanguage");
    if (languageCode) {
        try {
            i18n.System.setAppPreferredLanguage(languageCode);
        } catch(error) {
            let err: BusinessError = error as BusinessError;
            console.error(`設定應用偏好語言失敗,錯誤碼: ${err.code}, 訊息: ${err.message}.`);
        }
    }
}

(三)多語言切換的測試與驗證

  1. 全面測試不同語言組合
    • 對應用支援的所有語言組合進行測試,確保在各種語言切換情況下,應用的功能正常,介面顯示正確,資源載入無誤。包括從一種語言切換到另一種語言,以及多次切換語言的情況。例如,測試從英文切換到中文,再從中文切換到法文,檢查每次切換後介面文字、日期格式、數字格式等是否正確顯示,應用的各項功能(如按鈕點選、輸入框輸入等)是否正常工作。
  2. 測試邊界情況和特殊字元
    • 注意測試邊界情況,如切換到語言資源較少或特殊字元處理較複雜的語言時,應用是否能夠正確處理。例如,對於一些包含複雜文字系統(如阿拉伯文、希伯來文等從右到左書寫的語言)或特殊字元(如中文的生僻字、日文的特殊假名組合等)的語言,檢查介面佈局是否合理,文字顯示是否完整、清晰,輸入和輸出是否正常。同時,測試在語言切換過程中,與其他系統功能(如通知、分享等)的互動是否正常,確保應用在多語言環境下的穩定性和可靠性。

四、處理語言與區域設定相關的問題

(一)語言資源缺失問題

  1. 問題描述
    • 當應用在某些情況下無法找到與使用者語言偏好或系統語言匹配的資源時,可能會導致介面顯示異常,如顯示亂碼、部分文字缺失或顯示預設語言文字。例如,應用支援英文和中文,但使用者裝置的系統語言設定為一種應用未完全支援的語言(如西班牙語),且應用沒有提供西班牙語資源,此時可能出現介面顯示問題。
  2. 解決方案
    • 建立合理的資源回退機制。當找不到完全匹配的資源時,應用可以按照一定的優先順序順序查詢其他可用資源。通常的優先順序順序可以是:使用者偏好語言 > 系統語言 > 預設語言(如英文或應用開發者指定的基礎語言)。例如,如果找不到西班牙語資源,應用可以嘗試查詢使用者偏好語言(如果有)的資源,如果也沒有,則查詢系統語言的資源,最後使用預設語言資源,確保應用能夠正常顯示基本內容,而不是崩潰或顯示混亂。同時,在開發過程中,儘量全面地支援常見語言,減少資源缺失的可能性。如果發現某些語言的資源經常缺失或不完整,可以考慮增加對這些語言的支援,提高應用的國際化程度。

(二)區域格式適配問題

  1. 問題描述
    • 不同區域對於日期、時間、數字、貨幣等格式有不同的要求,應用可能無法正確適配這些區域格式。例如,在一個全球應用中,對於日期顯示,如果沒有根據使用者所在區域進行正確的格式設定,可能導致使用者誤解日期資訊。在某些區域,日期格式為“DD/MM/YYYY”,而在其他區域可能是“MM/DD/YYYY”或“YYYY - MM - DD”。
  2. 解決方案
    • 使用系統提供的格式化類和方法進行區域格式適配。對於日期和時間,使用 DateTimeFormat 類,根據使用者所在區域的區域標識,選擇合適的格式樣式進行格式化。例如:
import { intl } from '@kit.LocalizationKit';

let date = new Date(2023, 9, 15);
let dateFormat = new intl.DateTimeFormat("en - GB", {dateStyle: "long"}); // 根據英國區域格式設定日期格式
let formattedDate = dateFormat.format(date); // 顯示為“15 October 2023”

let timeFormat = new intl.DateTimeFormat("en - GB", {timeStyle: "medium"}); // 根據英國區域格式設定時間格式
let formattedTime = timeFormat.format(date); // 顯示為“15:00:00”(假設當前時間為下午3點)
  • 對於數字和貨幣,使用 NumberFormat 類進行格式化。例如:
import { intl } from '@kit.LocalizationKit';

let numberFormat = new intl.NumberFormat("en - US", {style: "currency", currency: "USD"}); // 根據美國區域格式設定貨幣格式
let formattedNumber = numberFormat.format(1234.56); // 顯示為“$1,234.56”

let numberFormat2 = new intl.NumberFormat("fr - FR", {style: "number", minimumFractionDigits: 2}); // 根據法國區域格式設定數字格式
let formattedNumber2 = numberFormat2.format(1234.56); // 顯示為“1 234,56”(注意法國數字格式中使用逗號作為小數點,空格作為數字分組符號)
  • 透過這種方式,應用能夠根據使用者所在區域準確地顯示日期、時間、數字和貨幣等資訊,提高使用者體驗的一致性和準確性。

(三)語言切換時的資料一致性問題

  1. 問題描述
    • 在多語言切換過程中,應用中的資料可能出現不一致的情況。例如,使用者在一種語言環境下輸入的資料,在切換語言後可能無法正確顯示或解釋。或者,應用中的某些快取資料、設定資訊等可能與新的語言環境不相容,導致功能異常。例如,一個購物應用中,使用者在英文介面下新增了商品到購物車,切換到中文介面後,購物車中的商品資訊顯示亂碼或無法正確計算總價。
  2. 解決方案
    • 在資料儲存和處理過程中,採用統一的編碼和格式標準,確保資料與語言無關。例如,對於文字資料,使用UTF - 8等通用編碼格式,避免因語言切換導致字元編碼問題。對於應用中的設定和配置資訊,進行語言無關的儲存和管理,在切換語言時,根據新的語言環境重新解釋和顯示這些資訊。對於涉及資料計算和處理的部分,確保演算法和邏輯不受語言影響,如在購物車總價計算中,使用統一的數字格式和計算規則,而不是依賴於特定語言環境下的顯示格式。同時,在語言切換後,對相關資料進行重新載入和重新整理,確保顯示的資訊與新語言環境一致。例如,在購物應用中,切換語言後重新獲取購物車商品資訊,根據新語言環境格式化顯示,並重新計算總價等相關資料,保證資料的一致性和正確性。

(四)動態語言更新問題

  1. 問題描述
    • 如果應用在執行過程中,系統語言或使用者偏好語言發生了動態變化(如使用者在系統設定中更改了語言,或者應用接收到了來自伺服器的語言更新指令),應用可能無法及時響應並更新介面語言。例如,使用者在使用應用過程中,從系統設定將語言從英文切換為中文,但應用仍然顯示英文介面,直到下次重新啟動應用才更新為中文。
  2. 解決方案
    • 監聽系統語言或應用偏好語言的變化事件。鴻蒙系統可能提供相應的語言變化監聽器,開發者可以註冊該監聽器,在語言發生變化時立即收到通知。例如:
import { i18n } from '@kit.LocalizationKit';

i18n.System.on('languageChange', () => {
    // 語言發生變化時的處理邏輯
    let newLanguage = i18n.System.getSystemLanguage();
    console.log("系統語言已更改為:", newLanguage);
    // 在這裡重新載入資源,更新介面語言
    loadResourcesForLanguage(newLanguage);
});
  • 在收到語言變化通知後,立即重新載入當前介面或整個應用的資源,應用新的語言設定。可以將資源載入和介面更新邏輯封裝成一個函式(如上述程式碼中的 loadResourcesForLanguage()),在語言變化時呼叫該函式進行處理。這樣,應用能夠實時響應語言變化,提供更加動態和靈活的語言支援,提升使用者體驗。

(五)不同版本系統的相容性問題

  1. 問題描述
    • 隨著鴻蒙系統的不斷升級,語言與區域設定相關的功能和介面可能會發生變化。應用在不同版本的系統上執行時,可能會遇到相容性問題,如舊版本系統不支援新的語言設定方法,或者新版本系統對某些介面的行為進行了修改,導致應用在舊版本或新版本系統上出現異常。例如,在鴻蒙系統的早期版本中,語言設定介面可能與當前版本有所不同,應用如果直接使用新版本的介面,在舊版本系統上執行時會報錯。
  2. 解決方案
    • 在開發過程中,進行版本相容性測試。針對不同版本的鴻蒙系統,分別進行語言與區域設定功能的測試,確保應用在各個版本上都能正常工作。可以使用條件編譯或執行時檢測系統版本的方式,根據不同版本呼叫相應的語言設定介面。例如:
import device from '@ohos.device';

device.getInfo().then((info) => {
    let systemVersion = info.version;
    if (systemVersion >= "5.0.0") {
        // 使用新版本的語言設定介面
        i18n.System.setAppPreferredLanguageV5("zh - Hans");
    } else {
        // 使用舊版本的語言設定介面(假設為 setAppPreferredLanguageV4)
        i18n.System.setAppPreferredLanguageV4("zh - Hans");
    }
});
  • 同時,關注鴻蒙系統的官方文件和版本更新說明,及時瞭解語言與區域設定相關功能的變化,提前做好適配工作。如果可能的話,保持應用的程式碼結構靈活性,以便在系統升級時能夠更容易地進行介面調整和功能最佳化。例如,將語言設定相關的程式碼封裝成獨立的模組,當系統版本變化時,只需修改該模組中的介面呼叫,而不影響整個應用的架構。

(六)語言與區域設定的許可權問題

  1. 問題描述
    • 在某些情況下,應用可能需要特定的許可權才能獲取或設定系統語言和區域資訊。如果應用沒有獲取到相應許可權,可能無法正常進行語言與區域設定相關操作,導致功能受限。例如,在一些安全要求較高的裝置或系統環境中,應用可能需要使用者明確授權才能獲取系統語言資訊,否則呼叫 i18n.System.getSystemLanguage() 等方法時可能會失敗。
  2. 解決方案
    • 在應用的許可權宣告中,明確申請所需的語言與區域設定相關許可權。例如,在應用的 config.json 檔案中新增許可權宣告:
{
    "module": {
        "reqPermissions": [
            {
                "name": "ohos.permission.GET_SYSTEM_LOCALE",
                "reason": "用於獲取系統語言和區域資訊,以提供本地化服務",
                "usedScene": {
                    "ability": [
                        "com.example.myapp.MainAbility"
                    ],
                    "when": "always"
                }
            }
        ]
    }
}
  • 在應用執行時,檢查是否獲取到了相應許可權。如果沒有獲取到許可權,可以引導使用者手動授予許可權。例如:
import permission from '@ohos.permission';

async function checkPermission() {
    let hasPermission = await permission.checkPermission('ohos.permission.GET_SYSTEM_LOCALE');
    if (!hasPermission) {
        try {
            await permission.requestPermissionsFromUser(['ohos.permission.GET_SYSTEM_LOCALE']);
        } catch (error) {
            console.error('申請許可權失敗:', error);
        }
    }
}
  • 透過這種方式,確保應用在具備相應許可權的情況下進行語言與區域設定操作,避免因許可權問題導致功能異常。同時,合理向使用者解釋申請許可權的原因,提高使用者授予許可權的意願。

(七)應用內語言與系統語言同步問題

  1. 問題描述
    • 當系統語言發生變化時,應用可能無法及時與系統語言同步,導致應用內語言顯示與系統語言不一致。例如,使用者在系統設定中更改了語言,而應用仍然使用之前的語言設定,直到使用者手動在應用內進行語言切換才更新,這給使用者帶來了不便。
  2. 解決方案
    • 除了監聽系統語言變化事件(如前面所述)外,還可以在應用啟動時或從後臺恢復時,主動檢查系統語言是否發生變化,並根據變化情況更新應用內語言。例如:
import { i18n } from '@kit.LocalizationKit';

function checkAndSyncLanguage() {
    let currentSystemLanguage = i18n.System.getSystemLanguage();
    let savedAppLanguage = localStorage.getItem('appLanguage'); // 假設之前儲存的應用內語言設定儲存在本地儲存中
    if (currentSystemLanguage!== savedAppLanguage) {
        // 系統語言與應用內語言不一致,進行同步
        i18n.System.setAppPreferredLanguage(currentSystemLanguage);
        localStorage.setItem('appLanguage', currentSystemLanguage);
        // 重新載入資源,更新介面語言
        loadResourcesForLanguage(currentSystemLanguage);
    }
}

// 在應用啟動時呼叫
checkAndSyncLanguage();

// 在應用從後臺恢復時也可以呼叫(假設應用有相應的生命週期鉤子函式)
application.on('resume', () => {
    checkAndSyncLanguage();
});
  • 透過這種主動檢查和同步的方式,應用能夠更好地與系統語言保持一致,提供更加連貫的使用者體驗。同時,在進行語言同步時,注意儲存使用者在應用內的個性化語言設定(如果有),避免因同步操作而丟失使用者的偏好。

(八)多使用者環境下的語言設定問題

  1. 問題描述
    • 在支援多使用者的裝置上,不同使用者可能有不同的語言偏好。應用需要能夠在多使用者環境下正確處理語言設定,確保每個使用者都能看到符合自己偏好的語言介面。例如,一個家庭共享裝置上,家長和孩子可能分別使用不同的語言,應用應根據當前登入使用者的語言偏好進行顯示。
  2. 解決方案
    • 鴻蒙系統可能提供了獲取當前登入使用者資訊的介面,應用可以利用該介面獲取當前使用者標識,然後根據使用者標識關聯相應的語言偏好設定。例如:
import userIAM from '@ohos.userIAM';

userIAM.getUserInfo().then((userInfo) => {
    let userId = userInfo.userId;
    // 根據 userId 查詢對應的語言偏好設定(假設語言偏好設定儲存在本地資料庫或伺服器中)
    let preferredLanguage = getPreferredLanguageForUser(userId);
    i18n.System.setAppPreferredLanguage(preferredLanguage);
    // 載入相應語言資源,顯示介面
    loadResourcesForLanguage(preferredLanguage);
});
  • 在使用者切換時,及時更新應用的語言設定。可以監聽使用者切換事件,在事件處理函式中重新獲取新使用者的語言偏好並進行設定。例如:
userIAM.on('userSwitch', (newUserId) => {
    let preferredLanguage = getPreferredLanguageForUser(newUserId);
    i18n.System.setAppPreferredLanguage(preferredLanguage);
    // 重新載入資源,更新介面語言
    loadResourcesForUser(newUserId, preferredLanguage);
});
  • 透過這種方式,應用能夠在多使用者環境下正確處理語言設定,為每個使用者提供個性化的語言體驗。同時,注意在多使用者環境下,資源的管理和載入應進行合理最佳化,避免因頻繁切換使用者而導致資源浪費或載入緩慢。

透過對這些語言與區域設定相關問題的有效處理,我們能夠打造出更加穩定、靈活、使用者友好的鴻蒙Next應用。在國際化的道路上,不斷關注使用者需求、系統更新和最佳實踐,持續最佳化應用的語言與區域設定功能,將有助於提高應用的競爭力和使用者滿意度,使其更好地適應全球市場的需求。希望本文能夠為鴻蒙系統同行者在處理語言與區域設定方面提供全面、實用的參考和指導,助力應用在國際化程序中取得成功。

相關文章