Skip to content

Commit

Permalink
Support key hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamco committed Mar 25, 2024
1 parent 43ccf24 commit 97b8ed4
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 14 deletions.
69 changes: 67 additions & 2 deletions src/My.Extensions.Localization.Json/Internal/JsonResourceLoader.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace My.Extensions.Localization.Json.Internal;
Expand All @@ -23,9 +22,75 @@ public static IDictionary<string, string> Load(string filePath)

using var document = JsonDocument.Parse(reader.BaseStream, _jsonDocumentOptions);

resources = document.RootElement.EnumerateObject().ToDictionary(e => e.Name, e => e.Value.ToString());
var rootELement = document.RootElement.Clone();

JsonElementToDictionary(rootELement, resources);
}

return resources;
}

private static void JsonElementToDictionary(JsonElement element, Dictionary<string, string> result)
{
foreach (var item in element.EnumerateObject())
{
JsonElementToObject(item.Value, result, item.Name);
}
}

private static void JsonElementToObject(JsonElement element, Dictionary<string, string> result, string path)
{
const char period = '.';
if (element.ValueKind == JsonValueKind.Object)
{
foreach (var item in element.EnumerateObject())
{
if (string.IsNullOrEmpty(path))
{
path = item.Name;
}
else
{
path += period + item.Name;
}

JsonElementToObject(item.Value, result, path);

if (path.Contains(period))
{
path = path[..path.LastIndexOf(period)];
}
}
}
else if (element.ValueKind == JsonValueKind.Array)
{
JsonElementToArray(element, result, path);
}
else
{
JsonElementToValue(element, result, path);
}
}

private static void JsonElementToArray(JsonElement element, Dictionary<string, string> result, string path)
{
const char openBracket = '[';
var index = 0;
foreach (var item in element.EnumerateArray())
{
path += $"[{index}]";

JsonElementToObject(item, result, path);

if (path.Contains(openBracket))
{
path = path[..path.LastIndexOf(openBracket)];
}

++index;
}
}

private static void JsonElementToValue(JsonElement element, Dictionary<string, string> result, string path)
=> result.Add(path, element.ToString());
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace My.Extensions.Localization.Json.Internal;

Expand Down Expand Up @@ -30,7 +32,7 @@ public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo c
var allResources = new ConcurrentDictionary<string, string>();
do
{
if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources))
if (_resourcesCache.TryGetValue(culture.Name, out var resources))
{
foreach (var entry in resources)
{
Expand All @@ -45,7 +47,7 @@ public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo c
}
else
{
_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources);
_resourcesCache.TryGetValue(culture.Name, out var resources);

return resources;
}
Expand All @@ -63,11 +65,11 @@ public virtual string GetString(string name)

do
{
if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources))
if (_resourcesCache.TryGetValue(culture.Name, out var resources))
{
if (resources.TryGetValue(name, out string value))
if (resources.TryGetValue(name, out var value))
{
return value;
return value.ToString();
}
}

Expand All @@ -86,13 +88,13 @@ public virtual string GetString(string name, CultureInfo culture)
return null;
}

if (!_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources))
if (!_resourcesCache.TryGetValue(culture.Name, out var resources))
{
return null;
}

return resources.TryGetValue(name, out string value)
? value
return resources.TryGetValue(name, out var value)
? value.ToString()
: null;
}

Expand Down Expand Up @@ -157,4 +159,26 @@ ConcurrentDictionary<string, string> GetOrAddResourceCache(string resourceFile)
});
}
}

private static string GetJsonElement(JsonElement jsonElement, string path)
{
if (jsonElement.ValueKind == JsonValueKind.Null || jsonElement.ValueKind == JsonValueKind.Undefined)
{
return default;
}

string[] segments = path.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

for (int n = 0; n < segments.Length; n++)
{
jsonElement = jsonElement.TryGetProperty(segments[n], out JsonElement value) ? value : default;

if (jsonElement.ValueKind == JsonValueKind.Null || jsonElement.ValueKind == JsonValueKind.Undefined)
{
return default;
}
}

return jsonElement.ToString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ public void GetTranslation_StronglyTypeResourceName()
}

[Theory]
[InlineData(true, 3)]
[InlineData(false, 2)]
[InlineData(true, 9)]
[InlineData(false, 8)]
public void JsonStringLocalizer_GetAllStrings(bool includeParent, int expected)
{
// Arrange
Expand Down Expand Up @@ -160,6 +160,23 @@ public async void CultureBasedResourcesUsesIStringLocalizer()
var response = await client.GetAsync("/");
}

[Theory]
[InlineData("fr-FR", "Book.Page.One", "Page Un")]
[InlineData("fr-FR", "Book.Page.Two", "Page Deux")]
[InlineData("fr-FR", "Articles[0].Content", "Contenu 1")]
[InlineData("fr-FR", "Articles[1].Content", "Contenu 2")]
public void GetTranslationUsingKeyHeirarchy(string culture, string name, string expected)
{
// Arrange
LocalizationHelper.SetCurrentCulture(culture);

// Act
string translation = _localizer[name];

// Assert
Assert.Equal(expected, translation);
}

private class SharedResource
{
public string Hello { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
{
"Hello": "Bonjour",
"Hello, {0}": "Bonjour, {0}"
"Hello, {0}": "Bonjour, {0}",
"Book": {
"Page": {
"One": "Page Un",
"Two": "Page Deux"
}
},
"Articles": [
{
"Title": "Titre 1",
"Content": "Contenu 1"
},
{
"Title": "Titre 2",
"Content": "Contenu 2"
}
]
}

0 comments on commit 97b8ed4

Please sign in to comment.