如何在ASP.NET Core 2.2中创建切换语言链接?

7
一个网站支持多种语言。支持多语言的代码,包括路由都已经就位且工作正常。
使用RouteDataRequestCultureProvider进行本地化设置,详细说明请参见https://joonasw.net/view/aspnet-core-localization-deep-dive
app.UseRouter(routes =>
{
    routes.MapMiddlewareRoute("{culture=en-US}/{*mvcRoute}", subApp =>
    {
        subApp.UseRequestLocalization(localizationOptions);

        subApp.UseMvc(mvcRoutes =>
        {
             // Routes are here
        }   
    });
});

如何创建一个通用的标签,以显示当前页面的不同语言版本?

理想情况下,我只需要指定这个链接应该指向哪种语言版本,并且它应该保留所有其他路由参数(比如当前控制器、当前操作和当前路由模型),这样我就可以在_Layout.cshtml中使用这个链接了。


我觉得我还没有完全理解这个。您是否打算让用户在不更改UI文化的情况下暂时将某一页切换到另一种语言?如果是这样,您是否考虑过一种特定的语言,还是应该以任何方式动态进行? - LocEngineer
不,链接应该指向当前页面/视图,只是以不同的语言呈现(在大多数情况下,如果当前页面为/en-US/about,则链接应该指向/de-DE/about)。 - alik
2个回答

3
我用语言下拉列表的局部视图实现了这一点。
  • 首先,通过向局部视图注入RequestLocalizationOptions获取受支持文化的列表
  • 将路由数据值和查询字符串参数收集到一个字典中,因此如果您有以下链接,它将捕获所有参数。
  • /en-US/Products/?page=5&keyword=bla-bla-bla

  • 循环遍历支持的文化以创建链接,并在循环中使用适当的路由值替换{culture}。唯一需要考虑的是在全局路由中定义{culture}。
这是我的_Languages.cshtml局部视图:
@using Microsoft.AspNetCore.Builder
@using Microsoft.Extensions.Options

@inject IOptions<RequestLocalizationOptions> LocOps

@{
    var requestCulture = CultureInfo.CurrentCulture;

    var supportedCultures = LocOps.Value.SupportedUICultures

        .Select(c => new SelectListItem
        {
            Value = $"{c.Name}",
            Text = $"{c.DisplayName}"
        }).ToList();

    var routeData = new Dictionary<string, string>();

    foreach (var r in ViewContext.RouteData.Values)
    {
        routeData.Add(r.Key, r.Value.ToString());
    }

    foreach(var qs in Context.Request.Query)
    {
        routeData.Add(qs.Key, qs.Value);
    }
}

<div class="dropdown">
    <a class="btn-sm btn-default border border-secondary dropdown-toggle" href="#" role="button" id="dropdownLang" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        @($"{requestCulture.DisplayName}")
    </a>

    <div class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdownLang">
        @foreach (var culture in supportedCultures)
        {
            if (culture.Value.ToLower() != requestCulture.Name.ToLower())
            {
                // replace {culture} value with the one from the list
                routeData["culture"] = culture.Value;

                <a class="dropdown-item small"
                   asp-all-route-data="@routeData">
                    @culture.Text
                </a>
            }
        }
    </div>
</div>

顺便提一下,我正在使用Bootstrap 4。

更新

我创建了一个NuGet包,只需要一行代码,就可以创建一个语言导航菜单:)

  • 安装NuGet包
PM > Install-Package LazZiya.RazorLibrary -Version 1.0.1

创建一个语言导航下拉菜单:
<partial name="/Areas/LazZiya/Pages/_LanguageMenu.cshtml" />

兼容 .NetCore 2.1 及以上版本和 Bootstrap 4

  • 注意:路由键名称必须为 culture

更新2(2019年4月14日)

我创建了一个标签助手,支持当前所有 dotnet core 框架的版本,并可根据支持的语言环境或手动选择的语言环境列表创建语言导航。

安装 NuGet 包(其中还包含其他有用的标签助手):

Install-Package LazZiya.TagHelpers -Version 2.0.0

将标记助手添加到_ViewImports.cshtml文件
@addTagHelper *, LazZiya.TagHelpers

创建语言导航:
<language-nav view-context="ViewContext"></language-nav>

更多详细信息请访问项目网站,查看实时演示



0

这不是非常优雅,但应该能解决问题。这里只提供en-US和de-DE的示例:

var switchLang = new Dictionary<string, string>{{"de-DE", "en-US"}, {"en-US", "de-DE"}};
var controller = Html.ViewContext.RouteData.Values["controller"].ToString();
var action = Html.ViewContext.RouteData.Values["action"].ToString();
var lang = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
var newLang = lang;
switchLang.TryGetValue(lang, out newLang);

然后,您可以使用变量控制器、操作和newLang来构建到其他语言的ActionLink。我只是在我的_Layout.cshtml中插入了一行代码以显示其值。

var url = string.Format("{0}/{1}/{2}",newLang, controller, action);

看起来还不错。


是的,那听起来确实像是一种紧急的hack :) 我希望有一种更优雅/通用的方法来实现这个。 - alik
如果您更清楚地定义了何时使用哪种语言链接以及使用什么默认设置,可能会有所帮助。此外,语言路由的具体过程是如何进行的也需要说明。 - LocEngineer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接