Browse Source

feat(l8n): add support for nested objects in localization files

Closes #18208
pull/23701/head
Jack Fistelmann 5 months ago
parent
commit
62a8e8a165
  1. 55
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs
  2. 7
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs
  3. 13
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs
  4. 6
      framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json

55
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs

@ -47,12 +47,11 @@ public static class JsonLocalizationDictionaryBuilder
{
throw new AbpException("Can not parse json string. " + ex.Message);
}
if (jsonFile == null)
{
return null;
}
var cultureCode = jsonFile.Culture;
if (string.IsNullOrEmpty(cultureCode))
{
@ -61,18 +60,20 @@ public static class JsonLocalizationDictionaryBuilder
var dictionary = new Dictionary<string, LocalizedString>();
var dublicateNames = new List<string>();
foreach (var item in jsonFile.Texts)
// Flache Struktur in Dictionary umwandeln
var flatTexts = FlattenTexts(jsonFile.Texts);
foreach (var item in flatTexts)
{
if (string.IsNullOrEmpty(item.Key))
{
throw new AbpException("The key is empty in given json string.");
}
if (dictionary.GetOrDefault(item.Key) != null)
{
dublicateNames.Add(item.Key);
}
dictionary[item.Key] = new LocalizedString(item.Key, item.Value.NormalizeLineEndings());
}
@ -85,4 +86,48 @@ public static class JsonLocalizationDictionaryBuilder
return new StaticLocalizationDictionary(cultureCode, dictionary);
}
private static Dictionary<string, string> FlattenTexts(Dictionary<string, object> texts, string prefix = "")
{
var result = new Dictionary<string, string>();
foreach (var item in texts)
{
var currentKey = string.IsNullOrEmpty(prefix) ? item.Key : $"{prefix}__{item.Key}";
if (item.Value is JsonElement jsonElement)
{
if (jsonElement.ValueKind == JsonValueKind.String)
{
result[currentKey] = jsonElement.GetString() ?? "";
}
else if (jsonElement.ValueKind == JsonValueKind.Object)
{
var nestedDict = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonElement.GetRawText());
if (nestedDict != null)
{
var flattenedNested = FlattenTexts(nestedDict, currentKey);
foreach (var nested in flattenedNested)
{
result[nested.Key] = nested.Value;
}
}
}
}
else if (item.Value is string stringValue)
{
result[currentKey] = stringValue;
}
else if (item.Value is Dictionary<string, object> nestedDict)
{
var flattenedNested = FlattenTexts(nestedDict, currentKey);
foreach (var nested in flattenedNested)
{
result[nested.Key] = nested.Value;
}
}
}
return result;
}
}

7
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs

@ -9,10 +9,5 @@ public class JsonLocalizationFile
/// </summary>
public string Culture { get; set; } = default!;
public Dictionary<string, string> Texts { get; set; }
public JsonLocalizationFile()
{
Texts = new Dictionary<string, string>();
}
public Dictionary<string, object> Texts { get; set; } = [];
}

13
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs

@ -375,4 +375,17 @@ public class AbpLocalization_Tests : AbpIntegratedTest<AbpLocalizationTestModule
var externalLocalizer = _localizerFactory.CreateByResourceName(TestExternalLocalizationStore.TestExternalResourceNames.ExternalResource1);
externalLocalizer["Car"].Value.ShouldBe("Car");
}
/// <summary>
/// <see href="https://github.com/abpframework/abp/issues/18208"/>
/// </summary>
[Fact]
public void Should_Get_Nested_Translations()
{
using (CultureHelper.Use("en"))
{
_localizer["MyNestedTranslation__SomeKey"].Value.ShouldBe("Some nested value");
_localizer["MyNestedTranslation__SomeOtherKey"].Value.ShouldBe("Some other nested value");
}
}
}

6
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/en.json

@ -1,6 +1,10 @@
{
"culture": "en",
"texts": {
"SeeYou": "See you"
"SeeYou": "See you",
"MyNestedTranslation": {
"SomeKey": "Some nested value",
"SomeOtherKey": "Some other nested value"
}
}
}
Loading…
Cancel
Save