Lokalisierungsgrenze und Quellgenerator

PowerPortalsPro holt jeden von Dataverse Metadata abgeleiteten String, den eine Route benötigt, vor dem ersten Paint der Route, sodass Nutzer nie den kurzen Rückfall-Key-Text sehen, den On-Demand-Lokalisierungsbibliotheken normalerweise erzeugen. Der Mechanismus besteht aus drei Hälften – einem statischen Standardbundle , das einmal pro Sitzung geladen wird und Framework + App-Strings (alles außerhalb tables.* / choices.*abdeckt), einen Build-Time-Quellcode-Generator, der ein Manifest pro Komponente der Tabelle und View-Tokens ausgibt, die jede Komponente benötigt, sowie eine Laufzeitkomponente LocalizationBoundary , die die Routenansicht umwickelt und parallele Pro-Ressourcen-Bundle-Abrufe verteilt, bevor die Route rendert.

Die LocalizationBoundary-Komponente

LocalizationBoundary wickelt AuthorizeRouteView (oder RouteView) in Routes.razor. Bei jeder Navigation liest es das quellgenerierte LocalizationManifest statische Feld des aktuellen Seitentyps, vereint die Token mit beliebigen BaselinePrefixes Consumer-Konfigurationen, ruft IAsyncStringLocalizer.EnsurePrefixesLoadedAsync die kombinierte Tokenliste auf und hält die Kinder vom Rendern ab, bis jedes Ressourcenpaket abgerufen und in den Cache eingegliedert wurde. Während das Abholen im Flug ist, bedeckt ein durchscheinendes Overlay mit einem Spinner das Sichtfenster, sodass der abgestandene Text der vorherigen Seite nicht sichtbar ist.

Baseline-Token

Die meisten Apps müssen überhaupt nicht gesetzt BaselinePrefixes werden – der Quellgenerator erkennt die Route pro Route Tabelle und sieht automatisch Token aus deinem Komponentencode an. Verwende es nur für app-bekannte tables.{name} / views.{viewId} Tokens, die nicht statisch erkennbar sind (z. B. eine Layout-Komponente, die immer einen Account Picker rendert, bei der die Tabelle implizit ist, aber kein TableName="account" Attribut im Markup erscheint, das der Generator scannt). Andere Token-Formen werden während der Laufzeit stillschweigend verworfen – die eigenen Komponentenstrings des Frameworks werden im statischen Standardpaket ausgeliefert, daher ist Passing components.PowerPortalsPro.* or app.* Here ein No-Op.

Verkabeln

Die Starter-Vorlage konfiguriert LocalizationBoundary sich für dich. Wenn du es manuell integrierst, platziere es im Wrapping Routes.razor der Routenansicht, so:

React
Blazor

Der Quellgenerator und das Manifest

Das PowerPortalsPro.Localization NuGet-Paket liefert einen Roslyn-Quellcode-Generator, der alle und Code-Behind *.razor im konsumierenden Projekt zur Build-Zeit scannt. Für jede Komponente (alles, was erbt ComponentBase) emittiert sie eine partielle Klassenerweiterung, die einen public static readonly LocalizationKeyManifest LocalizationManifest Körper trägt. Das Manifest enthält die transitive Menge von tables.{name} und views.{viewId} Tokens, die die Komponente (und jedes statisch deklarierte Kind, das sie rendert) zur Laufzeit anfordert – jeder Token löst sich auf eine pro-Ressourcen-Bundle-URL auf, in der die Grenze vor dem ersten Malen parallel abruft. Strings außerhalb des tables.* / choices.* Teilbaums (app.*, components.*) stammen vom statischen Standardbündel und werden absichtlich aus dem Manifest ausgeschlossen.

Was der Generator erkennt

Der Scanner erkennt die gängigen Muster automatisch – keine Anmerkungen erforderlich:

Inspektion eines Manifests

Das generierte LocalizationManifest Feld ist ein gewöhnliches öffentliches statisches Feld – du kannst es aus jedem C#-Code überprüfen oder in deinem Debugger erweitern. Tokens sind deterministisch sortiert, damit inkrementelle Builds die generierte Datei nicht umkrempeln.

React
Blazor

On-Demand-Fallback

Alles, was der Generator zur Kompilierungszeit nicht auflösen kann – Schlüssel, die aus Laufzeitausdrücken zusammengesetzt sind, Referenzen, new Guid(SomeQualifiedConst) die eine Projekt-Referenz-Grenze überschreiten usw. – fällt in den On-Demand-Pfad des Lokalizers. Ein Cache-Miss auf einem tables.X.… oder tables.X.views.Y.… Schlüssel wird in den besitzenden Bundle-Token gezwungen, in die Warteschlange gestellt, kurz entbounced und im Hintergrund abgerufen; LocalizationBoundary der Nachfolge-Teilbaum wird nach Abruf wieder eingebunden, sodass veralteter Fallback-Text automatisch korrigiert wird. Fehler bei anderen Tastenformen (app.*, components.*) werden ignoriert – das statische Standardbündel hatte seine Chance, also bedeutet ein Fehler, dass der Schlüssel tatsächlich nicht existiert.

Benutzerdefinierte Ansichten, die in JSON definiert sind

Benutzerdefinierte Ansichten, die Sie in einer Lokalisierungs-JSON-Datei ausliefern (z. B. app.en.json) – typischerweise Grid-Ansichten mit einem handverlesenen GUID, clientseitig CustomViewDefinitions auf einem Raster definiert – werden vom Per-View-Bundle-Endpunkt automatisch aufgenommen. Der Bundle-Service leitet die Besitztabelle aus der Schlüsselform (tables.{owningTable}.views.{viewId}.…) ab und nicht aus der reinen savedquery Metadaten-Karte, sodass eine Ansicht, die in Dataverse nicht existiert, weiterhin über das Manifest ausgeliefert wird. Schlüssel werden unbeschreibungssensitiv abgeglichen: Eine JSON-Datei mit "28299C6F-EBC0-4206-9E11-A373D4C9891F" (Großbuchstaben, die natürliche Art, ein GUID-Literal zu erstellen) löst sich korrekt auf, wenn der Quellgenerator aus deinem Code sendet views.28299c6f-ebc0-4206-9e11-a373d4c9891f .

Anmerkung

Referenz PowerPortalsPro.Localization aus jedem Projekt, das Blazor-Komponenten hostet. Das Paket liefert sowohl die Laufzeittypen (IStringLocalizer, IAsyncStringLocalizer, , LocalizationKeyManifest) LocalizationBoundaryals auch den Quellgenerator als Analysator-Asset – die Verbraucher erhalten beim nächsten Build automatisch manifeste Emission ohne zusätzliche Konfiguration.

Reagieren Blazor

LocalizationBoundary Baureihe

Parameter

Name
Typ
Default
Beschreibung
BaselinePrefixesIEnumerable<string>?
Zusätzliche Tabellen.* / Choice.* Präfixe/Schlüssel zum Vorabladen auf jeder Navigation – typischerweise weiß eine App, dass sie sie immer benötigt – Dataverse-Metadaten-Baselines (z. B. tables.account , wenn jede Route einen Account Picker zeigt). Sonstiges Präfix Formen werden durch die Laufzeit weggelassen, da das statische Bündel sie bereits bedeckt. Bereits geladene Präfixe werden pro Sitzung zwischengespeichert und nicht erneut abgerufen.
ChildContentRenderFragment?
Der Routen-Inhalt wird gerendert, sobald die Lokalisierungen bereit sind. Normalerweise ist ein AuthorizeRouteView.
RouteDataRouteData?
Die aktuelle Route ist LocalizationBoundary.RouteData. Das abgeleitete Präfix ist Komponenten. {RouteData.PageType.FullName}.
Name: BaselinePrefixes
Typ: IEnumerable<string>?
Beschreibung: Zusätzliche Tabellen.* / Choice.* Präfixe/Schlüssel zum Vorabladen auf jeder Navigation – typischerweise weiß eine App, dass sie sie immer benötigt – Dataverse-Metadaten-Baselines (z. B. tables.account , wenn jede Route einen Account Picker zeigt). Sonstiges Präfix Formen werden durch die Laufzeit weggelassen, da das statische Bündel sie bereits bedeckt. Bereits geladene Präfixe werden pro Sitzung zwischengespeichert und nicht erneut abgerufen.
Name: ChildContent
Typ: RenderFragment?
Beschreibung: Der Routen-Inhalt wird gerendert, sobald die Lokalisierungen bereit sind. Normalerweise ist ein AuthorizeRouteView.
Name: RouteData
Typ: RouteData?
Beschreibung: Die aktuelle Route ist LocalizationBoundary.RouteData. Das abgeleitete Präfix ist Komponenten. {RouteData.PageType.FullName}.