using System; using Oqtane.Models; namespace Oqtane.Shared { public class CookieRequestCultureProvider { private const char _cookieSeparator = '|'; private const string _culturePrefix = "c="; private const string _uiCulturePrefix = "uic="; /// /// Represent the default cookie name used to track the user's preferred culture information, which is ".AspNetCore.Culture". /// public static readonly string DefaultCookieName = ".AspNetCore.Culture"; /// /// The name of the cookie that contains the user's preferred culture information. /// Defaults to . /// public string CookieName { get; set; } = DefaultCookieName; /// /// Creates a string representation of a for placement in a cookie. /// /// The . /// The cookie value. public static string MakeCookieValue(RequestCulture requestCulture) { ArgumentNullException.ThrowIfNull(requestCulture); return string.Join(_cookieSeparator, $"{_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 RequestCulture ParseCookieValue(string value) { if (string.IsNullOrWhiteSpace(value)) { return null; } Span parts = stackalloc Range[3]; var valueSpan = value.AsSpan(); if (valueSpan.Split(parts, _cookieSeparator, StringSplitOptions.RemoveEmptyEntries) != 2) { return null; } var potentialCultureName = valueSpan[parts[0]]; var potentialUICultureName = valueSpan[parts[1]]; if (!potentialCultureName.StartsWith(_culturePrefix, StringComparison.Ordinal) || ! potentialUICultureName.StartsWith(_uiCulturePrefix, StringComparison.Ordinal)) { return null; } var cultureName = potentialCultureName.Slice(_culturePrefix.Length); var uiCultureName = potentialUICultureName.Slice(_uiCulturePrefix.Length); if (cultureName.IsEmpty && uiCultureName.IsEmpty) { // No values specified for either so no match return null; } if (!cultureName.IsEmpty && uiCultureName.IsEmpty) { // Value for culture but not for UI culture so default to culture value for both uiCultureName = cultureName; } else if (cultureName.IsEmpty && !uiCultureName.IsEmpty) { // Value for UI culture but not for culture so default to UI culture value for both cultureName = uiCultureName; } return new RequestCulture(cultureName.ToString(), uiCultureName.ToString()); } } }