Extend language code handling

This commit is contained in:
Shadowghost 2023-03-09 14:13:57 +01:00
parent 47b6f74533
commit daefdaf8b0
3 changed files with 55 additions and 36 deletions

View File

@ -184,10 +184,19 @@ namespace Emby.Server.Implementations.Localization
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<ParentalRating> GetParentalRatings() public IEnumerable<ParentalRating> GetParentalRatings()
{ {
var ratings = GetParentalRatingsDictionary().Values.ToList(); // Use server default language for ratings
// Fall back to empty list if there are no parental ratings for that language
var ratings = GetParentalRatingsDictionary()?.Values.ToList()
?? new List<ParentalRating>();
// Add common ratings to ensure them being available for selection. // Add common ratings to ensure them being available for selection
// Based on the US rating system due to it being the main source of rating in the metadata providers // Based on the US rating system due to it being the main source of rating in the metadata providers
// Unrated
if (!ratings.Any(x => x.Value is null))
{
ratings.Add(new ParentalRating("Unrated", null));
}
// Minimum rating possible // Minimum rating possible
if (!ratings.Any(x => x.Value == 0)) if (!ratings.Any(x => x.Value == 0))
{ {
@ -237,36 +246,26 @@ namespace Emby.Server.Implementations.Localization
/// <summary> /// <summary>
/// Gets the parental ratings dictionary. /// Gets the parental ratings dictionary.
/// </summary> /// </summary>
/// <param name="countryCode">The optional two letter ISO language string.</param>
/// <returns><see cref="Dictionary{String, ParentalRating}" />.</returns> /// <returns><see cref="Dictionary{String, ParentalRating}" />.</returns>
private Dictionary<string, ParentalRating> GetParentalRatingsDictionary() private Dictionary<string, ParentalRating>? GetParentalRatingsDictionary(string? countryCode = null)
{ {
var countryCode = _configurationManager.Configuration.MetadataCountryCode; // Fallback to server default if no country code is specified.
// Fall back to US ratings if no country code is specified or country code does not exist.
if (string.IsNullOrEmpty(countryCode)) if (string.IsNullOrEmpty(countryCode))
{ {
countryCode = "us"; countryCode = _configurationManager.Configuration.MetadataCountryCode;
} }
return GetRatings(countryCode) if (_allParentalRatings.TryGetValue(countryCode, out var countryValue))
?? GetRatings("us") {
?? throw new InvalidOperationException($"Invalid resource path: '{CountriesPath}'"); return countryValue;
} }
/// <summary> return null;
/// Gets the ratings for a country.
/// </summary>
/// <param name="countryCode">The country code.</param>
/// <returns>The ratings.</returns>
private Dictionary<string, ParentalRating>? GetRatings(string countryCode)
{
_allParentalRatings.TryGetValue(countryCode, out var countryValue);
return countryValue;
} }
/// <inheritdoc /> /// <inheritdoc />
public int? GetRatingLevel(string rating) public int? GetRatingLevel(string rating, string? countryCode = null)
{ {
ArgumentException.ThrowIfNullOrEmpty(rating); ArgumentException.ThrowIfNullOrEmpty(rating);
@ -280,32 +279,51 @@ namespace Emby.Server.Implementations.Localization
rating = rating.Replace("Rated :", string.Empty, StringComparison.OrdinalIgnoreCase); rating = rating.Replace("Rated :", string.Empty, StringComparison.OrdinalIgnoreCase);
rating = rating.Replace("Rated ", string.Empty, StringComparison.OrdinalIgnoreCase); rating = rating.Replace("Rated ", string.Empty, StringComparison.OrdinalIgnoreCase);
var ratingsDictionary = GetParentalRatingsDictionary(); // Use rating system matching the language
if (!string.IsNullOrEmpty(countryCode))
if (ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
{ {
return value.Value; var ratingsDictionary = GetParentalRatingsDictionary(countryCode);
if (ratingsDictionary is not null && ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
{
return value.Value;
}
} }
else
// If we don't find anything check all ratings systems
foreach (var dictionary in _allParentalRatings.Values)
{ {
if (dictionary.TryGetValue(rating, out value)) // Fall back to server default language for ratings check
// If it has no ratings, use the US ratings
var ratingsDictionary = GetParentalRatingsDictionary() ?? GetParentalRatingsDictionary("us");
if (ratingsDictionary is not null && ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
{ {
return value.Value; return value.Value;
} }
} }
// Try splitting by : to handle "Germany: FSK 18" // If we don't find anything, check all ratings systems
foreach (var dictionary in _allParentalRatings.Values)
{
if (dictionary.TryGetValue(rating, out var value))
{
return value.Value;
}
}
// Try splitting by : to handle "Germany: FSK-18"
if (rating.Contains(':', StringComparison.OrdinalIgnoreCase)) if (rating.Contains(':', StringComparison.OrdinalIgnoreCase))
{ {
return GetRatingLevel(rating.AsSpan().RightPart(':').ToString()); return GetRatingLevel(rating.AsSpan().RightPart(':').ToString());
} }
// Remove prefix country code to handle "DE-18" // Handle prefix country code to handle "DE-18"
if (rating.Contains('-', StringComparison.OrdinalIgnoreCase)) if (rating.Contains('-', StringComparison.OrdinalIgnoreCase))
{ {
return GetRatingLevel(rating.AsSpan().RightPart('-').ToString()); var ratingSpan = rating.AsSpan();
// Extract culture from country prefix
var culture = FindLanguageInfo(ratingSpan.LeftPart('-').ToString());
// Check rating system of culture
return GetRatingLevel(ratingSpan.RightPart('-').ToString(), culture?.TwoLetterISOLanguageName);
} }
return null; return null;

View File

@ -30,8 +30,9 @@ namespace MediaBrowser.Model.Globalization
/// Gets the rating level. /// Gets the rating level.
/// </summary> /// </summary>
/// <param name="rating">The rating.</param> /// <param name="rating">The rating.</param>
/// <param name="countryCode">The optional two letter ISO language string.</param>
/// <returns><see cref="int" /> or <c>null</c>.</returns> /// <returns><see cref="int" /> or <c>null</c>.</returns>
int? GetRatingLevel(string rating); int? GetRatingLevel(string rating, string? countryCode = null);
/// <summary> /// <summary>
/// Gets the localized string. /// Gets the localized string.

View File

@ -83,7 +83,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
await localizationManager.LoadAll(); await localizationManager.LoadAll();
var ratings = localizationManager.GetParentalRatings().ToList(); var ratings = localizationManager.GetParentalRatings().ToList();
Assert.Equal(53, ratings.Count); Assert.Equal(54, ratings.Count);
var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal)); var tvma = ratings.FirstOrDefault(x => x.Name.Equals("TV-MA", StringComparison.Ordinal));
Assert.NotNull(tvma); Assert.NotNull(tvma);
@ -100,7 +100,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
await localizationManager.LoadAll(); await localizationManager.LoadAll();
var ratings = localizationManager.GetParentalRatings().ToList(); var ratings = localizationManager.GetParentalRatings().ToList();
Assert.Equal(18, ratings.Count); Assert.Equal(19, ratings.Count);
var fsk = ratings.FirstOrDefault(x => x.Name.Equals("FSK-12", StringComparison.Ordinal)); var fsk = ratings.FirstOrDefault(x => x.Name.Equals("FSK-12", StringComparison.Ordinal));
Assert.NotNull(fsk); Assert.NotNull(fsk);