<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Felipe Pedrosa</title>
    <description>The latest articles on Forem by Felipe Pedrosa (@felipepedrosa).</description>
    <link>https://forem.com/felipepedrosa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F696098%2F5d695a09-a5d9-46b0-80e0-8df79655a325.jpeg</url>
      <title>Forem: Felipe Pedrosa</title>
      <link>https://forem.com/felipepedrosa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/felipepedrosa"/>
    <language>en</language>
    <item>
      <title>Como internacionalizar as mensagens de suas APIs criadas com Spring ?</title>
      <dc:creator>Felipe Pedrosa</dc:creator>
      <pubDate>Mon, 13 Dec 2021 19:43:59 +0000</pubDate>
      <link>https://forem.com/felipepedrosa/como-adicionar-internacionalizacao-as-mensagens-de-sua-api-80e</link>
      <guid>https://forem.com/felipepedrosa/como-adicionar-internacionalizacao-as-mensagens-de-sua-api-80e</guid>
      <description>&lt;p&gt;Quando pensamos em internacionalizar nossas APIs parece que será uma tarefa extremamente árdua, quando na verdade é relativamente simples. Nesse post iremos ver como aplicar a internacionalização à sua API!&lt;/p&gt;

&lt;p&gt;Para nossa implementação iremos utilizar apenas as dependências WEB e DevTools do Spring. Utilizando o inicializador do Spring, crie um projeto com as dependências citadas acima.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qOlKI6OQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59to89uv1tjnlh3smgbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qOlKI6OQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59to89uv1tjnlh3smgbk.png" alt="Spring initializer, using Web and DevTools extensions" width="880" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como estamos criando uma implementação bem simples, criarei apenas um pacote de controllers e dentro será adicionada uma classe chamada MessageController. Esse controller irá receber chamadas no endpoint "/message" e "/messages" e conterá apenas um método mapeado com o método HTTP GET, onde é obrigatório que o header "name" seja informado e o header "accept-language" é opcional (mas extremamente necessário para a internacionalização funcionar).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;io.github.felipepedrosa.springapiinternationalization.controllers&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.MessageSource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.i18n.LocaleContextHolder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.http.ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RequestHeader&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RequestMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RestController&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"/messages"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/message"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MessageController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;MessageSource&lt;/span&gt; &lt;span class="n"&gt;messageSource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MessageController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageSource&lt;/span&gt; &lt;span class="n"&gt;messageSource&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;messageSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messageSource&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getGreetingMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestHeader&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messageSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"greeting.withName"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;[]{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;},&lt;/span&gt;
                &lt;span class="nc"&gt;LocaleContextHolder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLocale&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para obtenção das mensagens iremos injetar o &lt;code&gt;MessageSource&lt;/code&gt;&lt;br&gt;
desta forma será possível recuperar as mensagens criadas no diretório de recursos, nesse diretório serão adicionados três arquivos &lt;code&gt;.properties&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;messages.properties com o conteúdo
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;greeting.withName&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Hi {0}, are you fine?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;messages_pt.properties com o conteúdo
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;greeting.withName&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Oi {0}, como vai?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;messages_fr.properties com o conteúdo
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;greeting.withName&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Salut {0}, ça va?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas você deve estar se perguntando onde está sendo feita a definição de qual mensagem será selecionada, ao executar o método &lt;code&gt;messageResouce.getMessage()&lt;/code&gt; foi passado como parâmetro o &lt;code&gt;LocaleContextHolder.getLocale()&lt;/code&gt; é ele quem faz toda a mágica e é responsável por obter o Locale informado na requisição, caso não exista irá utilizar a mensagem padrão (que vem do messages.properties - arquivo que está em inglês).&lt;/p&gt;

&lt;p&gt;Pronto, dessa maneira sua API está internacionalizada! Vale lembrar que a estrutura que fiz aqui não é obrigatória, então o MessageSource pode ser utilizado na camada de serviços ou em qualquer outra que faça sentido para você.&lt;/p&gt;

&lt;p&gt;Abaixo resultado das requisições, caso queira mais informações &lt;a href="https://github.com/felipepedrosa/spring-api-internationalization"&gt;acesse o repositório da implementação&lt;/a&gt; (&lt;strong&gt;lá existem testes unitários para a mesma :D&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ncQaOJUz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/weyvqzcnz6wmiypo7x6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ncQaOJUz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/weyvqzcnz6wmiypo7x6f.png" alt="Mensagem em Inglês" width="824" height="347"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ND-FY1-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeti9y7he3mge5daljut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ND-FY1-p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeti9y7he3mge5daljut.png" alt="Mensagem em Português" width="805" height="384"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yW1OgCK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcutbmdzv2jfjbalmgs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yW1OgCK1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcutbmdzv2jfjbalmgs5.png" alt="Mensagem em francês" width="822" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>api</category>
      <category>springboot</category>
      <category>developer</category>
    </item>
  </channel>
</rss>
