Concrete Logo
Hamburger button

Um papo sobre Localizable e Constants em Swift

  • Blog
  • 26 de Setembro de 2016
Share

Antes de tudo, importante dizer que esse post foi criado a quatro mãos, ou duas cabeças (ocas… rsrsrs). Já que não dá para atribuir o texto para duas pessoas lá embaixo, queria deixar anotada a participação do Thiago Holanda (ou Trollanda, como é conhecido por alguns).

Esse post foi oriundo de um momento comum que temos aqui na Concrete. Após criar uma feature interessante, corremos na mesa de amigos, mostramos e discutimos melhorias ou alterações. Vou tentar transcrever como foi a conversa sobre essa feature em especial.

Um belo dia, às 9:40, Holanda chegou à CS e… ok, ok, sem tanto detalhe. Estávamos mostrando alguns conceitos que vimos e então o Holanda mostrou uma forma de trabalharmos com Localizable, que basicamente é a utilização de diversos idiomas no app. Trata-se de utilizar enums para abstrair a utilização (e repetição) de NSLocalizedString e organizar a estrutura da chamada dos strings necessários. A estrutura é bem simples, são apenas enums com chaves para cada string no documento (Ex: pt-BR.lproj/Localizable.strings, en.proj/Localizable.strings ou qualquer outro idioma que se queira dar suporte).

Esses documentos utilizam o seguinte padrão:

A partir da localização configurada no iPhone, ele utilizará um desses idiomas (veja aqui mais informações sobre internacionalização de app).

Mas vocês falaram sobre usar enums, como é isso?

A ideia nasceu no Android e foi estendida a alguns frameworks em Swift, como SwiftGen, R.swift e outros. Aplicamos o mesmo conceito, como no exemplo abaixo:

Está ficando mais claro. Mas como utilizamos?

É realmente bem simples usar essa estrutura no seu projeto. Em primeiro lugar, após configurar todos os valores nos enums, você ganha o poder do code completion, o que impede que você se engane na hora de usar o string desejado.
image01

Digamos que você vá configurar o valor em algum UILabel:

Essa estrutura é bem legal! Por que não usá-la para estruturar nossas constantes ou até mesmo para nossas strings de imagens? Boa ideia, vamos lá:

Muito bom! Agora, para usar esse string, basta:

É, assim está meio estranho. Será que podemos melhorar isso? Claro! Vamos lá.

Inicializar o NSLocalizedString, assim como UIImage toda vez pode ser cansativo (e feio). Uma extensão pode ser útil para colocarmos isso em propriedades. Vamos lá:

Swift nos dá uma gama de protocolos que são implementados por alguns tipos. Por exemplo, o enum implementa o RawRepresentable, que nos permite usar a propriedade rawValue, que é o valor correspondente ao raw, aquele que atribuímos em cada case (Exemplo: “common.change”). Além disso, garantimos que seu tipo é String usando where RawValue == String. Com isso, apenas enums que têm seu rawValue string poderão utilizar as variáveis image e localized.

Hmmmm… interessante! E a chamada?

Opa, tá bem melhor! Mas olhando bem, a chamada abaixo pode dar problema:

Sim, não existe essa imagem, o string se refere a um Localizable. Droga! O que podemos fazer?

image00

Programação Orientada a Protocolo FTW! (Nota do Erick: sou meio dislexo escrevendo, olhei 10 vezes para ter certeza que não escrevi WTF.. rsrsrsrs)!

Uma das grandes features do Swift 2.0 é permitir extensões de Protocolo. Com isso, conseguimos atribuir um comportamento a nossos enums separadamente. Como fazer isso? Vamos começar com os protocolos:

Adicionamos responsabilidades específicas para cada protocolo, eles implementam RawRepresentable e possuem propriedades que definem sua responsabilidade. Assim, podemos criar extensions desses protocolos e implementar nossas propriedades como no exemplo a seguir:

Nota 1: a documentação da Apple nos diz que caso uma imagem não possa ser encontrada quando informamos o “named” dela, o retorno será nil. Dessa forma, é necessário configurar a nossa propriedade como Optional (UIImage?) e testar com um If let na hora de chamar a propriedade image.

Nota 2: normalmente, vemos o uso do NSLocalizedString(_:comment🙂 com as frases prontas previamente, como NSLocalizedString(“Olá Mundo”, comment: nil). Dessa forma, caso essa frase não seja encontrada nos arquivos Localizable.string, essa mesma frase é retornada. No caso desse artigo, incentivamos o uso dessa estrutura de “path” (“common.change”). Se por algum motivo você seguir a sugestão do post e usar essa forma de identificação das frases, não esqueça de adicionar essa chave com a frase traduzida em todos os arquivos Localizable.string. Se isso não for feito, existe o risco de você encontrar em algum label, button ou qualquer outro elemento um texto parecido com: common.change.

Implementamos nossas variáveis nas extensões, agora basta aplicar nossos protocolos aos seus devidos enums:

E Voilà!

image02

Adicionamos comportamentos distintos para cada enum. User possui a propriedade image e não possui localized, e Common possui localized mas não image.

Você ainda pode perguntar: “mas por que diabos isso serve pra mim ?”

Então… Você pode minimizar e/ou dificultar que erros básicos possam ocorrer, como por exemplo digitar errado o nome de uma imagem ou localizável ou mudar a string apenas em um lugar e não por todo o código, o que pode prevenir dores de cabeça desnecessárias.

Bem, é isso! Temos certeza que ainda podemos melhorar de outras formas, até porque nunca está legal o suficiente. E por que não ajudar a gente a melhorar? Deixe comentários e dicas, vamos fazer algo mais legal! =) 

Veja o exemplo completo aqui.

É desenvolvedor iOS e quer trabalhar em um time ágil de verdade? Clique aqui.