martes, 30 de septiembre de 2014

Localización

Android se utiliza en muchos países y/o regiones al rededor de todo el mundo. Para poder llegar al mayor número de usuarios posible, nuestra aplicación tendrá que ser capaz de adaptarse a múltiples idiomas, formas de escritura, formatos de fecha, datos numéricos, archivos de sonido e imágenes relacionados con los idiomas y países de origen.

Los recursos son las cadenas de texto, plantillas, sonidos, imágenes y cualquier otro tipo de dato que nuestra aplicación necesite para su funcionamiento. Una aplicación puede incluir múltiples conjuntos de recursos adaptados a configuraciones diferentes de dispositivo. Cuando el usuario ejecuta la aplicación, Android seleccionará y cargará de manera automática los recursos que mejor se adapten a la configuración actual.

En nuestra aplicación, además de crear los recursos por defecto, tendremos que crear los recursos asociados a las diferentes localizaciones. Será el sistema el encargado de seleccionar los recursos adecuados en función de localización configurada en el dispositivo.

Recursos por defecto.

Cuando una aplicación se ejecuta en una localización para la que no hemos tenido en cuenta su idioma, Android usará por defecto las cadenas de texto localizadas en el archivo res/values/strings.xml. Si este archivo no existe, o si alguna cadena de texto de la aplicación no se encuentra en él, la aplicación dejará de funcionar y se nos mostrará un error.

Ejemplo:

Una aplicación hace referencia desde su código Java a dos cadenas: text_a y text_b. La aplicación cuenta con el recurso res/values-en/strings.xml que define las cadenas text_a y text_b para el idioma inglés. La aplicación también cuenta con el archivo res/values/strings.xml que define la cadena por defecto para text_a pero no para text_b:
  • En esta situación, la aplicación compilará sin problemas.
  • Cuando ejecutamos la aplicación en un dispositivo con el idioma en inglés, no se producirán errores puesto que el archivo res/values-en/strings.xml contiene la definición de ambas cadenas de texto.
  • Sin embargo, se mostrará un mensaje de error al usuario y se dejará de ejecutar la aplicación cuando ésta se ejecute en un dispositivo con un idioma diferente.

Para prevenir esta situación, nos aseguraremos de que el archivo res/values/strings.xml existe y que define todas y cada una de las cadenas de texto utilizadas nuestro código fuente. Esta situación puede repetirse con otro tipo de recursos, por lo que tendremos que actuar de la misma manera para ellos: plantillas, imágenes, animaciones, etc.

Utilizando recursos de localización.

Creando recursos por defecto.

Las cadenas de texto por defecto en nuestra aplicación las definiremos en el archivo res/values/strings.xml. El idioma de las cadenas contenidas en este archivo será el idioma por defecto, es decir, el idioma mayoritario en los usuarios a los que va dirigida nuestra aplicación.

Los recursos por defecto también tendrán que incluir imágenes, plantillas, animaciones, etc. Cada tipo de recurso cuenta con su propia carpeta:
  • res/drawable/. Obligatoria. Almacena imágenes. Al menos debe contener el icono de nuestra aplicación que será usado tanto para el lanzador de aplicaciones como para la tienda Google Play.
  • res/layout/. Obligatoria. Almacena plantillas. Al menos debe contener la plantilla por defecto.
  • res/anim/. Obligatoria si hemos definido alguna carpeta del tipo res/anim-<parámetros>.
  • res/xml/. Obligatoria si hemos definido alguna carpeta del tipo res/xml-<parámetros>.
  • res/raw/. Obligatoria si hemos definido alguna carpeta del tipo res/raw-<parámetros>.

Creando recursos alternativos.

Una aplicación puede tener definidas múltiples carpetas de recursos con diferentes parámetros de configuración. Para crear recursos asociados a una localización determinada, tendremos que usar los parámetros de configuración idioma y país en su carpeta contenedora: <tipo_recurso>-<idioma>[-r<país>].

Ejemplo:

Supongamos que el idioma por defecto para nuestra aplicación es el inglés. Supongamos también que queremos dar soporte a los idiomas francés y japonés (exceptuando el título de la aplicación). Para el escenario descrito, necesitaremos tres archivos strings.xml, cada uno almacenado en una carpeta con sus parámetros de idioma correspondientes:
  1. res/values/strings.xml. Archivo por defecto. Contiene las cadenas de texto en inglés, incluyendo el título de la aplicación.
  2. res/values-fr/strings.xml. Contiene las cadenas en francés, incluyendo el título de la aplicación.
  3. res/values-ja/strings.xml. Contiene las cadenas en japonés, a excepción del título de la aplicación.
Si desde nuestro código Java hacemos referencia a la constante R.string.title, esto es lo que sucederá en tiempo de ejecución:
  • Si el idioma del dispositivo es distinto del francés, Android utilizará la cadena definida en el archivo res/values/strings.xml.
  • Si el idioma del dispositivo es francés, Android utilizará la cadena definida en el archivo res/values-fr/strings.xml.

Es decir, que cuando el idioma del dispositivo es japonés, Android intenta localizar la cadena asociada al título en el archivo res/values-ja/strings.xml. Como la cadena no se encuentra definida en este archivo, Android utilizará la definición por defecto definida en el archivo res/values/strings.xml.

Precedencia entre recursos.

Si la configuración del dispositivo coincide con varias alternativas para un mismo recurso, Android sigue un conjunto de reglas para discernir qué recurso elegir. Entre los parámetros de configuración que podemos utilizar a la hora de especificar el nombre de una carpeta de recursos, son los asociados a la localización los de mayor precedencia.

Ejemplo:

Supongamos que una aplicación cuenta con un juego de imágenes optimizadas para varias configuraciones de dispositivo:
  • res/drawable/. Carpeta por defecto.
  • res/drawable-small-land-stylus/. Contiene las imágenes optimizadas para una densidad de pantalla baja (QVGA), orientación de pantalla horizontal y uso de lápiz (stylus).
  • res/drawable-ja/. Contiene las imágenes para dispositivos configurados en japonés.

Si la aplicación se ejecuta sobre un dispositivo en japonés, Android utilizará las imágenes contenidas en res/drawable-ja aún si el dispositivo cuenta con una densidad de pantalla baja (QVGA), su orientación de pantalla es horizontal y esté optimizado para ser usado con un lápiz.

Nota. Los únicos parámetros de configuración que tienen mayor precedencia a los relacionados con la localización son los de país y red móvil (MCC y MNC respectivamente).

Ejemplo:

Supongamos el siguiente escenario:
  • El código fuente hace referencia a la cadena de texto R.string.text_a.
  • Contamos con los siguientes recursos:
    • res/values-mcc404/strings.xml. Incluye la cadena text_a en inglés.
    • res/valus-hi/strings.xml. Incluye la cadena text_a en hindi.
  • La aplicación se está ejecutando en un dispositivo con la siguiente configuración:
    • La tarjeta SIM pertenece a la red móvil India MCC 404.
    • El idioma es hindi (hi).

Android utilizará la cadena text_a del archivo res/values-mcc404/strings.xml en inglés, aún cuando el dispositivo está configurado en indi. En este caso, la red móvil (MCC) tiene mayor precedencia que el idioma.

Algunos consejos.

Nuestra aplicación debe ser independientemente de la localización.

No haremos suposiciones de antemano con respecto al dispositivo que acabará ejecutando nuestra aplicación. El dispositivo puede contar con un hardware o una localización que no hayamos previsto. Debemos diseñar nuestra aplicación para que ésta pueda seguir ejecutándose en estos casos.

Importante. Asegurar el funcionamiento de nuestra aplicación es sinónimo de definir un juego completo para los recursos por defecto.

Nos aseguraremos de incluir las carpetas res/drawable/ y res/values/ conteniendo todas y cada una de las imágenes y cadenas de texto de nuestra aplicación.

Solo con que hayamos olvidado especificar uno de los recursos por defecto necesarios, será suficiente para que nuestra aplicación deje de funcionar en todos aquellos dispositivos cuya configuración lo requiera. Por ejemplo, si a nuestra aplicación le falta una cadena de texto en el archivo res/values/strings.xml y el dispositivo está configurado con un idioma para el que no damos soporte, al intentar cargar la cadena y no encontrarla, mostrará un error al usuario y detendrá la aplicación. Debemos tener en cuenta que Android Studio no nos avisará de este tipo de errores y tendremos que anticiparnos a ellos.

Diseñar plantillas flexibles.

Si el diseño de nuestra plantilla depende del idioma (por ejemplo el alemán cuenta con palabras de mayor longitud y lo deberíamos tener en cuenta), como solución podríamos crear una plantilla para cada idioma (por ejemplo, res/layout-de/main.xml para el alemán). Sin embargo, crear una plantilla para cada uno de los idiomas no nos facilitará su mantenimiento. Para este caso es mucho mejor crear una plantilla base, la plantilla por defecto, para que cubra la mayoría de las variantes posibles.

Otro escenario típico es cuando un idioma concreto require de alguna particularidad en la plantilla. Por ejemplo, deberíamos de contar con dos campos asociados al nombre del usuario en un dispositivo con el idioma en japonés, pero para el resto de idiomas deberíamos mostrar tres campos. Para solucionar este problema podremos actuar de dos maneras:
  • Crear una plantilla con un campo que podemos activar o desactivar a través de código y basándonos en la configuración actual del idioma, o bien
  • Tener una plantilla base que incluya otra plantilla que a su vez incluye el campo. Ésta última contará con dos versiones: una para el idioma japonés y otra para el resto de idiomas.

Crear los recursos necesarios.

Lo más probable es que no necesitemos crear recursos alternativos basados en la localización. Por ejemplo, la plantilla definida en res/layout/main.xml puede servirnos para cualquier configuración de localización, por lo que no será necesario crear plantillas alternativas.

Por otro lado, tampoco tendremos que crear cadenas alternativas para todos los idiomas. Por ejemplo, supongamos lo siguiente:
  • El idioma por defecto de nuestra aplicación es inglés americano. Todas las cadenas de texto en inglés americano se encontrarán definidas en res/values/strings.xml.
  • Para determinadas frases especiales, queremos especificar también su variante en inglés británico. De esta manera, estas frases alternativas aparecerán para dispositivos usados desde Reino Unido.

Para hacer esto, crearemos el archivo res/values-en-rGB/strings.xml incluyendo ese repertorio de frases especiales escritas en inglés británico. Para el resto de cadenas de nuestra aplicación, utilizaremos los valores por defecto contenidos en res/values/strings.xml.

Usar el contexto para acceder a la configuración de localización.

Podemos acceder a la información relacionada con la localización del dispositivo a través del contexto de nuestra aplicación:
String locale = context.getResources().getConfiguration().locale.getDisplayName();
En el ejemplo, la variable locale vale English (United States).

Probando la localización en nuestras aplicaciones.

Pruebas sobre un dispositivo real.

Tenemos que tener en cuenta que el dispositivo que estamos probando puede tener características diferentes con respecto a los dispositivos disponibles en otros puntos geográficos. Las localizaciones disponibles en nuestro dispositivo pueden diferir sobre las localizaciones en otros. Además, la resolución y la densidad de pantalla de nuestro dispositivo pueden afectar a la hora de visualizar las cadenas de texto y las imágenes en nuestra interfaz de usuario.

Para cambiar la localización de un dispositivo, lo haremos a partir de la aplicación Ajustes, sección de Idioma e introducción de texto.

Pruebas sobre un dispositivo emulado.

Como requisito previo, necesitaremos haber dado de alta un dispositivo desde la herramienta AVD con la configuración necesaria.

Cambiando la localización desde Android.

Utilizaremos nuestro propio código de localización (idioma-país) cuando la imagen de Android que estamos usando no disponga de soporte para dicho código. Tenemos dos maneras de crear una nueva localización:
  • Utilizar la aplicación Custom Locale disponible desde el lanzador de aplicaciones del sistema Android.
  • Cambiar la localización utilizando la herramienta adb.

Cuando cambiamos a una localización que no está soportada por el sistema, éste pasará a trabajar con la localización que tenga definida por defecto, sin embargo, nuestra aplicación si que utilizará utilizará la nueva localización.

Cambiando la localización con la herramienta adb.

Para cambiar la localización utilizando adb:
  1. Elegimos la localización: por ejemplo, es para idioma español y ES para el país/región España.
  2. Ejecutamos el dispositivo emulado.
  3. Desde la consola de comandos del sistema anfitrión, ejecutamos: adb shell si solo hay un dispositivo emulado en ejecución. Si contamos con más de uno, tendremos que especificar su número de serie: adb -s emulator-5556 shell.
  4. Una vez conectados al dispositivo, ejecutamos el comando:
    setprop persist.sys.language es;setprop persist.sys.country ES;stop;sleep 5;start

Los pasos anteriores harán que el dispositivo emulado se acabe reiniciando con la nueva configuración. La próxima vez que ejecutemos el emulador para ese dispositivo, su localización seguirá siendo es-ES.

Probando los recursos por defecto.

Para probar que nuestra aplicación cuenta con todos los recursos por defecto necesarios, procederemos de la siguiente manera:
  1. Cambiamos la localización del dispositivo por una localización no soportada por nuestra aplicación.
  2. Ejecutamos la aplicación.
  3. Si la aplicación nos muestra un mensaje de error y nos obliga a salir, significará que alguna de las cadenas utilizadas no se ha encontrado en el archivo res/values/strings.xml. Añadiremos las cadenas necesarias hasta que la aplicación se ejecute sin problemas.

Seguiremos el mismo procedimiento para el resto de recursos. Por ejemplo, si la aplicación tiene una plantilla en res/layout-land/main.xml pero no cuenta con una plantilla en res/layout-port/main.xml, cambiaremos la orientación de la pantalla  a vertical y comprobaremos el resultado por defecto.

No hay comentarios:

Publicar un comentario