Fornecer recursos localizados para idiomas e culturas em um aplicativo ASP.NET Core

Por Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana e Hisham Bin Ateya

Uma tarefa para localizar um aplicativo é fornecer cadeias de caracteres localizadas em arquivos de recurso. Este artigo é sobre como trabalhar com arquivos de recurso.

SupportedCultures e SupportedUICultures

O ASP.NET Core tem duas coleções de valores de cultura: SupportedCultures e SupportedUICultures. O objeto CultureInfo para SupportedCultures determina os resultados das funções dependentes de cultura, como data, hora, número e formatação de moeda. SupportedCultures também determina a ordem de classificação de texto, convenções de uso de maiúsculas e comparações de cadeia de caracteres. Consulte StringComparer.CurrentCulture para obter mais informações sobre como o servidor obtém a cultura. O SupportedUICultures determina quais cadeias de caracteres traduzidas (de arquivos .resx) são pesquisadas pelo ResourceManager. O ResourceManager apenas pesquisa cadeias de caracteres específicas a uma cultura determinadas por CurrentUICulture. Cada thread no .NET tem objetos CurrentCulture e CurrentUICulture. O ASP.NET Core inspeciona esses valores durante a renderização de funções dependentes de cultura. Por exemplo, se a cultura do thread atual estiver definida como "en-US" (inglês, Estados Unidos), DateTime.Now.ToLongDateString() exibirá "Thursday, February 18, 2016", mas se CurrentCulture estiver definida como "es-ES" (espanhol, Espanha), o resultado será "jueves, 18 de febrero de 2016".

Arquivos de recurso

NOTA:ResX Visualizador e Editor fornece um mecanismo alternativo para trabalhar com arquivos de recurso usando o Visual Studio Code.

Um arquivo de recurso é um mecanismo útil para separar cadeias de caracteres localizáveis do código. Cadeias de caracteres traduzidas para o idioma não padrão são arquivos de recurso .resx isolados. Por exemplo, talvez você queira criar um arquivo de recurso em espanhol chamado Welcome.es.resx contendo cadeias de caracteres traduzidas. "es" são o código de idioma para o espanhol. Para criar esse arquivo de recurso no Visual Studio:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse na pasta que conterá o arquivo de recurso e, em seguida, selecione Adicionar>Novo Item.

    Nested contextual menu: In Solution Explorer, a contextual menu is open for Resources. A second contextual menu is open for Add showing the New Item command highlighted.

  2. Na caixa Pesquisar modelos instalados, insira "recurso" e nomeie o arquivo.

    Add New Item dialog

  3. Insira o valor da chave (cadeia de caracteres nativa) na coluna Nome e a cadeia de caracteres traduzida na coluna Valor.

    Welcome.es.resx file (the Welcome resource file for Spanish) with the word Hello in the Name column and the word Hola (Hello in Spanish) in the Value column

    O Visual Studio mostra o arquivo Welcome.es.resx.

    Solution Explorer showing the Welcome Spanish (es) resource file

Nomenclatura do arquivo de recurso

Os recursos são nomeados com o nome completo do tipo de sua classe menos o nome do assembly. Por exemplo, um recurso em francês em um projeto cujo assembly principal é LocalizationWebsite.Web.dll para a classe LocalizationWebsite.Web.Startup será nomeado Startup.fr.resx. Um recurso para a classe LocalizationWebsite.Web.Controllers.HomeController será nomeado Controllers.HomeController.fr.resx. Se o namespace da classe de destino não for o mesmo que o nome do assembly, você precisará do nome completo do tipo. Por exemplo, no projeto de exemplo, um recurso para o tipo ExtraNamespace.Tools será nomeado ExtraNamespace.Tools.fr.resx.

No projeto de exemplo, o método ConfigureServices define o ResourcesPath como "Resources", de modo que o caminho relativo do projeto para o arquivo de recurso em francês do controlador principal seja Resources/Controllers.HomeController.fr.resx. Como alternativa, você pode usar pastas para organizar arquivos de recurso. Para o controlador principal, o caminho será Resources/Controllers/HomeController.fr.resx. Se você não usar a opção ResourcesPath, o arquivo .resx entrará no diretório base do projeto. O arquivo de recurso para HomeController será nomeado Controllers.HomeController.fr.resx. A opção de usar a convenção de nomenclatura de ponto ou caminho depende de como você deseja organizar os arquivos de recurso.

Nome do recurso Nomenclatura de ponto ou caminho
Resources/Controllers.HomeController.fr.resx Ponto
Resources/Controllers/HomeController.fr.resx Caminho

Os arquivos de recurso que usam @inject IViewLocalizer em exibições do Razor seguem um padrão semelhante. O arquivo de recurso de uma exibição pode ser nomeado usando a nomenclatura de ponto ou de caminho. Os arquivos de recurso da exibição do Razor simulam o caminho de seu arquivo de exibição associado. Supondo que definimos o ResourcesPath como "Resources", o arquivo de recurso em francês associado à exibição Views/Home/About.cshtml pode ser um dos seguintes:

  • Resources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resx

Se você não usar a opção ResourcesPath, o arquivo .resx de uma exibição estará localizado na mesma pasta da exibição.

RootNamespaceAttribute

O atributo RootNamespaceAttribute fornece o namespace raiz de um assembly quando o namespace raiz de um assembly é diferente do nome do assembly.

Aviso

Isso pode ocorrer quando o nome de um projeto não for um identificador .NET válido. Por exemplo, my-project-name.csproj usará o namespace raiz my_project_name e o nome do assembly my-project-name que gera esse erro.

Se o namespace raiz de um assembly é diferente do nome do assembly:

  • A localização não funciona por padrão.
  • A localização falha devido à maneira como os recursos são pesquisados dentro do assembly. RootNamespace é um valor de tempo de build que não está disponível para o processo em execução.

Se o RootNamespace é diferente de AssemblyName, inclua o seguinte no AssemblyInfo.cs (com valores de parâmetro substituídos pelos valores reais):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

O código anterior permite a resolução bem-sucedida de arquivos resx.

Comportamento de fallback da cultura

Ao procurar por um recurso, a localização participa do "fallback de cultura". Começando com a cultura solicitada, se ela não for encontrada, ela será revertida para a cultura pai dessa cultura. Além disso, a propriedade CultureInfo.Parent representa a cultura pai. Isso normalmente (mas nem sempre) significa a remoção do significante do código language-and-culture. Por exemplo, o dialeto do espanhol falado no México é "es-MX". Ele tem o pai "es", ou seja, espanhol, não específico de nenhum país.

Imagine que seu site receba uma solicitação de um recurso “Boas-vindas" usando a cultura"fr-CA". O sistema de localização procura os seguintes recursos, em ordem, e seleciona a primeira correspondência:

  • Welcome.fr-CA.resx
  • Welcome.fr.resx
  • Welcome.resx (se o NeutralResourcesLanguage for "fr-CA")

Por exemplo, se você remover o designador de cultura ".fr" e tiver a cultura definida como francês, o arquivo de recurso padrão será lido e as cadeias de caracteres serão localizadas. O Gerenciador de Recursos designa um padrão ou um recurso de fallback para quando nenhuma opção atende à cultura solicitada. Se você deseja apenas retornar a chave quando um recurso está ausente para a cultura solicitada, não deve ter um arquivo de recurso padrão.

Gerar arquivos de recurso com o Visual Studio

Se você criar um arquivo de recurso no Visual Studio sem uma cultura no nome do arquivo (por exemplo, Welcome.resx), o Visual Studio criará uma classe do C# com uma propriedade para cada cadeia de caracteres. Geralmente isso não é o desejado com o ASP.NET Core. Normalmente você não tem um arquivo de recurso .resx padrão (um arquivo .resx sem o nome de cultura). Sugerimos que você crie o arquivo .resx com um nome de cultura (por exemplo Welcome.fr.resx). Quando você criar um arquivo .resx com um nome de cultura, o Visual Studio não gerará o arquivo de classe.

Adicionar outras culturas

Cada combinação de idioma e cultura (que não seja o idioma padrão) exige um arquivo de recurso exclusivo. Crie arquivos de recurso para diferentes culturas e localidades criando novos arquivos de recurso, nos quais os códigos e de idioma fazem parte do nome do arquivo (por exemplo, en-us, fr-ca e en-gb). Esses códigos são colocados entre o nome do arquivo e a extensão de arquivo .resx, como em Welcome.es-MX.resx (espanhol/México).

Próximas etapas

A localização de um aplicativo também envolve as seguintes tarefas:

Recursos adicionais

Por Rick Anderson, Damien Bowden, Bart Calixto, Nadeem Afana e Hisham Bin Ateya

Uma tarefa para localizar um aplicativo é fornecer cadeias de caracteres localizadas em arquivos de recurso. Este artigo é sobre como trabalhar com arquivos de recurso.

SupportedCultures e SupportedUICultures

O ASP.NET Core tem duas coleções de valores de cultura: SupportedCultures e SupportedUICultures. O objeto CultureInfo para SupportedCultures determina os resultados das funções dependentes de cultura, como data, hora, número e formatação de moeda. SupportedCultures também determina a ordem de classificação de texto, convenções de uso de maiúsculas e comparações de cadeia de caracteres. Consulte StringComparer.CurrentCulture para obter mais informações sobre como o servidor obtém a cultura. O SupportedUICultures determina quais cadeias de caracteres traduzidas (de arquivos .resx) são pesquisadas pelo ResourceManager. O ResourceManager apenas pesquisa cadeias de caracteres específicas a uma cultura determinadas por CurrentUICulture. Cada thread no .NET tem objetos CurrentCulture e CurrentUICulture. O ASP.NET Core inspeciona esses valores durante a renderização de funções dependentes de cultura. Por exemplo, se a cultura do thread atual estiver definida como "en-US" (inglês, Estados Unidos), DateTime.Now.ToLongDateString() exibirá "Thursday, February 18, 2016", mas se CurrentCulture estiver definida como "es-ES" (espanhol, Espanha), o resultado será "jueves, 18 de febrero de 2016".

Arquivos de recurso

Um arquivo de recurso é um mecanismo útil para separar cadeias de caracteres localizáveis do código. Cadeias de caracteres traduzidas para o idioma não padrão são arquivos de recurso .resx isolados. Por exemplo, talvez você queira criar um arquivo de recurso em espanhol chamado Welcome.es.resx contendo cadeias de caracteres traduzidas. "es" são o código de idioma para o espanhol. Para criar esse arquivo de recurso no Visual Studio:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse na pasta que conterá o arquivo de recurso e, em seguida, selecione Adicionar>Novo Item.

    Nested contextual menu: In Solution Explorer, a contextual menu is open for Resources. A second contextual menu is open for Add showing the New Item command highlighted.

  2. Na caixa Pesquisar modelos instalados, insira "recurso" e nomeie o arquivo.

    Add New Item dialog

  3. Insira o valor da chave (cadeia de caracteres nativa) na coluna Nome e a cadeia de caracteres traduzida na coluna Valor.

    Welcome.es.resx file (the Welcome resource file for Spanish) with the word Hello in the Name column and the word Hola (Hello in Spanish) in the Value column

    O Visual Studio mostra o arquivo Welcome.es.resx.

    Solution Explorer showing the Welcome Spanish (es) resource file

Nomenclatura do arquivo de recurso

Os recursos são nomeados com o nome completo do tipo de sua classe menos o nome do assembly. Por exemplo, um recurso em francês em um projeto cujo assembly principal é LocalizationWebsite.Web.dll para a classe LocalizationWebsite.Web.Startup será nomeado Startup.fr.resx. Um recurso para a classe LocalizationWebsite.Web.Controllers.HomeController será nomeado Controllers.HomeController.fr.resx. Se o namespace da classe de destino não for o mesmo que o nome do assembly, você precisará do nome completo do tipo. Por exemplo, no projeto de exemplo, um recurso para o tipo ExtraNamespace.Tools será nomeado ExtraNamespace.Tools.fr.resx.

No projeto de exemplo, o método ConfigureServices define o ResourcesPath como "Resources", de modo que o caminho relativo do projeto para o arquivo de recurso em francês do controlador principal seja Resources/Controllers.HomeController.fr.resx. Como alternativa, você pode usar pastas para organizar arquivos de recurso. Para o controlador principal, o caminho será Resources/Controllers/HomeController.fr.resx. Se você não usar a opção ResourcesPath, o arquivo .resx entrará no diretório base do projeto. O arquivo de recurso para HomeController será nomeado Controllers.HomeController.fr.resx. A opção de usar a convenção de nomenclatura de ponto ou caminho depende de como você deseja organizar os arquivos de recurso.

Nome do recurso Nomenclatura de ponto ou caminho
Resources/Controllers.HomeController.fr.resx Ponto
Resources/Controllers/HomeController.fr.resx Caminho

Os arquivos de recurso que usam @inject IViewLocalizer em exibições do Razor seguem um padrão semelhante. O arquivo de recurso de uma exibição pode ser nomeado usando a nomenclatura de ponto ou de caminho. Os arquivos de recurso da exibição do Razor simulam o caminho de seu arquivo de exibição associado. Supondo que definimos o ResourcesPath como "Resources", o arquivo de recurso em francês associado à exibição Views/Home/About.cshtml pode ser um dos seguintes:

  • Resources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resx

Se você não usar a opção ResourcesPath, o arquivo .resx de uma exibição estará localizado na mesma pasta da exibição.

RootNamespaceAttribute

O atributo RootNamespaceAttribute fornece o namespace raiz de um assembly quando o namespace raiz de um assembly é diferente do nome do assembly.

Aviso

Isso pode ocorrer quando o nome de um projeto não for um identificador .NET válido. Por exemplo, my-project-name.csproj usará o namespace raiz my_project_name e o nome do assembly my-project-name que gera esse erro.

Se o namespace raiz de um assembly é diferente do nome do assembly:

  • A localização não funciona por padrão.
  • A localização falha devido à maneira como os recursos são pesquisados dentro do assembly. RootNamespace é um valor de tempo de build que não está disponível para o processo em execução.

Se o RootNamespace é diferente de AssemblyName, inclua o seguinte no AssemblyInfo.cs (com valores de parâmetro substituídos pelos valores reais):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

O código anterior permite a resolução bem-sucedida de arquivos resx.

Comportamento de fallback da cultura

Ao procurar por um recurso, a localização participa do "fallback de cultura". Começando com a cultura solicitada, se ela não for encontrada, ela será revertida para a cultura pai dessa cultura. Além disso, a propriedade CultureInfo.Parent representa a cultura pai. Isso normalmente (mas nem sempre) significa a remoção do significante do código language-and-culture. Por exemplo, o dialeto do espanhol falado no México é "es-MX". Ele tem o pai "es", ou seja, espanhol, não específico de nenhum país.

Imagine que seu site receba uma solicitação de um recurso “Boas-vindas" usando a cultura"fr-CA". O sistema de localização procura os seguintes recursos, em ordem, e seleciona a primeira correspondência:

  • Welcome.fr-CA.resx
  • Welcome.fr.resx
  • Welcome.resx (se o NeutralResourcesLanguage for "fr-CA")

Por exemplo, se você remover o designador de cultura ".fr" e tiver a cultura definida como francês, o arquivo de recurso padrão será lido e as cadeias de caracteres serão localizadas. O Gerenciador de Recursos designa um padrão ou um recurso de fallback para quando nenhuma opção atende à cultura solicitada. Se você deseja apenas retornar a chave quando um recurso está ausente para a cultura solicitada, não deve ter um arquivo de recurso padrão.

Gerar arquivos de recurso com o Visual Studio

Se você criar um arquivo de recurso no Visual Studio sem uma cultura no nome do arquivo (por exemplo, Welcome.resx), o Visual Studio criará uma classe do C# com uma propriedade para cada cadeia de caracteres. Geralmente isso não é o desejado com o ASP.NET Core. Normalmente você não tem um arquivo de recurso .resx padrão (um arquivo .resx sem o nome de cultura). Sugerimos que você crie o arquivo .resx com um nome de cultura (por exemplo Welcome.fr.resx). Quando você criar um arquivo .resx com um nome de cultura, o Visual Studio não gerará o arquivo de classe.

Adicionar outras culturas

Cada combinação de idioma e cultura (que não seja o idioma padrão) exige um arquivo de recurso exclusivo. Crie arquivos de recurso para diferentes culturas e localidades criando novos arquivos de recurso, nos quais os códigos e de idioma fazem parte do nome do arquivo (por exemplo, en-us, fr-ca e en-gb). Esses códigos são colocados entre o nome do arquivo e a extensão de arquivo .resx, como em Welcome.es-MX.resx (espanhol/México).

Próximas etapas

A localização de um aplicativo também envolve as seguintes tarefas:

Recursos adicionais