asp.net mvc 多语言 url/路由

发布于 2024-11-24 22:08:25 字数 944 浏览 1 评论 0原文

这是一个关于 ASP.NET MVC 多语言 url/路由和 SEO 最佳实践/好处的两部分问题...

问题第 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部分)

为了实现Fashion 2,我已经在这里找到了一篇文章: ASP.NET MVC - 本地化路线

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

有谁有链接吗?

此外,据我所知,URL 重写不是我正在寻找的东西,因为我不希望“重定向”用户......我只是希望 URL 以适当的语言显示,而不需要必须在网址中显示文化

提前感谢您对此的任何帮助!

This is a two part question regarding asp.net mvc multilanguage urls/routing and SEO best practices/benefits…

Question Part 1)

I’m being asked to create a new ASP.NET MVC website that will support a minimum (at first) of two languages (English and French) perhaps in the future, 3 languages…

As far as localizing the application (labels, jQuery errors, etc) things should be ok using resource files and I’ve found many examples on this…but my concern/question is more about the URLs.

In terms of SEO, what is the recommended approach between these two fashions?

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 

Is there a known issue/penalty in using one over the other?

Or is it so small that it becomes irrelevant!


Question Part 2)

To achieve Fashion 2, I’ve already found an article here:
ASP.NET MVC - Localization route

But I’d be curious to find how to achieve Fashion 1.

Does anyone have any links?

In addition and as far as I know, URL Rewriting is not what I’m looking for since I do not wish to “redirect” users…I simply want the urls to be showing in the appropriate language without having to show the culture in the url

Thanks in advance for any help on this!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

¢蛋碎的人ぎ生 2024-12-01 22:08:26

您可以创建一个具有如下本地化逻辑的基本控制器:

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 部分,只是不要在 RouteData 中分配 lang。当然,要实现第 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})?"}
);

You can create a base controller that has the localization logic as below:

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;
  }
}

The above controller satisfy part 2 of your question if you want to ignore the culture folder just don't assign the lang in the RouteData. Of course to achieve part 2 you have to add routing for culture as below:

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})?"}
);
二智少女 2024-12-01 22:08:26

为了实现你想要的,你基本上需要实现三件事:

多语言感知路由来处理传入的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 视图中执行此操作,您能做的最好的事情就是编写几个扩展方法来使您的 Html.ActionLinkUrl.Action 接受 CultureInfo 对象作为参数(和/或使用 CultureInfo.CurrentCulture 作为默认对象),如下所示:

(两者均用 C# 编写)

您还可以避免扩展方法模式并将其编写为 MultiLanguageActionLink /相反,MultiLanguageAction

有关此主题的其他信息和更多示例,您还可以阅读 这篇文章在我的博客上。

To achieve what you want you basically need to implement three things:

A multi-language aware route to handle incoming URLs:

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 }
);

A LocalizationAttribute to handle these kinds of multi-language requests:

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));
            }
        }
    }
}

An helper method to generate these URLs within your application: this can be done in multiple ways, depending on your application logic. For example, if you need to do it within your Razor Views, the best thing you can do is to write a couple extension methods to make your Html.ActionLink and Url.Action accept a CultureInfo object as a parameter (and/or use CultureInfo.CurrentCulture as the default one), such as the following:

(both are written in C#)

You can also avoid the extension method pattern and write them as MultiLanguageActionLink / MultiLanguageAction instead.

For additional info and further samples on this topic you can also read this post on my blog.

你曾走过我的故事 2024-12-01 22:08:26

AttributeRouting可以解决Fashion 1:

AttributeRouting - Localization

AttributeRouting can solve Fashion 1:

AttributeRouting - Localization

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文