我有一个 MVC 应用程序,必须以不同的方式处理这个问题。我们的应用程序使用 url 参数化语言。我可以推荐,因为接受的答案无法更改为另一种语言。它还可以被不同语言的搜索引擎抓取,并允许用户保存或发送具有特定语言的 URL。
但是,根据最初的请求,我想检测用户语言,现在 OP 提到它无法更改顺序,这是因为某些浏览器(Chrome)正在确定这一点,无论您设置的语言如何。
如您所见,我将界面语言设置为英语,但为了测试,我将德语移至仅用于翻译的顶部,结果:
因此,Chrome 只是将用户在设置中设置的任何内容放在首位。大多数用户可能只会将他们的用户界面语言设置为他们想要用于翻译/拼写检查的一些语言。所以这是我的代码
全球.asax
protected void Session_Start(Object sender, EventArgs e)
{
Session["sessionId"] = Session.SessionID;
Session.Timeout = 120;
//first point of request, get the user's browser language
string[] languages = Request.UserLanguages;
if (languages != null && Session.IsNewSession)
{
LanguageEnum requestLanguage = LanguageHelper.GetLanguage(languages);
if (requestLanguage != LanguageEnum.NL)//NL is default for the sources
{
Response.RedirectToRoute("Locolized", new { lang = requestLanguage.ToString().ToLower() });//Locolized is an route name, see below
}
}
}
语言助手
public static LanguageEnum GetLanguage(string[] languages)
{
if (languages == null) return DefaultLanguage;
LanguageEnum lang = DefaultLanguage;
bool firstDone = false;
foreach (string language in languages)
{
string realLanguage = Regex.Replace(language, "[;q=(0-9).]", "");
LanguageEnum givenlang = GetLanguage(realLanguage);//converts it to an enum, overload method.
//first one should be the used language that is set for a browser (if user did not change it their self).
//In some browsers their might be multiple languages (for translations)
if (!firstDone)
{
firstDone = true;
lang = givenlang;
}
else
{
//ranking others
lang = RankLanguage(lang, givenlang);
}
}
return lang;
}
private static LanguageEnum RankLanguage(LanguageEnum existing, LanguageEnum newLnag)
{
if (existing == LanguageEnum.EN && newLnag != LanguageEnum.EN)
{
//everything that is other then english gets a higher rank
return newLnag;
}
//add other usecases here specific to your application/use case, keep in mind that all other languages could pass
return existing;
}
//below code is for setting the language culture I use,
//fixed number and date format for now, this can be improved.
//might be if your interests if you want to use parameterized languages
public static void SetLanguage(LanguageEnum language)
{
string lang = "";
switch (language)
{
case LanguageEnum.NL:
lang = "nl-NL";
break;
case LanguageEnum.EN:
lang = "en-GB";
break;
case LanguageEnum.DE:
lang = "de-DE";
break;
}
try
{
NumberFormatInfo numberInfo = CultureInfo.CreateSpecificCulture("nl-NL").NumberFormat;
CultureInfo info = new CultureInfo(lang);
info.NumberFormat = numberInfo;
//later, we will if-else the language here
info.DateTimeFormat.DateSeparator = "/";
info.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
Thread.CurrentThread.CurrentUICulture = info;
Thread.CurrentThread.CurrentCulture = info;
}
catch (Exception)
{
}
}
我处理参数化 url 的方式可能会引起您的兴趣:
RouteConfig.cs
下面的其他映射
routes.MapRoute(
name: "Locolized",
url: "{lang}/{controller}/{action}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" }, // en or en-US
defaults: new { controller = "shop", action = "index", id = UrlParameter.Optional }
);
FilterConfig.cs(可能需要添加,如果需要,添加FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
到Application_start()
方法中Global.asax
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ErrorHandler.AiHandleErrorAttribute());
//filters.Add(new HandleErrorAttribute());
filters.Add(new LocalizationAttribute("nl-NL"), 0);
}
}
最后,LocalizationAttribute
public class LocalizationAttribute : ActionFilterAttribute
{
private string _DefaultLanguage = "nl-NL";
private string[] allowedLanguages = { "nl", "en" };
public LocalizationAttribute(string defaultLanguage)
{
_DefaultLanguage = defaultLanguage;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string lang = (string) filterContext.RouteData.Values["lang"] ?? _DefaultLanguage;
LanguageHelper.SetLanguage(lang);
}
}
剩下要做的是添加资源,这是我写的一个较早的答案,涵盖:https ://stackoverflow.com/a/35813707/2901207