Internacionalização orientada a protocolo

Essa postagem foi feita utilizando Xcode 9.2 e Swift 4.

Para melhor entendimento desta postagem você deve ter conhecimento sobre:

Programação orientada a protocolo :

Sumário

Neste post você vai aprender sobre:

  • O que é internacionalização?
  • Por que internacionalizar?
  • Como eu posso internacionalizar?
  • Como internacionalizar orientado a protocolo?

O que é internacionalização?

Quando falamos sobre internacionalização ou localização de aplicações estamos nos referindo a possibilidade de adaptar o aplicativo de acordo com o idioma e região do dispositivo do usuário.

Essa adaptação não está restrita apenas a textos, mas também abrange valores como moedas, unidades de medida, datas e imagens. Porém iremos nos limitar a internacionalização de textos do seu aplicativo.

Por que internacionalizar?

Para justificar todo o trabalho envolvido a localizar seu aplicativo para diversas línguas e culturas nós vamos precisar falar de estatísticas de fatia de mercado.

Segundo o site www.statista.com o iOS terminou o ano de 2017 com 9,68% do mercado nacional (https://www.statista.com/statistics/262167/market-share-held-by-mobile-operating-systems-in-brazil/), contando com a continentalidade do nosso país é um número bastante alto de usuários, porém há um público bem maior fora do nosso país, como podemos ver na imagem abaixo.

9to5mac

Temos grandes mercados utilizando o sistema da maçã e com o crescente número de aplicativos para atender as suas demandas não faz sentido o usuário baixar um aplicativo em outra língua para resolver algum problema. Então ao internacionalizar o seu aplicativo você se torna mais competitivo na guerra por downloads da App Store.

Como eu posso internacionalizar?

Existem duas maneiras de internacionalizar seus textos em uma aplicação para iOS. A primeira é através da Storyboard e de xibs e a segunda é programaticamente utilizando Localizable.strings, neste artigo vamos falar apenas da segunda.

Localizable.strings

Neste modo nós devemos criar um arquivo de String com o nome de Localizable. Criando este arquivo nós poderemos colocar uma série de itens usando notação de chave-valor(Ex: “title” = “Título”;), observe que o uso da marcação (;) é necessário para este tipo de arquivo.

Após criar esse arquivo, devemos clicar no arquivo Localizable.strings e adicionar um idioma novo no File Inspector.

Ao clicar no botão note que você irá possuir apenas o idioma base do projeto, deve-se adicionar os novos idiomas desejados. Para acrescentar uma nova lingua selecione o projeto, na secção Localizations clique em + e escolha o novo idioma. Ao fazer isso serão criadas cópias do arquivo de string, onde o trabalho de tradução será feito. Sempre seguindo o modelo key” = “value”;.

Desta forma para usarmos essa String nós precisamos utilizar uma NSLocalizedString, o construtor recebe uma string chamada key e outra chamada comment. O parâmetro key deve ter equivalência com alguma key string do arquivo Localizable.strings, caso isso aconteça a string construída será a que for usada como valor do arquivo de strings, dependendo do idioma que o dispositivo do usuário está configurado.

Como internacionalizar orientado a protocolo?

A fim de promover reuso e aumentar a segurança na localização do aplicativo iremos utilizar uma abordagem orientada a protocolo.

Iremos trabalhar com dois protocolos, um deles para ser utilizado em conjunto com um enum e o outro em uma controller. Vamos iniciar com o protocolo criado para ser implementado por um enum, porém nada impede deste protocolo seja utilizado em outro contexto.

Protocolo para o enum.

Pode parecer um pouco complexo, mas vamos explicar cada parte do código.

1 — Um protocolo chamado Localizable que implementa os protocolos CustomStringConvertible e RawRepresentable. Para se adequar ao primeiro é necessário declarar uma variável chamada description, esta variável será usada quando uma instância que implemente esse protocolo precise implicitamente ser convertida em uma string, por exemplo na concatenação/interpolação de strings, realizar um print da instância e em testes. No nosso caso poderemos utilizar o case do enum para realizar uma concatenação. Já o RawRepresentable é um protocolo que permite conversão de tipos para um tipo associado (associatedtype) chamado RawValue, ou seja, o tipo que implementar RawRepresentable pode ser convertido ou construído a partir de algum outro tipo.

Criamos um Fruit através de uma String e podemos converter um Fruits em string através do rawValue.

2 — Ao fazer uma extensão do protocolo podemos definir um comportamento padrão (default implementation) para quem implementar o protocolo em questão, desta forma diminuímos a quantidade de código que temos que escrever já que todos usarão o que está definido na extensão, potencializando o reuso de código.

Caso seja necessário realizar alguma ação diferente do procedimento padrão é possível que o tipo implemente um comportamento específico para ele. Note que não foi criado nenhum valor padrão para a variável comment, logo quem implementar o protocolo Localizable terá que definir essa propriedade.

Na extensão existe uma cláusula condicional (where) para restringir a implementação padrão apenas para os casos onde o RawValue é do tipo String, ou seja, se o RawValue não obedecer essa limitação imposta através da condicional não será aplicada a implementação padrão.

3 — A declaração padrão da propriedade localizable traz a chamada da função global NSLocalizedString que explicamos no tópico anterior, a key passada é o rawValue (com r minúsculo). O rawValue é o valor convertido para o tipo do associatedtype RawValue. Quando um enum possui RawValue como String o rawValue é o case como texto, exemplo: se o case do enum for title por padrão o rawValue dele é "title".

4 — O description é a variável que será usada quando a instância do tipo que implementa o protocolo CustomStringConvertible é usado para nos dar a flexibilidade de utilizar o case diretamente na concatenação de string sem a necessidade de chamar a propriedade localizable.

ViewController

Para utilizar este método criamos uma controller modelo.

Vamos explicando os pontos:

1 — Podemos usar a String destas duas formas. A segunda forma só é possível por conta da implementação de CustomStringConvertible.

2 — Por conta do associatedtype Strings o protocolo te força a declarar algo com a mesma assinatura, desta forma podemos escrever de forma mais padronizada. Podendo cada controller ter sua própria enum com seus cases de localização. Evitando a criação de uma struct que contém todas as strings do projeto na forma de constantes estáticas, por exemplo.

Conclusão

Esta é uma abordagem diferente para fazer a internacionalização do seu aplicativo, como pontos positivos:

  • Uma abordagem fortemente tipada deixando o código mais seguro evitando erro de digitações nas chaves de localização;
  • Não possui code smells em relação a Strings;
  • O uso de enums fornece o uso do auto-completion do Xcode.
  • Cada controller possui as chaves que lhe dizem respeito, facilitando a manutenção do código;
  • Podemos facilmente integrar com strings concatenadas mantendo a legibilidade do código, pois não teremos que acrescentar NSLocalizedString durante uma concatenação;

Porém nem tudo são flores e também temos pontos negativos:

  • Falta de um controle de acesso eficiente, ou seja, as controllers tem acesso a enum de Strings uma das outras;

Obrigado por sua atenção, espero que as informações desse post tenham ficado claras para você.

O projeto está disponível no github: https://github.com/davicabral/protocol-oriented-localization

--

--