Skip to content

Commit 2d6509d

Browse files
authored
Fix: LocalizationProvider.GetString with fallback culture (#484)
* Fix method `LocalizationProvider.GetString(string, CultureInfo?)` to correctly handle fallback culture. * Introduce tests for fallback culture and key return behavior in `LocalizationProviderTest`. Implement a FakeResourceManager for resource simulation. * `LocalizationProvider` now has full code coverage Resolves issue 483
1 parent c313597 commit 2d6509d

2 files changed

Lines changed: 75 additions & 8 deletions

File tree

src/SmartFormat.Tests/Extensions/LocalizationProviderTests.cs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Globalization;
33
using System.Linq;
4+
using System.Resources;
45
using NUnit.Framework;
56
using SmartFormat.Core.Settings;
67
using SmartFormat.Extensions;
@@ -123,6 +124,75 @@ public void GetString_NonExisting_Value()
123124
Assert.That(result, Is.Null);
124125
}
125126

127+
[Test]
128+
public void GetString_UsesFallbackCulture_WhenValueNotFoundInRequestedCulture()
129+
{
130+
// Provide a resource value for "Greeting" only in "en-US"
131+
var resources = new Dictionary<(string, string), string>
132+
{
133+
{ ("Greeting", "en-US"), "Hello" }
134+
};
135+
136+
var fakeResourceManager = new FakeResourceManager("TestResource", resources);
137+
var provider = new LocalizationProvider();
138+
provider.AddResource(fakeResourceManager);
139+
140+
// Set the fallback culture to en-US.
141+
provider.FallbackCulture = CultureInfo.GetCultureInfo("en-US");
142+
143+
// Request "Greeting" using "fr-FR" which is missing, expecting to fallback to "en-US".
144+
var result = provider.GetString("Greeting", CultureInfo.GetCultureInfo("fr-FR"));
145+
146+
// Assert:
147+
Assert.That(result, Is.EqualTo("Hello"));
148+
}
149+
150+
[Test]
151+
public void GetString_ReturnsKey_WhenResourceNotFound_AndReturnNameIfNotFoundIsTrue()
152+
{
153+
var resources = new Dictionary<(string, string), string>();
154+
var fakeResourceManager = new FakeResourceManager("TestResource", resources);
155+
156+
var provider = new LocalizationProvider();
157+
provider.AddResource(fakeResourceManager);
158+
provider.ReturnNameIfNotFound = true;
159+
160+
// No resource exists, so we get the key back.
161+
var result = provider.GetString("NonExistingKey", CultureInfo.GetCultureInfo("en-US"));
162+
163+
Assert.That(result, Is.EqualTo("NonExistingKey"));
164+
}
165+
166+
#region * Fake ResourceManager *
167+
168+
// A fake resource manager to simulate resource lookup.
169+
private class FakeResourceManager : ResourceManager
170+
{
171+
private readonly Dictionary<(string Key, string CultureName), string> _resources;
172+
private readonly string _baseName;
173+
174+
public FakeResourceManager(string baseName, Dictionary<(string, string), string> resources)
175+
{
176+
_baseName = baseName;
177+
_resources = resources;
178+
}
179+
180+
public override string BaseName => _baseName;
181+
182+
public override string? GetString(string? name, CultureInfo? culture)
183+
{
184+
if (name is null || culture is null)
185+
return null;
186+
187+
if (_resources.TryGetValue((name, culture.Name), out var value))
188+
return value;
189+
190+
return null;
191+
}
192+
}
193+
194+
#endregion
195+
126196
#region * Custom ILocalizationProvider Implementation *
127197

128198
[Test]
@@ -175,4 +245,4 @@ public DictLocalizationProvider()
175245
}
176246

177247
#endregion
178-
}
248+
}

src/SmartFormat/Utilities/LocalizationProvider.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ private void DoAddResource(ResourceManager resourceManager, bool isCaseSensitive
5252
/// <returns><see langword="true"/>, if the resource could be removed, else <see langword="false"/>.</returns>
5353
public virtual bool Remove(string resourceBaseName)
5454
{
55-
if (!Resources.ContainsKey(resourceBaseName)) return false;
56-
57-
Resources.Remove(resourceBaseName);
58-
return true;
59-
55+
return Resources.Remove(resourceBaseName);
6056
}
6157

6258
/// <summary>
@@ -111,7 +107,8 @@ public virtual void Clear()
111107
? resourceManager.GetString(name, cultureInfo)
112108
: resourceManager.GetString(name);
113109

114-
if (value is null && FallbackCulture != null) resourceManager.GetString(name, FallbackCulture);
110+
if (value is null && FallbackCulture != null)
111+
value = resourceManager.GetString(name, FallbackCulture);
115112

116113
if (value is null) continue;
117114

@@ -133,4 +130,4 @@ public virtual void Clear()
133130
/// Same behavior as e.g. <c>Microsoft.Extensions.Localization.ResourceManagerStringLocalizer</c>, if <see langword="true"/>.
134131
/// </remarks>
135132
public virtual bool ReturnNameIfNotFound { get; set; } = false;
136-
}
133+
}

0 commit comments

Comments
 (0)