Gerador de Fronteira e Fonte de Localização
O PowerPortalsPro pré-busca todas as strings derivadas de metadados do Dataverse que uma rota precisará antes da primeira pintura da rota, para que os usuários nunca vejam o breve flash de texto de recurso que bibliotecas de localização sob demanda normalmente produzem. O mecanismo possui três metades — um bundle padrão estático carregado uma vez por sessão que cobre as strings framework + app (tudo fora tables.* de / choices.*), um gerador de fonte em tempo de construção que emite um manifesto por componente dos tokens de tabela e view que cada componente precisa, e um componente de runtime LocalizationBoundary que envolve a rota view e espalha coletas paralelas por bundle antes de permitir a renderização da rota.
O Componente Localização Fronteira
LocalizationBoundary envolve AuthorizeRouteView (ou RouteView) dentro Routes.razorde . Em cada navegação, ele lê o campo estático gerado LocalizationManifest pela fonte do tipo de página atual, une os tokens com qualquer BaselinePrefixes configuração do consumidor, chama IAsyncStringLocalizer.EnsurePrefixesLoadedAsync a lista combinada de tokens e adia a renderização dos filhos até que todos os pacotes por recurso sejam buscados e mesclados no cache. Enquanto o fetch está em voo, uma sobreposição translúcida com um spinner cobre a viewport, de modo que o texto velho da página anterior não fica visível.
Tokens de Referência
A maioria dos aplicativos nem precisa configurar BaselinePrefixes — o gerador de código-fonte detecta automaticamente a tabela por rota e visualiza os tokens do seu código de componente. Use-o apenas para tokens conhecidos tables.{name} views.{viewId} / apps que não são detectáveis estaticamente (por exemplo, um componente layout que sempre renderiza um seletor de conta, onde a tabela é implícita mas nenhum TableName="account" atributo aparece na marcação que o gerador escaneia). Outras formas de token são descartadas silenciosamente pelo runtime — as próprias strings de componentes do framework são incluídas no bundle padrão estático, então passar components.PowerPortalsPro.* ou app.* aqui é um no-op.
Ligando
O modelo inicial é LocalizationBoundary configurado para você. Se você está integrando manualmente, coloque-o dentro Routes.razor do wrapping da vista de rota, assim:
// <LocalizationBoundary> Encerra o conteúdo por rota e adia</LocalizationBoundary>
// renderizando até que os bundles declarados de cada página estejam estabilizados. Ela herda
// as declarações de prefixo das chamadas descendentes useLocalization() e
// a partir dos 'prefixos' prop no conjunto pai <PowerPortalsProProvider> (set</PowerPortalsProProvider>
// lá para tabelas de app que o Chrome toca em todas as páginas).
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>O Gerador de Fonte e o Manifesto
O PowerPortalsPro.Localization pacote NuGet inclui um gerador de código-fonte Roslyn que escaneia todos *.razor os códigos e códigos do projeto que consume no momento da compilação. Para cada componente (qualquer coisa que ComponentBaseherde ), ele emite uma extensão de classe parcial que carrega um public static readonly LocalizationKeyManifest LocalizationManifest corpo. O manifesto contém o conjunto transitivo de tables.{name} e views.{viewId} tokens que o componente (e todo filho declarado estaticamente que ele renderiza) solicita em tempo de execução — cada token resolve para uma URL por pacote de recurso que a fronteira busca em paralelo antes da primeira pintura. Cadeias fora da tables.* subárvore / choices.* (app.*, components.*) vêm do fibrado padrão estático e são deliberadamente excluídas do manifesto.
O que o Gerador Detecta
O scanner capta automaticamente os padrões comuns — sem necessidade de anotações:
_localizer["tables.foo.…"]Acessos indexadores são coagidos a entrar no token proprietáriotables.foo;_localizer["tables.foo.views.{guid}.…"]acessos tornam-se tokensviews.{guid}.@inject IStringLocalizer<T>Em um arquivo Razor, o gerador permite rastrear a quais campos o localizador está vinculado, para que os acessos do indexador nesses campos contribuam corretamente com seus tokens.GetPrefixedLocalizer("tables.foo")chamadas têm seu prefixo forçado a entrar na tabela ou token de visualização correspondente.DefaultViewId/ViewId/ViewIdsatributos nos componentes da grade emitemviews.{guid}tokens — o servidor resolve a tabela proprietária do id no momento da solicitação, então o manifesto não precisa saber disso.TableName="name"Atributos nos componentes de grade/registro emitem umtables.{name}token. O conjunto correspondente por tabela retorna nomes de exibição, metadados de colunas, as visualizações da tabela (e suas sobrescrituras de colunas) e quaisquer escolhas globais de conjunto de opções referenciadas pelas colunas da tabela — tudo o que a página pode precisar para aquela tabela em uma única busca.- Tags diretas de componentes filhos E
@typeof(SomeComponent)referências nos valores de atributos puxam o manifesto do filho para o conjunto transitivo do pai, então uma página que hospeda componentes dinâmicos ainda pré-busca seus tokens.
Inspecionando um Manifesto
O campo gerado LocalizationManifest é uma estática pública comum — você pode inspecioná-lo a partir de qualquer código C# ou expandi-lo no seu depurador. Os tokens são ordenados deterministicamente para que builds incrementais não descarreguem o arquivo gerado.
// O React não tem um manifesto em tempo de construção — declare prefixos por página
// imperativamente via useLocalization(). O gancho enfileura as fichas
// o mesmo pipeline de busca debouncado do LocalizationBoundary lê,
// Então, uma página que os declara não mostrará as chaves brutas quando navegadas para elas.
import { useLocalization } from '@powerportalspro/react';
function Dashboard() {
useLocalization([
'tables.opportunity',
'views.a1b2c3d4-e5f6-4789-abcd-112233445566',
]);
// ... conteúdo da página ...
}// Gerado por PowerPortalsPro.Localization.SourceGenerators
public partial class Dashboard
{
public static readonly LocalizationKeyManifest LocalizationManifest =
new LocalizationKeyManifest(
"tables.opportunity",
"views.a1b2c3d4-e5f6-4789-abcd-112233445566"
);
}Recurso Sob Demanda
Tudo o que o gerador não consegue resolver em tempo de compilação — chaves construídas a partir de expressões em tempo de execução, new Guid(SomeQualifiedConst) referências que cruzam o limite de referência do projeto, etc. — cai para o caminho sob demanda do localizador. Um erro de cache em uma tables.X.… chave ou tables.X.views.Y.… é forçado a entrar no token do pacote proprietário, colocado em fila, debouncado brevemente e buscado em segundo plano; LocalizationBoundary remonta a subárvore descendente assim que a busca termina, de modo que texto de reserva obsoleto é corrigido automaticamente. Erros em outras formas de chave (app.*, components.*) são ignorados — o bundle padrão estático já teve sua chance, então um erro significa que a chave realmente não existe.
Views Personalizados Definidos em JSON
Visões personalizadas que você envia em um arquivo JSON de localização (por exemplo app.en.json) — tipicamente visualizações em grade com um GUID escolhido a dedo, definido do lado do cliente via CustomViewDefinitions em grade — são captadas automaticamente pelo endpoint do pacote por visualização. O serviço de bundle deriva a tabela proprietária da forma de chave (tables.{owningTable}.views.{viewId}.…) em vez do mapa apenas savedquery de metadados, então uma visualização que não existe no Dataverse ainda é enviada pelo manifesto. As chaves são combinadas de forma insensível a maiúsculas e minúsculas: um arquivo JSON com "28299C6F-EBC0-4206-9E11-A373D4C9891F" (maiúsculas, a forma natural de criar um literal GUID) resolve corretamente quando o gerador fonte emite views.28299c6f-ebc0-4206-9e11-a373d4c9891f a partir do seu código.
Nota
Referência
PowerPortalsPro.Localizationde qualquer projeto que hospede componentes do Blazor. O pacote envia tanto os tipos de runtime (IStringLocalizer,IAsyncStringLocalizer,LocalizationKeyManifest, )LocalizationBoundaryquanto o gerador de origem como um ativo de analisador — os consumidores recebem emissão manifesta automaticamente na próxima compilação, sem configuração adicional.
LocalizationBoundary Classe
Parâmetros
Nome | Tipo | Padrão | Descrição |
|---|---|---|---|
BaselinePrefixes | IEnumerable<string>? | ||
ChildContent | RenderFragment? | O conteúdo da rota será renderizado quando as localizações estiverem prontas. Normalmente um | |
RouteData | RouteData? | A rota atual é LocalizationBoundary.RouteData. Prefixo derivado é |
BaselinePrefixesChildContentRouteDataLocalizationBoundary.RouteData. Prefixo derivado é 