代码之家  ›  专栏  ›  技术社区  ›  AmateurCoder

如何在MVC中设置多语言和本地化视图?

  •  0
  • AmateurCoder  · 技术社区  · 4 年前

    英国观点

    ~/视图/关于.cshtml

    阿拉伯观点
    ~/ar/视图/索引.cshtml

    英文网址(有效)
    www.samplesite.com/home/index
    www.samplesite.com/home/index

    阿拉伯语URL(不起作用)
    www.samplesite.com/ar/home/index

    我需要返回英文视图,如果url带有/en或没有语言参数,如果url以/ar开头,我需要返回ar/Views文件夹中的视图。我应该在route config和actions中做什么更改以获得基于URL的正确视图?

    enter image description here

    0 回复  |  直到 4 年前
        1
  •  5
  •   David Liang    4 年前

    1. 根据语言代码设置当前区域性(如果存在)

    您需要定义路由映射,以便只要URL上有语言代码,它就会被放入路由数据集合中。

    您可以在 RouteConfig :

    namespace DL.SO.Globalization.DotNet.Web.UI
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.LowercaseUrls = true;
    
                routes.MapRoute(
                    name: "DefaultWithLang",
                    url: "{lang}/{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                    constraints: new { lang = new LanguageRouteConstraint() }
                );
    
                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                );
            }
        }
    }
    

    我们将回到route约束,但这里的想法是先运行这个“DefaultWithLang”映射,看看传入的请求是否附加了语言代码。如果是,请使用键将其保存到路由集合 lang . 否则,请按正常方式处理。

    假设我们定义了这两个映射,传入的请求看起来像 /home/index . 如果没有该路由约束,它将映射到“DefaultWithLang”,其中 是“家”,这是不正确的。

    我们需要一种方法来测试语言代码是否是有效的2字母代码。为此,可以创建管线约束:

    using System.Text.RegularExpressions;
    using System.Web;
    using System.Web.Routing;
    
    namespace DL.SO.Globalization.DotNet.Web.UI.RouteConstraints
    {
        public class LanguageRouteConstraint : IRouteConstraint
        {
            public bool Match(HttpContextBase httpContext, Route route, string parameterName, 
                RouteValueDictionary values, RouteDirection routeDirection)
            {
                return Regex.IsMatch((string)values[parameterName], @"^[a-z]{2}$");
            }
        }
    }
    


    2根据语言代码设置当前区域性(如果存在)

    现在我们知道语言代码将被放入路由数据收集中。我们可以在此基础上设置当前线程的当前区域性和当前UI区域性。

    ActionFilter :

    namespace DL.SO.Globalization.DotNet.Web.UI.Filters
    {
        public class LanguageFilter : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var values = filterContext.RouteData.Values;
    
                string languageCode = (string)values["lang"] ?? "en";
    
                var cultureInfo = new CultureInfo(languageCode);
    
                Thread.CurrentThread.CurrentCulture = cultureInfo;
                Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
            }
        }
    }
    

    在这里,我从路由数据收集中读取语言代码值,如果不存在,则默认为“en”。

    要在整个应用程序中启用它,可以将其添加到 FilterConfig.cs :

    namespace DL.SO.Globalization.DotNet.Web.UI
    {
        public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new LanguageFilter());
                filters.Add(new HandleErrorAttribute());
            }
        }
    }
    

    三。如果出现语言代码,请将请求路由到本地化视图

    与步骤2类似,现在我们有了语言代码,我们需要创建一个自定义视图引擎,将请求路由到不同的视图:

    namespace DL.SO.Globalization.DotNet.Web.UI
    {
        public class GlobalizationRazorViewEngine : RazorViewEngine
        {
            protected override IView CreatePartialView(ControllerContext controllerContext, 
                string partialPath)
            {
                partialPath = GetGlobalizeViewPath(controllerContext, partialPath);
                return base.CreatePartialView(controllerContext, partialPath);
            }
    
            protected override IView CreateView(ControllerContext controllerContext, 
                string viewPath, string masterPath)
            {
                viewPath = GetGlobalizeViewPath(controllerContext, viewPath);
                return base.CreateView(controllerContext, viewPath, masterPath);
            }
    
            private string GetGlobalizeViewPath(ControllerContext controllerContext, 
                string viewPath)
            {
                var request = controllerContext.HttpContext.Request;
                var values = controllerContext.RouteData.Values;
    
                string languageCode = (string)values["lang"];
                if (!String.IsNullOrWhiteSpace(languageCode))
                {
                    string localizedViewPath = Regex.Replace(viewPath,
                        "^~/Views/",
                        String.Format("~/{0}/Views/", languageCode)
                    );
    
                    if (File.Exists(request.MapPath(localizedViewPath)))
                    {
                        viewPath = localizedViewPath;
                    }
                }
    
                return viewPath;
            }
        }
    }
    

    这里的逻辑应该是直截了当的:如果语言代码存在,尝试将其附加到MVC应用程序将用来查找相应视图的原始视图路径。

    注意 _viewStart.cshtml 以及 web.config 从原来的 Views 新本地化的文件夹 意见 ~/Views 文件夹。

    Application_Start() :

    namespace DL.SO.Globalization.DotNet.Web.UI
    {
        public class MvcApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            {
                ViewEngines.Engines.Clear();
                ViewEngines.Engines.Add(new GlobalizationRazorViewEngine());
    
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
        }
    }
    

    截图

    enter image description here

    zh/ 在URL上:

    enter image description here

    文件夹结构:

    enter image description here

    Github源代码: https://github.com/davidliang2008/DL.SO.Globalization.DotNet/tree/master/DL.SO.Globalization.DotNet.Web.UI