多项目本地化解决方案
Localization in multiple projects solution
我在 UWP 中有一个包含 3 个不同项目(例如:A、B 和 C)的解决方案。 B是A和C项目访问的库。
我已经为 A 项目生成了翻译(使用 XLF 文件进行翻译)并且工作正常。我正在使用多语言应用程序工具包 (MAT)。
现在我已经开始翻译 B 项目(resx 文件和 xlf 文件在 B 项目中,就像在 A 中一样)
尽管我也在 B 项目中激活了 MAT,我无法将新的翻译语言添加到 B,所以我手动创建了文件。构建时只有一个警告:
GENERATEPROJECTPRIFILE : warning PRI257: 0xdef00522 - Resources found for language(s) 'es,en-us,eu' but no resources found for default language(s): ''. Change the default language or qualify resources with the default language. http://go.microsoft.com/fwlink/?LinkId=231899
似乎项目 B 没有默认语言,尽管它已在解决方案中设置 (Package.appxmanifest)。
当运行应用程序时,显示B项目中none个本地化字符串。
知道我该如何处理这个问题吗?
编辑 1:我已经更正了在 Assemby Info 中更改项目默认语言的警告。尽管如此,字符串仍然不可见。
编辑2:A项目和B项目中的代码相同:
ResourceLoader.GetForCurrentView().GetString("FileName_StringName");
可能感兴趣的其他细节是 B 项目 类 是(大部分)静态的。
启动应用程序时,首先发生的事情之一就是选择应用程序级别的语言:
// Hard coded language override
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "eu";
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
编辑 3:这是将 PRI 转储到 XML 文件包含的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PriInfo>
<ResourceMap name="CoreTPA" version="1.0" primary="true">
<Qualifiers>
<Language>ES,EN-US,EU</Language>
</Qualifiers>
<ResourceMapSubtree name="CoreTPA">
<ResourceMapSubtree name="Resources">
<NamedResource name="AuroraForecastImages_GetForecast_ErrorDeserializingData" uri="ms-resource://CoreTPA/CoreTPA/Resources/AuroraForecastImages_GetForecast_ErrorDeserializingData">
<Candidate qualifiers="Language-EU" type="String">
<Value>Error deserializing data</Value>
</Candidate>
<Candidate qualifiers="Language-ES" isDefault="true" type="String">
<Value>Error deserializing data</Value>
</Candidate>
<Candidate qualifiers="Language-EN-US" type="String">
<Value>Error deserializing data</Value>
</Candidate>
</NamedResource>
<NamedResource name="AuroraForecastImages_GetForecast_ErrorGettingDataFromServerIsNetworkWorkingCorrectly" uri="ms-resource://CoreTPA/CoreTPA/Resources/AuroraForecastImages_GetForecast_ErrorGettingDataFromServerIsNetworkWorkingCorrectly">
<Candidate qualifiers="Language-EU" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
<Candidate qualifiers="Language-ES" isDefault="true" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
<Candidate qualifiers="Language-EN-US" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
</ResourceMapSubtree>
<ResourceMapSubtree name="Files">
<ResourceMapSubtree name="CoreTPA">
<NamedResource name="Core_ml.xml" uri="ms-resource://CoreTPA/Files/CoreTPA/Core_ml.xml">
<Candidate type="Path">
<Value>CoreTPA\Core_ml.xml</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
</ResourceMapSubtree>
</ResourceMap>
</PriInfo>
经测试,项目B使用的本地化资源来自项目A(如果项目A调用项目B)或项目C(如果项目C调用项目B),而不是项目B中添加的本地化资源。
因此,不需要在项目B中手动添加资源文件,您需要在项目A或项目C中添加您的字符串资源,而不是项目B。
根据图书馆本身的名称,将图书馆的资源添加到单独的资源映射中。例如,如果我有以下项目设置(其中 MainUwpApp
引用了 UwpClassLibrary
):
MainUwpApp(EXE 项目)
Strings\Resources.resw
Resource Name = Source, Value = Main App
UwpClassLibrary(DLL 项目)
Strings\Resources.resw
Resource Name = Source, Value = Class Library
..然后当我构建 EXE 并转储资源文件时,我看到类似这样的内容:
> makepri dump -if resources.pri -of resources.xml -dt basic
Output File at resources.xml
Successfully Completed
>findstr Source resources.xml
<NamedResource name="Source" uri="ms-resource://{GUID}/Resources/Source">
<NamedResource name="Source" uri="ms-resource://{GUID}/UwpClassLibrary/Resources/Source">
从这里可以看出名为Source
的两个资源存在于两个独立的资源子图中。在运行时,您可以像这样看到它们:
var map = ResourceManager.Current.MainResourceMap;
var appResource = map["Resources/Source"];
Debug.WriteLine($"URI: {appResource.Uri}, Value: {appResource.Candidates[0].ValueAsString}");
var libraryResource = map["UwpClassLibrary/Resources/Source"];
Debug.WriteLine($"URI: {libraryResource.Uri}, Value: {libraryResource.Candidates[0].ValueAsString}");
这导致:
URI: ms-resource://{GUID}/Resources/Source, Value: Main App
URI: ms-resource://{GUID}/UwpClassLibrary/Resources/Source, Value: Class Library
我在 UWP 中有一个包含 3 个不同项目(例如:A、B 和 C)的解决方案。 B是A和C项目访问的库。
我已经为 A 项目生成了翻译(使用 XLF 文件进行翻译)并且工作正常。我正在使用多语言应用程序工具包 (MAT)。
现在我已经开始翻译 B 项目(resx 文件和 xlf 文件在 B 项目中,就像在 A 中一样)
尽管我也在 B 项目中激活了 MAT,我无法将新的翻译语言添加到 B,所以我手动创建了文件。构建时只有一个警告:
GENERATEPROJECTPRIFILE : warning PRI257: 0xdef00522 - Resources found for language(s) 'es,en-us,eu' but no resources found for default language(s): ''. Change the default language or qualify resources with the default language. http://go.microsoft.com/fwlink/?LinkId=231899
似乎项目 B 没有默认语言,尽管它已在解决方案中设置 (Package.appxmanifest)。
当运行应用程序时,显示B项目中none个本地化字符串。
知道我该如何处理这个问题吗?
编辑 1:我已经更正了在 Assemby Info 中更改项目默认语言的警告。尽管如此,字符串仍然不可见。
编辑2:A项目和B项目中的代码相同:
ResourceLoader.GetForCurrentView().GetString("FileName_StringName");
可能感兴趣的其他细节是 B 项目 类 是(大部分)静态的。
启动应用程序时,首先发生的事情之一就是选择应用程序级别的语言:
// Hard coded language override
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "eu";
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
编辑 3:这是将 PRI 转储到 XML 文件包含的内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PriInfo>
<ResourceMap name="CoreTPA" version="1.0" primary="true">
<Qualifiers>
<Language>ES,EN-US,EU</Language>
</Qualifiers>
<ResourceMapSubtree name="CoreTPA">
<ResourceMapSubtree name="Resources">
<NamedResource name="AuroraForecastImages_GetForecast_ErrorDeserializingData" uri="ms-resource://CoreTPA/CoreTPA/Resources/AuroraForecastImages_GetForecast_ErrorDeserializingData">
<Candidate qualifiers="Language-EU" type="String">
<Value>Error deserializing data</Value>
</Candidate>
<Candidate qualifiers="Language-ES" isDefault="true" type="String">
<Value>Error deserializing data</Value>
</Candidate>
<Candidate qualifiers="Language-EN-US" type="String">
<Value>Error deserializing data</Value>
</Candidate>
</NamedResource>
<NamedResource name="AuroraForecastImages_GetForecast_ErrorGettingDataFromServerIsNetworkWorkingCorrectly" uri="ms-resource://CoreTPA/CoreTPA/Resources/AuroraForecastImages_GetForecast_ErrorGettingDataFromServerIsNetworkWorkingCorrectly">
<Candidate qualifiers="Language-EU" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
<Candidate qualifiers="Language-ES" isDefault="true" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
<Candidate qualifiers="Language-EN-US" type="String">
<Value>Error getting data from server.
Is network working correctly?</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
</ResourceMapSubtree>
<ResourceMapSubtree name="Files">
<ResourceMapSubtree name="CoreTPA">
<NamedResource name="Core_ml.xml" uri="ms-resource://CoreTPA/Files/CoreTPA/Core_ml.xml">
<Candidate type="Path">
<Value>CoreTPA\Core_ml.xml</Value>
</Candidate>
</NamedResource>
</ResourceMapSubtree>
</ResourceMapSubtree>
</ResourceMap>
</PriInfo>
经测试,项目B使用的本地化资源来自项目A(如果项目A调用项目B)或项目C(如果项目C调用项目B),而不是项目B中添加的本地化资源。
因此,不需要在项目B中手动添加资源文件,您需要在项目A或项目C中添加您的字符串资源,而不是项目B。
根据图书馆本身的名称,将图书馆的资源添加到单独的资源映射中。例如,如果我有以下项目设置(其中 MainUwpApp
引用了 UwpClassLibrary
):
MainUwpApp(EXE 项目)
Strings\Resources.resw
Resource Name = Source, Value = Main App
UwpClassLibrary(DLL 项目)
Strings\Resources.resw
Resource Name = Source, Value = Class Library
..然后当我构建 EXE 并转储资源文件时,我看到类似这样的内容:
> makepri dump -if resources.pri -of resources.xml -dt basic
Output File at resources.xml
Successfully Completed
>findstr Source resources.xml
<NamedResource name="Source" uri="ms-resource://{GUID}/Resources/Source">
<NamedResource name="Source" uri="ms-resource://{GUID}/UwpClassLibrary/Resources/Source">
从这里可以看出名为Source
的两个资源存在于两个独立的资源子图中。在运行时,您可以像这样看到它们:
var map = ResourceManager.Current.MainResourceMap;
var appResource = map["Resources/Source"];
Debug.WriteLine($"URI: {appResource.Uri}, Value: {appResource.Candidates[0].ValueAsString}");
var libraryResource = map["UwpClassLibrary/Resources/Source"];
Debug.WriteLine($"URI: {libraryResource.Uri}, Value: {libraryResource.Candidates[0].ValueAsString}");
这导致:
URI: ms-resource://{GUID}/Resources/Source, Value: Main App
URI: ms-resource://{GUID}/UwpClassLibrary/Resources/Source, Value: Class Library