好问题!这是我需要自己做的事情。
我设法根据@Karl-Johan Sjögren 向您提出的建议解决了这个问题 - 即我能够创建超级简单视图引擎(SSVE)的扩展。
的背景
SSVE 的设计方式使您可以注入额外的“匹配器”,以便您可以在视图模板为请求的输出进行渲染时对其进行一些处理。
您会注意到 SSVE 中的以下构造函数(截至 2014/05/12),它允许您传递额外的“匹配器”:
public SuperSimpleViewEngine(IEnumerable<ISuperSimpleViewEngineMatcher> matchers)
{
this.matchers = matchers ?? Enumerable.Empty<ISuperSimpleViewEngineMatcher>();
this.processors = new List<Func<string, object, IViewEngineHost, string>>
{
PerformSingleSubstitutions,
PerformContextSubstitutions,
PerformEachSubstitutions,
PerformConditionalSubstitutions,
PerformPathSubstitutions,
PerformAntiForgeryTokenSubstitutions,
this.PerformPartialSubstitutions,
this.PerformMasterPageSubstitutions,
};
}
SSVE 中大多数模板替换的基本方式是针对视图模板进行非常简单的正则表达式匹配。如果正则表达式匹配,则调用替换方法,在其中发生适当的替换。
例如,SSVE 附带的默认 PerformSingleSubstitutions 处理器/匹配器用于执行基本的“@Model”。替换。可能会发生以下处理器工作流程:
- 文本“@Model.Name”在视图模板内匹配。
- 模型参数替换会触发替换方法。
- 为了获取“名称”属性的值,会对动态模型进行一些反射。
- 然后,使用“Name”属性的值替换视图模板中的“@Model.Name”字符串。
实施
好的,现在我们已经有了基础,下面是您如何创建自己的翻译匹配器。 :)
首先,您需要创建 ISuperSimpleViewEngineMatcher 的实现。下面是我为了说明目的而创建的一个非常基本的示例:
internal sealed class TranslateTokenViewEngineMatcher :
ISuperSimpleViewEngineMatcher
{
/// <summary>
/// Compiled Regex for translation substitutions.
/// </summary>
private static readonly Regex TranslationSubstitutionsRegEx;
static TranslateTokenViewEngineMatcher()
{
// This regex will match strings like:
// @Translate.Hello_World
// @Translate.FooBarBaz;
TranslationSubstitutionsRegEx =
new Regex(
@"@Translate\.(?<TranslationKey>[a-zA-Z0-9-_]+);?",
RegexOptions.Compiled);
}
public string Invoke(string content, dynamic model, IViewEngineHost host)
{
return TranslationSubstitutionsRegEx.Replace(
content,
m =>
{
// A match was found!
string translationResult;
// Get the translation 'key'.
var translationKey = m.Groups["TranslationKey"].Value;
// Load the appropriate translation. This could farm off to
// a ResourceManager for example. The below implementation
// obviously isn't very useful and is just illustrative. :)
if (translationKey == "Hello_World")
{
translationResult = "Hello World!";
}
else
{
// We didn't find any translation key matches so we will
// use the key itself.
translationResult = translationKey;
}
return translationResult;
});
}
}
好的,所以当上面的匹配器针对我们的视图模板运行时,它们将找到以“@Translate.”开头的字符串。 “@Translate”之后的文本。被认为是我们的翻译关键。所以在例如'@Translate.Hello_World' 的翻译键将为 'Hello_world'。
当发生匹配时,将触发替换方法来查找并返回翻译键的适当翻译。我当前的示例将仅返回“Hello_World”键的翻译 - 您当然必须填写自己的机制来进行翻译查找,也许会依赖 .net 的默认资源管理支持?
匹配器不会自动连接到 SSVE,您必须使用 Nancy 的 IoC 支持功能来根据我之前突出显示的构造函数参数注册您的匹配器。
为此,您需要重写 Nancy 引导程序中的ConfigureApplicationContainer 方法并添加类似于以下内容的注册:
public class MyNancyBootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
// Register the custom/additional processors/matchers for our view
// rendering within the SSVE
container
.Register<IEnumerable<ISuperSimpleViewEngineMatcher>>(
(c, p) =>
{
return new List<ISuperSimpleViewEngineMatcher>()
{
// This matcher provides support for @Translate. tokens
new TranslateTokenViewEngineMatcher()
};
});
}
...
最后一步是将翻译标记实际添加到您的视图中:
<!-- index.sshtml -->
<html>
<head>
<title>Translator Test</title>
</head>
<body>
<h1>@Translate.Hello_World;<h1>
</body>
</html>
正如我所说,这是一个非常基本的示例,您可以将其用作创建满足您需求的实现的基础。例如,您可以扩展正则表达式匹配器以考虑您想要转换成的目标区域性,或者仅使用在应用程序中注册的当前线程区域性。您可以灵活地做您想做的事。 :)