chore fix

This commit is contained in:
2025-12-06 13:30:17 +08:00
parent 2972886576
commit 8aca372fc1
43 changed files with 984 additions and 595 deletions

View File

@@ -0,0 +1,141 @@
using Microsoft.Extensions.Localization;
using System.Globalization;
using System.Net.Http;
using System.Text.Json;
namespace Atomx.Admin.Client.Services
{
public class JsonStringLocalizer : IStringLocalizer
{
private readonly string _resourcesPath;
private readonly Dictionary<string, Dictionary<string, string>> _resourcesCache = new();
private readonly object _lock = new();
private readonly HttpClient? _httpClient;
// resourcesPath 应为相对于站点根的“目录”名称,例如 "Localization"
// 在 Blazor WebAssembly 场景下,会使用注入的 HttpClient 从 wwwroot/Localization/{culture}.json 获取资源
public JsonStringLocalizer(string resourcesPath, HttpClient? httpClient = null)
{
_resourcesPath = (resourcesPath ?? "Localization").Trim('/'); // 规范化
_httpClient = httpClient;
}
public LocalizedString this[string name]
{
get
{
var value = GetString(name);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
}
}
public LocalizedString this[string name, params object[] arguments]
{
get
{
var format = GetString(name);
var value = string.Format(format ?? name, arguments);
return new LocalizedString(name, value, resourceNotFound: format == null);
}
}
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{
var culture = CultureInfo.CurrentUICulture.Name;
var resources = LoadResources(culture);
return resources.Select(r => new LocalizedString(r.Key, r.Value, false));
}
private string? GetString(string name)
{
var culture = CultureInfo.CurrentUICulture.Name;
var resources = LoadResources(culture);
// 尝试当前文化
if (resources.TryGetValue(name, out var value))
return value;
// 如果还找不到,尝试英文作为后备
if (culture != "en-US")
{
var enResources = LoadResources("en-US");
if (enResources.TryGetValue(name, out var enValue))
return enValue;
}
return null;
}
private Dictionary<string, string> LoadResources(string culture)
{
lock (_lock)
{
if (_resourcesCache.TryGetValue(culture, out var cachedResources))
return cachedResources;
var resources = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var fileName = $"{culture}.json";
// 在浏览器WASM环境下通过 HttpClient 从静态资源目录获取
if (OperatingSystem.IsBrowser() && _httpClient != null)
{
try
{
// 构造相对 URL例如 "Localization/zh-Hans.json"
var relativeUrl = $"{_resourcesPath}/{fileName}";
var json = _httpClient.GetStringAsync(relativeUrl).ConfigureAwait(false).GetAwaiter().GetResult();
var jsonResources = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
if (jsonResources != null)
{
foreach (var item in jsonResources)
{
resources[item.Key] = item.Value;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading localization file {fileName} via HttpClient: {ex.Message}");
}
_resourcesCache[culture] = resources;
return resources;
}
// 非浏览器(例如 Server 或在 prerender 阶段)尝试从文件系统读取。
// 尝试几种可能的路径:基路径为 AppContext.BaseDirectory 或当前工作目录,或直接使用传入的路径。
try
{
var candidates = new[]
{
Path.Combine(AppContext.BaseDirectory, _resourcesPath, fileName),
Path.Combine(Directory.GetCurrentDirectory(), _resourcesPath, fileName),
Path.Combine(_resourcesPath, fileName),
};
var filePath = candidates.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(filePath))
{
var json = File.ReadAllText(filePath);
var jsonResources = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
if (jsonResources != null)
{
foreach (var item in jsonResources)
{
resources[item.Key] = item.Value;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading localization file {fileName} from disk: {ex.Message}");
}
_resourcesCache[culture] = resources;
return resources;
}
}
}
}