Tailor your resources for language, scale, high contrast, and other qualifiers
描述了资源格量的整体慨念,如何使用它们,每个格量的目的。 ResourceContext.QualifierValues给出了所有可能的格量。
应用可以根据运行情境加载用料(assets)以及资源(resources)。情境中包含显示语言,是否高反,显示缩放系数,以及其他格量。需要把资源目录或者文件匹配到格量名字。
关于本地化的相关喜喜,参考Globalization and localization。
Qualifier name, qualifier value, and qualifier
格量名映射到一堆格量值,下面时个例子:
- 情境:the high contrast setting
- 格量名: contrast
- 格量值: standard, high, black, white
格量本身是通过组合格量名和值来命名的,形如<qualifier name>-<qualifier value>
。而且格量是大小写不敏感的,例子:contrast-standard
,Contrast-Standard
。
Use qualifiers in folder names
如果一个格量对应多个用料文件,可以使用格量来命名包含用料的目录:
\Assets\Images\contrast-standard\<logo.png, and other image files>
\Assets\Images\contrast-high\<logo.png, and other image files>
\Assets\Images\contrast-black\<logo.png, and other image files>
\Assets\Images\contrast-white\<logo.png, and other image files>
Use qualifiers in file names
也可以直接用格量来命名文件:
\Assets\Images\logo.contrast-standard.png
\Assets\Images\logo.contrast-high.png
\Assets\Images\logo.contrast-black.png
\Assets\Images\logo.contrast-white.png
Reference a string or image resource by name
参考:
- https://docs.microsoft.com/en-us/windows/uwp/app-resources/localize-strings-ui-manifest#refer-to-a-string-resource-identifier-from-xaml
- https://docs.microsoft.com/en-us/windows/uwp/app-resources/images-tailored-for-scale-theme-contrast#reference-an-image-or-other-asset-from-xaml-markup-and-code
Actual and neutral qualifier matches
没有必要为每个格量提供资源文件,例如:
\Assets\Images\logo.contrast-high.png
\Assets\Images\logo.png
高对比度下,第一个文件是真实匹配。真实匹配只有在格量包含格量值的时候才发生。第二个文件没有指定额外格量,所以是中立的,作为候补匹配。在非高对比的其他任意情形,第二个文件就会被选中。如果将第二个文件改成logo.contrast-standard.png,那么正常对比度下,就会有真实匹配。
如果有多个文件,可以使用目录形式组织:
\Assets\Images\contrast-high\<logo.png, and other images to load when high contrast theme is not None>
\Assets\Images\<logo.png, and other images to load when high contrast theme is None>
Multiple qualifiers
不管是用于文件还是目录,都可以将格量捆绑:
\Assets\Images\contrast-high\scale-400\<logo.png, and other image files>
另一种方式,应用于目录:
\Assets\Images\contrast-high_scale-400\<logo.png, and other image files>
另一种方式,应用于文件:
\Assets\Images\logo.contrast-high_scale-400.png
AlternateForm
主要应用场景是在使用msft-phonetic的时候用于提供furigana 。参考“Support Furigana for Japanese strings that can be sorted”。
Configuration
可以用于指定特定情境下才使用的配置,比如用于测试的资源。
Configuration可用于加载与环境变量MS_CONFIGURATION_ATTRIBUTE_VALUE最匹配的值。此环境变量示例:designer, test。
Contrast
对比度相关。
Custom
用于自定义情境,可以SetGlobalQualifierValue来加载,一个使用场景是根据授权来加载相应的资源。
DeviceFamily
设备类型相关。
DXFeatureLevel
Direct3D相关。
HomeRegion
跟用户的国家以及地域设置有关。
相关识别码来自https://unstats.un.org/unsd/methods/m49/m49regin.htm
Language
语言相关
LayoutDirection
布局相关,从左到右还是从右到左。
Scale
图像的缩放。
TargetSize
图像相关。主要用于在File Explorer中显示文件类型图标。
Theme
主题相关。
Shell light theme and unplated resources
Windows 10 May 2019 Update为Windows Shell引入了一个新的亮色主题。可能需要检验应用在此亮色主题下是否有足够高的对比度。
Providing light theme specific assets
通过altform-lightunplate
可以为新亮色主题提供资源。这个跟已有的altform-unplated格量是一致的。
Downlevel considerations
不要将theme-light和altform-unplated混在一起使用。
Compatibility behavior
出于向后兼容性的目的,Windows内建了侦测单色调图标是否与背景有足够对比度的逻辑。如果对比度不够,Windows回去寻找一个contrast-white版本。如果寻找的目标不存在,Windows会回退到plated版本。
Localize strings in your UI and app package manifest
Globalization and localization也有很多内容值得参考。
字符串字面值,如果在XAML标签或者app package manifest(Package.appxmanifest)中使用的话,可以提取Resource File(.resw)中。这样可以为不同语言的版本提供支持。
字符串资源和图像资源的差异是,一个文件对应一个图像资源,但是一个文件却可以包含多个字符串资源。通常把字符串资源文件放置在\Strings目录下。
Store strings in a resources file
- 设置应用的默认语言,假设为en-US
- 创建默认语言的资源文件
- 在资源文件中创建字符串
资源标识符不区分大小写,必须唯一。
Refer to a string resource identifier from XAML
通过x:Uid指令可以将一个控件或者元素关联到一个字符串资源标识符。当资源文件在运行时被加载的时候,x:Uid会触发相应的查找操作。如果资源文件中有:
- Greeting.Width
- Greeting.Text
对于一个TextBlock,如果其x:Uid是Greeting
,那么就会从资源文件中找到上面两项,并应用到TextBlock之上。如果只有Greeting且没有属性的话,是没办法应用到对应的对象上的。
如果将一个Button的x:Uid设置成Greeting
,由于Button没有Text辖属,所以在应用Greeting.Text的时候就会报错。
对于挂靠的辖属,需要用特定的语法。比如在Greeting上设置AutomationProperties.Name ,需要使用以下语法:
Greeting.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name
Refer to a string resource identifier from code
auto resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() };
myXAMLTextBlockElement().Text(resourceLoader.GetString(L"Farewell"));
必须在UI线程调用GetForCurrentView ,否则会出现异常"<typename> may not be created on threads that do not have a CoreWindow."
。可以用if (Windows.UI.Core.CoreWindow.GetForCurrentThread() != null)
判断是否在UI线程。
此操作也可以应用在Class Library或者Windows Runtime Library项目上。运行的时候,库的加载者所拥有的资源能被库代码查询到。建议库从其宿主加载资源,因为宿主作为应用会有更好的本地化支持。如果库需要提供资源的话,那么应该提供一个选项,让宿主可以替换其提供的资源。
如果资源名字是分段的(也就是包含.号),那么需要将.号替换成/
:
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Fare/Well"); // <data name="Fare.Well" ...> ...
<ResourceMapSubtree name="Fare"><NamedResource name="Well" uri="ms-resource://<GUID>/Resources/Fare/Well">...
Refer to a string resource identifier from your app package manifest
在Package.appxmanifest中引用资源,需要采用诸如ms-resource:AppDisplayName
此形式,其中AppDisplayName是资源名。
Localizable manifest items列出了所有可以本地化的条目。
Localize the string resources
略
Test your app
可以通过修改Windows设置Settings > Time & Language > Region & language > Languages
来告诉应用所需要加载的资源。
Factoring strings into multiple Resources Files
可以把所有字符串资源放置在一个resw文件中,或者也可以放在多个resw文件中。比如,你可能想把错误信息放在一个resw,app包自述字符串放在一个resw,UI字符串放在另一个resw。
如果要限定从一个resw中获取字符串资源,那么可以在x:Uid名字之前添加/<resources-file-name>/
,例如:
<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>
如果采用的是默认的Resources.resw,则不需要此限定。
下面的例子假设ErrorMessages.resw中有一个名为MismatchedPasswords的字符串资源。
auto resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView(L"ErrorMessages") };
myXAMLTextBlockElement().Text(resourceLoader.GetString(L"MismatchedPasswords"));
同理,如果将自述文件中的AppDisplayName从Resources.resw移到ManifestResources.resw,那么它的引用方式就变成了:ms-resource:/ManifestResources/AppDisplayName
。
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("Err.Msgs");
如果资源文件名字中包含点号,那么引用文件名的时候需要保留点号,不要将其替换成/
。
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("Err.Msgs");
如果不确定,可以使用MakePri.exe来回吐应用的PRI文件,每个资源的uri会在回吐出的文件中显示:
<ResourceMapSubtree name="Err.Msgs"><NamedResource name="MismatchedPasswords" uri="ms-resource://<GUID>/Err.Msgs/MismatchedPasswords">...
Load a string for a specific language or other context
从ResourceContext.GetForCurrentView获取的ResourceContext带有每种格量的格量名(根据当前机器以及用户的配置得出的)。如果你的应用想覆盖默认的设置,比如允许用户设置一个特定的语言,你需要创建一个新的ResourceContext:
var resourceContext = new Windows.ApplicationModel.Resources.Core.ResourceContext(); // not using ResourceContext.GetForCurrentView
resourceContext.QualifierValues["Language"] = "de-DE";
var resourceMap = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
this.myXAMLTextBlockElement.Text = resourceMap.GetValue("Farewell", resourceContext).ValueAsString;
剩余略。
Updating strings in response to qualifier value change events
通过ResourceContext.QualifierValues的MapChanged可以侦测系统设置的改变。
剩余略。
Load strings from a Class Library or a Windows Runtime Library
略。
Loading strings from other packages
可以通过ResourceMap来让当前包访问其他app包中的顶层资源,通过顶层资源就可以使用ResourceMap.GetSubtree来访问下级资源树。
也可以使用https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes以绝对路径的方式来访问资源。
Loading strings in non-packaged applications
从Windows Version 1903 (May 2019 Update)开始,非打包应用也可以使用RMS。
剩余略。
(未完待续)