在这个转换器中,我们需要尝试提取3个路由参数, language, controller,action,然后我们需要在模拟用的数据库类中,找到其对应的翻译。正如我们之前提到的,你通常会希望从数据库中查找对应的内容,因为使用这种方式,我们可以在应用程序生命周期的任何时刻,动态的影响路由。为了说明这一点,我们将使用TranslationDatabase类来模拟数据库操作,这里你可以把它想象成一个真正的数据库仓储服务。
public class TranslationDatabase { private static Dictionary<string, Dictionary<string, string>> Translations = new Dictionary<string, Dictionary<string, string>> { { "en", new Dictionary<string, string> { { "orders", "orders" }, { "list", "list" } } }, { "de", new Dictionary<string, string> { { "bestellungen", "orders" }, { "liste", "list" } } }, { "pl", new Dictionary<string, string> { { "zamowienia", "order" }, { "lista", "list" } } }, }; public async Task<string> Resolve(string lang, string value) { var normalizedLang = lang.ToLowerInvariant(); var normalizedValue = value.ToLowerInvariant(); if (Translations.ContainsKey(normalizedLang) && Translations[normalizedLang] .ContainsKey(normalizedValue)) { return Translations[normalizedLang][normalizedValue]; } return null; } }到目前为止,我们已经很好的解决了这个问题。这里通过在MVC应用中启用这个设置,我们就可以向我们之前定义的3个路由发送请求了。
英语 - /en/orders/list
德语 - /de/bestellungen/liste
波兰语 - /pl/zamowienia/lista
每个请求都会命中OrderController控制器和List方法。当前你可以将这个方法进一步扩展到其他的控制器。但最重要的是,如果新增一种新语言或者新的路由别名映射到现有语言中的controller/actions,你是不需要做任何代码更改,甚至重启项目的。
请注意,在本文中,我们只关注路由转换,这里仅仅是为了演示ASP.NET Core 3.0中的动态路由特性。如果你希望在应用程序中实现本地化,你可能还需要阅读ASP.NET Core 3.0的本地化指南, 因为你可以需要根据语言的路由值设置正确的CurrentCulture。
最后, 我还想再补充一点,在我们之前的例子中,我们在路由模板中显式的使用了{controller}和{action}占位符。这并不是必须的,在其他场景中,你还可以使用"catch-all"路由通配符,并将其转换为controller/action路由值。
"catch-all"路由通配符是CMS系统中的典型解决方案,你可以使用它来处理不同的动态“页面”路由。
它看起来可能类似:
endpoints.MapDynamicControllerRoute<PageTransformer>("pages/{**slug}");然后,你需要将pages之后的整个URL参数转换为现有可执行控制器的内容 - 通常URL/路由的映射是保存在数据库中的。
希望你会发现这篇文章很有用 - 所有的演示源代码都可以在Github上找到。