mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Translate the ISO-639-2/B codes to ISO-639-2/T. (#13068)
* Translate the ISO-639-2/B codes to ISO-639-2/T. This enables 19 additional languages to be displayed correctly. * Convert the 2-dimensional array to a dictionary * Added the French language to the list of ISO-639-2/B codes * Don't change the property, use a local variable instead. * When creating the MediaStream in the MediaStreamRepository ensure that the ISO 639-2/T (f.e. deu) code is used for the language as that is the one the .NET culture info knows. The other code is most likely the ISO 639-2/B code (f.e. ger) which is unknown to the .NET culture info and will result in just displaying the code instead of the display name. * Move the substitution of ISO 639-2/B to /T to the localization manager. Some language (like Chinese) have multiple entries in the iso6392.txt file (f.e. zho|chi|zh|..., zho|chi|zh-tw|...) but the conversation between /T and /B is the same so use .TryAdd. * Change the method definition from GetISO6392TFromB to TryGetISO6392TFromB and return true if a case was found. * Add unit tests for TryGetISO6392TFromB.
This commit is contained in:
parent
77ad7f6139
commit
5fc1b1c862
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -38,6 +40,8 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
|
|
||||||
private List<CultureDto> _cultures = [];
|
private List<CultureDto> _cultures = [];
|
||||||
|
|
||||||
|
private FrozenDictionary<string, string> _iso6392BtoT = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="LocalizationManager" /> class.
|
/// Initializes a new instance of the <see cref="LocalizationManager" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -100,6 +104,7 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
private async Task LoadCultures()
|
private async Task LoadCultures()
|
||||||
{
|
{
|
||||||
List<CultureDto> list = [];
|
List<CultureDto> list = [];
|
||||||
|
Dictionary<string, string> iso6392BtoTdict = new Dictionary<string, string>();
|
||||||
|
|
||||||
using var stream = _assembly.GetManifestResourceStream(CulturesPath);
|
using var stream = _assembly.GetManifestResourceStream(CulturesPath);
|
||||||
if (stream is null)
|
if (stream is null)
|
||||||
@ -142,12 +147,17 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
threeLetterNames = [parts[0], parts[1]];
|
threeLetterNames = [parts[0], parts[1]];
|
||||||
|
|
||||||
|
// In cases where there are two TLN the first one is ISO 639-2/T and the second one is ISO 639-2/B
|
||||||
|
// We need ISO 639-2/T for the .NET cultures so we cultivate a dictionary for the translation B->T
|
||||||
|
iso6392BtoTdict.TryAdd(parts[1], parts[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Add(new CultureDto(name, name, twoCharName, threeLetterNames));
|
list.Add(new CultureDto(name, name, twoCharName, threeLetterNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
_cultures = list;
|
_cultures = list;
|
||||||
|
_iso6392BtoT = iso6392BtoTdict.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,5 +515,26 @@ namespace Emby.Server.Implementations.Localization
|
|||||||
yield return new LocalizationOption("漢語 (繁體字)", "zh-TW");
|
yield return new LocalizationOption("漢語 (繁體字)", "zh-TW");
|
||||||
yield return new LocalizationOption("廣東話 (香港)", "zh-HK");
|
yield return new LocalizationOption("廣東話 (香港)", "zh-HK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool TryGetISO6392TFromB(string isoB, [NotNullWhen(true)] out string? isoT)
|
||||||
|
{
|
||||||
|
// Unlikely case the dictionary is not (yet) initialized properly
|
||||||
|
if (_iso6392BtoT == null)
|
||||||
|
{
|
||||||
|
isoT = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = _iso6392BtoT.TryGetValue(isoB, out isoT) && !string.IsNullOrEmpty(isoT);
|
||||||
|
|
||||||
|
// Ensure the ISO code being null if the result is false
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
isoT = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,18 @@ public class MediaStreamRepository : IMediaStreamRepository
|
|||||||
|
|
||||||
dto.IsAVC = entity.IsAvc;
|
dto.IsAVC = entity.IsAvc;
|
||||||
dto.Codec = entity.Codec;
|
dto.Codec = entity.Codec;
|
||||||
dto.Language = entity.Language;
|
|
||||||
|
var language = entity.Language;
|
||||||
|
|
||||||
|
// Check if the language has multiple three letter ISO codes
|
||||||
|
// if yes choose the first as that is the ISO 639-2/T code we're needing
|
||||||
|
if (language != null && _localization.TryGetISO6392TFromB(language, out string? isoT))
|
||||||
|
{
|
||||||
|
language = isoT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dto.Language = language;
|
||||||
|
|
||||||
dto.ChannelLayout = entity.ChannelLayout;
|
dto.ChannelLayout = entity.ChannelLayout;
|
||||||
dto.Profile = entity.Profile;
|
dto.Profile = entity.Profile;
|
||||||
dto.AspectRatio = entity.AspectRatio;
|
dto.AspectRatio = entity.AspectRatio;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@ -272,7 +273,7 @@ namespace MediaBrowser.Model.Entities
|
|||||||
// Do not display the language code in display titles if unset or set to a special code. Show it in all other cases (possibly expanded).
|
// Do not display the language code in display titles if unset or set to a special code. Show it in all other cases (possibly expanded).
|
||||||
if (!string.IsNullOrEmpty(Language) && !_specialCodes.Contains(Language, StringComparison.OrdinalIgnoreCase))
|
if (!string.IsNullOrEmpty(Language) && !_specialCodes.Contains(Language, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Get full language string i.e. eng -> English. Will not work for some languages which use ISO 639-2/B instead of /T codes.
|
// Get full language string i.e. eng -> English.
|
||||||
string fullLanguage = CultureInfo
|
string fullLanguage = CultureInfo
|
||||||
.GetCultures(CultureTypes.NeutralCultures)
|
.GetCultures(CultureTypes.NeutralCultures)
|
||||||
.FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
|
.FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
|
||||||
@ -375,7 +376,7 @@ namespace MediaBrowser.Model.Entities
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(Language))
|
if (!string.IsNullOrEmpty(Language))
|
||||||
{
|
{
|
||||||
// Get full language string i.e. eng -> English. Will not work for some languages which use ISO 639-2/B instead of /T codes.
|
// Get full language string i.e. eng -> English.
|
||||||
string fullLanguage = CultureInfo
|
string fullLanguage = CultureInfo
|
||||||
.GetCultures(CultureTypes.NeutralCultures)
|
.GetCultures(CultureTypes.NeutralCultures)
|
||||||
.FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
|
.FirstOrDefault(r => r.ThreeLetterISOLanguageName.Equals(Language, StringComparison.OrdinalIgnoreCase))
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Globalization;
|
namespace MediaBrowser.Model.Globalization;
|
||||||
@ -61,4 +62,12 @@ public interface ILocalizationManager
|
|||||||
/// <param name="language">The language.</param>
|
/// <param name="language">The language.</param>
|
||||||
/// <returns>The correct <see cref="CultureDto" /> for the given language.</returns>
|
/// <returns>The correct <see cref="CultureDto" /> for the given language.</returns>
|
||||||
CultureDto? FindLanguageInfo(string language);
|
CultureDto? FindLanguageInfo(string language);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the language in ISO 639-2/T when the input is ISO 639-2/B.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="isoB">The language in ISO 639-2/B.</param>
|
||||||
|
/// <param name="isoT">The language in ISO 639-2/T.</param>
|
||||||
|
/// <returns>Whether the language could be converted.</returns>
|
||||||
|
public bool TryGetISO6392TFromB(string isoB, [NotNullWhen(true)] out string? isoT);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BitFaster.Caching;
|
||||||
using Emby.Server.Implementations.Localization;
|
using Emby.Server.Implementations.Localization;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
@ -51,6 +52,30 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
|
|||||||
Assert.Contains("ger", germany.ThreeLetterISOLanguageNames);
|
Assert.Contains("ger", germany.ThreeLetterISOLanguageNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task TryGetISO6392TFromB_Success()
|
||||||
|
{
|
||||||
|
var localizationManager = Setup(new ServerConfiguration
|
||||||
|
{
|
||||||
|
UICulture = "de-DE"
|
||||||
|
});
|
||||||
|
await localizationManager.LoadAll();
|
||||||
|
|
||||||
|
string? isoT;
|
||||||
|
|
||||||
|
// Translation ger -> deu
|
||||||
|
Assert.True(localizationManager.TryGetISO6392TFromB("ger", out isoT));
|
||||||
|
Assert.Equal("deu", isoT);
|
||||||
|
|
||||||
|
// chi -> zho
|
||||||
|
Assert.True(localizationManager.TryGetISO6392TFromB("chi", out isoT));
|
||||||
|
Assert.Equal("zho", isoT);
|
||||||
|
|
||||||
|
// eng is already ISO 639-2/T
|
||||||
|
Assert.False(localizationManager.TryGetISO6392TFromB("eng", out isoT));
|
||||||
|
Assert.Null(isoT);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("de")]
|
[InlineData("de")]
|
||||||
[InlineData("deu")]
|
[InlineData("deu")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user