asp.net 核心 2.1 中基于国家/地区的本地化

Localization based on country in asp.net core 2.1

我正在尝试根据用户正在查看我的应用程序的国家/地区对发送回用户的内容进行本地化,这意味着他们的国家/地区代码应该是请求的一部分 url。例如,如果用户在美国,所有请求 URL 应该是 http://website.com/us/{controller}/{action}.

话虽如此,有没有办法识别用户的原籍国,然后通过将他们的国家 Iso-2-Letter-Code 附加到 URL 来修改请求 URL,然后使用新 URL 重定向用户。如果请求URL有国家代码,那么应该绕过这个请求修改。

我更喜欢使用或创建 asp.net 核心中间件的解决方案,我可以在 Startup.cs 中将其附加到我的 HTTP 请求管道,或者涉及将新自定义路由添加到默认 MVC 的解决方案路线。

非常感谢您的帮助和想法。

.Net有个现成的功能,可以知道是什么来头。它被称为Culture Info

默认情况下,每个客户端都会传递一个文化信息,或者他们可以指定他们打算使用的当前 language/country 是什么。

我的建议是允许客户在 Header 名称调用 "Accept-Language" 中指定 culture-info。例如,我在美国并且打算使用英语,我会在 header.

中发送 'en-us' 作为我请求的一部分

在后端服务器内部,我会检查这个 header 并适当地设置 culture-info。

 public class LanguageMessageHandler : DelegatingHandler
{
    private const string LangenUS = "en-US";

    private readonly List<string> _supportedLanguages = new List<string> { LangenUS };

    private bool SetHeaderIfAcceptLanguageMatchesSupportedLanguage(HttpRequestMessage request)
    {
        foreach (var lang in request.Headers.AcceptLanguage)
        {
            if (_supportedLanguages.Contains(lang.Value))
            {
                SetCulture(request, lang.Value);
                return true;
            }
        }

        return false;
    }

    private void SetCulture(HttpRequestMessage request, string lang)
    {
        request.Headers.AcceptLanguage.Clear();
        request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(lang));
        Thread.CurrentThread.CurrentCulture = new CultureInfo(lang);
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (!SetHeaderIfAcceptLanguageMatchesSupportedLanguage(request))
        {
            // Whoops no localization found. Lets try Globalisation
            if (!SetHeaderIfGlobalAcceptLanguageMatchesSupportedLanguage(request))
            {
                // no global or localization found
                SetCulture(request, LangenUS);
            }
        }

        var response = await base.SendAsync(request, cancellationToken);
        return response;
    }

    private bool SetHeaderIfGlobalAcceptLanguageMatchesSupportedLanguage(HttpRequestMessage request)
    {
        foreach (var lang in request.Headers.AcceptLanguage)
        {
            var globalLang = lang.Value.Substring(0, 2);
            if (_supportedLanguages.Any(t => t.StartsWith(globalLang)))
            {
                SetCulture(request, _supportedLanguages.FirstOrDefault(i => i.StartsWith(globalLang)));
                return true;
            }
        }

        return false;
    }
}