Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os aplicativos dependem do Gerenciador de Recursos do .NET Framework, representado pela ResourceManager classe, para recuperar recursos localizados. O Resource Manager assume que o modelo "hub and spoke" é utilizado para empacotar e implantar recursos. O hub é o assembly principal que contém o código executável não localizável e os recursos para uma única cultura, chamada de cultura neutra ou padrão. A cultura padrão é a cultura de reserva para a aplicação; é a cultura cujos recursos são utilizados se não for possível encontrar recursos localizados. Cada spoke se conecta a um assembly satélite que contém os recursos para uma única cultura, mas não contém nenhum código.
Existem várias vantagens neste modelo:
- Você pode adicionar recursos incrementalmente para novas culturas depois de implantar um aplicativo. Como o desenvolvimento subsequente de recursos específicos de cultura pode exigir uma quantidade significativa de tempo, isso permite que você lance seu aplicativo principal primeiro e forneça recursos específicos de cultura em uma data posterior.
- Você pode atualizar e alterar as bibliotecas satélites da aplicação sem recompilá-la.
- Uma aplicação necessita carregar apenas os assemblies satélite que contêm os recursos necessários para uma cultura específica. Isso pode reduzir significativamente o uso de recursos do sistema.
No entanto, também existem desvantagens neste modelo:
- Você deve gerenciar vários conjuntos de recursos.
- O custo inicial de testar um aplicativo aumenta, porque você deve testar várias configurações. Note-se que, a longo prazo, será mais fácil e menos dispendioso testar uma aplicação central com vários satélites, do que testar e manter várias versões internacionais paralelas.
Convenções de nomenclatura de recursos
Ao empacotar os recursos do aplicativo, você deve nomeá-los usando as convenções de nomenclatura de recursos esperadas pelo Common Language Runtime. O tempo de execução identifica um recurso pelo seu nome de cultura. Cada cultura recebe um nome único, que geralmente é uma combinação de um nome de cultura minúsculo de duas letras associado a um idioma e, se necessário, um nome de subcultura maiúsculo de duas letras associado a um país ou região. O nome da subcultura segue o nome da cultura, separado por um traço (-). Exemplos incluem ja-JP para o japonês falado no Japão, en-US para o inglês falado nos Estados Unidos de-DE para o alemão falado na Alemanha ou de-AT para o alemão falado na Áustria. Consulte a coluna Marca de idioma na lista de nomes de idioma/região suportados pelo Windows. Os nomes das culturas seguem o padrão definido pelo BCP 47.
Observação
Existem algumas exceções para os nomes de cultura de duas letras, como zh-Hans
para chinês (simplificado).
Para obter mais informações, consulte Criar arquivos de recursos e Criar assemblies satélite.
O processo de substituição de recursos
O modelo hub and spoke para empacotamento e implantação de recursos usa um processo de fallback para localizar os recursos apropriados. Se um aplicativo solicitar um recurso localizado que não está disponível, o Common Language Runtime procurará na hierarquia de culturas um recurso de fallback apropriado que mais se aproxime da solicitação do aplicativo do usuário e lançará uma exceção apenas como último recurso. Em cada nível da hierarquia, se um recurso apropriado for encontrado, o tempo de execução o usará. Se o recurso não for encontrado, a pesquisa continua no próximo nível.
Para melhorar o desempenho da pesquisa, aplique o NeutralResourcesLanguageAttribute atributo ao assembly principal e passe a ele o nome da linguagem neutra que funcionará com o assembly principal.
Processo de recuperação de recursos do .NET Framework
O processo de fallback de recursos do .NET Framework envolve as seguintes etapas:
Sugestão
Você poderá usar o <elemento de configuração relativeBindForResources> para otimizar o processo de fallback de recursos e o processo pelo qual o tempo de execução investiga assemblies de recursos. Para obter mais informações, consulte Otimizando o processo de fallback de recursos.
O tempo de execução primeiro verifica o cache de assembly global em busca de um assembly que corresponda à cultura solicitada para seu aplicativo.
O cache de assembly global pode armazenar assemblies de recursos que são compartilhados por muitos aplicativos. Isso libera você de ter que incluir conjuntos específicos de recursos na estrutura de diretórios de cada aplicativo que você criar. Se o tempo de execução encontrar uma referência ao assembly, ele procurará o recurso solicitado dentro desse assembly. Caso encontre a entrada na assemblagem, utilizará o recurso solicitado. Se não encontrar a entrada, continua a pesquisa.
Em seguida, o tempo de execução verifica o diretório do assembly em execução no momento em busca de um subdiretório que corresponda à cultura solicitada. Caso encontre o subdiretório, procura nesse subdiretório um assembly satélite válido para a cultura solicitada. Em seguida, o tempo de execução procura o recurso requisitado no assembly satélite. Se ele encontrar o recurso no assembly, ele o usará. Se não encontrar o recurso, continua a pesquisa.
Em seguida, o tempo de execução consulta o Windows Installer para determinar se o assembly satélite deve ser instalado sob demanda. Em caso afirmativo, ele lida com a instalação, carrega a assemblagem e pesquisa-a ou o recurso solicitado. Se ele encontrar o recurso no assembly, ele o usará. Se não encontrar o recurso, continua a pesquisa.
O tempo de execução gera o AppDomain.AssemblyResolve evento para indicar que não é possível encontrar o assembly satélite. Se você optar por manipular o evento, seu manipulador de eventos poderá retornar uma referência ao assembly satélite cujos recursos serão usados para a pesquisa. Caso contrário, o manipulador de eventos retornará
null
e a pesquisa continuará.Em seguida, o runtime pesquisa novamente o cache de assembly global, desta vez para o assembly principal da cultura solicitada. Se o assembly pai existir no cache de assembly global, o tempo de execução procurará o recurso solicitado no assembly.
A cultura principal é definida como a cultura de fallback apropriada. Considere os pais como candidatos de reserva, porque fornecer qualquer recurso é preferível a gerar uma exceção. Este processo também permite reutilizar recursos. Você deve incluir um recurso específico no nível pai somente se a cultura filho não precisar localizar o recurso solicitado. Por exemplo, se você fornecer conjuntos de satélites para
en
(inglês neutro),en-GB
(inglês falado no Reino Unido) een-US
(inglês falado nos Estados Unidos), oen
satélite conterá a terminologia comum, e osen-GB
satélites een-US
poderão fornecer substituições apenas para os termos que diferem.Em seguida, o runtime verifica o diretório do assembly que está atualmente em execução para ver se contém um diretório pai. Se existir um diretório pai, o tempo de execução procurará no diretório um assembly satélite válido para a cultura pai. Se encontrar a assemblagem, o tempo de execução procurará na assemblagem o recurso solicitado. Se encontrar o recurso, utiliza-o. Se não encontrar o recurso, continua a pesquisa.
Em seguida, o runtime consulta o Windows Installer para determinar se o assembly satélite pai deve ser instalado sob demanda. Em caso afirmativo, ele lida com a instalação, carrega a assemblagem e pesquisa-a ou o recurso solicitado. Se ele encontrar o recurso no assembly, ele o usará. Se não encontrar o recurso, continua a pesquisa.
A execução gera o AppDomain.AssemblyResolve evento para indicar que não é capaz de encontrar um recurso alternativo apropriado. Se você optar por manipular o evento, seu manipulador de eventos poderá retornar uma referência ao assembly satélite cujos recursos serão usados para a pesquisa. Caso contrário, o manipulador de eventos retornará
null
e a pesquisa continuará.O tempo de execução em seguida pesquisa assemblies pai, como nas três etapas anteriores, através de muitos níveis potenciais. Cada cultura tem apenas um progenitor, definido pela propriedade CultureInfo.Parent, mas um progenitor pode ter o seu próprio progenitor. A busca por culturas parentais termina quando a propriedade de uma cultura retorna Parent; para o fallback de recursos, a cultura invariante não é considerada uma cultura pai nem uma cultura que possa ter recursos.
Se a cultura que foi originalmente especificada e todos os pais tiverem sido pesquisados, e ainda assim o recurso não for encontrado, o recurso para a cultura padrão (de reserva) será usado. Normalmente, os recursos para a cultura padrão são incluídos no assembly do aplicativo principal. No entanto, pode especificar um valor de Satellite para a propriedade Location do atributo NeutralResourcesLanguageAttribute para indicar que o local de fallback final para recursos é um assembly satélite, em vez do assembly principal.
Observação
O recurso padrão é o único recurso que pode ser compilado com a assemblagem principal. A menos que você especifique um assembly satélite usando o NeutralResourcesLanguageAttribute atributo, ele é o fallback final (pai final). Portanto, recomendamos que você sempre inclua um conjunto padrão de recursos em seu assembly principal. Isso ajuda a evitar que exceções sejam lançadas. Ao incluir um recurso padrão, você fornece um fallback para todos os recursos e garante que pelo menos um recurso esteja sempre presente para o usuário, mesmo que não seja culturalmente específico.
Finalmente, se o tempo de execução não encontrar um recurso para uma cultura padrão (fallback), será lançada uma exceção MissingManifestResourceException ou MissingSatelliteAssemblyException para indicar que o recurso não pôde ser encontrado.
Por exemplo, suponha que o aplicativo solicite um recurso localizado para espanhol (México) (a es-MX
cultura). O runtime primeiro procura no cache global de assemblies pelo assembly que corresponde a es-MX
, mas não o encontra. Em seguida, o tempo de execução pesquisa o diretório es-MX
no diretório do assembly em execução no momento. Caso contrário, o tempo de execução pesquisa o cache de assembly global novamente em busca de um assembly pai que reflita a cultura de fallback apropriada — neste caso, es
(espanhol). Se o assembly pai não for encontrado, o tempo de execução pesquisará todos os níveis potenciais de assemblies pai para a es-MX
cultura até encontrar um recurso correspondente. Caso um recurso não seja encontrado, o tempo de execução utilizará o recurso da cultura padrão.
Otimizar o processo de substituição de recursos no .NET Framework
Sob as seguintes condições, você pode otimizar o processo pelo qual o tempo de execução procura recursos em assemblies satélite:
Os assemblies de satélite são implantados no mesmo local que o assembly de código. Se o assembly de código estiver instalado no Cache Global de Assembly, os assemblies satélite também serão instalados no Cache Global de Assembly. Se a assemblagem de código estiver instalada num diretório, as assemblagens satélite serão instaladas em pastas específicas para a cultura desse diretório.
Os conjuntos de satélite não são instalados sob demanda.
O código do aplicativo não manipula o AppDomain.AssemblyResolve evento.
Você otimiza a sonda para satélites incluindo o elemento <relativeBindForResources> e definindo o seu atributo enabled
como true
no ficheiro de configuração da aplicação, como mostrado no exemplo a seguir.
<configuration>
<runtime>
<relativeBindForResources enabled="true" />
</runtime>
</configuration>
A sonda otimizada para conjuntos de satélites é um recurso opcional. Ou seja, o tempo de execução segue as etapas documentadas em O processo de fallback do recurso , a menos que o <elemento relativeBindForResources> esteja presente no arquivo de configuração do aplicativo e seu enabled
atributo esteja definido como true
. Se este for o caso, o processo de sondagem de um conjunto satélite é modificado da seguinte forma:
O tempo de execução usa o local do assembly de código pai para investigar o assembly satélite. Se o assembly pai estiver instalado no cache de assembly global, o tempo de execução será investigado no cache, mas não no diretório do aplicativo. Se o assembly pai estiver instalado em um diretório de aplicativo, o tempo de execução investigará no diretório do aplicativo, mas não no cache de assembly global.
O runtime não consulta o Windows Installer para instalação sob demanda de assemblies satélite.
Se o teste para um assembly de recurso específico falhar, o tempo de execução não gerará o AppDomain.AssemblyResolve evento.
Processo de recuperação de recursos do .NET Core
O processo de fallback de recursos do .NET Core envolve as seguintes etapas:
O tempo de execução tenta carregar um assembly satélite para a cultura solicitada.
Verifica o diretório do assembly em execução no momento em busca de um subdiretório que corresponda à cultura solicitada. Se encontrar o subdiretório, procura nele um assembly satélite válido para a cultura solicitada e carrega-o.
Observação
Em sistemas operacionais com sistemas de arquivos que diferenciam maiúsculas de minúsculas (ou seja, Linux e macOS), a pesquisa do subdiretório do nome da cultura diferencia maiúsculas de minúsculas. O nome do subdiretório deve corresponder exatamente ao caso do CultureInfo.Name (por exemplo,
es
oues-MX
).Observação
Se o programador tiver derivado um contexto de carga de montagem personalizado do AssemblyLoadContext, a situação é complicada. Se o conjunto em execução foi carregado no contexto personalizado, o ambiente de execução carrega o conjunto satélite no contexto personalizado. Os detalhes estão fora do escopo deste documento. Consulte AssemblyLoadContext.
Se um conjunto de satélite não tiver sido encontrado, o AssemblyLoadContext gera o evento AssemblyLoadContext.Resolving para indicar que é incapaz de encontrar o conjunto de satélite. Se você optar por manipular o evento, seu manipulador de eventos poderá carregar e retornar uma referência ao assembly satélite.
Se um assembly satélite ainda não tiver sido encontrado, o AssemblyLoadContext fará com que o AppDomain acione um AppDomain.AssemblyResolve evento para indicar que ele não consegue localizar o assembly satélite. Se você optar por manipular o evento, seu manipulador de eventos poderá carregar e retornar uma referência ao assembly satélite.
Se um assembly satélite for encontrado, o ambiente de execução buscará o recurso solicitado. Se ele encontrar o recurso no assembly, ele o usará. Se não encontrar o recurso, continua a pesquisa.
Observação
Para encontrar um recurso dentro do assembly satélite, o tempo de execução procura o arquivo de recurso solicitado pelo ResourceManager para o atual CultureInfo.Name. Dentro do arquivo de recurso, ele procura o nome do recurso solicitado. Se um deles não for encontrado, o recurso será tratado como não encontrado.
Em seguida, o runtime pesquisa os assemblies de cultura pai em muitos níveis potenciais, repetindo as etapas 1 e 2 de cada vez.
A cultura principal é definida como uma cultura de recurso apropriada. Considere os pais como candidatos de reserva, porque fornecer qualquer recurso é preferível a gerar uma exceção. Este processo também permite reutilizar recursos. Você deve incluir um recurso específico no nível pai somente se a cultura filho não precisar localizar o recurso solicitado. Por exemplo, se você fornecer conjuntos de satélites para
en
(inglês neutro),en-GB
(inglês falado no Reino Unido) een-US
(inglês falado nos Estados Unidos), oen
satélite conterá a terminologia comum, e oen-GB
een-US
satélites fornecerá substituições apenas para os termos que diferem.Cada cultura tem apenas um progenitor, definido pela propriedade CultureInfo.Parent, mas um progenitor pode ter o seu próprio progenitor. A pesquisa por culturas parentais é interrompida quando a propriedade Parent de uma cultura retorna CultureInfo.InvariantCulture. Para recurso de substituição, a cultura invariante não é considerada uma cultura-mãe ou uma cultura que pode ter recursos.
Se a cultura que foi originalmente especificada e todos os pais tiverem sido pesquisados, e ainda assim o recurso não for encontrado, o recurso para a cultura padrão (de reserva) será usado. Normalmente, os recursos para a cultura padrão são incluídos no assembly do aplicativo principal. No entanto, pode especificar um valor de Satellite para a propriedade Location para indicar que o local final de fallback para recursos é um assembly satélite em vez do assembly principal.
Observação
O recurso padrão é o único recurso que pode ser compilado com a assemblagem principal. A menos que você especifique um assembly satélite usando o NeutralResourcesLanguageAttribute atributo, ele é o fallback final (pai final). Portanto, recomendamos que você sempre inclua um conjunto padrão de recursos em seu assembly principal. Isso ajuda a evitar que exceções sejam lançadas. Ao incluir um arquivo de recurso padrão, você fornece um fallback para todos os recursos e garante que pelo menos um recurso esteja sempre presente para o usuário, mesmo que não seja culturalmente específico.
Finalmente, se o tempo de execução não encontrar um arquivo de recurso para uma cultura padrão (fallback), uma MissingManifestResourceException exceção ou MissingSatelliteAssemblyException será lançada para indicar que o recurso não pôde ser encontrado. Se o arquivo de recurso for encontrado, mas o recurso solicitado não estiver presente, a solicitação retornará
null
.
Fallback definitivo para a montagem de satélites
Opcionalmente, você pode remover recursos do assembly principal e especificar que o tempo de execução deve carregar os recursos de fallback finais de um assembly satélite que corresponda a uma cultura específica. Para controlar o processo de fallback, utilize o construtor NeutralResourcesLanguageAttribute(String, UltimateResourceFallbackLocation) e dê um valor para o parâmetro UltimateResourceFallbackLocation, que especifica se o Resource Manager deve extrair os recursos de fallback do assembly principal ou de um assembly satélite.
O exemplo do .NET Framework a seguir usa o atributo NeutralResourcesLanguageAttribute para armazenar recursos de retorno de um aplicativo em um assembly satélite para o idioma francês (fr
). O exemplo tem dois arquivos de recurso baseados em texto que definem um único recurso de cadeia de caracteres chamado Greeting
. O primeiro, resources.fr.txt, contém um recurso em língua francesa.
Greeting=Bon jour!
O segundo recurso,ru.txt, contém um recurso no idioma russo.
Greeting=Добрый день
Esses dois arquivos são compilados para arquivos .resources executando Resource File Generator (resgen.exe) a partir da linha de comando. Para o recurso em francês, o comando é:
resgen.exe resources.fr.txt
Para o recurso de idioma russo, o comando é:
resgen.exe resources.ru.txt
Os arquivos .resources são incorporados em bibliotecas de vínculo dinâmico executando Assembly Linker (al.exe) a partir da linha de comando para o recurso de idioma francês da seguinte maneira:
al /t:lib /embed:resources.fr.resources /culture:fr /out:fr\Example1.resources.dll
e para o recurso de língua russa da seguinte forma:
al /t:lib /embed:resources.ru.resources /culture:ru /out:ru\Example1.resources.dll
O código-fonte do aplicativo reside em um arquivo chamado Example1.cs ou Example1.vb. Ele inclui o NeutralResourcesLanguageAttribute atributo para indicar que o recurso de aplicativo padrão está no subdiretório fr. Ele instancia o Gerenciador de Recursos, recupera o valor do Greeting
recurso e o exibe no console.
using System;
using System.Reflection;
using System.Resources;
[assembly:NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)]
public class Example
{
public static void Main()
{
ResourceManager rm = new ResourceManager("resources",
typeof(Example).Assembly);
string greeting = rm.GetString("Greeting");
Console.WriteLine(greeting);
}
}
Imports System.Reflection
Imports System.Resources
<Assembly: NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)>
Module Example
Public Sub Main()
Dim rm As New ResourceManager("resources", GetType(Example).Assembly)
Dim greeting As String = rm.GetString("Greeting")
Console.WriteLine(greeting)
End Sub
End Module
Em seguida, você pode compilar o código-fonte C# a partir da linha de comando da seguinte maneira:
csc Example1.cs
O comando para o compilador do Visual Basic é muito semelhante:
vbc Example1.vb
Como não há recursos incorporados no assembly principal, não é necessário compilar usando o /resource
switch.
Quando você executa o exemplo de um sistema cujo idioma é qualquer coisa diferente do russo, ele exibe a seguinte saída:
Bon jour!
Alternativa de embalagem sugerida
Restrições de tempo ou orçamento podem impedir que você crie um conjunto de recursos para cada subcultura suportada pelo seu aplicativo. Em vez disso, pode criar um único conjunto satélite para uma cultura principal que todas as subculturas relacionadas podem utilizar. Por exemplo, você pode fornecer um único assembly de satélite em inglês (en) que é recuperado por usuários que solicitam recursos em inglês específicos da região e um único assembly de satélite alemão (de) para usuários que solicitam recursos alemães específicos da região. Por exemplo, os pedidos de alemão falado na Alemanha (de-DE), Áustria (de-AT), e Suíça (de-CH) seriam redirecionados para a montagem satélite alemã (de). Os recursos padrão são o fallback final e, portanto, devem ser os recursos que serão solicitados pela maioria dos usuários do seu aplicativo, portanto, escolha esses recursos com cuidado. Essa abordagem implanta recursos que são menos específicos culturalmente, mas podem reduzir significativamente os custos de localização do seu aplicativo.