Bonjour à vous,

Aujourd’hui je vous propose de vous expliquer rapidement comment n’avoir qu’un fichier de ressources partagés pour la traduction des data annotations ainsi que la possibilité de l’utiliser dans vos vues razor.

Introduction

Quel intérêt me direz vous?

Dans certains contextes applicatifs notamment de petites applications, cela peut être intéressant pour éviter la duplication de certaines clés ainsi que devoir maintenir une multitude de fichiers de ressources.

Par défaut, le middleware de localisation recherche un fichier de ressources correspondant à la vue. Exemple: Votre vue se nomme Toto.cshtml et votre contrôleur TataController, le fichier de ressources sera par exemple Views.Tata.Toto.fr-FR.resx .

L’idée ici est de voir comment nous pouvons avoir un unique fichier resx pour la data annotations et nos vues.

Voyons comment l’implémentation se  passe.

Implémentation

Pour commencer, au sein de votre projet asp.net, créez une répertoire Resources et créez dedans une classe SharedResources.cs Laissez la classe vide comme ci dessous:

public class SharedResource
{
}

Nous allons également créer notre service de Localisation qui nous permettra d’aller chercher nos valeurs dans notre fichier resx.

Créez une classe LocalizationService avec le code ci dessous:

public class LocalizationService
{
/// <summary> The localizer. </summary>
private readonly IStringLocalizer _localizer;

/// <summary> Constructor. </summary>
///
/// <param name="factory"> The factory. </param>

public LocalizationService(IStringLocalizerFactory factory)
{
var type = typeof(SharedResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create("SharedResource", assemblyName.Name);
}

/// <summary> Gets localized HTML string. </summary>
///
/// <param name="key"> The key. </param>
///
/// <returns> The localized HTML string. </returns>

public LocalizedString GetLocalizedHtmlString(string key)
{
return _localizer[key];
}
}

Ensuite, nous avons besoin de configurer nos services et nos middleware, comme ci dessous:

public void ConfigureServices(IServiceCollection services)
{

services.AddSingleton<LocalizationService>();
services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})

.AddViewLocalization()
.AddDataAnnotationsLocalization(options => options.DataAnnotationLocalizerProvider = (type, factory) =>
{
var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName);
return factory.Create("SharedResource", assemblyName.Name);
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<RequestLocalizationOptions>(
options =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("fr-FR")
};

options.DefaultRequestCulture = new RequestCulture(culture: "fr-FR", uiCulture: "fr-FR");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;

options.RequestCultureProviders.Insert(0, new QueryStringRequestCultureProvider());
});
services.AddLocalization(options => options.ResourcesPath = "Resources");

}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, SeedData seeder)
{

var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);

}

Note: Si vous avez une application qui doit gérer plusieurs langues, n’oubliez pas d’ajouter vos langues dans les SupportedCultures

Une fois cette configuration faites, il suffit de créer votre ou vos fichiers RESX en utilisant la convention de nommage suivante: SharedResource.fr-FR.resx. Remplacez fr-FR par le code langue correspondant à votre contexte.

Le fichier RESX fonctionnement sur un principe de Clé/valeur avec la possibilité d’ajouter un commentaire si vous en avez besoin.

Utilisation

Vue

Dans le cadre de l’utilisation au sein d’une vue, nous avons besoin d’injecter notre LocalizationService afin de pouvoir l’utiliser comme l’exemple ci dessous:

@using MyProject.Localization
@inject LocalizationService SharedLocalizer

// Usage example

@SharedLocalizer.GetLocalizedHtmlString("Name") // Will display "Nom"

// Can be used in taghelper also

Controlleur

Nous allons encore une fois ici notre LocalizationService que nous allons injecter à notre controller comme l’exemple ci dessous:

public class MyController : BaseController

{

private readonly LocalizationService _localizationService;

public MyController(LocalizationService localizationService){

_localizationService = localizationService;

}

public async Task<IActionResult> MyActîon(){

// Usage example

_localizationService.GetLocalizedHtmlString("Name"); // Will return "Nom"

}

}

DataAnnotation

Au sein de vos modéles vous pouvez ajouter l’annotation DisplayName afin de définir un libellé pour vos champs. Pour l’utilisation de la ressource partagée, il suffit de définir en displayName la clé de votre ressource RESX. Exemple: je créé dans mon fichier resx fr-FR une ressource avec la clé: Name et la valeur Nom.

Il suffit donc de définir le displayname comme ci dessous:

[Display(Name = "Name")]

public string Name { get; set; }

 

En espérant que ça puisse vous aider dans votre contexte applicatif, par défaut un resx doit être créé par vues et en activant le middleware il retrouve les ressources automatiquement.

Je vous dit à bientôt pour un autre post et en attendant développez bien 😉