Localização no Xamarin.iOS
Este documento aborda os recursos de localização do SDK do iOS e como acessá-los com o Xamarin.
Consulte as Codificações de Internacionalização para obter instruções sobre como incluir conjuntos de caracteres/páginas de código em aplicativos que devem processar dados não-Unicode.
Recursos da plataforma iOS
Esta seção descreve alguns dos recursos de localização no iOS. Vá para a próxima seção para ver códigos e exemplos específicos.
Idioma
Os usuários escolhem seu idioma no aplicativo Configurações . Essa configuração afeta as cadeias de caracteres de idioma e as imagens exibidas pelo sistema operacional e em aplicativos.
Para determinar o idioma que está sendo usado em um aplicativo, obtenha o primeiro elemento de NSBundle.MainBundle.PreferredLocalizations
:
var lang = NSBundle.MainBundle.PreferredLocalizations[0];
Esse valor será um código de idioma, como en
para inglês, espanhol, japonês, es
ja
etc. O valor retornado é restrito a uma das localizações suportadas pelo aplicativo (usando regras de fallback para determinar a melhor correspondência).
O código do aplicativo nem sempre precisa verificar esse valor – o Xamarin e o iOS fornecem recursos que ajudam a fornecer automaticamente a cadeia de caracteres ou o recurso correto para o idioma do usuário. Esses recursos são descritos no restante deste documento.
Observação
Use NSLocale.PreferredLanguages
para determinar as preferências de idioma do usuário, independentemente das localizações suportadas pelo aplicativo. Os valores retornados por esse método foram alterados no iOS 9; consulte a Nota Técnica TN2418 para obter detalhes.
Localidade
Os usuários escolhem sua localidade no aplicativo Configurações . Essa configuração afeta a maneira como datas, horas, números e moeda são formatados.
Isso permite que os usuários escolham se veem formatos de horário de 12 ou 24 horas, se o separador decimal é uma vírgula ou um ponto e a ordem de exibição de dia, mês e ano na data.
Com o Xamarin, você tem acesso às classes iOS da Apple (NSNumberFormatter
) e às classes .NET no System.Globalization. Os desenvolvedores devem avaliar qual é mais adequado às suas necessidades, pois há diferentes recursos disponíveis em cada um. Em particular, se você estiver recuperando e exibindo preços de compra no aplicativo usando o StoreKit, você deve usar as classes de formatação da Apple para as informações de preço retornadas.
A localidade atual pode ser consultada de duas maneiras:
NSLocale.CurrentLocale.LocaleIdentifier
NSLocale.AutoUpdatingCurrentLocale.LocaleIdentifier
O primeiro valor pode ser armazenado em cache pelo sistema operacional e, portanto, nem sempre pode refletir a localidade selecionada atualmente do usuário. Use o segundo valor para obter a localidade selecionada no momento.
Observação
O Mono (o tempo de execução do .NET no qual o Xamarin.iOS se baseia) e as APIs do iOS da Apple não oferecem suporte a conjuntos idênticos de combinações de idioma/região. Por isso, é possível selecionar uma combinação de idioma/região no aplicativo Configurações do iOS que não mapeia para um valor válido no Mono. Por exemplo, definir o idioma de um iPhone para inglês e sua região para Espanha fará com que as seguintes APIs produzam valores diferentes:
CurrentThead.CurrentCulture
: en-US (Mono API)CurrentThread.CurrentUICulture
: en-US (Mono API)NSLocale.CurrentLocale.LocaleIdentifier
: en_ES (API da Apple)
Como o Mono usa CurrentThread.CurrentUICulture
para selecionar recursos e formatar datas e CurrentThread.CurrentCulture
moedas, a localização baseada em Mono (por exemplo, com arquivos .resx) pode não produzir os resultados esperados para essas combinações de idioma/região. Nessas situações, conte com as APIs da Apple para localizar conforme necessário.
NSCurrentLocaleDidChangeNotification
O iOS gera um NSCurrentLocaleDidChangeNotification
quando o usuário atualiza sua localidade. Os aplicativos podem escutar essa notificação enquanto estão em execução e podem fazer as alterações apropriadas na interface do usuário.
Noções básicas de localização no iOS
Os seguintes recursos do iOS são facilmente aproveitados no Xamarin para fornecer recursos localizados para exibição ao usuário. Consulte o exemplo TaskyL10n para ver como implementar essas ideias.
Especificando idiomas padrão e com suporte no Info.plist
Em QA1828: How iOS Determine the Language For Your App, a Apple descreve como o iOS seleciona um idioma para usar em um aplicativo. Os seguintes fatores afetam o idioma exibido:
- Os idiomas preferidos do usuário (encontrados no aplicativo Configurações )
- As localizações incluídas no aplicativo (pastas .lproj)
CFBundleDevelopmentRegion
(Valor Info.plist especificando o idioma padrão para o aplicativo)CFBundleLocalizations
(Matriz Info.plist especificando todas as localizações suportadas)
Conforme indicado nas Perguntas e respostas técnicas, CFBundleDevelopmentRegion
representa a região e o idioma padrão de um aplicativo. Se o aplicativo não oferecer suporte explícito a nenhum dos idiomas preferidos de um usuário, ele usará o idioma especificado por esse campo.
Importante
O iOS 11 aplica esse mecanismo de seleção de idioma de forma mais rigorosa do que as versões anteriores do sistema operacional. Por causa disso, qualquer aplicativo do iOS 11 que não declare explicitamente suas localizações suportadas – seja incluindo pastas .lproj ou definindo um valor para CFBundleLocalizations
– pode exibir um idioma diferente no iOS 11 do que no iOS 10.
Se CFBundleDevelopmentRegion
não tiver sido especificado no arquivo Info.plist , as ferramentas de compilação do Xamarin.iOS atualmente usam um valor padrão de en_US
. Embora isso possa mudar em uma versão futura, significa que o idioma padrão é o inglês.
Para garantir que seu aplicativo selecione um idioma esperado, execute as seguintes etapas:
- Especifique um idioma padrão. Abra o Info.plist e use a visualização Código-fonte para definir um valor para a
CFBundleDevelopmentRegion
chave, em XML, ela deve ser semelhante à seguinte:
<key>CFBundleDevelopmentRegion</key>
<string>es</string>
Este exemplo usa "es" para especificar que, quando nenhum dos idiomas preferenciais de um usuário é suportado, o padrão é espanhol.
- Declare todas as localizações suportadas. Em Info.plist, use o modo de exibição Código-fonte para definir uma matriz para a
CFBundleLocalizations
chave, em XML, ela deve ser semelhante à seguinte:
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
...
</array>
Os aplicativos Xamarin.iOS que foram localizados usando mecanismos .NET, como arquivos .resx, também devem fornecer esses valores Info.plist .
Para obter mais informações sobre essas chaves Info.plist, consulte a Referência de chave da lista de propriedades de informações da Apple.
GetLocalizedString método
O NSBundle.MainBundle.GetLocalizedString
método procura texto localizado que foi armazenado em arquivos .strings no projeto. Esses arquivos são organizados por idioma, em diretórios especialmente nomeados com um sufixo .lproj (note que a primeira letra da extensão é um "L" minúsculo).
Locais do arquivo .strings
- Base.lproj é o diretório que contém recursos para o idioma padrão. Ele geralmente está localizado na raiz do projeto (mas também pode ser colocado na pasta Recursos ).
- <Os diretórios language.lproj> são criados para cada idioma suportado, geralmente na pasta Recursos.
Pode haver vários arquivos .strings diferentes em cada diretório de idioma:
- Localizable.strings – a lista principal de texto localizado.
- InfoPlist.strings – certas chaves específicas são permitidas neste arquivo para traduzir coisas como o nome do aplicativo.
- <storyboard-name.strings> – arquivo opcional que contém traduções para elementos da interface do usuário em um storyboard.
A ação de compilação para esses arquivos deve ser recurso de pacote.
Formato de arquivo .strings
A sintaxe para valores de cadeia de caracteres localizados é:
/* comment */
"key"="localized-value";
Você deve escapar dos seguintes caracteres em cadeias de caracteres:
- Cota de
\"
\\
barra invertida\n
Newline
Este é um exemplo es/Localizable.strings (ou seja. Espanhol) da amostra:
"<new task>" = "<new task>";
"Task Details" = "Detalles de la tarea";
"Name" = "Nombre";
"task name" = "nombre de la tarea";
"Notes" = "Notas";
"other task info"= "otra información de tarea";
"Done" = "Completo";
"Save" = "Guardar";
"Delete" = "Eliminar";
Imagens
Para localizar uma imagem no iOS:
Consulte a imagem em código, por exemplo:
UIImage.FromBundle("flag");
Coloque o sinalizador de arquivo de imagem padrão.png em Base.lproj (o diretório de linguagem de desenvolvimento nativo).
Opcionalmente, coloque versões localizadas da imagem em pastas .lproj para cada idioma (por exemplo. es.lproj, ja.lproj). Use o mesmo sinalizador de nome de arquivo.png em cada diretório de idioma.
Se uma imagem não estiver presente para um idioma específico, o iOS retornará para a pasta de idioma nativo padrão e carregará a imagem a partir daí.
Iniciar imagens
Use as convenções de nomenclatura padrão para as imagens de lançamento (e os modelos XIB ou Storyboard para iPhone 6) ao colocá-las nos diretórios .lproj para cada idioma.
Default.png
Default@2x.png
Default-568h@2x.png
LaunchScreen.xib
Nome do aplicativo
Colocar um arquivo InfoPlist.strings em um diretório .lproj permite substituir alguns valores do Info.plist do aplicativo, incluindo o nome do aplicativo:
"CFBundleDisplayName" = "LeónTodo";
Outras chaves que você pode usar para localizar cadeias de caracteres específicas do aplicativo são:
- CFBundleName
- CFBundleShortVersionString
- NSHumanReadableDireitos autorais
Datas e horas
Embora seja possível usar as funções internas de data e hora do .NET (junto com a atual CultureInfo
) para formatar datas e horas para uma localidade, isso ignoraria as configurações de usuário específicas da localidade (que podem ser definidas separadamente do idioma).
Use o iOS NSDateFormatter
para produzir uma saída que corresponda à preferência de localidade do usuário. O código de exemplo a seguir demonstra as opções básicas de formatação de data e hora:
var date = NSDate.Now;
var df = new NSDateFormatter ();
df.DateStyle = NSDateFormatterStyle.Full;
df.TimeStyle = NSDateFormatterStyle.Long;
Debug.WriteLine ("Full,Long: " + df.StringFor(date));
df.DateStyle = NSDateFormatterStyle.Short;
df.TimeStyle = NSDateFormatterStyle.Short;
Debug.WriteLine ("Short,Short: " + df.StringFor(date));
df.DateStyle = NSDateFormatterStyle.Medium;
df.TimeStyle = NSDateFormatterStyle.None;
Debug.WriteLine ("Medium,None: " + df.StringFor(date));
Resultados para o inglês nos Estados Unidos:
Full,Long: Friday, August 7, 2015 at 10:29:32 AM PDT
Short,Short: 8/7/15, 10:29 AM
Medium,None: Aug 7, 2015
Resultados para o espanhol na Espanha:
Full,Long: viernes, 7 de agosto de 2015, 10:26:58 GMT-7
Short,Short: 7/8/15 10:26
Medium,None: 7/8/2015
Consulte a documentação do Apple Date Formatters para obter mais informações. Ao testar a formatação de data e hora sensível à localidade, verifique as configurações de idioma e região do iPhone.
Layout da direita para a esquerda (RTL)
O iOS fornece vários recursos para ajudar na criação de aplicativos compatíveis com RTL:
- Use layouts automáticos
leading
e atributos para alinhamento de controle (que corresponde à esquerda etrailing
à direita para o inglês, mas é revertido para idiomas RTL). OUIStackView
controle é particularmente útil para estabelecer controles com reconhecimento de RTL. - Use
TextAlignment = UITextAlignment.Natural
para alinhamento de texto (que será deixado para a maioria dos idiomas, mas à direita para RTL). UINavigationController
Inverte automaticamente o botão Voltar e inverte a direção do gesto de deslizar.
As capturas de tela a seguir mostram o exemplo Tasky localizado em árabe e hebraico (embora o inglês tenha sido inserido nos campos):
O iOS reverte automaticamente o , e os outros controles são colocados dentro UIStackView
ou alinhados com o UINavigationController
Layout Automático.
O texto RTL é localizado usando arquivos .strings da mesma forma que o texto LTR.
Localizando a interface do usuário no código
O exemplo Tasky (localizado em código) mostra como localizar um aplicativo onde a interface do usuário é criada em código (em vez de XIBs ou storyboards).
Estrutura do Projeto
Arquivo Localizable.strings
Conforme descrito acima, o formato de arquivo Localizable.strings consiste em pares chave-valor. A chave descreve a intenção da cadeia de caracteres e o valor é o texto traduzido a ser usado no aplicativo.
As localizações em espanhol (es) para a amostra são mostradas abaixo:
"<new task>" = "<new task>";
"Task Details" = "Detalles de la tarea";
"Name" = "Nombre";
"task name" = "nombre de la tarea";
"Notes" = "Notas";
"other task info"= "otra información de tarea";
"Done" = "Completo";
"Save" = "Guardar";
"Delete" = "Eliminar";
Executando a localização
No código do aplicativo, onde quer que o texto de exibição de uma interface do usuário esteja definido (seja o texto de um rótulo, o espaço reservado de uma entrada, etc.), o código usa a função iOS GetLocalizedString
para recuperar a tradução correta para exibir:
var localizedString = NSBundle.MainBundle.GetLocalizedString ("key", "optional");
someControl.Text = localizedString;
Localizando interfaces de usuário de storyboard
O exemplo Tasky (storyboard localizado) mostra como localizar texto em controles em um storyboard.
Estrutura do projeto
O diretório Base.lproj contém o storyboard e também deve conter todas as imagens usadas no aplicativo.
Os outros diretórios de idioma contêm um arquivo Localizable.strings para quaisquer recursos de cadeia de caracteres referenciados no código, bem como um arquivo MainStoryboard.strings que contém traduções para texto no storyboard.
Os diretórios de idioma devem conter uma cópia de todas as imagens que foram localizadas, para substituir a presente em Base.lproj.
ID do objeto / ID de localização
Ao criar e editar controles em um storyboard, selecione cada controle e verifique a ID a ser usada para localização:
- No Visual Studio para Mac, ele está localizado no Bloco de Propriedades e é chamado de ID de Localização.
- No Xcode, ele é chamado de ID do objeto.
Esse valor de cadeia de caracteres geralmente tem um formulário como "NF3-h8-xmR", conforme mostrado na captura de tela a seguir:
Esse valor é usado no arquivo .strings para atribuir texto traduzido automaticamente a cada controle.
MainStoryboard.strings
O formato do arquivo de tradução de storyboard é semelhante ao arquivo Localizable.strings , exceto que a chave (o valor à esquerda) não pode ser definida pelo usuário, mas deve ter um formato muito específico: ObjectID.property
.
No exemplo Mainstoryboard.strings abaixo, você pode ver UITextField
s tem uma placeholder
propriedade text que pode ser localizada; UILabel
s têm uma text
propriedade, e UIButton
s texto padrão é definido usando normalTitle
:
"SXg-TT-IwM.placeholder" = "nombre de la tarea";
"Pqa-aa-ury.placeholder"= "otra información de tarea";
"zwR-D9-hM1.text" = "Detalles de la tarea";
"bAM-2j-Rzw.text" = "Notas"; /* Notes */
"NF3-h8-xmR.text" = "Completo"; /* Done */
"MWt-Ya-pMf.normalTitle" = "Guardar"; /* Save */
"IGr-pR-05L.normalTitle" = "Eliminar"; /* Delete */
Importante
Usar um storyboard com classes de tamanho pode resultar em traduções que não aparecem no aplicativo. As notas de versão do Xcode da Apple indicam que um storyboard ou XIB não será localizado corretamente se três coisas forem verdadeiras: ele usa classes de tamanho, a localização base e o destino de compilação são definidos como Universal e a compilação visa iOS 7.0. A correção é duplicar o arquivo de cadeias de caracteres do storyboard em dois arquivos idênticos: MainStoryboard~iphone.strings e MainStoryboard~ipad.strings, conforme mostrado na captura de tela a seguir:
Listagem da App Store
Segue as perguntas frequentes da Apple sobre a localização da App Store para inserir traduções para cada país em que seu aplicativo está à venda. Observe o aviso de que as traduções só aparecerão se o aplicativo também contiver um diretório .lproj localizado para o idioma.
Resumo
Este artigo aborda os conceitos básicos da localização de aplicativos iOS usando os recursos internos de manipulação de recursos e storyboard.
Você pode saber mais sobre i18n e L10n para iOS, Android e aplicativos de plataforma cruzada (incluindo Xamarin.Forms) neste guia multiplataforma.