在 MvvmCross ViewModels 中本地化文本
Posted
技术标签:
【中文标题】在 MvvmCross ViewModels 中本地化文本【英文标题】:Localising text in MvvmCross ViewModels 【发布时间】:2013-02-14 17:04:15 【问题描述】:我想从 ViewModel 中获取所有本地化文本(因为它通常是动态的),我想知道您如何使用转换器从用于本地化的 json 文件中获取文本。例如,在下面的代码中,我希望 LocalisedString 使用我目前在静态文本绑定中的视图中使用的转换器 -
public string MyText // used in the binding in the View
get
string exclamation;
if (MyValue <= 3.3)
exclamation = LocalisedString("Rubbish!");
else if (OverallScore > 3.3 && OverallScore <= 6.6)
exclamation = LocalisedString("Good!");
else
exclamation = LocalisedString("Excellent!");
return exclamation;
当前使用的是 MvvmCross 版本 1。
非常感谢任何帮助。
【问题讨论】:
【参考方案1】:注意:这个答案是关于 vNext - 移植回 master 应该相当容易......该区域的差异不是那么大。
MvvmCross 中内置了文本本地化机制。
唯一使用它的公共示例是会议示例。
此示例包括共享的和特定于 ViewModel 的 Json 文件 - see
这些 Json 文件每个都包含简单的键值对,例如:
"Title":"SQLBits X",
"Welcome":"Welcome",
"Sessions":"Sessions",
"Sponsors":"Sponsors",
"Tweets":"Tweets",
"Favorites":"Favorites"
它们作为内容或资产链接到 Droid、Touch 和 WP...所有这些都由平台使用 ResourceLoader 插件访问。
为了在运行时使用这些 JSON 文件,核心项目将它们加载到 TextProviderBuilder:
protected override IDictionary<string, string> ResourceFiles
get
var dictionary = this.GetType()
.Assembly
.GetTypes()
.Where(t => t.Name.EndsWith("ViewModel"))
.Where(t => !t.Name.StartsWith("Base"))
.ToDictionary(t => t.Name, t => t.Name);
dictionary[Constants.Shared] = Constants.Shared;
return dictionary;
如果您愿意,显然可以在此处轻松加载其他 JSON 文件。我的一些应用拥有以下情况并不少见:
错误文件 一般共享语句的文件 特定组件的文件 每个 ViewModel 一个文件而其他人有:
只有一个大文件!国际化 - 完成后 - 通过加载一组不同的 JSON 文件来完成。通常所做的是首先加载默认集,然后加载增量覆盖 - 因此您可以加载英语作为默认值,Cat 作为覆盖,Cat-Lol 作为进一步细化。
有关这方面的一些讨论,请参阅:
MvvmCross localization: switch at runtime 以及一些未来的增强功能 - https://github.com/slodge/MvvmCross/issues/55假设每个 ViewModel 有一个共享文件和一个文件,那么为了提供对 JSON 文本值的运行时访问,BaseViewModel 提供了 2 个属性:
public IMvxLanguageBinder TextSource
get return new MvxLanguageBinder(Constants.GeneralNamespace, GetType().Name);
public IMvxLanguageBinder SharedTextSource
get return new MvxLanguageBinder(Constants.GeneralNamespace, Constants.Shared);
这些属性在数据绑定中使用:
指定是使用 SharedTextSource 还是 TextSource 的路径 MvxLanguageBinderConverter 作为转换器 作为 ConverterParameter 的文本键例如,在 Droid 中是:
<TextView
style="@style/AboutPageBodyText"
local:MvxBind="'Text':'Path':'TextSource','Converter':'Language','ConverterParameter':'Title'"
/>
尽管在现代“瑞士”绑定中,这会写成:
<TextView
style="@style/AboutPageBodyText"
local:MvxBind="Text TextSource, Converter=Language, ConverterParameter='Title'"
/>
任何希望使用文本的代码也可以这样做 - 例如,请参阅如何从 TimeAgoConverter.cs 中的资源字符串创建 TimeAgo 文本,它使用如下资源字符串:
"TimeAgo.JustNow":"just now",
"TimeAgo.SecondsAgo":"0s ago",
"TimeAgo.MinutesAgo":"0m ago",
"TimeAgo.HoursAgo":"0h ago",
"TimeAgo.DaysAgo":"0d ago",
"TimeAgo.Never":"never"
这个代码是有效的:
var valueToFormat = 42;
var whichFormat = "TimeAgo.DaysAgo";
var textProvider = this.GetService<IMvxTextProvider>();
var format = textProvider.GetText(Constants.GeneralNamespace, Constants.Shared, whichFormat);
return string.Format(format, valueToFormat)
语言Binder和ValueConverter真的是非常简单的代码
MvxLanguageBinder.cs MvxLanguageBinderConverter.cs因此,如果您需要,请随时为您的应用构建更复杂的东西。
还有其他跨平台的文本本地化技术——我自己特别想有一天尝试一下白话——https://github.com/rdio/vernacular
【讨论】:
只是添加另一个链接主题 - ***.com/questions/13471994/… 非常感谢 - 我会在接下来的几天里尝试解决 - 我会带着我的结果回来。 太棒了 - 正如你所说,我现在一切正常,最后很简单 Fab - 如果有任何您认为遗漏或误导的内容,请随时在博客上发表相关内容,或在github.com/slodge/MvvmCross/issues/55 或 github.com/slodge/MvvmCross/issues/53 或 github.com/slodge/MvvmCross/issues/63 上为 wiki 或 cmets 贡献内容:) Stuart 你试过白话吗?【参考方案2】:也许您应该返回枚举而不是字符串并在视图中处理本地化。
【讨论】:
因为它是一个跨平台的应用程序(iPhone、android 和 Win),我们试图避免在视图中做太多事情 将不得不同意不同意。在我看来,本地化严格来说是一个视图问题,因为每个平台处理它的方式不同,并且每个平台都有不同的指导。在 ViewModel 级别处理它会将您的 View 与您的 ViewModel 联系起来,这是 MVVM 试图避免的问题。 我认为从 View 到 VM 属性的绑定无论如何都会与您联系起来......以上是关于在 MvvmCross ViewModels 中本地化文本的主要内容,如果未能解决你的问题,请参考以下文章
Mvvmcross - 从常规活动中显示 mvvmcross 视图模型