Mehrsprachigkeit in ASP.NET Core in separater Assembly

Maurice J. | Softwareentwickler
10/2020

Auslagerung von Ressourcen in separate Assemblys

ASP.NET Core als Basis

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.

Projektaufteilung

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.

Klassendefinition

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.

ConfigureServices

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.

Das Ergebnis

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.

Expertentipp: Ohne eine zusätzliche Klasse wie LocService ist eine separate Assembly vermutlich nicht umsetzbar.

Maurice J. | Softwareentwickler
Zurück zur Übersicht

Gemeinsam Großes schaffen

Wir freuen uns auf ein kostenloses Erstgespräch mit Ihnen!
Unser Geschäftsführer Tibor Csizmadia und unser Kundenbetreuer Jens Walter stehen Ihnen persönlich zur Verfügung. Profitieren Sie von unserer langjährigen Erfahrung und erhalten Sie eine kompetente Erstberatung in einem unverbindlichen Austausch.
Foto von Tibor

Tibor Csizmadia

Geschäftsführer
Foto von Jens

Jens Walter

Projektmanager
Devware GmbH verpflichtet sich, Ihre Privatsphäre zu schützen. Wir benötigen Ihre Kontaktinformationen, um Sie bezüglich unserer Produkte und Dienstleistungen zu kontaktieren. Mit Klick auf Absenden geben Sie sich damit einverstanden. Weitere Informationen finden Sie unter Datenschutz.
Vielen Dank für Ihre Nachricht!

Wir haben Ihre Anfrage erhalten und melden uns in Kürze bei Ihnen.

Falls Sie in der Zwischenzeit Fragen haben, können Sie uns jederzeit unter Kontaktanfrage@devware.de erreichen.

Wir freuen uns auf die Zusammenarbeit!
Oops! Something went wrong while submitting the form.
KontaktImpressumDatenschutz