aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowghost <Shadowghost@users.noreply.github.com>2026-09-15 11:16:22 -0400
committerCody Robibero <cody@robibe.ro>2026-09-15 11:16:22 -0400
commitda3031628fda013be20ae4f89906882cc5d72e14 (patch)
tree95e60472a8952e7ca028546c39c5a1d09b9e531d
parent6937f03dc2c719b730f092fe4a87d8d4b6c2fc93 (diff)
Backport pull request #18002 from jellyfin/release-12.z
Fix slashed rating handling Original-merge: 4405fccda92426b01903e3fe4c5985f1d7c30957 Merged-by: crobibero <cody@robibe.ro> Backported-by: Cody Robibero <cody@robibe.ro>
-rw-r--r--Emby.Server.Implementations/Localization/LocalizationManager.cs12
-rw-r--r--tests/Jellyfin.Controller.Tests/Entities/AggregateFolderTests.cs1
-rw-r--r--tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs1
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs26
4 files changed, 40 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs
index c77717c76e..3f89237ab2 100644
--- a/Emby.Server.Implementations/Localization/LocalizationManager.cs
+++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs
@@ -382,9 +382,21 @@ namespace Emby.Server.Implementations.Localization
return null;
}
+ // Several rating systems contain a '/' inside a single rating (e.g. "M/12" in PT,
+ // "U/A 13+" in IN, "7/i/fig" in ES), so the value as a whole always wins over the split below.
+ var wholeValueScore = GetSingleRatingScore(rating, countryCode);
+ if (wholeValueScore is not null)
+ {
+ return wholeValueScore;
+ }
+
// Some providers may list multiple ratings separated by '/' (e.g. "SE:15 / SE:15+ / SE:Från 15 år").
// Try each one in order and use the first that resolves.
var ratingValues = rating.Split('/', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ if (ratingValues.Length == 1)
+ {
+ return null;
+ }
foreach (var ratingValue in ratingValues)
{
diff --git a/tests/Jellyfin.Controller.Tests/Entities/AggregateFolderTests.cs b/tests/Jellyfin.Controller.Tests/Entities/AggregateFolderTests.cs
index 6c297673d4..272c434fe9 100644
--- a/tests/Jellyfin.Controller.Tests/Entities/AggregateFolderTests.cs
+++ b/tests/Jellyfin.Controller.Tests/Entities/AggregateFolderTests.cs
@@ -9,6 +9,7 @@ using Xunit;
namespace Jellyfin.Controller.Tests.Entities;
+[Collection("LibraryManagerTests")]
public class AggregateFolderTests
{
[Fact]
diff --git a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
index f363968909..588f9d5530 100644
--- a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
+++ b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs
@@ -27,6 +27,7 @@ using Xunit;
namespace Jellyfin.Controller.Tests.Entities;
+[Collection("LibraryManagerTests")]
public class BaseItemTests
{
[Fact]
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
index 221f1d8ec8..93014e7244 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
@@ -297,6 +297,32 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
}
[Theory]
+ // Ratings that contain a '/' themselves must not be split into a list of ratings
+ [InlineData("M/3", "pt", 3, null)]
+ [InlineData("M/12", "pt", 12, null)]
+ [InlineData("M/18", "pt", 18, null)]
+ [InlineData("PT-M/12", "pt", 12, null)] // TMDB style country prefix
+ [InlineData("M/12", "us", 12, null)] // Resolved through the all-systems fallback
+ [InlineData("U/A 13+", "in", 13, null)]
+ [InlineData("7/i", "es", 11, null)]
+ [InlineData("7/i/fig", "es", 11, null)]
+ [InlineData("18/fig", "es", 18, null)]
+ public async Task GetRatingScore_RatingContainingSlash_IsNotSplit(string value, string countryCode, int expectedScore, int? expectedSubScore)
+ {
+ var localizationManager = Setup(new ServerConfiguration
+ {
+ MetadataCountryCode = countryCode
+ });
+ await localizationManager.LoadAll();
+
+ var score = localizationManager.GetRatingScore(value);
+
+ Assert.NotNull(score);
+ Assert.Equal(expectedScore, score.Score);
+ Assert.Equal(expectedSubScore, score.SubScore);
+ }
+
+ [Theory]
[InlineData("-NO RATING SHOWN-")]
[InlineData(":NO RATING SHOWN:")]
public async Task GetRatingLevel_Split_Success(string value)