3

我想从 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。

非常感谢任何帮助。

4

2 回答 2

9

注意:这个答案是关于 vNext - 移植回 master 应该相当容易......该区域的差异不是那么大。


MvvmCross 中内置了一个文本本地化机制。

唯一使用它的公共示例是会议示例。


此示例包括共享的和 ViewModel 特定的 Json 文件 -请参阅

这些 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 作为进一步细化。

有关这方面的一些讨论,请参见:


假设每个 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'"
  />

任何希望使用 Text 的代码也可以这样做 - 例如,请参阅 TimeAgo 文本是如何从 TimeAgoConverter.cs 中的资源字符串创建的, 使用如下资源字符串:

{
"TimeAgo.JustNow":"just now",
"TimeAgo.SecondsAgo":"{0}s ago",
"TimeAgo.MinutesAgo":"{0}m ago",
"TimeAgo.HoursAgo":"{0}h ago",
"TimeAgo.DaysAgo":"{0}d 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 是非常简单的代码

因此,如果您需要,请随意为您的应用构建更复杂的东西。


其他跨平台文本本地化技术可用 - 我自己特别想有一天尝试白话 - https://github.com/rdio/vernacular

于 2013-02-14T18:08:32.157 回答
0

也许您应该返回枚举而不是字符串并处理视图中的本地化。

于 2013-02-14T17:17:33.903 回答