Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #84

Merged
merged 2 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;

namespace My.Extensions.Localization.Json.Caching
namespace My.Extensions.Localization.Json.Caching;

public interface IResourceNamesCache
{
public interface IResourceNamesCache
{
IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory);
}
IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace My.Extensions.Localization.Json.Caching
namespace My.Extensions.Localization.Json.Caching;

public class ResourceNamesCache : IResourceNamesCache
{
public class ResourceNamesCache : IResourceNamesCache
{
private readonly ConcurrentDictionary<string, IList<string>> _cache = new ConcurrentDictionary<string, IList<string>>();
private readonly ConcurrentDictionary<string, IList<string>> _cache = new();

public IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory)
{
return _cache.GetOrAdd(name, valueFactory);
}
}
public IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory)
=> _cache.GetOrAdd(name, valueFactory);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System.Collections.Generic;
using System.Globalization;

namespace My.Extensions.Localization.Json.Internal
namespace My.Extensions.Localization.Json.Internal;

public interface IResourceStringProvider
{
public interface IResourceStringProvider
{
IList<string> GetAllResourceStrings(CultureInfo culture, bool throwOnMissing);
}
IList<string> GetAllResourceStrings(CultureInfo culture, bool throwOnMissing);
}
249 changes: 118 additions & 131 deletions src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,193 +5,180 @@
using System.Linq;
using System.Text.Json;

namespace My.Extensions.Localization.Json.Internal
namespace My.Extensions.Localization.Json.Internal;

public class JsonResourceManager(string resourcesPath, string resourceName = null)
{
public class JsonResourceManager
private static readonly JsonDocumentOptions _jsonDocumentOptions = new()
{
private static readonly JsonDocumentOptions _jsonDocumentOptions = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};
CommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};

private ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _resourcesCache = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _resourcesCache = new();

public JsonResourceManager(string resourcesPath, string resourceName = null)
{
ResourcesPath = resourcesPath;
ResourceName = resourceName;
}
public string ResourceName { get; } = resourceName;

public string ResourceName { get; }
public string ResourcesPath { get; } = resourcesPath;

public string ResourcesPath { get; }
public string ResourcesFilePath { get; private set; }

public string ResourcesFilePath { get; private set; }
public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo culture, bool tryParents)
{
TryLoadResourceSet(culture);

public virtual ConcurrentDictionary<string, string> GetResourceSet(CultureInfo culture, bool tryParents)
if (!_resourcesCache.ContainsKey(culture.Name))
{
TryLoadResourceSet(culture);

if (!_resourcesCache.ContainsKey(culture.Name))
{
return null;
}
return null;
}

if (tryParents)
if (tryParents)
{
var allResources = new ConcurrentDictionary<string, string>();
do
{
var allResources = new ConcurrentDictionary<string, string>();
do
if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources))
{
if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources))
foreach (var entry in resources)
{
foreach (var entry in resources)
{
allResources.TryAdd(entry.Key, entry.Value);
}
allResources.TryAdd(entry.Key, entry.Value);
}
}

culture = culture.Parent;
} while (culture != CultureInfo.InvariantCulture);
culture = culture.Parent;
} while (culture != CultureInfo.InvariantCulture);

return allResources;
}
else
{
_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources);
return allResources;
}
else
{
_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> resources);

return resources;
}
return resources;
}
}

public virtual string GetString(string name)
{
var culture = CultureInfo.CurrentUICulture;
GetResourceSet(culture, tryParents: true);
public virtual string GetString(string name)
{
var culture = CultureInfo.CurrentUICulture;
GetResourceSet(culture, tryParents: true);

if (_resourcesCache.Count == 0)
{
return null;
}
if (_resourcesCache.IsEmpty)
{
return null;
}

do
do
{
if (_resourcesCache.ContainsKey(culture.Name))
{
if (_resourcesCache.ContainsKey(culture.Name))
if (_resourcesCache[culture.Name].TryGetValue(name, out string value))
{
if (_resourcesCache[culture.Name].TryGetValue(name, out string value))
{
return value;
}
return value;
}
}

culture = culture.Parent;
} while (culture != culture.Parent);
culture = culture.Parent;
} while (culture != culture.Parent);

return null;
}

public virtual string GetString(string name, CultureInfo culture)
{
GetResourceSet(culture, tryParents: true);

if (_resourcesCache.IsEmpty)
{
return null;
}

public virtual string GetString(string name, CultureInfo culture)
if (!_resourcesCache.ContainsKey(culture.Name))
{
GetResourceSet(culture, tryParents: true);
return null;
}

if (_resourcesCache.Count == 0)
{
return null;
}
return _resourcesCache[culture.Name].TryGetValue(name, out string value)
? value
: null;
}

if (!_resourcesCache.ContainsKey(culture.Name))
{
return null;
}
private void TryLoadResourceSet(CultureInfo culture)
{
if (string.IsNullOrEmpty(ResourceName))
{
var file = Path.Combine(ResourcesPath, $"{culture.Name}.json");
var resources = LoadJsonResources(file);

return _resourcesCache[culture.Name].TryGetValue(name, out string value)
? value
: null;
_resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary<string, string>(resources.ToDictionary(r => r.Key, r => r.Value)));
}

private void TryLoadResourceSet(CultureInfo culture)
else
{
if (string.IsNullOrEmpty(ResourceName))
var resourceFiles = Enumerable.Empty<string>();
var rootCulture = culture.Name[..2];
if (ResourceName.Contains('.'))
{
var file = Path.Combine(ResourcesPath, $"{culture.Name}.json");
var resources = LoadJsonResources(file);
resourceFiles = Directory.EnumerateFiles(ResourcesPath, $"{ResourceName}.{rootCulture}*.json");

_resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary<string, string>(resources.ToDictionary(r => r.Key, r => r.Value)));
}
else
{
var resourceFiles = Enumerable.Empty<string>();
var rootCulture = culture.Name.Substring(0, 2);
if (ResourceName.Contains("."))
{
resourceFiles = Directory.EnumerateFiles(ResourcesPath, $"{ResourceName}.{rootCulture}*.json");

if (resourceFiles.Count() == 0)
{
resourceFiles = GetResourceFiles(rootCulture);
}
}
else
if (!resourceFiles.Any())
{
resourceFiles = GetResourceFiles(rootCulture);
}
}
else
{
resourceFiles = GetResourceFiles(rootCulture);
}

foreach (var file in resourceFiles)
{
var resources = LoadJsonResources(file);
var fileName = Path.GetFileNameWithoutExtension(file);
var cultureName = fileName.Substring(fileName.LastIndexOf(".") + 1);
foreach (var file in resourceFiles)
{
var resources = LoadJsonResources(file);
var fileName = Path.GetFileNameWithoutExtension(file);
var cultureName = fileName[(fileName.LastIndexOf('.') + 1)..];

culture = CultureInfo.GetCultureInfo(cultureName);
culture = CultureInfo.GetCultureInfo(cultureName);

if (_resourcesCache.ContainsKey(culture.Name))
{
foreach (var resource in resources)
{
_resourcesCache[culture.Name].TryAdd(resource.Key, resource.Value);
}
}
else
if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary<string, string> value))
{
foreach (var resource in resources)
{
_resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary<string, string>(resources.ToDictionary(r => r.Key, r => r.Value)));
value.TryAdd(resource.Key, resource.Value);
}
}
}

IEnumerable<string> GetResourceFiles(string culture)
{
var resourcePath = ResourceName.Replace('.', Path.AltDirectorySeparatorChar);
var resourcePathLastDirectorySeparatorIndex = resourcePath.LastIndexOf(Path.AltDirectorySeparatorChar);
var resourceName = resourcePath.Substring(resourcePathLastDirectorySeparatorIndex + 1);
string resourcesPath = null;
if (resourcePathLastDirectorySeparatorIndex == -1)
{
resourcesPath = ResourcesPath;
}
else
{
resourcesPath = Path.Combine(ResourcesPath, resourcePath.Substring(0, resourcePathLastDirectorySeparatorIndex));
_resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary<string, string>(resources.ToDictionary(r => r.Key, r => r.Value)));
}

return Directory.Exists(resourcesPath)
? Directory.EnumerateFiles(resourcesPath, $"{resourceName}.{culture}*.json")
: Enumerable.Empty<string>();
}
}

private static IDictionary<string, string> LoadJsonResources(string filePath)
IEnumerable<string> GetResourceFiles(string culture)
{
var resources = new Dictionary<string, string>();
if (File.Exists(filePath))
{
using var reader = new StreamReader(filePath);
var resourcePath = ResourceName.Replace('.', Path.AltDirectorySeparatorChar);
var resourcePathLastDirectorySeparatorIndex = resourcePath.LastIndexOf(Path.AltDirectorySeparatorChar);
var resourceName = resourcePath[(resourcePathLastDirectorySeparatorIndex + 1)..];
var resourcesPath = resourcePathLastDirectorySeparatorIndex == -1
? ResourcesPath
: Path.Combine(ResourcesPath, resourcePath[..resourcePathLastDirectorySeparatorIndex]);

return Directory.Exists(resourcesPath)
? Directory.EnumerateFiles(resourcesPath, $"{resourceName}.{culture}*.json")
: [];
}
}

using var document = JsonDocument.Parse(reader.BaseStream, _jsonDocumentOptions);
private static IDictionary<string, string> LoadJsonResources(string filePath)
{
var resources = new Dictionary<string, string>();
if (File.Exists(filePath))
{
using var reader = new StreamReader(filePath);

resources = document.RootElement.EnumerateObject().ToDictionary(e => e.Name, e => e.Value.ToString());
}
using var document = JsonDocument.Parse(reader.BaseStream, _jsonDocumentOptions);

return resources;
resources = document.RootElement.EnumerateObject().ToDictionary(e => e.Name, e => e.Value.ToString());
}

return resources;
}
}
Loading
Loading