net core 多语言国际化,语言参数放在URL中的实现
本来最简单的做法,就是将语言选择放在cookie中,但出于对SEO的考虑,这样做无法让搜索引擎抓取多语种页面,最好的做法,还是不同语言有不同的路径,例如:
http://www.xxx.com/zh-ch/products
http://www.xxx.com/en-us/products
....
静态类 Langs.cs 中,定义可以用的语言:
public readonly static string[] LangCodes = new string[] { "vi-vn", "en-us", "zh-cn" };
识别用的路由约束类,其中的 "auto" 是特殊定义的,主要用于用户第一次进入时对用户的 Accept-Languages 进行自动识别:
public class LanguageRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.ContainsKey("culture"))
return false;
var culture = values["culture"]?.ToString();
if (culture == null) return false;
return culture == "auto" || Langs.LangCodes.Contains(culture);
}
}
路由约束:
public class LanguageRouteConstraint : IRouteConstraint
{
public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
if (!values.ContainsKey("culture"))
return false;
var culture = values["culture"]?.ToString();
if (culture == null) return false;
return culture == "auto" || Langs.LangCodes.Contains(culture);
}
}
然后在 program.cs 中配置:
builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.Add(new CulturePageRouteConvention());
}).AddRazorRuntimeCompilation();
builder.Services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});
builder.Services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("culture", typeof(LanguageRouteConstraint));
});
路由:
app.MapControllerRoute(name: "default", pattern: "{culture:culture=auto}/{controller:slugify=Home}/{action:slugify=Index}/{id?}");