90 lines
3.4 KiB
C#
90 lines
3.4 KiB
C#
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=";
|
|
|
|
/// <summary>
|
|
/// Represent the default cookie name used to track the user's preferred culture information, which is ".AspNetCore.Culture".
|
|
/// </summary>
|
|
public static readonly string DefaultCookieName = ".AspNetCore.Culture";
|
|
|
|
/// <summary>
|
|
/// The name of the cookie that contains the user's preferred culture information.
|
|
/// Defaults to <see cref="DefaultCookieName"/>.
|
|
/// </summary>
|
|
public string CookieName { get; set; } = DefaultCookieName;
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of a <see cref="RequestCulture"/> for placement in a cookie.
|
|
/// </summary>
|
|
/// <param name="requestCulture">The <see cref="RequestCulture"/>.</param>
|
|
/// <returns>The cookie value.</returns>
|
|
public static string MakeCookieValue(RequestCulture requestCulture)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(requestCulture);
|
|
|
|
return string.Join(_cookieSeparator,
|
|
$"{_culturePrefix}{requestCulture.Culture.Name}",
|
|
$"{_uiCulturePrefix}{requestCulture.UICulture.Name}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses a <see cref="RequestCulture"/> from the specified cookie value.
|
|
/// Returns <c>null</c> if parsing fails.
|
|
/// </summary>
|
|
/// <param name="value">The cookie value to parse.</param>
|
|
/// <returns>The <see cref="RequestCulture"/> or <c>null</c> if parsing fails.</returns>
|
|
public static RequestCulture ParseCookieValue(string value)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
Span<Range> 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());
|
|
}
|
|
}
|
|
}
|