diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2026-05-04 21:57:11 +0200 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2026-05-12 23:18:38 +0200 |
| commit | 5cfb379aa63689435077c8f1ebc10c98f625238c (patch) | |
| tree | 8493e6f87a7e244905479c990ba6afedff0742e8 /Emby.Server.Implementations | |
| parent | 4be3f5f1f9ff8bd0333033d6ad9c99711da03f96 (diff) | |
Use native middleware
Diffstat (limited to 'Emby.Server.Implementations')
3 files changed, 33 insertions, 62 deletions
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 6dc6d9d289..17070c39ba 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -1,6 +1,5 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Globalization; using System.IO.Pipelines; using System.Net; @@ -9,7 +8,6 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using Emby.Server.Implementations.Localization; using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net.WebSocketMessages; @@ -73,12 +71,6 @@ namespace Emby.Server.Implementations.HttpServer public IPAddress? RemoteEndPoint { get; } /// <summary> - /// Gets or initializes the culture fallback chain captured from the - /// <c>Accept-Language</c> header of the upgrade request. - /// </summary> - public IReadOnlyList<string>? RequestCultureFallback { get; init; } - - /// <summary> /// Gets or initializes the UI culture name captured from the upgrade request. /// </summary> public string? RequestUICulture { get; init; } @@ -98,22 +90,18 @@ namespace Emby.Server.Implementations.HttpServer /// <inheritdoc /> public void ApplyRequestCulture() { - if (RequestCultureFallback is not null) + if (string.IsNullOrEmpty(RequestUICulture)) { - LocalizationManager.RequestCultureFallback = RequestCultureFallback; + return; } - if (!string.IsNullOrEmpty(RequestUICulture)) + try { - try - { - CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(RequestUICulture); - } - catch (CultureNotFoundException) - { - // Jellyfin culture codes (e.g. "es_419") aren't always valid .NET cultures — - // skip setting CurrentUICulture; RequestCultureFallback above carries the chain. - } + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(RequestUICulture); + } + catch (CultureNotFoundException) + { + // Codes that aren't valid .NET cultures are ignored. } } diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index 3b5f6d1d09..dcdfda5472 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -8,7 +8,6 @@ using System.Globalization; using System.Linq; using System.Net.WebSockets; using System.Threading.Tasks; -using Emby.Server.Implementations.Localization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; @@ -50,7 +49,7 @@ namespace Emby.Server.Implementations.HttpServer WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false); - // Capture the culture context set by AcceptLanguageMiddleware so it can be + // Capture the culture set by RequestLocalizationMiddleware so it can be // restored both when processing incoming messages and when periodic // listeners produce server-initiated payloads on background tasks. var connection = new WebSocketConnection( @@ -59,7 +58,6 @@ namespace Emby.Server.Implementations.HttpServer authorizationInfo, context.GetNormalizedRemoteIP()) { - RequestCultureFallback = LocalizationManager.RequestCultureFallback, RequestUICulture = CultureInfo.CurrentUICulture.Name }; connection.OnReceive = result => diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 2a7a3388aa..5c2376ea00 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -8,7 +8,6 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text.Json; -using System.Threading; using System.Threading.Tasks; using Jellyfin.Extensions; using Jellyfin.Extensions.Json; @@ -32,10 +31,9 @@ namespace Emby.Server.Implementations.Localization private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly string[] _unratedValues = ["n/a", "unrated", "not rated", "nr"]; - /// <summary> - /// Gets the mapping from BCP-47 hyphenated culture codes to Jellyfin's underscore-based codes. - /// </summary> - public static readonly FrozenDictionary<string, string> Bcp47ToJellyfinMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) + // Maps BCP-47 hyphenated culture codes (set by ASP.NET Core's RequestLocalizationMiddleware + // and used as CurrentUICulture.Name) to Jellyfin's underscore-based resource file codes. + private static readonly FrozenDictionary<string, string> _bcp47ToJellyfinMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["es-419"] = "es_419", ["es-DO"] = "es_DO", @@ -47,8 +45,6 @@ namespace Emby.Server.Implementations.Localization private readonly Dictionary<string, Dictionary<string, ParentalRatingScore?>> _allParentalRatings = new(StringComparer.OrdinalIgnoreCase); - private static readonly AsyncLocal<IReadOnlyList<string>?> _requestCultureFallback = new(); - private readonly ConcurrentDictionary<string, Dictionary<string, string>> _cultureOnlyDictionaries = new(StringComparer.OrdinalIgnoreCase); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; @@ -76,24 +72,28 @@ namespace Emby.Server.Implementations.Localization } /// <summary> - /// Gets or sets the per-request culture fallback chain resolved from Accept-Language. - /// Each entry is a Jellyfin culture code (e.g. "de", "nl", "en-US") in priority order. + /// Gets the supported UI cultures. /// </summary> - public static IReadOnlyList<string>? RequestCultureFallback + /// <returns>A list of <see cref="CultureInfo"/> objects covering every embedded translation.</returns> + public static IList<CultureInfo> GetSupportedUICultures() { - get => _requestCultureFallback.Value; - set => _requestCultureFallback.Value = value; - } + var cultures = new List<CultureInfo>(); + foreach (var option in _localizationOptions) + { + // Resource files use underscores for some variants (e.g. es_419); + // CultureInfo only accepts hyphenated BCP-47 codes. + var code = option.Value.Replace('_', '-'); + try + { + cultures.Add(CultureInfo.GetCultureInfo(code)); + } + catch (CultureNotFoundException) + { + // Skip novelty codes (e.g. "pr" Pirate, "jbo" Lojban) that .NET cannot resolve. + } + } - /// <summary> - /// Checks whether a translation resource file exists for the given culture code. - /// </summary> - /// <param name="culture">The culture code to check (e.g. "de", "pt-BR", "es_419").</param> - /// <returns><c>true</c> if an embedded translation resource exists for the culture.</returns> - public static bool HasTranslation(string culture) - { - var resourceName = CoreResourcePrefix + GetResourceFilename(culture); - return _assembly.GetManifestResourceInfo(resourceName) is not null; + return cultures; } private static void OnConfigurationUpdated(object? sender, EventArgs e) @@ -472,21 +472,6 @@ namespace Emby.Server.Implementations.Localization /// <inheritdoc /> public string GetLocalizedString(string phrase) { - var fallback = _requestCultureFallback.Value; - if (fallback is not null) - { - foreach (var culture in fallback) - { - var dict = GetLocalizationDictionary(culture); - if (dict.TryGetValue(phrase, out var value)) - { - return value; - } - } - - return phrase; - } - return GetLocalizedString(phrase, CultureInfo.CurrentUICulture.Name); } @@ -510,7 +495,7 @@ namespace Emby.Server.Implementations.Localization } // Normalize BCP-47 hyphenated codes to Jellyfin's underscore-based codes - if (Bcp47ToJellyfinMap.TryGetValue(culture, out var mapped)) + if (_bcp47ToJellyfinMap.TryGetValue(culture, out var mapped)) { culture = mapped; } @@ -626,7 +611,7 @@ namespace Emby.Server.Implementations.Localization private static string GetDisplayName(string cultureCode) { // Handle Jellyfin-specific codes that aren't valid CultureInfo names - if (Bcp47ToJellyfinMap.Values.Contains(cultureCode)) + if (_bcp47ToJellyfinMap.Values.Contains(cultureCode)) { // Convert underscore to hyphen for CultureInfo lookup var normalized = cultureCode.Replace('_', '-'); |
