ASP.NET Core : Mise en cache des traductions au démarrage

Les traductions en ASP.NET Core sont chargées en cache lors de la première sollicitation. Cela augmente le temps de réponse pour la première requête, déjà conséquent en ASP.NET Core. Pour améliorer les performances, il est possible de charger les traductions au démarrage du site.

Barrage au Lac du Verdon
Barrage au Lac du Verdon

Les providers de localisation (du moins ceux fournit par Microsoft) met en cache les traductions lues. Donc pour mettre en cache l'ensemble des traductions, il faut forcer la lecture de toutes les traductions. À cette fin, on peut écrire une méthode d'extension qui va lire toutes les traductions dans les langues spécifiées :

public static void LoadTranslation(
    this IStringLocalizerFactory localizerFactory,
    IEnumerable<Type> types,
    IEnumerable<CultureInfo> cultures)
{
    Task.Run(() =>
    {
        foreach (var type in types)
        {
            var localizer = localizerFactory.Create(type);
            foreach (var culture in cultures)
            {
                CultureInfo.CurrentUICulture = culture;
                _ = localizer.GetAllStrings().ToList();
            }
        }
    });
}

La logique est encapsulée dans une tâche pour charger les traductions en asynchrone et ainsi ne pas ralentir le démarrage de l'application. Autre avantage, la modification de la culture courante se limite au contexte de la tâche et n'impactera pas le fonctionnement de l'application. Du moins en .NET Core et .NET Framework à partir de 4.6, pour les versions antérieures il sera nécessaire de restaurer la culture courante.

Ensuite, il suffit d'appeler cette méthode au démarrage du site. La méthode Configure de la classe Startup est approprié à ce besoin. Elle est appelée au démarrage du site avec la résolution des services pour ces paramètres.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IStringLocalizerFactory localizerFactory)
{
    var translationTypes = new Type[]
    {
        typeof(Trad),
        typeof(AboutController),
        typeof(HelloController)
    };
    var translationCultures = new CultureInfo[]
    {
        new CultureInfo("en"),
        new CultureInfo("en-US"),
        new CultureInfo("fr"),
        new CultureInfo("es")
    };
    localizerFactory.LoadTranslation(translationTypes, translationCultures);
    ...
}

Ce n'est pas la charge, mais l'excès de charge qui tue la bête.