Generador de Fronteras y Fuentes de Localización
PowerPortalsPro recupera previamente todas las cadenas derivadas de metadatos de Dataverse que una ruta necesitará antes de la primera pintura de la ruta, por lo que los usuarios nunca ven el breve destello de texto clave de respaldo que normalmente producen las bibliotecas de localización bajo demanda. El mecanismo tiene tres mitades: un bundle por defecto estático cargado una vez por sesión que cubre las cadenas de framework + app (todo lo que está fuera tables.* de / choices.*), un generador de fuentes en tiempo de compilación que emite un manifiesto por componente de los tokens de tabla y vista que cada componente necesita, y un componente de runtime LocalizationBoundary que envuelve la vista de ruta y distribuye recopilaciones paralelas por bundle por recurso antes de permitir que la ruta se renderice.
El componente de frontera de localización
LocalizationBoundary envuelve AuthorizeRouteView (o RouteView) dentro Routes.razorde . En cada navegación lee el campo estático generado LocalizationManifest por la fuente del tipo de página actual, une los tokens con cualquiera BaselinePrefixes que configure el consumidor, solicita IAsyncStringLocalizer.EnsurePrefixesLoadedAsync la lista combinada de tokens y detiene a los hijos para que se rendericen hasta que todos los paquetes por recurso hayan sido recuperados y fusionados en la caché. Mientras el recado está en vuelo, una superposición translúcida con un spinner cubre la ventana de visualización, de modo que el texto rancio de la página anterior no es visible.
Tokens de referencia
La mayoría de las apps no necesitan configurarse BaselinePrefixes en absoluto: el generador de código fuente detecta automáticamente la tabla por ruta y visualiza los tokens de tu código de componente. Úsalo solo para tokens conocidos tables.{name} views.{viewId} por la app que no sean detectables estáticamente (por ejemplo, un componente de layout que siempre renderiza un selector de cuentas, donde la tabla es implícita pero no aparece ningún TableName="account" atributo en el marcado que escanea el generador). Otras formas de token se descartan silenciosamente por el tiempo de ejecución — las propias cadenas de componentes del framework se envían en el paquete estático por defecto, así que pasar components.PowerPortalsPro.* o app.* aquí es un no-op.
Cableándolo
La plantilla de inicio se LocalizationBoundary configura para ti. Si lo estás integrando manualmente, colócalo dentro Routes.razor de la vista de ruta, así:
// <LocalizationBoundary> envuelve el contenido por ruta y se espera</LocalizationBoundary>
// renderizando hasta que los paquetes declarados de cada página se hayan estabilizado. Hereda
// las declaraciones prefijo de las llamadas descendentes a useLocalization() y
// del 'prefijo' prop en el padre <PowerPortalsProProvider> (set</PowerPortalsProProvider>
// Ahí hay tablas que abarcan toda la app y que Chrome toca en cada página).
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>El Generador de Fuentes y el Manifiesto
El PowerPortalsPro.Localization paquete NuGet incluye un generador de código fuente Roslyn que escanea cada *.razor código detrás del proyecto que consume en momento de compilación. Para cada componente (cualquier cosa heredadora ComponentBase) emite una extensión de clase parcial que lleva un public static readonly LocalizationKeyManifest LocalizationManifest campo. El manifiesto contiene el conjunto transitivo de tables.{name} y views.{viewId} los tokens que el componente (y cada hijo declarado estáticamente que renderiza) solicita en tiempo de ejecución — cada token se resuelve a una URL por paquete de recursos que el límite recupera en paralelo antes de la primera pintura. Las cadenas fuera del tables.* subárbol / choices.* (app.*, components.*) provienen del fibrado por defecto estático y se excluyen deliberadamente del manifiesto.
Lo que detecta el generador
El escáner detecta automáticamente los patrones comunes — no se requieren anotaciones:
_localizer["tables.foo.…"]Los accesos indexadores se obligan a entrar en el token propietariotables.foo;_localizer["tables.foo.views.{guid}.…"]los accesos se convierten en tokenviews.{guid}.@inject IStringLocalizer<T>En un archivo Razor, el generador rastrea a qué campos está vinculado el localizador, así que los accesos indexadores en esos campos contribuyen correctamente con sus tokens.GetPrefixedLocalizer("tables.foo")las llamadas tienen su prefijo forzado a entrar en la tabla o token de vista correspondiente.DefaultViewId/ViewId/ViewIdsLos atributos en los componentes de la red emitenviews.{guid}tokens — el servidor resuelve la tabla propietaria desde el id en el momento de la solicitud, por lo que el manifiesto no necesita saberlo.TableName="name"Los atributos en los componentes de la cuadrícula/registro emiten untables.{name}token. El conjunto por tabla correspondiente devuelve nombres de visualización, metadatos de columnas, las vistas de la tabla (y sus sobrescrituras de columnas) y cualquier elección global de conjunto de opciones que referencian las columnas de la tabla — todo lo que la página podría necesitar para esa tabla en una sola búsqueda.- Las etiquetas directas de componentes hijos Y
@typeof(SomeComponent)las referencias en valores de atributos atraen el manifiesto del hijo al conjunto transitivo del padre, por lo que una página que aloja componentes dinámicos sigue pre-trayendo sus tokens.
Inspección de un manifiesto
El campo generado LocalizationManifest es una estática pública ordinaria — puedes inspeccionarlo desde cualquier código C# o expandirlo en tu depurador. Los tokens están ordenados de forma determinista para que las construcciones incrementales no abandonen el archivo generado.
// React no tiene un manifiesto en tiempo de compilación — declara prefijos por página
// imperativamente a través de useLocalization(). El gancho coloca las fichas en cola
// la misma tubería de recolección rebotada de la que lee LocalizationBoundary,
// Así que una página que los declara no mostrará claves en RAW al navegar por ellas.
import { useLocalization } from '@powerportalspro/react';
function Dashboard() {
useLocalization([
'tables.opportunity',
'views.a1b2c3d4-e5f6-4789-abcd-112233445566',
]);
// ... contenido de la página ...
}// Generado por PowerPortalsPro.Localization.SourceGenerators
public partial class Dashboard
{
public static readonly LocalizationKeyManifest LocalizationManifest =
new LocalizationKeyManifest(
"tables.opportunity",
"views.a1b2c3d4-e5f6-4789-abcd-112233445566"
);
}Respaldo bajo demanda
Cualquier cosa que el generador no pueda resolver en tiempo de compilación — claves construidas a partir de expresiones en tiempo de ejecución, new Guid(SomeQualifiedConst) referencias que crucen el límite de referencia del proyecto, etc. — cae en la ruta bajo demanda del localizador. Un error de caché en una tables.X.… clave o tables.X.views.Y.… se obliga a entrar en el token del paquete propietario, se pone en cola, se debota brevemente y se recupera en segundo plano; LocalizationBoundary se vuelve a montar el subárbol descendente una vez que se completa el fetch para que el texto de respaldo obsoleto se corrija automáticamente. Se ignoran los fallos en otras formas de clave (app.*, components.*) — el paquete por defecto estático ha tenido su oportunidad, así que un error significa que la clave realmente no existe.
Vistas personalizadas definidas en JSON
Las vistas personalizadas que envias en un archivo JSON de localización (por ejemplo app.en.json) — normalmente vistas de cuadrícula con un GUID seleccionado a mano, definido en el lado del cliente mediante CustomViewDefinitions una cuadrícula — son recogidas automáticamente por el endpoint del paquete por vista. El servicio de bundle deriva la tabla propietaria de la forma clave (tables.{owningTable}.views.{viewId}.…) en lugar del mapa solo savedquery de metadatos, por lo que una vista que no existe en Dataverse sigue enviándose a través del manifiesto. Las claves se emparejan de forma insensible a mayúsculas: un archivo JSON con "28299C6F-EBC0-4206-9E11-A373D4C9891F" (mayúsculas, la forma natural de crear un literal GUID) se resuelve correctamente cuando el generador fuente emite views.28299c6f-ebc0-4206-9e11-a373d4c9891f tu código.
Nota
Referencia
PowerPortalsPro.Localizationde cualquier proyecto que aloje componentes de Blazor. El paquete envía tanto los tipos de ejecución (IStringLocalizer,IAsyncStringLocalizer,LocalizationKeyManifest,LocalizationBoundary) como el generador de código fuente como un activo analizador: los consumidores obtienen emisión de manifiesto automáticamente en la siguiente compilación sin ninguna configuración adicional.
LocalizationBoundary Clase
Parámetros
Nombre | Tipo | Default | Descripción |
|---|---|---|---|
BaselinePrefixes | IEnumerable<string>? | ||
ChildContent | RenderFragment? | El contenido de la ruta debe renderizar una vez que las localizaciones estén listas. Normalmente un | |
RouteData | RouteData? | La ruta actual es LocalizationBoundary.RouteData. El prefijo derivado es |
BaselinePrefixesChildContentRouteDataLocalizationBoundary.RouteData. El prefijo derivado es 