當地語系化您的 UI 及應用程式套件資訊清單中的字串
如想深入了解將 Windows 應用程式 SDK 的應用程式當地語系化的價值主張,請參閱全球化與當地語系化。
如果希望應用程式支援不同的顯示語言,而且您的程式碼、XAML 標記或應用程式套件資訊清單也含有字串常值時,請將這些字串移入資源檔案 (.resw)。 您可以接著針對應用程式支援的每一種語言建立該資源檔案的翻譯複本。
硬編碼的字串常值可顯示在命令式程式碼或 XAML 標記中,例如當做 TextBlock 的 Text 屬性。 它們也可能顯示在應用程式套件資訊清單來源檔 (Package.appxmanifest
檔案),例如在 Visual Studio 資訊清單設計工具的 [應用程式] 索引標籤中顯示為顯示名稱的值。 將這些檔案移到資源檔案 (.resw),然後將應用程式和資訊清單中的硬編碼字串常值替換為資源識別碼的參照。
與僅包含一個影像資源的影像資源檔案不同,字串資源檔案中包含多個字串資源。 字串資源檔案是一種資源檔案 (.resw),您通常會在專案的 \Strings 資料夾建立這種資源檔案。 如需了解在資源檔案 (.resw) 的名稱中使用限定詞的背景資訊,請參閱量身打造語言、比例和其他限定詞適用的資源。
在資源檔案存放字串
設定應用程式的預設語言。
- 在解決方案已於 Visual Studio 開啟的情況下,開啟
Package.appxmanifest
。 - 確認 [應用程式] 索引標籤的預設語言已設定妥當 (例如「en」或「en-US」)。 剩下的步驟皆假定您已將預設語言設為「en-US」。
注意
您至少必須為該預設語言提供當地語言化的字串資源。 如果系統無法從使用者的偏好語言或顯示語言設定找到較好的比對結果,就會載入這些資源。
- 在解決方案已於 Visual Studio 開啟的情況下,開啟
為預設語言建立資源檔案 (.resw)。
- 在專案節點之下建立新資料夾,並命名為
Strings
。 - 在
Strings
之下建立新子資料夾,並命名為en-US
。 - 在
en-US
之下建立新資源檔案 (.resw) (位於「新增項目」對話方塊的 WinUI 檔案類型之下),並確認它已命名為Resources.resw
。
注意
如果您有想要移植的 .NET 資源檔案 (.resx),請參閱移植 XAML 和 UI。
- 在專案節點之下建立新資料夾,並命名為
開啟
Resources.resw
並新增這些字串資源。Strings/en-US/Resources.resw
在此範例中,「Greeting」是您可以從標記中參照的字串資源識別碼,我們接下來將會示範操作。 在「Greeting」識別碼中,會有一個為 Text 屬性而設的字串,以及一個為 Width 屬性而設的字串。 「Greeting.Text」是屬性識別碼的一種範例,它正好對應 UI 元素的屬性。 舉例來說,您也可以在「名稱」欄加入「Greeting.Foreground」,並將值設為「Red」。 「Farewell」識別碼是一組簡單的字串資源識別碼,沒有子屬性,且可從命令式程式碼載入,我們接下來將會示範操作。 「評論」欄是很適合用來向譯者提供特別指示的位置。
在此範例中,我們已經有一組名稱為「Farewell」的簡單字串資源識別碼項目,所以不能再加入以相同識別碼為依據的屬性識別碼。 如果加入「Farewell.Text」,組建
Resources.resw
時會發生「重複項目」錯誤。資源識別碼需區分大小寫,且在每個資源檔案中都不得重複。 提供額外脈絡給譯者時,請務必使用有效的資源識別碼。 此外,字串資源送交翻譯後,請勿再變更資源識別碼。 當地語系化團隊會使用資源識別碼來追蹤資源中的增補、刪除和更新項目。 變更資源識別碼即為「資源識別碼移位」,會導致字串需要重新翻譯,因為它的呈現方式宛如刪除字串後新增其他字串。
參照 XAML 的字串資源識別碼
將標記中的控制項或其他元素與字串資源識別碼建立關聯時,您會使用 x:Uid directive。
<TextBlock x:Uid="Greeting"/>
\Strings\en-US\Resources.resw
會在執行階段載入 (因為此時它是專案中唯一的資源檔案)。 TextBlock 的指示詞 x:Uid 會產生查詢動作,尋找 Resources.resw
當中包含字串資源識別碼「Greeting」的屬性識別碼。 系統會找到「Greeting.Text」和「Greeting.Width」屬性識別碼,它們的值都會套用到 TextBlock,覆寫任何在標記中已完成本機設定的值。 如果您有新增「Greeting.Foreground」,該值也一樣會經過套用。 但只有屬性識別碼會用於設定 XAML 標記元素的屬性,所以在這個 TextBlock 將 x:Uid 設為「Farewell」不會發生任何效果。 Resources.resw
會包含字串資源標識碼 「Farewell」,但不包含它的屬性識別碼。
將字串資源識別碼指派給 XAML 元素時,請確認該識別碼的所有屬性識別碼都適用於 XAML 元素。 舉例來說,如果您在 TextBlock 設定了 x:Uid="Greeting"
,「Greeting.Text」就可解析,因為 TextBlock 類型含有 Text 屬性。 但如果您在 Button 設定 x:Uid="Greeting"
,「Greeting.Text」就會造成執行階段錯誤,因為 Button 類型不含 Text 屬性。 這種情況的一種解決方案是編寫名稱為「ButtonGreeting.Content」的屬性識別碼,然後在 Button 設定 x:Uid="ButtonGreeting"
。
與其設定資源檔案的 Width,建議您讓控制項對內容動態縮放大小。
注意
如果是附加屬性,您在 .resw 檔案的「名稱」欄必須使用特殊語法。 舉例來說,如果要為「Greeting」識別碼設定附加屬性 AutomationProperties.Name 的值,您就必須在「名稱」欄輸入這種語法。
Greeting.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name
參照程式碼的字串資源識別碼
您可以根據簡單字串資源識別碼來明確載入字串資源。
var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");
您可以在類別庫專案當中使用上述的同一個程式碼。 到了執行階段,主控類別庫的應用程式資源就會載入。 由於應用程式的當地語系化程度可能較大,我們建議讓類別庫載入主控應用程式的資源。 如果類別庫需要提供資源,就必須為它的主控應用程式提供選項,讓應用程式在輸入中替換掉這些資源。
如果資源名稱有分段 (內含「.」字元),則請將資源名稱中的點替換成往前的斜線 (「/」)。 舉例來說,屬性識別碼包含點,您就必須執行上述替換作業,才能載入程式碼中的其一屬性。
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Fare/Well"); // <data name="Fare.Well" ...> ...
如有疑慮,您可以使用 MakePri.exe 來傾印應用程式的 PRI 檔案。 每個資源的 uri
都會顯示在傾印檔案中。
<ResourceMapSubtree name="Fare"><NamedResource name="Well" uri="ms-resource://<GUID>/Resources/Fare/Well">...
參照應用程式套件資訊清單的字串資源識別碼
開啟應用程式套件資訊清單資源檔案 (
Package.appxmanifest
檔案);根據預設,應用程式的Display name
會在該檔案中表達為字串常值的格式。若要製作該字串的可當地語系化版本,請開啟
Resources.resw
,並以名稱「AppDisplayName」和值「Adventure Works Cycles」新增字串資源。以您剛建立的字串資源識別碼 (「AppDisplayName」) 參照來替換顯示名稱字串常值。 執行此作業時您會使用
ms-resource
URI (統一資源識別項) 配置。針對您在資訊清單中想要當地語系化的每個字串重複此程序。 例如您應用程式的短名稱 (您可以設定讓它顯示在「開始」的應用程式圖磚)。 如需應用程式套件資訊清單的完整項目清單,以便您當地語系化,請參閱可當地語系化的資訊清單項目。
將字串資源當地語系化
製作資源檔案 (.resw) 的複本供其他語言使用。
- 在「字串」之下建立新的子資料夾,然後命名為「de-DE」供德語使用。
注意
您可以在資料夾名稱使用任何 BCP-47 語言標籤。 請參閱針對語言、比例和其他限定詞量身打造資源詳細了解語言限定詞和常用語言標籤清單。 2. 在
Strings/de-DE
資料夾製作Strings/en-US/Resources.resw
複本。翻譯字串。
- 開啟
Strings/de-DE/Resources.resw
並翻譯「值」欄中的值。 您不需要翻譯評論。
Strings/de-DE/Resources.resw
- 開啟
如有需要,您可以針對其他語言重複步驟 1 和 2。
Strings/fr-FR/Resources.resw
測試您的應用程式
測試應用程式的預設顯示語言。 您接著可以在 [設定]>[時間]&[語言]>[區域]&[語言]>[語言] 變更顯示語言,然後重新測試應用程式。 請注意 UI 和殼層中的字串 (例如標題列,亦即顯示名稱,以及圖磚中的短名稱)。
注意
如果找到的資料夾名稱與顯示名稱設定相符,則資料夾中的資源檔案就會載入。 否則系統會進行遞補,以應用程式預設語言的資源結尾。
將字串分解到多個資源檔案中
您可以保留單一資源檔案 (resw) 中的所有字串,也可以將字串分解到多個資源檔案。 舉例來說,您可以分別將錯誤訊息、應用程式套件資訊清單字串和 UI 字串保留在三個資源檔案。 這種情況下,資料夾結構如下。
若要讓字串資源識別碼參照特定檔案,在識別碼前加上 /<resources-file-name>/
即可。 下方的標記範例假定 ErrorMessages.resw
包含名稱為「PasswordTooWeak.Text」的資源,且該值描述錯誤。
<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>
您只需要在 以外的Resources.resw
資源檔案字串資源識別碼之前新增 /<resources-file-name>/
。 這是因為「Resources.resw」是預設檔案名稱,如果您略過檔案名稱 (正如我們在本主題前文的範例所做的示範),系統就會做出如上假設。
下方的程式碼範例假定 ErrorMessages.resw
包含名稱為「MismatchedPasswords」的資源,且該值描述錯誤。
var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ErrorMessages");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("MismatchedPasswords");
如果您要將 Resources.resw
資源中的「AppDisplayName」移到 ManifestResources.resw
,則您必須在應用程式套件資訊清單中將 ms-resource:AppDisplayName
變更為 ms-resource:/ManifestResources/AppDisplayName
。
如果資源檔案名稱有分段 (包含「.」字元),您在參照此名稱時請保留點。 請勿將點替換成 (「/」) 字元,該動作適用於資源名稱。
var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("Err.Msgs");
如有疑慮,您可以使用 MakePri.exe 來傾印應用程式的 PRI 檔案。 每個資源的 uri
都會顯示在傾印檔案中。
<ResourceMapSubtree name="Err.Msgs"><NamedResource name="MismatchedPasswords" uri="ms-resource://<GUID>/Err.Msgs/MismatchedPasswords">...
載入特定語言或其他脈絡的字串
預設的 ResourceContext (於建立 ResourceLoader 時獲得) 內含每個限定詞名稱的限定詞值,代表的是預設執行階段脈絡 (也就是目前的使用者與機器設定)。 系統會依據資源檔案 (.resw) 名稱中的限定詞比對執行階段脈絡中的限定詞值。
但有些時候,您可能想在尋找要載入的資源檔案時,讓應用程式覆寫系統設定,並明確指定要使用的語言、比例或其他限定詞值。 舉例來說,您可能想讓使用者為工具提示或錯誤訊息選取替代語言。
如想達成此目的,您可以建構新的 ResourceContext 來覆寫值,然後在字串查詢中使用該脈絡物件。
var resourceManager = new Microsoft.Windows.ApplicationModel.Resources.ResourceManager();
var resourceContext = resourceManager.CreateResourceContext();
resourceContext.QualifierValues["Language"] = "de-DE";
var resourceMap = resourceManager.MainResourceMap.GetSubtree("Resources");
this.myXAMLTextBlockElement.Text = resourceMap.GetValue("Farewell", resourceContext).ValueAsString;
按照上方程式碼範例使用 QualifierValues,對於任何限定詞皆適用。 遇到特殊的語言案例,您就可以改為使用這種方法來替代。
resourceContext.Languages = new string[] { "de-DE" };
載入類別庫的字串
參照類別庫的字串資源通常會在組建程序中加到套件的子資料夾。 這類字串的資源識別碼通常會採用 LibraryName/ResourcesFileName/ResourceIdentifier 的格式。
類別庫可能會為自己的資源取得 ResourceLoader。 舉例來說,下列程式碼展示了參照此程式碼的類別庫或應用程式如何為類別庫的字串資源取得 ResourceLoader。
var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ContosoControl/Resources");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("exampleResourceName");
如果您對路徑有疑慮,可以指定 MakePri.exe 命令列選項來傾印元件或類別庫的 PRI 檔案。 每個資源的 uri
都會顯示在傾印檔案中。
<NamedResource name="exampleResourceName" uri="ms-resource://Contoso.Control/Contoso.Control/ReswFileName/exampleResourceName">...
載入其他套件的字串
應用程式套件的資源是透過套件自有的最頂層 ResourceMap 來管理與存取,該字串可從 ResourceManager 存取。 在每個套件中,各種元件都可能有自己的 ResourceMap 樹狀子目錄,可經由 ResourceMap.GetSubtree 存取。
架構套件可透過絕對資源識別碼 URI 存取自己的資源。 另請參閱 UWP 文件的 URI 配置了解詳細資訊。
載入未封裝應用程式的字串
至 Windows 版本 1903 (2019 年 5 月更新版),未封裝的應用程式也可以運用資源管理系統。
您只要建立 Windows 應用程式 SDK 的使用者控制項/程式庫,然後在資源檔案存放任何字串即可。 您接著就能參照 XAML 的字串資源識別碼、參照程式碼的字串資源識別碼,或載入類別庫的字串。
若要使用未封裝應用程式的資源,您需要採取幾個動作:
- 在從程式碼解析資源時,使用多載的 ResourceManager 建構函式傳遞應用程式 .pri 檔案的檔案名稱,因為未封裝的案例並沒有預設檢視。
- 使用 MakePri.exe 手動產生應用程式的 resources.pri 檔案。
makepri new /pr <PROJECTROOT> /cf <PRICONFIG> /of resources.pri
執行- <PRICONFIG> 必須刪去<「packaging」>區段,這樣才能讓所有資源都封裝在單一 resources.pri 檔案。 如果使用 createconfig 建立的預設 MakePri.exe 設定檔,您必須在建立後手動刪除<「packaging」>區段。
- <PRICONFIG> 必須包含所有相關的必需索引子,才能將專案的所有資源合併到單一 resources.pri 檔案。 createconfig 建立的預設 MakePri.exe 設定檔就包含所有索引子。
- 如果您未使用預設組態,請確定已啟用 PRI 索引器(檢閱如何執行此動作的預設組態),以合併從項目參考、NuGet 參考等中找到的 PRIS,這些 URI 位於專案根目錄內。
注意
刪去
/IndexName
之後,加上專案沒有應用程式資訊清單,PRI 檔案的 IndexName/root 命名空間會自動設為 Application,亦即執行階段理解了未封裝應用程式的需求 (這個動作移除了之前對套件 ID 的硬相依性)。 指定資源 URI 時,刪去根目錄命名空間的 ms-resource:/// 參照會將 Application 推論為未封裝應用程式的根目錄命名空間 (您也可以在 ms-resource://Application/ 明確指定 Application)。
- 將 PRI 檔案複製到 .exe 的組建輸出目錄
- 執行 .exe
注意
資源管理系統在根據未封裝應用程式的語言解析資源時,會使用系統顯示語言,而非使用者偏好語言清單。 使用者偏好語言清單只會使用在 Windows 應用程式 SDK 的封裝應用程式。
重要
只要資源經過修改,您就必須手動重新建立 PRI 檔案。 建議使用建立後指令碼來處理 MakePri.exe 命令,並將 resources.pri 輸出複製到 .exe 目錄。