CultureService
Descriere Generală
CultureService
este serviciul responsabil pentru gestionarea schimbării culturii/limbii în aplicații Blazor. Serviciul permite setarea culturii atât pe partea de client (prin localStorage), cât și pe partea de server (prin cookie), asigurând o experiență consistentă de localizare în întreaga aplicație.
Configurare
Înregistrare în Dependency Injection
// Client-side (Blazor WebAssembly sau Component)
builder.Services.AddScoped<ICultureService, CultureService>();
// Server-side (ASP.NET Core)
builder.Services.AddScoped<FOD.Components.Server.Services.ICultureService, FOD.Components.Server.Services.CultureService>();
builder.Services.AddHttpContextAccessor();
Configurare Localizare ASP.NET Core
// În Program.cs
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { "ro", "ru", "en" };
options.SetDefaultCulture("ro")
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
});
app.UseRequestLocalization();
Script JavaScript necesar
// Inclus automat în FodComponents.js
window.blazorCulture = {
get: () => window.localStorage["BlazorCulture"],
set: (value) => (window.localStorage["BlazorCulture"] = value),
};
Endpoint server-side
// În ServicesSetup.cs
endpoints.MapGet("api/fod/culture={cultureEscaped}&redirectUri={uriEscaped}",
async (string cultureEscaped, string uriEscaped,
[FromServices] ICultureService cultureService) =>
{
cultureService.SetCultureCookie(cultureEscaped);
uriEscaped = uriEscaped.Replace("%2F", "/");
return Results.Redirect(uriEscaped, permanent: false);
});
Interfețe
Client-side ICultureService
namespace FOD.Components.Services.Culture
{
public interface ICultureService
{
void SetCulture(CultureInfo newCulture);
}
}
Server-side ICultureService
namespace FOD.Components.Server.Services
{
public interface ICultureService
{
void SetCultureCookie(string culture);
}
}
Metode disponibile
Client-side: SetCulture
Setează noua cultură pentru aplicație.
Parametri:
- newCulture: CultureInfo
- Cultura de setat
Comportament: 1. Verifică dacă cultura nouă diferă de cea curentă 2. Setează cultura în localStorage prin JavaScript 3. Navighează la endpoint-ul server pentru setarea cookie-ului 4. Reîncarcă pagina pentru aplicarea schimbărilor
Server-side: SetCultureCookie
Setează cookie-ul de cultură pentru cereri viitoare.
Parametri:
- culture: string
- Codul culturii (ex: "ro", "en", "ru")
Comportament: - Setează cookie-ul standard ASP.NET Core pentru localizare - Cookie-ul va fi folosit de middleware-ul de localizare
Exemple de utilizare
Selector de limbă simplu
@inject ICultureService CultureService
@inject IStringLocalizer<Shared> Localizer
<div class="language-selector">
<FodSelect Value="@currentCulture"
ValueChanged="@OnCultureChanged"
Label="@Localizer["Language"]">
<FodSelectItem Value="ro">Română</FodSelectItem>
<FodSelectItem Value="en">English</FodSelectItem>
<FodSelectItem Value="ru">Русский</FodSelectItem>
</FodSelect>
</div>
@code {
private string currentCulture = CultureInfo.CurrentCulture.Name;
private void OnCultureChanged(string newCulture)
{
var cultureInfo = new CultureInfo(newCulture);
CultureService.SetCulture(cultureInfo);
}
}
Component LanguageSelector dedicat
@inject ICultureService CultureService
@inject NavigationManager Navigation
<div class="language-buttons">
@foreach (var lang in availableLanguages)
{
<FodButton Variant="@(IsCurrentLanguage(lang.Code) ? FodVariant.Filled : FodVariant.Outlined)"
Size="FodSize.Small"
@onclick="() => ChangeLanguage(lang.Code)">
<img src="@lang.FlagUrl" alt="@lang.Name" class="flag-icon" />
@lang.Name
</FodButton>
}
</div>
@code {
private class Language
{
public string Code { get; set; }
public string Name { get; set; }
public string FlagUrl { get; set; }
}
private List<Language> availableLanguages = new()
{
new() { Code = "ro", Name = "RO", FlagUrl = "/images/flags/ro.svg" },
new() { Code = "en", Name = "EN", FlagUrl = "/images/flags/en.svg" },
new() { Code = "ru", Name = "RU", FlagUrl = "/images/flags/ru.svg" }
};
private bool IsCurrentLanguage(string code)
{
return CultureInfo.CurrentCulture.TwoLetterISOLanguageName == code;
}
private void ChangeLanguage(string languageCode)
{
if (!IsCurrentLanguage(languageCode))
{
var newCulture = new CultureInfo(languageCode);
CultureService.SetCulture(newCulture);
}
}
}
Meniu dropdown pentru limbă
@inject ICultureService CultureService
<FodMenu>
<ActivatorContent>
<FodIconButton Icon="translate" />
</ActivatorContent>
<ChildContent>
<FodMenuItem @onclick='() => SetLanguage("ro")'>
<FodIcon Icon="flag" /> Română
</FodMenuItem>
<FodMenuItem @onclick='() => SetLanguage("en")'>
<FodIcon Icon="flag" /> English
</FodMenuItem>
<FodMenuItem @onclick='() => SetLanguage("ru")'>
<FodIcon Icon="flag" /> Русский
</FodMenuItem>
</ChildContent>
</FodMenu>
@code {
private void SetLanguage(string culture)
{
CultureService.SetCulture(new CultureInfo(culture));
}
}
Service extins cu evenimente
public interface IExtendedCultureService : ICultureService
{
event EventHandler<CultureChangedEventArgs> CultureChanged;
CultureInfo CurrentCulture { get; }
IEnumerable<CultureInfo> SupportedCultures { get; }
}
public class ExtendedCultureService : IExtendedCultureService
{
private readonly ICultureService _innerService;
public event EventHandler<CultureChangedEventArgs> CultureChanged;
public CultureInfo CurrentCulture => CultureInfo.CurrentCulture;
public IEnumerable<CultureInfo> SupportedCultures { get; } = new[]
{
new CultureInfo("ro"),
new CultureInfo("en"),
new CultureInfo("ru")
};
public void SetCulture(CultureInfo newCulture)
{
var oldCulture = CurrentCulture;
_innerService.SetCulture(newCulture);
CultureChanged?.Invoke(this, new CultureChangedEventArgs
{
OldCulture = oldCulture,
NewCulture = newCulture
});
}
}
Persistență preferință utilizator
@inject ICultureService CultureService
@inject ILocalStorageService LocalStorage
@implements IAsyncDisposable
@code {
protected override async Task OnInitializedAsync()
{
// Restaurare preferință salvată
var savedCulture = await LocalStorage.GetItemAsync<string>("UserPreferredCulture");
if (!string.IsNullOrEmpty(savedCulture))
{
var culture = new CultureInfo(savedCulture);
if (culture.Name != CultureInfo.CurrentCulture.Name)
{
CultureService.SetCulture(culture);
}
}
}
private async Task SaveCulturePreference(string culture)
{
await LocalStorage.SetItemAsync("UserPreferredCulture", culture);
CultureService.SetCulture(new CultureInfo(culture));
}
public async ValueTask DisposeAsync()
{
// Cleanup if needed
}
}
Integrare cu componente FOD
Cu FodHeader
<FodHeader>
<ToolbarContent>
<FodSpacer />
<LanguageSelector />
<FodIconButton Icon="account_circle" />
</ToolbarContent>
</FodHeader>
Cu formulare multilingve
@inject IStringLocalizer<MyForm> Localizer
@inject ICultureService CultureService
<EditForm Model="@model" OnValidSubmit="@HandleSubmit">
<FodInput @bind-Value="model.Name"
Label="@Localizer["NameLabel"]"
HelperText="@Localizer["NameHelper"]" />
<FodSelect @bind-Value="model.Country"
Label="@Localizer["CountryLabel"]">
@foreach (var country in GetLocalizedCountries())
{
<FodSelectItem Value="@country.Code">
@country.Name
</FodSelectItem>
}
</FodSelect>
</EditForm>
Tratare erori
Service cu logging
public class LoggingCultureService : ICultureService
{
private readonly ICultureService _innerService;
private readonly ILogger<LoggingCultureService> _logger;
public void SetCulture(CultureInfo newCulture)
{
_logger.LogInformation("Changing culture from {OldCulture} to {NewCulture}",
CultureInfo.CurrentCulture.Name, newCulture.Name);
try
{
_innerService.SetCulture(newCulture);
_logger.LogInformation("Culture changed successfully to {Culture}",
newCulture.Name);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to change culture to {Culture}",
newCulture.Name);
throw;
}
}
}
Note tehnice
- Page reload - Schimbarea culturii necesită reîncărcarea paginii
- Cookie persistence - Cookie-ul de cultură persistă între sesiuni
- LocalStorage sync - Cultura client-side este salvată în localStorage
- Thread safety - Cultura este thread-safe în ASP.NET Core
- Blazor limitation - În Blazor WebAssembly, cultura trebuie setată la startup
Bune practici
- Default culture - Setați întotdeauna o cultură implicită
- Supported cultures - Definiți explicit culturile suportate
- Resource files - Organizați fișierele de resurse pe culturi
- Date formats - Testați formatarea datelor în toate culturile
- URL preservation - Păstrați URL-ul curent la schimbarea limbii
- User preference - Salvați preferința utilizatorului
- Graceful fallback - Gestionați culturi nesuportate
Concluzie
CultureService oferă o soluție completă pentru gestionarea multilingvismului în aplicații Blazor, integrând atât aspecte client-side cât și server-side. Cu suport pentru persistență și navigare fluidă, serviciul facilitează crearea de aplicații cu adevărat internaționale.