2011-07-19 48 views
17

这是关于asp.net的MVC多语言网址/路由和搜索引擎优化的最佳做法/收益两部分的问题...asp.net mvc的多语言网址/路由

问题第1部分)

我被要求创建一个新的ASP.NET MVC网站,将支持两种语言(英语和法语)的最低(最初),也许在未来,3种语言...

就本地化应用程序(标签,jQuery错误等),应该使用资源文件,我已经找到了很多这方面的例子......但我的意见/更多关于URL的问题。

在SEO方面,这两种时尚之间推荐的做法是什么?

Fashion 1 (no culture folder) 
www.mydomain.com/create-account 
www.mydomain.com/creer-un-compte 

Fashion 2 (with built in culture folder) 
www.mydomain.com/create-account 
www.mydomain.com/fr/creer-un-compte <--notice the “fr” folder 

是否存在已知的问题/使用惩罚之一?

还是它太小,它变得无关紧要!


问题第2部分)

为了实现时尚2,我已经在这里找到了一篇文章: ASP.NET MVC - Localization route

但我很好奇,想如何实现时尚1

有没有人有任何链接?

另外,据我所知,网址重写是而不是我在找什么,因为我不想“重定向”用户...我只是希望网址以适当的语言显示,而不必以显示网址中的文化

在此先感谢您的帮助!

回答

18

您可以创建具有如下定位逻辑基本控制器:如果你想忽略文化夹,只是没有在指定郎

public abstract class LocalizedController : Controller 
{ 
    protected override void ExecuteCore() 
    { 
     HttpCookie cookie; 
     string lang = GetCurrentCulture(); 
     Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang, false); 

     // set the lang value into route data 
     RouteData.Values["lang"] = lang; 

     // save the location into cookie 
     cookie = new HttpCookie("DPClick.CurrentUICulture", 
      Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName) 
      { 
       Expires = DateTime.Now.AddYears(1) 
      }; 

     HttpContext.Response.SetCookie(cookie); 
     base.ExecuteCore(); 
    } 

    private string GetCurrentCulture() 
    { 
     string lang; 

     // set the culture from the route data (url) 

     if (RouteData.Values["lang"] != null && 
      !string.IsNullOrWhiteSpace(RouteData.Values["lang"].ToString())) 
     { 
      lang = RouteData.Values["lang"].ToString(); 
      if (Localization.Locales.TryGetValue(lang, out lang)) 
      { 
       return lang; 
      } 
     } 
     // load the culture info from the cookie 
     HttpCookie cookie = HttpContext.Request.Cookies["DPClick.CurrentUICulture"]; 
     if (cookie != null) 
     { 
      // set the culture by the cookie content 
      lang = cookie.Value; 
      if (Localization.Locales.TryGetValue(lang, out lang)) 
      { 
       return lang; 
      } 

     } 
     // set the culture by the location if not speicified 
     lang = HttpContext.Request.UserLanguages[0]; 
     if (Localization.Locales.TryGetValue(lang, out lang)) 
     { 
      return lang; 
     } 
     //English is default 
     return Localization.Locales.FirstOrDefault().Value; 

    } 

} 

上述控制器满足你的问题的时尚2 RouteDate。offcourse实现时尚2你必须添加路由文化如下:

  routes.MapRoute(
      "Localization", // Route name 
      "{lang}/{controller}/{action}/{id}", // URL with parameters 
      new {controller = "Default", action = "Index", id = UrlParameter.Optional}, // Parameter defaults 
      new {lang = @"\w{2,3}(-\w{4})?(-\w{2,3})?"} 
      ); 
+0

哇谢谢费拉斯!这段代码非常好,可以帮助我更多地了解路由和本地化。 – Vlince

+0

欢迎随时。 –

+5

@FerasKayyali嗨费拉斯,感谢分享信息。我正在使用您的代码,但发现VS 2012无法识别本地化。它的名称空间和dll是什么? Thx – Franva

1

达到你想要什么,你基本上需要实现三两件事:

多语言感知路由处理传入的URL:

routes.MapRoute(
    name: "DefaultLocalized", 
    url: "{lang}/{controller}/{action}/{id}", 
    constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" }, // en or en-US 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 

一个LocalizationAttribute来处理这些多语言要求:

public class LocalizationAttribute : ActionFilterAttribute 
{ 
    private string _DefaultLanguage = "en"; 

    public LocalizationAttribute(string defaultLanguage) 
    { 
     _DefaultLanguage = defaultLanguage; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     string lang = (string)filterContext.RouteData.Values["lang"] ?? _DefaultLanguage; 
     if (lang != _DefaultLanguage) 
     { 
      try 
      { 
       Thread.CurrentThread.CurrentCulture = 
       Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang); 
      } 
      catch (Exception e) 
      { 
       throw new NotSupportedException(String.Format("ERROR: Invalid language code '{0}'.", lang)); 
      } 
     } 
    } 
} 

一种辅助方法来生成你的应用程序中的这些URL:这可以通过多种方式来实现,这取决于你应用逻辑。例如,如果您需要在Razor Views中执行此操作,则最好的做法是编写一对扩展方法,以使您的Html.ActionLinkUrl.Action接受CultureInfo对象作为参数(和/或使用CultureInfo.CurrentCulture作为默认值),如下列:

(两者都是用C#编写)

你可以也避免了扩展方法模式,并将它们写为MultiLanguageActionLink/MultiLanguageAction

有关此主题的其他信息和更多示例,您还可以阅读this post