Files

55 lines
2.4 KiB
C#

using System.Globalization;
using System.Resources;
namespace SharepointToolbox.Web.Localization;
/// <summary>
/// String lookup backed by Strings.resx / Strings.fr.resx.
///
/// Registered as Scoped: in Blazor Server each circuit gets its own instance with its own
/// explicit <see cref="Culture"/>. The culture is stored as a field (not read from the
/// ambient <see cref="CultureInfo.CurrentUICulture"/>) because the interactive circuit does
/// NOT inherit the request/middleware culture, and ambient culture does not reliably flow
/// across render batches and SPA navigations. An explicit per-circuit field is deterministic:
/// set it once at circuit start and every page in that circuit renders in the same language.
///
/// The static <see cref="Instance"/> (used by the export services) has no explicit culture and
/// falls back to the ambient culture.
/// </summary>
public class TranslationSource
{
public static readonly TranslationSource Instance = new();
// Construct the ResourceManager with the explicit manifest base name rather
// than Strings.ResourceManager: the generated designer carries a stale base
// name ("SharepointToolbox.Strings") from before the project was renamed to
// *.Web, so its lookups throw MissingManifestResourceException. The embedded
// resource is "SharepointToolbox.Web.Localization.Strings".
private readonly ResourceManager _resourceManager =
new ResourceManager("SharepointToolbox.Web.Localization.Strings", typeof(TranslationSource).Assembly);
private CultureInfo? _culture;
public TranslationSource() { }
/// <summary>Explicit lookup culture. When unset, falls back to the ambient UI culture.</summary>
public CultureInfo Culture
{
get => _culture ?? CultureInfo.CurrentUICulture;
set => _culture = value;
}
public string this[string key] =>
_resourceManager.GetString(key, Culture) ?? $"[{key}]";
/// <summary>Sets this instance's culture from a language code ("fr" → French, else English/invariant).</summary>
public void SetCulture(string lang) => Culture = Resolve(lang);
/// <summary>"fr" → French; anything else → invariant (the base Strings.resx, i.e. English).</summary>
public static CultureInfo Resolve(string lang) => lang switch
{
"fr" => new CultureInfo("fr"),
_ => CultureInfo.InvariantCulture
};
}