Générateur de frontière et source de localisation
PowerPortalsPro pré-recherche toutes les chaînes dérivées des métadonnées Dataverse dont une route aura besoin avant la première peinture de la route, de sorte que les utilisateurs ne voient jamais le bref flash de texte clé de secours que produisent normalement les bibliothèques de localisation à la demande. Le mécanisme comporte trois moitiés — un bundle statique par défaut chargé une fois par session qui couvre les chaînes framework + application (tout ce qui est en dehors tables.* de / choices.*), un générateur de source en temps de construction qui émet un manifeste par composant des tokens table et view dont chaque composant a besoin, et un composant d’exécution LocalizationBoundary qui enveloppe la vue de route et étale des récupérations parallèles par bundle par ressource avant de laisser le routage être rendu en détail.
La composante Frontière de Localisation
LocalizationBoundary enroule AuthorizeRouteView (ou RouteView) à l’intérieur Routes.razor. À chaque navigation, il lit le champ statique généré LocalizationManifest par la source du type de page actuel, relie les jetons à ceux BaselinePrefixes configurés par le consommateur, appelle IAsyncStringLocalizer.EnsurePrefixesLoadedAsync la liste combinée des jetons et retarde le rendu des enfants jusqu’à ce que chaque bundle par ressource soit récupéré et fusionné dans le cache. Pendant que la récupération est en vol, une superposition translucide avec un spinner recouvre la fenêtre de vue, de sorte que le texte obsolète de la page précédente n’est pas visible.
Jetons de base
La plupart des applications n’ont pas besoin de configurer BaselinePrefixes — le générateur source détecte automatiquement la table par itinéraire et affiche automatiquement les jetons de votre code composant. Utilisez-le uniquement pour les jetons connus tables.{name} views.{viewId} / app-known qui ne sont pas détectables statiquement (par exemple, un composant de layout qui affiche toujours un sélecteur de compte, où la table est implicite mais aucun TableName="account" attribut n’apparaît dans le balisage scanné par le générateur). D’autres formes de jetons sont supprimées silencieusement par l’exécution — les chaînes de composants propres au framework sont livrées dans le bundle statique par défaut, donc passer components.PowerPortalsPro.* ou app.* ici est une op.
Le câblage
Le modèle de démarrage se LocalizationBoundary configure pour vous. Si vous l’intégrez manuellement, placez-le à l’intérieur Routes.razor de la vue de route, comme ceci :
// <LocalizationBoundary> enroule le contenu par route et retarde</LocalizationBoundary>
// rendu jusqu’à ce que les paquets déclarés de chaque page soient stabilisés. Elle hérite
// les déclarations de préfixe issues des appels descendants useLocalization() et
// à partir du prop « préfixes » sur le parent <PowerPortalsProProvider> (set</PowerPortalsProProvider>
// il y a des tableaux à l’échelle de l’application que Chrome touche à chaque page).
import { LocalizationBoundary } from '@powerportalspro/react-fluent';
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<LocalizationBoundary>
<Outlet />
</LocalizationBoundary>
);
}@using PowerPortalsPro.Web.Blazor.FluentUI.Components
<Router AppAssembly="typeof(MyApp.RouteUrls).Assembly">
<Found Context="routeData">
<LocalizationBoundary RouteData="routeData">
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)" />
</LocalizationBoundary>
</Found>
</Router>Le Générateur de Source et le Manifeste
Le PowerPortalsPro.Localization package NuGet inclut un générateur de source Roslyn qui analyse chaque *.razor code et code derrière le projet en cours de compilation. Pour chaque composante (tout ce qui héritière ComponentBase), elle émet une extension de classe partielle portant un public static readonly LocalizationKeyManifest LocalizationManifest champ. Le manifeste contient l’ensemble transitif et tables.{name} views.{viewId} les jetons que le composant (et chaque enfant déclaré statiquement qu’il rend) demande à l’exécution — chaque jeton se résout à une URL par bundle de ressource que la frontière récupère en parallèle avant la première peinture. Les chaînes en dehors du tables.* sous-arbre / choices.* (app.*, components.*) proviennent du fibré statique par défaut et sont délibérément exclues du manifeste.
Ce que détecte le générateur
Le scanner capte automatiquement les motifs courants — aucune annotation requise :
_localizer["tables.foo.…"]Les accès indexeurs sont contraints à entrer dans le jeton propriétairetables.foo;_localizer["tables.foo.views.{guid}.…"]les accès deviennent unviews.{guid}jeton.@inject IStringLocalizer<T>Sur un fichier Razor, le générateur suit les champs auxquels le localisateur est lié afin que les accès indexeurs sur ces champs contribuent correctement à leurs jetons.GetPrefixedLocalizer("tables.foo")les appels ont leur préfixe forcé à entrer dans la table ou le jeton de vue correspondant.DefaultViewId/ViewId/ViewIdsLes attributs sur les composants de la grille émettentviews.{guid}des jetons — le serveur résout la table propriétaire depuis l’identifiant au moment de la requête, donc le manifeste n’a pas besoin de le connaître.TableName="name"Les attributs sur les composants de grille/enregistrement émettent untables.{name}jeton. Le bundle par table correspondant retourne les noms d’affichage, les métadonnées de colonnes, les vues de la table (et leurs surrogations de colonnes), ainsi que tous les choix globaux d’options auxquels les colonnes de la table font référence — tout ce dont la page pourrait avoir besoin pour cette table en une seule source.- Les balises directes de composantes enfant ET
@typeof(SomeComponent)les références dans les valeurs d’attributs tirent le manifeste de l’enfant dans l’ensemble transitif du parent, donc une page qui héberge des composants dynamiques pré-charge toujours leurs jetons.
Inspection d’un manifeste
Le champ généré LocalizationManifest est une statique publique ordinaire — vous pouvez l’inspecter à partir de n’importe quel code C# ou l’étendre dans votre débogueur. Les jetons sont triés de manière déterministe afin que les builds incrémentaux ne fassent pas revendre le fichier généré.
// React n’a pas de manifeste au moment de la compilation — déclarez les préfixes par page
// impérativement via useLocalization(). Le crochet met les jetons en file d’attente
// le même pipeline de récupération débouncé que le LocalizationBoundary lit,
// Donc une page qui les déclare n’affichera pas les clés brutes lorsqu’on y navigue.
import { useLocalization } from '@powerportalspro/react';
function Dashboard() {
useLocalization([
'tables.opportunity',
'views.a1b2c3d4-e5f6-4789-abcd-112233445566',
]);
// ... contenu de la page ...
}// Généré par PowerPortalsPro.Localization.SourceGenerators
public partial class Dashboard
{
public static readonly LocalizationKeyManifest LocalizationManifest =
new LocalizationKeyManifest(
"tables.opportunity",
"views.a1b2c3d4-e5f6-4789-abcd-112233445566"
);
}Repli à la demande
Tout ce que le générateur ne peut pas résoudre au moment de la compilation — clés construites à partir d’expressions d’exécution, new Guid(SomeQualifiedConst) références franchissant une frontière de référence de projet, etc. — revient sur le chemin à la demande du localisateur. Un échec de cache sur une tables.X.… clé ou tables.X.views.Y.… est contraint dans le jeton bundle propriétaire, mis en file d’attente, brièvement annulé, puis récupéré en arrière-plan ; LocalizationBoundary remonté le sous-arbre descendant une fois la récupération terminée, de sorte que le texte de secours obsolet est automatiquement corrigé. Les manques sur d’autres formes de clés (app.*, components.*) sont ignorées — le bundle statique par défaut a eu sa chance, donc un échec signifie que la clé n’existe en réalité pas.
Vues personnalisées définies en JSON
Les vues personnalisées que vous livrez dans un fichier JSON de localisation (par exemple app.en.json) — généralement des vues en grille avec un GUID choisi à la main, défini côté client via CustomViewDefinitions une grille — sont automatiquement captées par le point d’extrémité du bundle par vue. Le service bundle dérive la table propriétaire de la forme clé (tables.{owningTable}.views.{viewId}.…) plutôt que de la carte uniquement savedquery métadonnées, donc une vue qui n’existe pas dans Dataverse est toujours expédiée via le manifeste. Les clés sont associées sans sensibilité à la casse : un fichier JSON avec "28299C6F-EBC0-4206-9E11-A373D4C9891F" (majuscules, la manière naturelle d’écrire un GUID littéral) se résout correctement lorsque le générateur source émet views.28299c6f-ebc0-4206-9e11-a373d4c9891f à partir de votre code.
Note
Référence
PowerPortalsPro.Localizationde tout projet hébergeant des composants Blazor. Le package expédie à la fois les types d’exécution (IStringLocalizer,IAsyncStringLocalizer,LocalizationKeyManifest,LocalizationBoundary) et le générateur source en tant qu’asset d’analyseur — les consommateurs reçoivent automatiquement l’émission de manifestes lors de la prochaine compilation sans configuration supplémentaire.
LocalizationBoundary Classe
Paramètres
Nom | Type | Par défaut | Description |
|---|---|---|---|
BaselinePrefixes | IEnumerable<string>? | ||
ChildContent | RenderFragment? | Le contenu de la route à rendre une fois les localisations prêtes. Normalement un | |
RouteData | RouteData? | L’itinéraire actuel est LocalizationBoundary.RouteData. Le préfixe dérivé est |
BaselinePrefixesChildContentRouteDataLocalizationBoundary.RouteData. Le préfixe dérivé est 