Skip to content

Instantly share code, notes, and snippets.

@hardye
Created April 29, 2015 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hardye/68f8a9a02d9d7ab96734 to your computer and use it in GitHub Desktop.
Save hardye/68f8a9a02d9d7ab96734 to your computer and use it in GitHub Desktop.
Sitefinity ServiceStack Language Request Filter Attribute
/// <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