实现多语言切换

This commit is contained in:
2025-12-09 03:31:07 +08:00
parent 9631e00a12
commit 429fb39140
18 changed files with 1173 additions and 41 deletions

View File

@@ -0,0 +1,82 @@
@inject ILocalizationProvider LocalizationProvider
@inject NavigationManager Navigation
@inject IJSRuntime JS
<select @onchange="OnChange" value="@selected">
@foreach (var item in options)
{
<option value="@item.Key">@item.Value</option>
}
</select>
@code {
private string selected = "zh";
private readonly Dictionary<string, string> options = new(StringComparer.OrdinalIgnoreCase)
{
{ "zh", "<22><><EFBFBD><EFBFBD>" },
{ "en", "English" }
};
protected override async Task OnInitializedAsync()
{
var current = LocalizationProvider.CurrentCulture;
var mapping = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "zh", "zh-Hans" },
{ "en", "en-US" }
};
var found = mapping.FirstOrDefault(kv => string.Equals(kv.Value, current, StringComparison.OrdinalIgnoreCase)).Key;
if (!string.IsNullOrEmpty(found)) selected = found;
LocalizationProvider.LanguageChanged += (s, c) =>
{
var found2 = mapping.FirstOrDefault(kv => string.Equals(kv.Value, c, StringComparison.OrdinalIgnoreCase)).Key;
if (!string.IsNullOrEmpty(found2)) selected = found2;
StateHasChanged();
};
}
private async Task OnChange(ChangeEventArgs e)
{
if (e?.Value is string val)
{
selected = val;
await LocalizationProvider.SetCultureAsync(selected);
try
{
// Use NavigationManager to inspect and modify the current client-side path
var relative = Navigation.ToBaseRelativePath(Navigation.Uri).Trim('/');
var segments = string.IsNullOrEmpty(relative) ? Array.Empty<string>() : relative.Split('/', StringSplitOptions.RemoveEmptyEntries);
var mapping = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "zh", "zh-Hans" },
{ "en", "en-US" }
};
string newUrl;
if (segments.Length > 0 && mapping.ContainsKey(segments[0]))
{
// replace existing locale prefix
var remaining = segments.Length > 1 ? "/" + string.Join('/', segments.Skip(1)) : "/";
newUrl = "/" + selected + remaining;
}
else
{
// keep current path, but trigger remount by navigating to same URI
newUrl = Navigation.Uri;
}
// trigger client-side navigation (no hard reload) so components remount and re-evaluate localizer
Navigation.NavigateTo(newUrl, forceLoad: false);
return;
}
catch
{
// fallback: just request UI refresh
StateHasChanged();
}
}
}
}