Localization em Web APIs dotnet 6/7
Motivação
Criei este documento para registrar algo não encontrei um bom material compilado para ler. Então reuni todas as informações que encontrei e organizei de forma mais lógica, para facilitar a vida de quem precisar utilizar este recurso.
Aplicação
- Web APIs dotnet 6 e 7 (foco do material)
- Web Applications dotnet 6 e 7
Incluindo middleware de localização
Primeiro é necessário configurar a classe Program com as informações de Localização
Importante: a posição da inclusão dos parâmetros é relevante
builder.Services.AddLocalization();
var supportedCultures = new[] { "en", "pt-BR", "pt-PT", "es", "fr", "ru" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture("en")
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
Detalhamento
var supportedCultures = new[] { "en", "pt-BR", "pt-PT", "es", "fr", "ru" }; - A lista de idiomas que estarão disponíveis. A lista de language tags está disponivel aqui
var localizationOptions = new RequestLocalizationOptions() - Objeto sendo instânciado
.SetDefaultCulture("en") - É possivel passar o parametro de duas formas, ou como uma string, ou passando o array criado anteriormente indicando o índice da linguagem que será o padrão, por exemplo supportedCultures[0]. Este será o idioma padrão da API quando não for passado nenhum idioma
.AddSupportedCultures(supportedCultures) - indica para qual idioma o sistema deve alterar a apresentação de formatação de datas, números, moedas, etc.
.AddSupportedUICultures(supportedCultures); - Indica quais os idiomas vão ter suporte dentro da API para tradução de termos.
Arquivo de resources
Com a API configurada devemos criar os arquivos de resources, existem 3 abordagens
Nomeando por Path
Um arquivo relacionado a cada Controller ou View criado na mesma estrutura de pastas. Ex: Controllers/Calculos/Soma.en.resx
Arquivos de recursos sendo criados com a mesma estrutura de pasta da Controller e da View |
Resource por "dot file"
- Um arquivo para cada Controller todos na mesma pasta, nomeados com a estrutura de pastas da controler separada por pontos. Ex: Controllers.Calculos.Soma.en.resx
Arquivo de recursos indicando o caminho no nome do arquivo, separando nome das pastas por pontos |
Um único arquivo para todas as Controllers
Criar uma pasta ou Projeto onde a classe de recursos e os recursos serão armazenados.
Pasta onde a classe de recursos doi criada |
Classe dummy de recursos, vazia para agregar os arquivos de recursos |
Nessa pasta onde foi criado a classe Resource, cria-se um arquivo de recursos |
Adicionando a sigla do idioma ao nome do resource, ele automaticamente deve se aninhar a classe Resource. |
Arquivos aninhados |
Dentro do Resource
O arquivo de recursos tem 3 campos, Name (chave), Value (valor), Comment (comentário) |
Aplicando Localization
Obs: Vou focar na explicação do uso da terceira forma de uso de recursos, um arquivo único para todas as controllers.
Dentro da controller é necessário injetar uma Interface de IStringLocalizer do tipo da classe criada anteriormente, no caso deste exemplo, Resource e inicializar o objeto no construtor.
private readonly IStringLocalizer<Resource> _localizer;
public ResoucesTesteController(IStringLocalizer<Resource> localizer)
{
_localizer = localizer;
}
Para utilizar o localizer, basta chamar a instância injetada, passando a chave do resource
[HttpGet("ResourceCadeira")]
public string ResourceCadeira()
{
return _localizer["stringCadeira"];
}
Também é possivel recuperar a lista de strings existencer no resource:
[HttpGet("ResourceStringList")]
public List<string> ResourceStringList()
{
return _localizer.GetAllStrings().ToList().Select(s => s.Value).ToList();
}
Ou ainda uma lista de objetos do tipo LocalizedString
[HttpGet("ResourceList")]
public List<LocalizedString> ResourceList()
{
return _localizer.GetAllStrings().ToList();
}
Como utilizar
Ao fazer a requisição na API, adicione a querystring ?culture=fr no final do link para o endpoint utilizar o idioma indicado. Alguns exemplos de uso:
Utilizando o idioma Francês |
Utilizando o idioma Russo |
Utilizando o idioma pt-BR |
Utilizando o idioma padrão do sistema |
Conclusão
Meu caso de uso é tradução de mensagens de erros enviadas pela API, facilita bastante o dia a dia, pois preciso me preocupar apenas com as mensagens no meu idioma e criar chaves para estas mensagens.
Repositório
A aplicação que crie para a POC (proof of concept) está no meu github para consulta, está em docker, então para rodar na máquina provavelmente será necessário instalar o docker. Se você não usa docker, recomendo fortemente aprender nem que seja o básico, foi um divisor de águas na minha vida profissional.
https://github.com/khayo/ResourcesTeste