在 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 视图模型

MvvmCross 6 中的子类 UIWindow

是否有mvvmcross提供的标签式布局平台?

MvvmCross、Xamarin Studio 和 ICommands

mvvmcross 应用程序单例生命周期

在 Xamarin.Android 中通过 MVVMCross 绑定 OxyPlot