ASP.NET.Core
- Criando API Multilíngues
![]() |
Neste artigo veremos como criar uma API multilíngue na ASP.NET Core. |
Criar APIs multilíngues em ASP.NET Core significa oferecer suporte a vários idiomas para os recursos retornados pela sua API. Isso é particularmente útil quando você deseja fornecer respostas localizadas para diferentes usuários com base em suas preferências de idioma. O suporte multilíngue geralmente envolve a tradução dinâmica de mensagens de texto, mensagens de erro e outros recursos da API.
Os principais termos usados quando estamos tratando com a globalização são:
Globalização (G11N): O processo de fazer um aplicativo
suportar diferentes idiomas e regiões. A abreviatura vem da primeira e da última
letras e do número de letras entre elas.
Localização (L10N):
O processo de personalização de um aplicativo globalizado para idiomas e regiões
específicas.
Internacionalização (I18N): Globalização e localização.
Culture: Um idioma e, opcionalmente, uma região.
Neutral culture (Cultura neutra): Uma cultura que possui um
idioma específico, mas não uma região (por exemplo, "en", "es").
Specific Culture (Cultura específica) : uma cultura que possui um
idioma e uma região específicos (por exemplo, "en-US", "en-GB", "es-CL").
Parente Culture (Cultura pai) : A cultura neutra que contém
uma cultura específica (por exemplo, “en” é a cultura pai de “en-US” e “en-GB”).
Locale (Localidade) : Uma localidade é o mesmo que uma
cultura.
Veremos como preparar a aplicação para globalização e localização, como criar e gerenciar arquivos de recursos, como usar traduções no código da aplicação e por fim, veremos estratégias de seleção de idioma.
Preparando a sua aplicação para a globalização
Vamos criar um novo projeto usando o template ASP.NET Core Web API e nomeá-lo como ApiMultilingue usando o .NET 8.0 e habilitando o suporte a OpenApi e o uso de controladores, e, iniciar a configuração dos serviços para globalização.
No projeto vamos criar a pasta Resources onde iremos armazenar os arquivos de recursos usados na aplicação e vamos criar a pasta Models onde vamos criar a classe User com o seguinte código:
| public class
User { [Required(ErrorMessage = "The Name field is required.")] [StringLength(50, ErrorMessage = "The Name field cannot be more than 50 characters.")] public string Name { get; set; } [Required(ErrorMessage = "The Email field is required.")] [EmailAddress(ErrorMessage = "The Email field does not have a valid format.")] public string Email { get; set; } } |
Agora crie na pasta Controllers os controladores AboutController , UserController e HomeController que iremos usar mais adiante.
Quando falamos em globalização estamos nos referindo ao processo de fazer com que um aplicativo suporte diferentes idiomas e regiões, formatos de datas, moedas, etc.
A primeira tarefa a realizar é configurar o serviço de localização na classe Program:
AddLocalization(…) - Configura os serviços que podemos
usar posteriormente em nossos componentes e controladores.
ResourcesPath - Especifica a pasta que contém os arquivos de
recursos.
A seguir precisamos adicionar o suporte a localização nos middlewares
|
// Configure e habilita a localização baseada em request app.UseRequestLocalization(); |
O principal objetivo desta configuração é detectar e definir a cultura para cada request HTTP recebido com base na preferência do usuário, informações do navegador ou qualquer outra lógica personalizada definida, geralmente baseada em cabeçalhos HTTP como Accept-Language e outras opções como QueryString ou por meio de cookies, que veremos mais tarde.
Podemos configurar as opções de localização definindo o seguinte código na classe Program:
|
builder.Services.Configure<RequestLocalizationOptions>(options
=> { var supportedCultures = new[] { "en-US", "es-ES" }; options.SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); }); |
Essa configuração global é essencial para garantir que as operações de localização na aplicação respeitem as preferências do usuário quanto ao idioma.
Aqui temos o seguinte:
«RequestLocalizationOptions» é a classe utilizada para
configurar as opções de localização da solicitação.
«supportedCultures[…]» define a cultura padrão a ser usada se nenhuma
preferência de cultura for especificada na solicitação.
«AddSupportedCultures(…)» define a lista de culturas suportadas pela
aplicação.
«AddSupportedUICultures(…)» define as culturas
suportadas para a interface do usuário (IU).
Criando e gerenciando os arquivos de recursos
Quando falamos em localização estamos nos referindo ao
processo de customização de uma aplicação para regiões e idiomas específicos.
Isto envolve a tradução de textos e conteúdos para os idiomas suportados.
Assim precisamos criar os arquivos de recursos, que são as strings de texto
para cada cultura, a cultura é um código de idioma e opcionalmente um código de
país ou região (“en”, “en-US”)
O formato RFC 4646 para o nome da cultura é <language code>-<country/region code>, onde <language code> identifica o idioma e <country/region code> identifica a subcultura. Por exemplo, es-CL para espanhol (Chile), en-US para inglês (Estados Unidos) e en-AU para inglês (Austrália).
Na pasta "Resources" podemos criar
os arquivos de recursos para cada cultura suportada. Por exemplo, para inglês
(padrão) e português (Brasil), você teria os seguintes arquivos:
Resources/Strings.en-US.resx e
Resources/Strings.pt-BR.resx.
Nota: Para criar os arquivos seleciona a opção Add New Item e informe resource selecinando a opção Resources file.
Vamos criar dentro da pasta Resources a pasta Controllers e definir arquivos de recursos para o inglês e para o espanhol
Backend
├── Resources
│ ├── Controllers
│ ├── AboutController.en-US.resx (Inglês americano)
│ ├── AboutController.en.resx (Inglês)
│ ├── AboutController.es-ES.resx (Espanhol de Espanha)
│ └── AboutController.es.resx (Espanhol)
└── ...
No nosso exemplo vamos usar a nomenclatura definindo o caminho para organizar os arquivos de recursos para os idiomas e uma vez criado os recursos ,
Assim, para criar o arquivo AboutController.en-US.resx na pasta Controllers usamos a opção mostrada abaixo:

O arquivo será aberto e escrevemos o valor da chave na coluna 'Name' e a string traduzida na coluna 'Value'.

Vamos criar um arquivo para cada idioma.
Com isso podemos usar os arquivos de recursos em nossa API.
Fazendo traduções no código da aplicação
Podemos usar a interface IStringLocalizer para encontrar strings de texto.
A interface IStringLocalizer
faz parte do sistema de localização no ASP.NET Core e é usada para obter cadeias
de caracteres localizadas a partir dos arquivos de recursos correspondentes para
diferentes culturas. Essa interface é fundamental para a internacionalização e
localização de uma aplicação, permitindo que você forneça mensagens e recursos
específicos de idioma com base nas preferências do usuário.
A interface IStringLocalizer
define métodos que permitem obter cadeias de caracteres localizadas de
diferentes maneiras. Geralmente, você injeta essa interface em seus
controladores, serviços ou outros componentes da aplicação.
Para nosso exemplo, iremos utilizá-lo no controlador, injetando o serviço e utilizando as strings de texto conforme mostrado a seguir:
using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; namespace ApiMultilingue.Controllers; [ApiController] [Route("api/[controller]")] public class AboutController : ControllerBase { private readonly IStringLocalizer<AboutController> _localizer; public AboutController(IStringLocalizer<AboutController> localizer) { _localizer = localizer; } [HttpGet] public string Get() { return _localizer["About Title"]; } } |
Usando traduções em
mensagens de erro
Também podemos utilizá-lo para retornar
as mensagens de erro que a API retorna ao usuário ou desenvolvedor quando ocorre
algum problema, como “Erro 404: Recurso não encontrado” ou “Erro
de autenticação”, elas podem exigir tradução se a API for destinada a
usuários ou desenvolvedores que falam idiomas diferentes.
[ApiController
|
Usando traduções com
DataAnnotations
Podemos adaptar as mensagens de validação
e rótulos gerados automaticamente pelas anotações de validação do
DataAnnotations para diferentes idiomas e regiões, permitindo que as mensagens
sejam exibidas de acordo com as preferências culturais dos usuários.
public
class
User |
Precisamos adicionar o método «AddDataAnnotationsLocalization(…)» que é usado para configurar a localização de mensagens de validação com base em anotações de dados no aplicativo.
|
builder.Services.AddControllers() .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource)); }); |
Neste código
«options.DataAnnotationLocalizerProvider» é o provedor de
localização de anotação de dados. Isso significa que quando as mensagens de
validação precisarem ser localizadas, um recurso compartilhado (classe
SharedResource) será usado como fonte de localização.
Assim
vamos criar na pasta Resources os arquivos SharedResource para
cada idioma traduzindo o texto.

E finalmente podemos criar o método Action no controlador UserController que trata o método HTTP POST:
[Route("api/[controller]")] |
Aqui é verificado se o modelo “User” passado como parâmetro atende às regras de validação definidas em sua classe e caso não cumpra, exibe as mensagens de validação no idioma do usuário.
Recursos compartilhados
entre componentes
Os recursos compartilhados referem-se a
arquivos de recursos que contêm sequências de texto usadas em vários componentes
de um aplicativo. A ideia por trás dos recursos compartilhados é centralizar e
reutilizar traduções em diferentes componentes da aplicação.
Criamos os
arquivos de recursos compartilhados na pasta “Resources”:
Resources
│ ├── SharedResource.en-US.resx (Inglés estadounidense)
│ ├── SharedResource.en.resx (Inglés)
│ ├── SharedResource.es-ES.resx (Español de España)
│ ├── SharedResource.es.resx (Español)
│ └── ...
Precisamos criar na raiz do projeto o arquivo SharedResource.cs contendo o código:
| namespace ApiMultilingue; public class SharedResource { } |
E com isso podemos usar estes recursos em diferente controllers da nossa aplicação:
| [ApiController] [Route("api/[controller]")] public class HomeController : ControllerBase { private readonly IStringLocalizer public HomeController(IStringLocalizer { _sharedLocalizer = sharedLocalizer; } [HttpGet] public IActionResult Get() { return Ok(_sharedLocalizer["Your application shared resources."].Value); } |
Estratégias de seleção
de idioma ou cultura
O idioma refere-se às seleções
feitas por um usuário nas configurações do navegador, cookies, configurações de
consulta e outras fontes, mas o aplicativo, em última análise, define a
propriedade CurrentCulture do idioma solicitado pelo usuário.
«RequestCultureProviders» permitem que a aplicação
determine a cultura preferida do usuário com base nas informações fornecidas
pelo navegador, cookies, parâmetros de consulta e outras fontes. Podemos
configurar vários provedores, lembrando que a ordem em que esses provedores são
adicionados afeta a prioridade com que é escolhida a cultura preferida do
usuário. Os RequestCultureProviders são avaliados na ordem em
que são cadastrados nas configurações de localização do app.
Para
realizar a detecção de idioma via cabeçalho HTTP Accept-Language
usamos o provedor
AcceptLanguageHeaderRequestCultureProvider
que determina a cultura preferida.
builder.Services.Configure<RequestLocalizationOptions>(options => { var SupportedCultures = new[] { "en-US", "es-ES", "en", "es" }; options.SetDefaultCulture(SupportedCultures[0]) .AddSupportedCultures(SupportedCultures) .AddSupportedUICultures(SupportedCultures) .RequestCultureProviders = new List<IRequestCultureProvider> { new AcceptLanguageHeaderRequestCultureProvider(), //new QueryStringRequestCultureProvider(), //new CookieRequestCultureProvider(), //new RouteDataRequestCultureProvider(), /*new CustomRequestCultureProvider(async context => { //Here logic to determine the culture //This example simulates getting the culture "es-ES" as the default. string culture = "es-ES"; return new ProviderCultureResult(culture); })*/ }; }); |
Seleção do idioma usando QueryString
O provedor QueryStringRequestCultureProvider determinará a cultura preferida com base nos valores da string de consulta do URL.
.RequestCultureProviders = new List<IRequestCultureProvider>
{
new QueryStringRequestCultureProvider(),
...
};
Para alterar o idioma, modifique a string de consulta, por exemplo, localhost/api/home?culture=en-US, localhost/api/home?culture=es-ES
Seleção do idioma via cookie
O provedor CookieRequestCultureProvider determinará a cultura preferida com base em um cookie na solicitação.
.RequestCultureProviders = new List<IRequestCultureProvider>
{
new CookieRequestCultureProvider(),
...
};
Para alterar a linguagem invoque o método SetLanguage :
[HttpPost]
public IActionResult SetLanguage(string culture)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);
return Ok();
}
Para deletar o cookie chame 'ClearLanguage' :
[HttpDelete("ClearLanguage")] public IActionResult ClearLanguage() { Response.Cookies.Delete(CookieRequestCultureProvider.DefaultCookieName); return Ok(); }
Seleção de idioma via path
O provedor RouteDataRequestCultureProvider determina a cultura preferida baseado nos valores do path na URL:
.RequestCultureProviders = new List<IRequestCultureProvider>
{
new RouteDataRequestCultureProvider(),
...
};
Seleção do idioma customizado
O provedor customizado CustomRequestCultureProvider pode implementar uma lógica específica para determinar a cultura preferida:
.RequestCultureProviders = new List<IRequestCultureProvider>
{
new CustomRequestCultureProvider(async context =>
{
// Here logic to determine the culture
// This example simulates getting the culture "en-US" as the default.
string culture = "es-ES";
return new ProviderCultureResult(culture);
}),
...
};
Para testar as diferentes formas de seleção de idiomas, comente os provedores e deixe apenas aquele que deseja experimentar. Você também pode tentar mais de um provedor, basta manter a ordem em mente.
.RequestCultureProviders = new List<IRequestCultureProvider>
{
new AcceptLanguageHeaderRequestCultureProvider(),
new QueryStringRequestCultureProvider(),
//new CookieRequestCultureProvider(),
//new RouteDataRequestCultureProvider(),
//new CustomRequestCultureProvider(async context => {...})
};
E estamos conversados...
Pegue o projeto aqui : ApiMultilingue.zip
"Ora, o fim do mandamento é o amor de um
coração puro, e de uma boa consciência, e de uma fé não fingida."
1 Timóteo 1:5
Referências:
C# - Tasks x Threads. Qual a diferença
DateTime - Macoratti.net
Null o que é isso ? - Macoratti.net
Formatação de data e hora para uma cultura ...
C# - Calculando a diferença entre duas datas
NET - Padrão de Projeto - Null Object Pattern
C# - Fundamentos : Definindo DateTime como Null ...
C# - Os tipos Nullable (Tipos Anuláveis)