feat(i18n): persist Bokmal preference globally

This commit is contained in:
cesnimda
2026-08-28 12:44:02 +02:00
parent b6dcc7c760
commit 5805c1a621
21 changed files with 359 additions and 66 deletions
+30 -1
View File
@@ -96,6 +96,7 @@ public sealed class AuthController : ControllerBase
{
public string AppVersion { get; init; } = "unknown";
public string? AppCommitSha { get; init; }
public string UiLanguage { get; init; } = "en";
}
public sealed record PendingEmailChangeResult(string? PendingEmail, DateTimeOffset? RequestedAtUtc);
private const int MaxAvatarBytes = 1_000_000;
@@ -539,6 +540,21 @@ public sealed class AuthController : ControllerBase
return NoContent();
}
public sealed record UpdateLanguagePreferenceRequest(string? Language);
[HttpPut("preferences/language")]
[Authorize(AuthenticationSchemes = "local")]
public async Task<IActionResult> UpdateLanguagePreference([FromBody] UpdateLanguagePreferenceRequest request)
{
var user = await _users.GetUserAsync(User);
if (user is null) return Unauthorized();
var language = NormalizeUiLanguage(request?.Language);
if (language is null) return BadRequest("Supported languages are en and nb-NO.");
user.UiLanguage = language;
var result = await _users.UpdateAsync(user);
return result.Succeeded ? NoContent() : BadRequest(string.Join("; ", result.Errors.Select(error => error.Description)));
}
public sealed record RequestEmailChangeRequest(string Email, string CurrentPassword);
public sealed record ConfirmEmailChangeRequest(string UserId, string Email, string Token);
public sealed record CancelEmailChangeRequest(string CurrentPassword);
@@ -1200,7 +1216,20 @@ public sealed class AuthController : ControllerBase
MicrosoftLink: new MicrosoftLinkDto(
Linked: !string.IsNullOrWhiteSpace(user.MicrosoftTenantId) && !string.IsNullOrWhiteSpace(user.MicrosoftObjectId),
Email: user.MicrosoftEmail,
LinkedAt: user.MicrosoftLinkedAt));
LinkedAt: user.MicrosoftLinkedAt))
{
UiLanguage = NormalizeUiLanguage(user.UiLanguage) ?? "en",
};
}
private static string? NormalizeUiLanguage(string? language)
{
var value = language?.Trim();
if (string.Equals(value, "en", StringComparison.OrdinalIgnoreCase)) return "en";
if (string.Equals(value, "nb", StringComparison.OrdinalIgnoreCase)
|| string.Equals(value, "nb-NO", StringComparison.OrdinalIgnoreCase)
|| string.Equals(value, "no", StringComparison.OrdinalIgnoreCase)) return "nb-NO";
return null;
}
private MeResult WithBuildMetadata(MeResult result, bool include)