如何拦截请求以获取用于站点本地化的原始 URL?

How to intercept a request to get the raw URL for site localization?

我的网站是这样工作的:

  1. 所有内容都有 {culture/slug} URLs
  2. 的自动路由
  3. 用户可以select站点文化,以便一切都以他们选择的语言呈现

我正在尝试实现此功能:

  1. 用户 select 的英语站点。
  2. 用户转到 "site.com/es/content",这是西班牙语内容。
  3. 站点必须自动将文化更改为西班牙语和return请求的内容。

我认为我需要的是拦截请求,解析URL并获取文化,看看它是否与当前相同。

我尝试使用 IHttpContextAccessor 在 Orchard.Core.Contents 的 ItemsController 中获取它,但它没有原始 Url.

我也尝试在 Orchard.Autoroute 和 Orchard.Alias 服务中捕获请求,但它们不是处理请求的服务。

任何指点将不胜感激。

有一些方法可以做到这一点。

实施 ICultureSelector

namespace SomeModule
{
    using System;
    using System.Globalization;
    using System.Linq;
    using System.Web;
    using Orchard.Localization.Services;

    public class CultureSelectorByHeader : ICultureSelector
    {
        private readonly ICultureManager cultureManager;

        public CultureSelectorByHeader(ICultureManager cultureManager)
        {
            this.cultureManager = cultureManager;
        }

        public CultureSelectorResult GetCulture(HttpContextBase context)
        {
            var acceptedLanguageHeader = context?.Request?.UserLanguages?.FirstOrDefault();
            if ( acceptedLanguageHeader == null )
                return null;

            var enabledCultures = this.cultureManager.ListCultures();
            var siteCulture = this.cultureManager.GetSiteCulture();

            // Select the specified culture if it's enabled.
            // Otherwise, or if it wasn't found, fall back to the default site culture.
            var culture = enabledCultures.Contains(acceptedLanguageHeader, StringComparer.InvariantCultureIgnoreCase)
                ? CultureInfo.CreateSpecificCulture(acceptedLanguageHeader).Name
                : CultureInfo.CreateSpecificCulture(siteCulture).Name;

            return new CultureSelectorResult { CultureName = culture, Priority = 0 };
        }
    }
}

您可以在 GetCulture、读取 headers、cookie、查询字符串或从数据库中获取当前用户的一些设置。满足您的需求。

直接设置文化

private void SetWorkContextCulture(string cultureTwoLetterIsoCode)
{
    if ( !string.IsNullOrWhitespace(cultureTwoLetterIsoCode) )
    {
        try
        {
            var culture = CultureInfo.CreateSpecificCulture(cultureTwoLetterIsoCode);
            this.Services.WorkContext.CurrentCulture = culture.TwoLetterISOLanguageName;
        }
        catch ( CultureNotFoundException )
        {
            Debug.WriteLine("Couldn't change thread culture.");
        }
    }
}

只需在返回结果之前更改 WorkContext 的当前文化即可。

有趣的事实:在控制器中更改 WorkContext.Culture 将覆盖您在 ICultureSelector 实现中所做的一切。