// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.Extensions.Globalization; namespace Microsoft.AspNet.Localization { /// /// Determines the culture information for a request via the value of a cookie. /// public class CookieRequestCultureProvider : RequestCultureProvider { private static readonly char[] _cookieSeparator = new[] { '|' }; private static readonly string _culturePrefix = "c="; private static readonly string _uiCulturePrefix = "uic="; /// /// Represent the default cookie name used to track the user's preferred culture information, which is "ASPNET_CULTURE". /// public static readonly string DefaultCookieName = "ASPNET_CULTURE"; /// /// The name of the cookie that contains the user's preferred culture information. /// Defaults to . /// public string CookieName { get; set; } = DefaultCookieName; /// public override Task DetermineProviderCultureResult(HttpContext httpContext) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } var cookie = httpContext.Request.Cookies[CookieName]; if (cookie.Count == 0) { return Task.FromResult((ProviderCultureResult)null); } var providerResultCulture = ParseCookieValue(cookie); return Task.FromResult(providerResultCulture); } /// /// Creates a string representation of a for placement in a cookie. /// /// The . /// The cookie value. public static string MakeCookieValue(RequestCulture requestCulture) { if (requestCulture == null) { throw new ArgumentNullException(nameof(requestCulture)); } var seperator = _cookieSeparator[0].ToString(); return string.Join(seperator, $"{_culturePrefix}{requestCulture.Culture.Name}", $"{_uiCulturePrefix}{requestCulture.UICulture.Name}"); } /// /// Parses a from the specified cookie value. /// Returns null if parsing fails. /// /// The cookie value to parse. /// The or null if parsing fails. public static ProviderCultureResult ParseCookieValue(string value) { if (string.IsNullOrWhiteSpace(value)) { return null; } var parts = value.Split(_cookieSeparator, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2) { return null; } var potentialCultureName = parts[0]; var potentialUICultureName = parts[1]; if (!potentialCultureName.StartsWith(_culturePrefix) || !potentialUICultureName.StartsWith(_uiCulturePrefix)) { return null; } var cultureName = potentialCultureName.Substring(_culturePrefix.Length); var uiCultureName = potentialUICultureName.Substring(_uiCulturePrefix.Length); if (cultureName == null && uiCultureName == null) { // No values specified for either so no match return null; } if (cultureName != null && uiCultureName == null) { // Value for culture but not for UI culture so default to culture value for both uiCultureName = cultureName; } if (cultureName == null && uiCultureName != null) { // Value for UI culture but not for culture so default to UI culture value for both cultureName = uiCultureName; } return new ProviderCultureResult(cultureName, uiCultureName); } } }