【问题标题】:Asp.net Mvc, Razor and LocalizationAsp.net Mvc、Razor 和本地化
【发布时间】:2011-07-18 08:36:42
【问题描述】:

我知道这件事已经多次出现在这些页面上,但我仍然没有找到我需要找到的“好的解决方案”。让我们开始解释吧。

.net 和 mvc 中的本地化以两种方式进行,甚至可以混合在一起:

  • 资源文件(本地或全局)
  • 带有视图引擎的本地化视图,可根据文化调用适当的视图

我将解释我尝试过的解决方案以及我遇到的所有问题。

资源文件中的文本,视图中的所有标签

此解决方案将让我将每个文本放入资源中,将每个标签放入视图中,甚至是 [strong] 或 [span] 等内联标签。

优点:

  • 清晰的分离,本地化中没有任何结构。
  • 轻松编码:从资源返回的所有内容都经过 html 编码。

缺点:

  • 如果我有一个包含一些强项、几个链接等的段落,我必须将它拆分为许多资源键。这被认为会使视图太不可读,并且创建它也需要太多时间。
  • 出于与上述相同的原因,如果在两种不同的语言中,[strong] 文本位于不同的位置(如“Il cane di Marco”和“Marcos's dog "),我做不到,因为我所有的标签都在视图中。

资源文件中的文本和内联标签,通过参数

此方法将使资源包含一些用于 string.Format 的占位符,这些占位符将在编码后填充内联标签。

优点:

  • 清晰的分隔,文本中只有占位符,所以如果我要用 [em] 替换 [strong],我会在我将其作为参数传递的视图中执行此操作,并且它会在每种语言中进行更改

缺点:

  • 编码有点困难,我必须对资源中的值进行预编码,然后使用string.Format,最后以MvcHtmlString的形式返回,告诉视图引擎在显示时不要重新编码。
  • 出于与上述相同的原因,例如,包括一个 ActionLink 作为参数会很麻烦。假设我从资源中获取我的操作链接的文本。我的方法已经对其进行了编码。但是,ActionLink 方法会再次对其进行重新编码。我需要一种不同的方法来获取资源而不对其进行编码,或者需要新的辅助方法来获取 MvcHtmlString 而不是字符串作为文本参数,但两者都相当不切实际。
  • 仍然需要大量时间来构建视图,必须创建所有资源键然后填充它们。

本地化视图

优点:

  • 所有视图都是纯 html。没有可阅读的资源。

缺点:

  • 到处都是重复的 html。我什至不需要解释这完全是邪恶的。
  • 必须手动编码所有麻烦的字符,如重元音、引号等。

结论

上述技术的混合继承了优点和缺点,但仍然没有好处。我面临着寻找合适的有效解决方案的挑战,而以上所有这些都被认为是“不切实际的”和“耗时的”。

更糟糕的是,我发现没有一个工具可以将“文本”从 aspx 或 cshtml(甚至是 html)视图/页面重构为资源。那里的所有工具都可以仅将代码文件(.cs 或 .vb)中的 System.String 实例重构为资源(例如 resharper,还有一些我现在不记得了)。

所以我被困住了,自己找不到任何合适的东西,也无法在网上找到任何东西。有没有可能其他人之前没有遇到过这个问题并找到了解决方案?

【问题讨论】:

  • 您是否为此选择了解决方案?我很好奇你带了什么。
  • 实际上这个话题在工作中被冻结了。我提出了集成 Markdown,这可能是一个改进,但有人仍然不相信。我知道 .Net 中的本地化是通过这种方式完成的,我个人从未遇到过问题,但仍然无法说服我现在与之共事的人。
  • 这太糟糕了。我喜欢纯文本标记生成,因为它是人类和机器可读的:)。我刚刚在各处使用 Markdown 启动并运行了我的博客。 codetunnel.com

标签: c# asp.net-mvc resources localization


【解决方案1】:

我个人喜欢在资源文件中存储内联标签的想法。但是我做的有点不同。我存储了非常普通的标签,例如<span class='emphasis'>dog</span>,然后我使用 CSS 来适当地设置标签的样式。现在,我不再将标签作为参数“传入”,而是在我的 CSS 中适当地设置 span.emphasis 规则的样式。更改会延续到所有语言。


更性感的选择:

我想到并且非常喜欢的另一个选择是使用像 StackOverflow 自己的 MarkdownSharp 这样的“可读标记”语言。这样您就不会在资源文件中存储任何 HTML,只存储降价文本。因此,在您的资源中,您将拥有**dog**,然后它通过视图中的降价进行分流(我为此创建了一个助手,(用法:Html.Markdown(string text))。现在您不是存储标签,而是存储一个常见的人类可读的标记语言。markdownsharp 源是一个 .CS 文件,它很容易修改。因此您可以随时更改它呈现结尾 HTML 的方式。这使您可以完全控制所有资源,而无需存储 HTML,也无需复制视图或HTML 块。

编辑

这也让您可以控制编码。您可以轻松确保资源文件的内容不包含有效的 HTML。 Markdown 语法(正如您从使用堆栈溢出中知道的那样)不包含 HTML 标记,因此可以在没有损害的情况下进行编码。然后,您只需使用您的助手将 Markdown 语法转换为有效的 HTML。

编辑#2

markdown 中有一个错误,我必须自己修复。 Markdown 检测到的任何内容都将被呈现为“代码”块,并将进行 HTML 编码。如果您已经对所有传递给 markdown 的内容进行了 HTML 编码,这将是一个问题,因为代码块中的任何内容都将被重新编码,这会将 > 转换为 > 并完全破坏代码块中的文本。为了解决这个问题,我修改了 markdown.cs 文件以包含一个布尔选项,该选项可阻止 markdown 对代码块中的文本进行编码。 See this issue 用于我添加到 MarkdownSharp 项目问题中的固定 .cs 文件。

EDIT #3 - Html Helper 示例

public static class HtmlHelpers
{
    public static MvcHtmlString Markdown(this HtmlHelper helper, string text)
    {
        var markdown = new MarkdownSharp.Markdown
        {
            AutoHyperlink = true,
            EncodeCodeBlocks = false, // This option is my custom option to stop the code block encoding problem.
            LinkEmails = true,
            EncodeProblemUrlCharacters = true
        };
        string html = markdown.Transform(markdownText);
        return MvcHtmlString.Create(html);
    }
}

【讨论】:

  • 不错,虽然有一件事让我感到困惑。 aspx
  • 你不调用Html.Transform(string) 你调用自定义助手@Html.Markdown(string) 恰好返回MvcHtmlString。有关示例,请参见 EDIT #3。
  • 转念一想,我写错了。我应该首先对从资源中检索到的内容进行编码,然后对其进行转换,最后返回一个 MvcHtmlString,这样视图引擎就不会对其进行重新编码。
  • 大声笑也是这么想的。你很厉害,伙计。
  • 这会影响你的性能,除非你至少做一些输出缓存。
【解决方案2】:

没有什么能阻止您将 HTML 存储在资源文件中,然后调用 @Html.Raw(MyResources.Resource)。

【讨论】:

  • 这不是一个选项,我在帖子中说明了原因。如果我按照您的建议进行操作,那么我必须在 resx 文件中手动编码特殊字符(如 agrave、egrave、quote、ecc)。我希望能够在我的 resx 文件中正常写入(对翻译更友好),然后视图引擎进行编码。
  • @Matteo,看看我对 MarkdownSharp 的回答。有了它,您可以在资源文件中干净地编写,然后使用自定义帮助器将其呈现为降价。 @Html.Markdown(MyResources.Resource).
  • 我只是在调查。我会尝试一下,让你知道。谢谢。
  • @Matteo Mosca:你也可以实现一个辅助函数,例如@Html.EncodeText(MyResources.Resource),只编码文本而不编码标记(可以用正则表达式实现)。
【解决方案3】:

您是否考虑过使用本地化模型,让您的视图成为 IMyModel 的强类型,然后传入经过适当修饰的模型,然后您可以通过修改适当的模型来使用/更改您进行本地化的方式。

它干净、灵活且易于维护。

您可以从基于 Recourse 文件的本地化开始,然后根据需要更频繁地更新的步伐,将该模型切换到基于缓存数据库的本地化模型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多