Created
April 29, 2015 14:50
-
-
Save hardye/68f8a9a02d9d7ab96734 to your computer and use it in GitHub Desktop.
Sitefinity ServiceStack Language Request Filter Attribute
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Configures the current UI culture based on the client's 'Accept-Language' header. | |
/// </summary> | |
public class LanguageRequestFilterAttribute : RequestFilterAttribute | |
{ | |
private const string AcceptLanguageRegex = @"([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?"; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="LanguageRequestFilterAttribute" /> class. | |
/// </summary> | |
public LanguageRequestFilterAttribute() | |
{ | |
} | |
/// <summary> | |
/// Initializes a new instance of the <see cref="LanguageRequestFilterAttribute" /> class. | |
/// </summary> | |
/// <param name="applyTo">The HTTP verbs the filter should apply to..</param> | |
public LanguageRequestFilterAttribute(ApplyTo applyTo) | |
: base(applyTo) | |
{ | |
} | |
/// <summary> | |
/// Executes the specified request filter. | |
/// </summary> | |
/// <param name="req">The request.</param> | |
/// <param name="res">The response.</param> | |
/// <param name="requestDto">The request DTO.</param> | |
public override void Execute(IRequest req, IResponse res, object requestDto) | |
{ | |
string acceptLanguageHeader = req.Headers.Get("Accept-Language"); | |
// Do we have a multilingual system at all? | |
ResourcesConfig config = Config.Get<ResourcesConfig>(); | |
if (!config.Multilingual) | |
{ | |
// We don't. Nothing to do here. | |
return; | |
} | |
if (String.IsNullOrEmpty(acceptLanguageHeader)) | |
{ | |
/* The client didn't specify any language preferences. Use the application's default language */ | |
string defaultCulture = config.DefaultCulture.UICulture; | |
SetUICulture(defaultCulture); | |
} | |
else | |
{ | |
// We have a header. Let's parse it into a weighted list. | |
SortedList<float, string> languageList = ParseLanguageHeader(acceptLanguageHeader); | |
if (languageList.Count == 0) | |
{ | |
return; | |
} | |
string language = null; | |
// What languages do we offer? | |
ConfigElementDictionary<string, CultureElement> cultures = config.Cultures; | |
// Iterate through the accept-language header entries and pick the | |
// first entry that matches one of our cultures. | |
for (int i = languageList.Count - 1; i >= 0; i--) | |
{ | |
if (cultures.Elements.Any(ce => ce.UICulture.Equals(languageList.ElementAt(i).Value, StringComparison.InvariantCultureIgnoreCase))) | |
{ | |
language = languageList.ElementAt(i).Value; | |
break; | |
} | |
} | |
if (String.IsNullOrEmpty(language)) // No match found -> use the default language. | |
{ | |
language = Config.Get<ResourcesConfig>().DefaultCulture.UICulture; | |
} | |
SetUICulture(language); | |
} | |
} | |
/// <summary> | |
/// Sets the current thread's UI culture. | |
/// </summary> | |
/// <param name="language">The language.</param> | |
private void SetUICulture(string language) | |
{ | |
if (!String.IsNullOrEmpty(language)) | |
{ | |
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language); | |
} | |
} | |
/// <summary> | |
/// Parses an 'Accept-Language' language header into a list of languages sorted by the languages' weight. | |
/// </summary> | |
/// <param name="header">The 'Accept-Language' header as sent by the client.</param> | |
/// <returns>The sorted language list.</returns> | |
private SortedList<float, string> ParseLanguageHeader(string header) | |
{ | |
SortedList<float, string> entriesList = new SortedList<float, string>(); | |
Regex regex = new Regex(AcceptLanguageRegex, RegexOptions.IgnoreCase | RegexOptions.Compiled); | |
MatchCollection matchResults = regex.Matches(header); | |
if (matchResults.Count > 0) | |
{ | |
CultureInfo usCulture = new CultureInfo("en-US"); | |
for (int i = 0; i < matchResults.Count; i++) | |
{ | |
Match matchResult = matchResults[i]; | |
Group weightGroup = matchResult.Groups[4]; // -> group 4 contains the weight | |
float weight = String.IsNullOrEmpty(weightGroup.Value) ? 1 : float.Parse(weightGroup.Value, usCulture); | |
entriesList.Add(weight, matchResult.Groups[1].Value); // -> group 1 contains the language | |
} | |
} | |
return entriesList; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment