Der Artikel „Mehrsprachigkeit in ASP.NET Core“, der für diesen Blog als Grundlage dient, befasst sich mit der Implementierung von Mehrsprachigkeit in einer ASP.NET Core Anwendung. In diesem Artikel soll die Implementierung in einer separaten Assembly aufgezeigt werden.
Im vorangegangenen Beispiel befinden sich die Ressourcendateien in der gleichen Assembly wie die Web-Anwendung. Bei größeren Projekten ist es jedoch hilfreich, die Ressourcen in eine separate Assembly auszulagern.
Zunächst wird das vorhandene Projekt aus dem Artikel „Mehrsprachigkeit in ASP.NET Core“ in 3 Projekte aufgeteilt: Web, Models und Ressourcen.
Das aktuelle Projekt erhält die Benennung Mehrsprachigkeit.Web. Die beiden neuen Projekte heißen entsprechend Mehrsprachigkeit.Models und Mehrsprachigkeit.Resources.
Der Models-Ordner wird in das neue Projekt Mehrsprachigkeit.Models und der Ressourcen-Ordner in das Projekt Mehrsprachigkeit.Resources verschoben. Für jede Ressource legen wir eine gleichnamige Public-Klasse an. Bereits beim Entwurf einer Anwendung sollte demnach gut überlegt sein, inwiefern einheitliche oder verschiedene Ressourcendateien eingepflegt werden sollen. Die Ressource „Contact“ wurde in „Models“ umbenannt und auf die oberste Ebene im Ressourcenordner verschoben.
Anschließend wird im Projekt „Resources“ folgende Klasse hinzugefügt:
1public class LocService<T>
2{
3 private readonly IStringLocalizer _localizer;
4
5 public LocService(IStringLocalizerFactory factory)
6 {
7 Type type = typeof(T);
8 var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
9
10 var myRelativePath = String.Join(".", type.Namespace.Split('.').Skip(2));
11 if (myRelativePath.Length > 0)
12 myRelativePath += ".";
13
14 _localizer = factory.Create(myRelativePath + type.Name, assemblyName.Name);
15 }
16
17 public LocalizedString GetLocalizedHtmlString(string key)
18 {
19 if (_localizer != null)
20 return _localizer[key];
21 else
22 return new LocalizedString(key, key);
23 }
24}
Diese Klasse wird im Controller und in der View verwendet, um anschließend die richtige Assembly und die richtige Ressource auszuwählen.
Wenn mit der Methode ConfigureServices
aus der Klasse Startup.cs
gearbeitet wird, müssen folgende Änderungen vorgenommen werden, damit die Ressourcen ebenfalls in der anderen Assembly gefunden werden können.
1public void ConfigureServices(IServiceCollection services)
2{
3 services.AddSingleton<LocService<Mehrsprachigkeit.Resources.Resources.Views.Home.Index>>();
4 services.AddSingleton<LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController>>();
5
6 services.AddControllersWithViews();
7 services.AddLocalization();
8 services.AddMvc()
9 .AddViewLocalization()
10 .AddDataAnnotationsLocalization(options =>
11 {
12 options.DataAnnotationLocalizerProvider = (type, factory) =>
13 {
14 var assemblyName = new AssemblyName(
15 typeof(Mehrsprachigkeit.Resources.Resources.Models)
16 .GetTypeInfo().Assembly.FullName);
17 return factory.Create("Resources.Models", assemblyName.Name);
18 };
19 });
20
21 services.Configure<RequestLocalizationOptions>(opts =>
22 {
23 var supportedCultures = new List<CultureInfo> {
24 new CultureInfo("de-DE"),
25 new CultureInfo("en-GB"),
26 };
27
28 opts.DefaultRequestCulture = new RequestCulture("de-DE");
29 opts.SupportedCultures = supportedCultures;
30 opts.SupportedUICultures = supportedCultures;
31 });
32}
Nun fügt man die LocService
-Klasse per Dependency Injection im HomeController und in der Index View hinzu und ändert den Aufruf der StringLocalizer
-Klasse mit der neuen Methode GetLocalizedHtmlString
.
1public class HomeController : Controller
2{
3 private readonly LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController> _localizer;
4
5 public HomeController(LocService<Mehrsprachigkeit.Resources.Resources.Controllers.HomeController> localizer)
6 {
7 _localizer = localizer;
8 }
9
10 public IActionResult Index()
11 {
12 ViewData["Title"] = _localizer.GetLocalizedHtmlString("Hallo Welt vom Controller");
13 return View();
14 }
15}
16@using Microsoft.AspNetCore.Mvc.Localization
17@model Mehrsprachigkeit.Models.Models.Contact
18
19@inject Mehrsprachigkeit.Resources.LocService<Mehrsprachigkeit.Resources.Resources.Views.Home.Index> AccountLocalizer
20
21<h1>@ViewData["Title"]</h1>
22<h3 class="text-danger">@AccountLocalizer.GetLocalizedHtmlString("Hallo Welt von der View")</h3>
23
24@Html.LabelFor(c => c.Firstname)
25@Html.LabelFor(c => c.Lastname)
Nun wurden die Ressourcen erfolgreich in eine andere Assembly verschoben und der Aufruf der Lokalisierung entsprechend angepasst, sodass die Ressourcen in der anderen Assembly gefunden werden können.
Die Mehrsprachigkeit in einem Projekt ohne verschiedene Assemblys ist relativ einfach zu realisieren. Sobald die Ressourcen jedoch in einer separaten Assembly programmiert werden sollen, erhöht sich die Komplexität deutlich. Wichtig ist hierbei, von Beginn an strategisch zu entscheiden, ob für jedes DataModel eine eigene Ressource angelegt werden soll oder ob eine einheitliche Ressource verwendet wird. Letzteres ist einfacher umzusetzen und wurde in diesem Blogartikel angewendet.
LocService
ist eine separate Assembly vermutlich nicht umsetzbar.