Globalização e localização no ASP.NET CoreGlobalization and localization in ASP.NET Core

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

A criação de um site multilíngue com o ASP.NET Core permitirá que seu site alcance um público maior.Creating a multilingual website with ASP.NET Core will allow your site to reach a wider audience. O ASP.NET Core fornece serviços e middleware para localização em diferentes idiomas e culturas.ASP.NET Core provides services and middleware for localizing into different languages and cultures.

A internacionalização envolve Globalização e Localização.Internationalization involves Globalization and Localization. Globalização é o processo de criação de aplicativos que dão suporte a diferentes culturas.Globalization is the process of designing apps that support different cultures. A globalização adiciona suporte para entrada, exibição e saída de um conjunto definido de scripts de idiomas relacionados a áreas geográficas específicas.Globalization adds support for input, display, and output of a defined set of language scripts that relate to specific geographic areas.

Localização é o processo de adaptar um aplicativo globalizado, que você já processou para possibilidade de localização, a determinada cultura/localidade.Localization is the process of adapting a globalized app, which you have already processed for localizability, to a particular culture/locale. Para obter mais informações, consulte Termos de globalização e localização próximo ao final deste documento.For more information see Globalization and localization terms near the end of this document.

A localização de aplicativos envolve o seguinte:App localization involves the following:

  1. Tornar o conteúdo do aplicativo localizávelMake the app's content localizable

  2. Fornecer recursos localizados para as culturas e os idiomas aos quais você dá suporteProvide localized resources for the languages and cultures you support

  3. Implementar uma estratégia para selecionar o idioma e a cultura para cada solicitaçãoImplement a strategy to select the language/culture for each request

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Tornar o conteúdo do aplicativo localizávelMake the app's content localizable

Introduzidos no ASP.NET Core IStringLocalizer e IStringLocalizer<T> foram projetados para melhorar a produtividade ao desenvolver aplicativos localizados.Introduced in ASP.NET Core, IStringLocalizer and IStringLocalizer<T> were architected to improve productivity when developing localized apps. IStringLocalizer usa o ResourceManager e o ResourceReader para fornecer recursos específicos a uma cultura em tempo de execução.IStringLocalizer uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. A interface simples tem um indexador e um IEnumerable para retornar cadeias de caracteres localizadas.The simple interface has an indexer and an IEnumerable for returning localized strings. IStringLocalizer não exige o armazenamento das cadeias de caracteres de idioma padrão em um arquivo de recurso.IStringLocalizer doesn't require you to store the default language strings in a resource file. Você pode desenvolver um aplicativo direcionado à localização e não precisa criar arquivos de recurso no início do desenvolvimento.You can develop an app targeted for localization and not need to create resource files early in development. O código abaixo mostra como encapsular a cadeia de caracteres "About Title" para localização.The code below shows how to wrap the string "About Title" for localization.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

No código acima, a implementação IStringLocalizer<T> é obtida da Injeção de Dependência.In the code above, the IStringLocalizer<T> implementation comes from Dependency Injection. Se o valor localizado de "About Title" não é encontrado, a chave do indexador é retornada, ou seja, a cadeia de caracteres "About Title".If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "About Title". Deixe as cadeias de caracteres literais de idioma padrão no aplicativo e encapsule-as no localizador, de modo que você possa se concentrar no desenvolvimento do aplicativo.You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. Você pode desenvolve seu aplicativo com o idioma padrão e prepará-lo para a etapa de localização sem primeiro criar um arquivo de recurso padrão.You develop your app with your default language and prepare it for the localization step without first creating a default resource file. Como alternativa, você pode usar a abordagem tradicional e fornecer uma chave para recuperar a cadeia de caracteres de idioma padrão.Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. Para muitos desenvolvedores, o novo fluxo de trabalho de não ter um arquivo .resx de idioma padrão e simplesmente encapsular os literais de cadeia de caracteres pode reduzir a sobrecarga de localizar um aplicativo.For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. Outros desenvolvedores preferirão o fluxo de trabalho tradicional, pois ele pode facilitar o trabalho com literais de cadeia de caracteres mais longas e a atualização de cadeias de caracteres localizadas.Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

Use a implementação IHtmlLocalizer<T> para recursos que contêm HTML.Use the IHtmlLocalizer<T> implementation for resources that contain HTML. O IHtmlLocalizer codifica em HTML os argumentos que são formatados na cadeia de caracteres de recurso, mas não codifica em HTML a cadeia de caracteres de recurso em si.IHtmlLocalizer HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. Na amostra realçada abaixo, apenas o valor do parâmetro name é codificado em HTML.In the sample highlighted below, only the value of name parameter is HTML encoded.

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;

namespace Localization.Controllers
{
    public class BookController : Controller
    {
        private readonly IHtmlLocalizer<BookController> _localizer;

        public BookController(IHtmlLocalizer<BookController> localizer)
        {
            _localizer = localizer;
        }

        public IActionResult Hello(string name)
        {
            ViewData["Message"] = _localizer["<b>Hello</b><i> {0}</i>", name];

            return View();
        }

Observação: em geral, recomendamos localizar somente o texto e não o HTML.Note: You generally want to only localize text and not HTML.

No nível mais baixo, você pode obter IStringLocalizerFactory com a Injeção de Dependência:At the lowest level, you can get IStringLocalizerFactory out of Dependency Injection:

{
    public class TestController : Controller
    {
        private readonly IStringLocalizer _localizer;
        private readonly IStringLocalizer _localizer2;

        public TestController(IStringLocalizerFactory factory)
        {
            var type = typeof(SharedResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
            _localizer = factory.Create(type);
            _localizer2 = factory.Create("SharedResource", assemblyName.Name);
        }       

        public IActionResult About()
        {
            ViewData["Message"] = _localizer["Your application description page."] 
                + " loc 2: " + _localizer2["Your application description page."];

O código acima demonstra cada um dos dois métodos Create de alocador.The code above demonstrates each of the two factory create methods.

Você pode particionar as cadeias de caracteres localizadas por controlador, área ou ter apenas um contêiner.You can partition your localized strings by controller, area, or have just one container. No aplicativo de exemplo, uma classe fictícia chamada SharedResource é usada para recursos compartilhados.In the sample app, a dummy class named SharedResource is used for shared resources.

// Dummy class to group shared resources

namespace Localization
{
    public class SharedResource
    {
    }
}

Alguns desenvolvedores usam a classe Startup para conter cadeias de caracteres globais ou compartilhadas.Some developers use the Startup class to contain global or shared strings. Na amostra abaixo, os localizadores InfoController e SharedResource são usados:In the sample below, the InfoController and the SharedResource localizers are used:

public class InfoController : Controller
{
    private readonly IStringLocalizer<InfoController> _localizer;
    private readonly IStringLocalizer<SharedResource> _sharedLocalizer;

    public InfoController(IStringLocalizer<InfoController> localizer,
                   IStringLocalizer<SharedResource> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    public string TestLoc()
    {
        string msg = "Shared resx: " + _sharedLocalizer["Hello!"] +
                     " Info resx " + _localizer["Hello!"];
        return msg;
    }

Localização de exibiçãoView localization

O serviço IViewLocalizer fornece cadeias de caracteres localizadas para uma exibição.The IViewLocalizer service provides localized strings for a view. A classe ViewLocalizer implementa essa interface e encontra o local do recurso no caminho do arquivo de exibição.The ViewLocalizer class implements this interface and finds the resource location from the view file path. O seguinte código mostra como usar a implementação padrão de IViewLocalizer:The following code shows how to use the default implementation of IViewLocalizer:

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>

A implementação padrão de IViewLocalizer encontra o arquivo de recurso com base no nome de arquivo da exibição.The default implementation of IViewLocalizer finds the resource file based on the view's file name. Não há nenhuma opção para usar um arquivo de recurso compartilhado global.There's no option to use a global shared resource file. ViewLocalizer implementa o localizador usando IHtmlLocalizer e, portanto, o Razor não codifica em HTML a cadeia de caracteres localizada.ViewLocalizer implements the localizer using IHtmlLocalizer, so Razor doesn't HTML encode the localized string. Parametrize cadeias de recurso e o IViewLocalizer codificará em HTML os parâmetros, mas não a cadeia de caracteres de recurso.You can parameterize resource strings and IViewLocalizer will HTML encode the parameters, but not the resource string. Considere a seguinte marcação do Razor:Consider the following Razor markup:

@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]

Um arquivo de recurso em francês pode conter o seguinte:A French resource file could contain the following:

ChaveKey ValorValue
<i>Hello</i> <b>{0}!</b> <i>Bonjour</i> <b>{0} !</b>

A exibição renderizada contém a marcação HTML do arquivo de recurso.The rendered view would contain the HTML markup from the resource file.

Observação: em geral, recomendamos localizar somente o texto e não o HTML.Note: You generally want to only localize text and not HTML.

Para usar um arquivo de recurso compartilhado em uma exibição, injete IHtmlLocalizer<T>:To use a shared resource file in a view, inject IHtmlLocalizer<T>:

@using Microsoft.AspNetCore.Mvc.Localization
@using Localization.Services

@inject IViewLocalizer Localizer
@inject IHtmlLocalizer<SharedResource> SharedLocalizer

@{
    ViewData["Title"] = Localizer["About"];
}
<h2>@ViewData["Title"].</h2>

<h1>@SharedLocalizer["Hello!"]</h1>

Localização de DataAnnotationsDataAnnotations localization

As mensagens de erro de DataAnnotations são localizadas com IStringLocalizer<T>.DataAnnotations error messages are localized with IStringLocalizer<T>. Usando a opção ResourcesPath = "Resources", as mensagens de erro em RegisterViewModel podem ser armazenadas em um dos seguintes caminhos:Using the option ResourcesPath = "Resources", the error messages in RegisterViewModel can be stored in either of the following paths:

  • Resources/ViewModels.Account.RegisterViewModel.fr.resxResources/ViewModels.Account.RegisterViewModel.fr.resx
  • Resources/ViewModels/Account/RegisterViewModel.fr.resxResources/ViewModels/Account/RegisterViewModel.fr.resx
public class RegisterViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "The Password field is required.")]
    [StringLength(8, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

No ASP.NET Core MVC 1.1.0 e superior, atributos que não sejam de validação são localizados.In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. O ASP.NET Core MVC 1.0 não pesquisa cadeias de caracteres localizadas para atributos que não sejam de validação.ASP.NET Core MVC 1.0 does not look up localized strings for non-validation attributes.

Usando uma cadeia de caracteres de recurso para várias classesUsing one resource string for multiple classes

O seguinte código mostra como usar uma cadeia de caracteres de recurso para atributos de validação com várias classes:The following code shows how to use one resource string for validation attributes with multiple classes:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddDataAnnotationsLocalization(options => {
            options.DataAnnotationLocalizerProvider = (type, factory) =>
                factory.Create(typeof(SharedResource));
        });
}

No código anterior, SharedResource é a classe correspondente ao resx em que as mensagens de validação são armazenadas.In the preceeding code, SharedResource is the class corresponding to the resx where your validation messages are stored. Com essa abordagem, DataAnnotations usará apenas SharedResource, em vez de o recurso para cada classe.With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

Fornecer recursos localizados para as culturas e os idiomas aos quais você dá suporteProvide localized resources for the languages and cultures you support

SupportedCultures e SupportedUICulturesSupportedCultures and SupportedUICultures

O ASP.NET Core permite que você especifique dois valores de cultura, SupportedCultures e SupportedUICultures.ASP.NET Core allows you to specify two culture values, SupportedCultures and 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.The CultureInfo object for SupportedCultures determines the results of culture-dependent functions, such as date, time, number, and currency formatting. 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.SupportedCultures also determines the sorting order of text, casing conventions, and string comparisons. Consulte CultureInfo.CurrentCulture para obter mais informações sobre como o servidor obtém a Cultura.See CultureInfo.CurrentCulture for more info on how the server gets the Culture. O SupportedUICultures determina quais cadeias de caracteres traduzidas (de arquivos .resx) são pesquisadas pelo ResourceManager.The SupportedUICultures determines which translates strings (from .resx files) are looked up by the ResourceManager. O ResourceManager apenas pesquisa cadeias de caracteres específicas a uma cultura determinadas por CurrentUICulture.The ResourceManager simply looks up culture-specific strings that's determined by CurrentUICulture. Cada thread no .NET tem objetos CurrentCulture e CurrentUICulture.Every thread in .NET has CurrentCulture and CurrentUICulture objects. O ASP.NET Core inspeciona esses valores durante a renderização de funções dependentes de cultura.ASP.NET Core inspects these values when rendering culture-dependent functions. 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".For example, if the current thread's culture is set to "en-US" (English, United States), DateTime.Now.ToLongDateString() displays "Thursday, February 18, 2016", but if CurrentCulture is set to "es-ES" (Spanish, Spain) the output will be "jueves, 18 de febrero de 2016".

Arquivos de recursoResource files

Um arquivo de recurso é um mecanismo útil para separar cadeias de caracteres localizáveis do código.A resource file is a useful mechanism for separating localizable strings from code. Cadeias de caracteres traduzidas para o idioma não padrão são arquivos de recurso .resx isolados.Translated strings for the non-default language are isolated .resx resource files. Por exemplo, talvez você queira criar um arquivo de recurso em espanhol chamado Welcome.es.resx contendo cadeias de caracteres traduzidas.For example, you might want to create Spanish resource file named Welcome.es.resx containing translated strings. "es" são o código de idioma para o espanhol."es" is the language code for Spanish. Para criar esse arquivo de recurso no Visual Studio:To create this resource file in Visual Studio:

  1. No Gerenciador de Soluções, clique com o botão direito do mouse na pasta que conterá o arquivo de recurso > Adicionar > Novo Item.In Solution Explorer, right click on the folder which will contain the resource file > Add > New Item.

    Menu contextual aninhado: no Gerenciador de Soluções, um menu contextual é aberto para Recursos.

  2. Na caixa Pesquisar modelos instalados, insira "recurso" e nomeie o arquivo.In the Search installed templates box, enter "resource" and name the file.

    Caixa de diálogo Adicionar Novo Item

  3. Insira o valor da chave (cadeia de caracteres nativa) na coluna Nome e a cadeia de caracteres traduzida na coluna Valor.Enter the key value (native string) in the Name column and the translated string in the Value column.

    Arquivo Welcome.es.resx (o arquivo de recurso Welcome em espanhol) com a palavra Hello na coluna Nome e a palavra Hola (Olá, em espanhol) na coluna valor

    O Visual Studio mostra o arquivo Welcome.es.resx.Visual Studio shows the Welcome.es.resx file.

    Gerenciador de Soluções mostrando o arquivo de recurso Welcome em espanhol (es)

Nomenclatura do arquivo de recursoResource file naming

Os recursos são nomeados com o nome completo do tipo de sua classe menos o nome do assembly.Resources are named for the full type name of their class minus the assembly name. 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.For example, a French resource in a project whose main assembly is LocalizationWebsite.Web.dll for the class LocalizationWebsite.Web.Startup would be named Startup.fr.resx. Um recurso para a classe LocalizationWebsite.Web.Controllers.HomeController será nomeado Controllers.HomeController.fr.resx.A resource for the class LocalizationWebsite.Web.Controllers.HomeController would be named 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.If your targeted class's namespace isn't the same as the assembly name you will need the full type name. Por exemplo, no projeto de exemplo, um recurso para o tipo ExtraNamespace.Tools será nomeado ExtraNamespace.Tools.fr.resx.For example, in the sample project a resource for the type ExtraNamespace.Tools would be named 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.In the sample project, the ConfigureServices method sets the ResourcesPath to "Resources", so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. Como alternativa, você pode usar pastas para organizar arquivos de recurso.Alternatively, you can use folders to organize resource files. Para o controlador principal, o caminho será Resources/Controllers/HomeController.fr.resx.For the home controller, the path would be Resources/Controllers/HomeController.fr.resx. Se você não usar a opção ResourcesPath, o arquivo .resx entrará no diretório base do projeto.If you don't use the ResourcesPath option, the .resx file would go in the project base directory. O arquivo de recurso para HomeController será nomeado Controllers.HomeController.fr.resx.The resource file for HomeController would be named 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.The choice of using the dot or path naming convention depends on how you want to organize your resource files.

Nome do recursoResource name Nomenclatura de ponto ou caminhoDot or path naming
Resources/Controllers.HomeController.fr.resxResources/Controllers.HomeController.fr.resx PontoDot
Resources/Controllers/HomeController.fr.resxResources/Controllers/HomeController.fr.resx CaminhoPath

Os arquivos de recurso que usam @inject IViewLocalizer em exibições do Razor seguem um padrão semelhante.Resource files using @inject IViewLocalizer in Razor views follow a similar pattern. O arquivo de recurso de uma exibição pode ser nomeado usando a nomenclatura de ponto ou de caminho.The resource file for a view can be named using either dot naming or path naming. Os arquivos de recurso da exibição do Razor simulam o caminho de seu arquivo de exibição associado.Razor view resource files mimic the path of their associated view file. 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:Assuming we set the ResourcesPath to "Resources", the French resource file associated with the Views/Home/About.cshtml view could be either of the following:

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

  • Resources/Views.Home.About.fr.resxResources/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.If you don't use the ResourcesPath option, the .resx file for a view would be located in the same folder as the view.

RootNamespaceAttributeRootNamespaceAttribute

O atributo RootNamespace fornece o namespace raiz de um assembly quando o namespace raiz de um assembly é diferente do nome do assembly.The RootNamespace attribute provides the root namespace of an assembly when the root namespace of an assembly is different than the assembly name.

Se o namespace raiz de um assembly é diferente do nome do assembly:If the root namespace of an assembly is different than the assembly name:

  • A localização não funciona por padrão.Localization does not work by default.
  • A localização falha devido à maneira como os recursos são pesquisados dentro do assembly.Localization fails due to the way resources are searched for within the assembly. RootNamespace é um valor de tempo de build que não está disponível para o processo em execução.RootNamespace is a build-time value which is not available to the executing process.

Se o RootNamespace é diferente de AssemblyName, inclua o seguinte no AssemblyInfo.cs (com valores de parâmetro substituídos pelos valores reais):If the RootNamespace is different from the AssemblyName, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):

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.The preceding code enables the successful resolution of resx files.

Comportamento de fallback da culturaCulture fallback behavior

Ao procurar por um recurso, a localização participa do "fallback de cultura".When searching for a resource, localization engages in "culture fallback". Começando com a cultura solicitada, se ela não for encontrada, ela será revertida para a cultura pai dessa cultura.Starting from the requested culture, if not found, it reverts to the parent culture of that culture. Além disso, a propriedade CultureInfo.Parent representa a cultura pai.As an aside, the CultureInfo.Parent property represents the parent culture. Isso normalmente (mas nem sempre) significa a remoção do significante do ISO.This usually (but not always) means removing the national signifier from the ISO. Por exemplo, o dialeto do espanhol falado no México é "es-MX".For example, the dialect of Spanish spoken in Mexico is "es-MX". Ele tem o pai "es", ou seja, espanhol, não específico de nenhum país.It has the parent "es"—Spanish non-specific to any country.

Imagine que seu site receba uma solicitação de um recurso “Boas-vindas" usando a cultura"fr-CA".Imagine your site receives a request for a "Welcome" resource using culture "fr-CA". O sistema de localização procura os seguintes recursos, em ordem, e seleciona a primeira correspondência:The localization system looks for the following resources, in order, and selects the first match:

  • Welcome.fr-CA.resxWelcome.fr-CA.resx
  • Welcome.fr.resxWelcome.fr.resx
  • Welcome.resx (se o NeutralResourcesLanguage for "fr-CA")Welcome.resx (if the NeutralResourcesLanguage is "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.As an example, if you remove the ".fr" culture designator and you have the culture set to French, the default resource file is read and strings are localized. O Gerenciador de Recursos designa um padrão ou um recurso de fallback para quando nenhuma opção atende à cultura solicitada.The Resource manager designates a default or fallback resource for when nothing meets your requested culture. 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.If you want to just return the key when missing a resource for the requested culture you must not have a default resource file.

Gerar arquivos de recurso com o Visual StudioGenerate resource files with 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.If you create a resource file in Visual Studio without a culture in the file name (for example, Welcome.resx), Visual Studio will create a C# class with a property for each string. Geralmente isso não é o desejado com o ASP.NET Core.That's usually not what you want with ASP.NET Core. Normalmente você não tem um arquivo de recurso .resx padrão (um arquivo .resx sem o nome de cultura).You typically don't have a default .resx resource file (a .resx file without the culture name). Sugerimos que você crie o arquivo .resx com um nome de cultura (por exemplo Welcome.fr.resx).We suggest you create the .resx file with a culture name (for example Welcome.fr.resx). Quando você criar um arquivo .resx com um nome de cultura, o Visual Studio não gerará o arquivo de classe.When you create a .resx file with a culture name, Visual Studio won't generate the class file. A nossa previsão é que muitos desenvolvedores não criarão um arquivo de recurso de idioma padrão.We anticipate that many developers won't create a default language resource file.

Adicionar outras culturasAdd other cultures

Cada combinação de idioma e cultura (que não seja o idioma padrão) exige um arquivo de recurso exclusivo.Each language and culture combination (other than the default language) requires a unique resource file. Crie arquivos de recurso para diferentes culturas e localidades criando novos arquivos de recurso, nos quais os códigos ISO e de idioma fazem parte do nome do arquivo (por exemplo, en-us, fr-ca e en-gb).You create resource files for different cultures and locales by creating new resource files in which the ISO language codes are part of the file name (for example, en-us, fr-ca, and en-gb). Esses códigos ISO são colocados entre o nome do arquivo e a extensão de arquivo .resx, como em Welcome.es-MX.resx (espanhol/México).These ISO codes are placed between the file name and the .resx file extension, as in Welcome.es-MX.resx (Spanish/Mexico).

Implementar uma estratégia para selecionar o idioma e a cultura para cada solicitaçãoImplement a strategy to select the language/culture for each request

Configurar a localizaçãoConfigure localization

A localização é configurada no método Startup.ConfigureServices:Localization is configured in the Startup.ConfigureServices method:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();
  • AddLocalization Adiciona os serviços de localização ao contêiner de serviços.AddLocalization Adds the localization services to the services container. O código acima também define o caminho de recursos como "Resources".The code above also sets the resources path to "Resources".

  • AddViewLocalization Adiciona suporte para os arquivos de exibição localizados.AddViewLocalization Adds support for localized view files. Nesta amostra, a localização de exibição se baseia no sufixo do arquivo de exibição.In this sample view localization is based on the view file suffix. Por exemplo, "fr" no arquivo Index.fr.cshtml.For example "fr" in the Index.fr.cshtml file.

  • AddDataAnnotationsLocalization Adiciona suporte para as mensagens de validação DataAnnotations localizadas por meio de abstrações IStringLocalizer.AddDataAnnotationsLocalization Adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions.

Middleware de localizaçãoLocalization middleware

A cultura atual em uma solicitação é definida no Middleware de localização.The current culture on a request is set in the localization Middleware. O middleware de localização é habilitado no método Startup.Configure.The localization middleware is enabled in the Startup.Configure method. O middleware de localização precisa ser configurado antes de qualquer middleware que possa verificar a cultura de solicitação (por exemplo, app.UseMvcWithDefaultRoute()).The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()).

var supportedCultures = new[]
{
    new CultureInfo("en-US"),
    new CultureInfo("fr"),
};

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("en-US"),
    // Formatting numbers, dates, etc.
    SupportedCultures = supportedCultures,
    // UI strings that we have localized.
    SupportedUICultures = supportedCultures
});

app.UseStaticFiles();
// To configure external authentication, 
// see: http://go.microsoft.com/fwlink/?LinkID=532715
app.UseAuthentication();
app.UseMvcWithDefaultRoute();

UseRequestLocalization inicializa um objeto RequestLocalizationOptions.UseRequestLocalization initializes a RequestLocalizationOptions object. Em cada solicitação, a lista de RequestCultureProvider em RequestLocalizationOptions é enumerada e o primeiro provedor que pode determinar com êxito a cultura de solicitação é usado.On every request the list of RequestCultureProvider in the RequestLocalizationOptions is enumerated and the first provider that can successfully determine the request culture is used. Os provedores padrão são obtidos da classe RequestLocalizationOptions:The default providers come from the RequestLocalizationOptions class:

  1. QueryStringRequestCultureProvider
  2. CookieRequestCultureProvider
  3. AcceptLanguageHeaderRequestCultureProvider

A lista padrão é apresentada do mais específico ao menos específico.The default list goes from most specific to least specific. Mais adiante neste artigo, veremos como você pode alterar a ordem e até mesmo adicionar um provedor de cultura personalizado.Later in the article we'll see how you can change the order and even add a custom culture provider. Se nenhum dos provedores pode determinar a cultura de solicitação, o DefaultRequestCulture é usado.If none of the providers can determine the request culture, the DefaultRequestCulture is used.

QueryStringRequestCultureProviderQueryStringRequestCultureProvider

Alguns aplicativos usarão uma cadeia de caracteres de consulta para definir a cultura e a cultura da interface do usuário.Some apps will use a query string to set the culture and UI culture. Para aplicativos que usam a abordagem do cabeçalho Accept-Language ou do cookie, a adição de uma cadeia de caracteres de consulta à URL é útil para depurar e testar o código.For apps that use the cookie or Accept-Language header approach, adding a query string to the URL is useful for debugging and testing code. Por padrão, o QueryStringRequestCultureProvider é registrado como o primeiro provedor de localização na lista RequestCultureProvider.By default, the QueryStringRequestCultureProvider is registered as the first localization provider in the RequestCultureProvider list. Passe os parâmetros culture e ui-culture da cadeia de caracteres de consulta.You pass the query string parameters culture and ui-culture. O seguinte exemplo define a cultura específica (idioma e região) como espanhol/México:The following example sets the specific culture (language and region) to Spanish/Mexico:

http://localhost:5000/?culture=es-MX&ui-culture=es-MX

Se você passar somente uma das duas (culture ou ui-culture), o provedor da cadeia de caracteres de consulta definirá os dois valores usando aquela que foi passada.If you only pass in one of the two (culture or ui-culture), the query string provider will set both values using the one you passed in. Por exemplo, a definição apenas da cultura definirá a Culture e a UICulture:For example, setting just the culture will set both the Culture and the UICulture:

http://localhost:5000/?culture=es-MX

CookieRequestCultureProviderCookieRequestCultureProvider

Em geral, aplicativos de produção fornecerão um mecanismo para definir a cultura com o cookie de cultura do ASP.NET Core.Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use o método MakeCookieValue para criar um cookie.Use the MakeCookieValue method to create a cookie.

O CookieRequestCultureProvider DefaultCookieName retorna o nome padrão do cookie usado para acompanhar as informações de cultura preferencial do usuário.The CookieRequestCultureProvider DefaultCookieName returns the default cookie name used to track the user's preferred culture information. O nome padrão do cookie é .AspNetCore.Culture.The default cookie name is .AspNetCore.Culture.

O formato do cookie é c=%LANGCODE%|uic=%LANGCODE%, em que c é Culture e uic é UICulture, por exemplo:The cookie format is c=%LANGCODE%|uic=%LANGCODE%, where c is Culture and uic is UICulture, for example:

c=en-UK|uic=en-US

Se você especificar apenas as informações de cultura e a cultura da interface do usuário, a cultura especificada será usada para as informações de cultura e para a cultura da interface do usuário.If you only specify one of culture info and UI culture, the specified culture will be used for both culture info and UI culture.

O cabeçalho HTTP Accept-LanguageThe Accept-Language HTTP header

O cabeçalho Accept-Language é configurável na maioria dos navegadores e originalmente foi criado para especificar o idioma do usuário.The Accept-Language header is settable in most browsers and was originally intended to specify the user's language. Essa configuração indica que o navegador foi definido para enviar ou herdou do sistema operacional subjacente.This setting indicates what the browser has been set to send or has inherited from the underlying operating system. O cabeçalho HTTP Accept-Language de uma solicitação do navegador não é uma maneira infalível de detectar o idioma preferencial do usuário (consulte Definindo preferências de idioma em um navegador).The Accept-Language HTTP header from a browser request isn't an infallible way to detect the user's preferred language (see Setting language preferences in a browser). Um aplicativo de produção deve incluir uma maneira para que um usuário personalize sua opção de cultura.A production app should include a way for a user to customize their choice of culture.

Definir o cabeçalho HTTP Accept-Language no IESet the Accept-Language HTTP header in IE

  1. No ícone de engrenagem, toque em Opções da Internet.From the gear icon, tap Internet Options.

  2. Toque em Idiomas.Tap Languages.

    Opções da Internet

  3. Toque em Definir Preferências de Idioma.Tap Set Language Preferences.

  4. Toque em Adicionar um idioma.Tap Add a language.

  5. Adicione o idioma.Add the language.

  6. Toque no idioma e, em seguida, em Mover Para Cima.Tap the language, then tap Move Up.

Usar um provedor personalizadoUse a custom provider

Suponha que você deseje permitir que os clientes armazenem seus idiomas e culturas nos bancos de dados.Suppose you want to let your customers store their language and culture in your databases. Você pode escrever um provedor para pesquisar esses valores para o usuário.You could write a provider to look up these values for the user. O seguinte código mostra como adicionar um provedor personalizado:The following code shows how to add a custom provider:

private const string enUSCulture = "en-US";

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo(enUSCulture),
        new CultureInfo("fr")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture);
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;

    options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
    {
        // My custom request culture logic
        return new ProviderCultureResult("en");
    }));
});

Use RequestLocalizationOptions para adicionar ou remover provedores de localização.Use RequestLocalizationOptions to add or remove localization providers.

Definir a cultura de forma programáticaSet the culture programmatically

Este projeto de exemplo Localization.StarterWeb no GitHub contém a interface do usuário para definir a Culture.This sample Localization.StarterWeb project on GitHub contains UI to set the Culture. O arquivo Views/Shared/_SelectLanguagePartial.cshtml permite que você selecione a cultura na lista de culturas compatíveis:The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home" 
          asp-action="SetLanguage" asp-route-returnUrl="@returnUrl" 
          method="post" class="form-horizontal" role="form">
        <label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label> <select name="culture"
          onchange="this.form.submit();"
          asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
        </select>
    </form>
</div>

O arquivo Views/Shared/_SelectLanguagePartial.cshtml é adicionado à seção footer do arquivo de layout para que ele fique disponível para todos os exibições:The Views/Shared/_SelectLanguagePartial.cshtml file is added to the footer section of the layout file so it will be available to all views:

<div class="container body-content" style="margin-top:60px">
    @RenderBody()
    <hr>
    <footer>
        <div class="row">
            <div class="col-md-6">
                <p>&copy; @System.DateTime.Now.Year - Localization</p>
            </div>
            <div class="col-md-6 text-right">
                @await Html.PartialAsync("_SelectLanguagePartial")
            </div>
        </div>
    </footer>
</div>

O método SetLanguage define o cookie de cultura.The SetLanguage method sets the culture cookie.

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

Não é possível conectar o _SelectLanguagePartial.cshtml ao código de exemplo para este projeto.You can't plug in the _SelectLanguagePartial.cshtml to sample code for this project. O projeto Localization.StarterWeb no GitHub contém o código para o fluxo do RequestLocalizationOptions para uma parcial do Razor por meio do contêiner de Injeção de Dependência.The Localization.StarterWeb project on GitHub has code to flow the RequestLocalizationOptions to a Razor partial through the Dependency Injection container.

Termos de globalização e localizaçãoGlobalization and localization terms

O processo de localização do aplicativo também exige uma compreensão básica dos conjuntos de caracteres relevantes geralmente usados no desenvolvimento moderno de software e uma compreensão dos problemas associados a eles.The process of localizing your app also requires a basic understanding of relevant character sets commonly used in modern software development and an understanding of the issues associated with them. Embora todos os computadores armazenem texto como números (códigos), diferentes sistemas armazenam o mesmo texto usando números diferentes.Although all computers store text as numbers (codes), different systems store the same text using different numbers. O processo de localização se refere à tradução da interface do usuário do aplicativo para uma cultura/localidade específica.The localization process refers to translating the app user interface (UI) for a specific culture/locale.

Possibilidade de localização é um processo intermediário usado para verificar se um aplicativo globalizado está pronto para localização.Localizability is an intermediate process for verifying that a globalized app is ready for localization.

O formato RFC 4646 para o nome de cultura é <languagecode2>-<country/regioncode2>, em que <languagecode2> é o código de idioma e <country/regioncode2> é o código de subcultura.The RFC 4646 format for the culture name is <languagecode2>-<country/regioncode2>, where <languagecode2> is the language code and <country/regioncode2> is the subculture code. Por exemplo, es-CL para Espanhol (Chile), en-US para inglês (Estados Unidos) e en-AU para inglês (Austrália).For example, es-CL for Spanish (Chile), en-US for English (United States), and en-AU for English (Australia). O RFC 4646 é uma combinação de um código de cultura de duas letras minúsculas ISO 639 associado a um idioma e um código de subcultura de duas letras maiúsculas ISO 3166 associado a um país ou uma região.RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. Consulte Nome da cultura de idioma.See Language Culture Name.

Muitas vezes, internacionalização é abreviada como "I18N".Internationalization is often abbreviated to "I18N". A abreviação usa a primeira e última letras e o número de letras entre elas e, portanto, 18 significa o número de letras entre o primeiro "I" e o último "N".The abbreviation takes the first and last letters and the number of letters between them, so 18 stands for the number of letters between the first "I" and the last "N". O mesmo se aplica a Globalização (G11N) e Localização (L10N).The same applies to Globalization (G11N), and Localization (L10N).

Termos:Terms:

  • Globalização (G11N): o processo de fazer com que um aplicativo dê suporte a diferentes idiomas e regiões.Globalization (G11N): The process of making an app support different languages and regions.
  • Localização (L10N): o processo de personalizar um aplicativo para determinado idioma e região.Localization (L10N): The process of customizing an app for a given language and region.
  • Internacionalização (I18N): descreve a globalização e a localização.Internationalization (I18N): Describes both globalization and localization.
  • Cultura: um idioma e, opcionalmente, uma região.Culture: It's a language and, optionally, a region.
  • Cultura neutra: uma cultura que tem um idioma especificado, mas não uma região.Neutral culture: A culture that has a specified language, but not a region. (por exemplo, "en", "es")(for example "en", "es")
  • Cultura específica: uma cultura que tem um idioma e uma região especificados.Specific culture: A culture that has a specified language and region. (por exemplo, "en-US", "en-GB", "es-CL")(for example "en-US", "en-GB", "es-CL")
  • Cultura pai: a cultura neutra que contém uma cultura específica.Parent culture: The neutral culture that contains a specific culture. (por exemplo, "en" é a cultura pai de "en-US" e "en-GB")(for example, "en" is the parent culture of "en-US" and "en-GB")
  • Localidade: uma localidade é o mesmo que uma cultura.Locale: A locale is the same as a culture.

Observação

You may not be able to enter decimal commas in decimal fields. To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. This GitHub issue 4076 for instructions on adding decimal comma.

Recursos adicionaisAdditional resources