Localización en Xamarin.iOS

En este documento se describen las características de localización del SDK de iOS y cómo acceder a ellas con Xamarin.

Consulte las codificaciones de internacionalización para obtener instrucciones sobre cómo incluir páginas de códigos o conjuntos de caracteres en aplicaciones que deben procesar datos que no son Unicode.

Características de la plataforma iOS

En esta sección se describen algunas de las características de localización en iOS. Vaya a la sección siguiente para ver ejemplos y código específico.

Lenguaje

Los usuarios eligen su idioma en la aplicación Configuración. Este valor afecta a las cadenas de idioma y las imágenes que se muestran en el sistema operativo y en las aplicaciones.

Para determinar el idioma que se usa en una aplicación, obtenga el primer elemento de NSBundle.MainBundle.PreferredLocalizations:

var lang = NSBundle.MainBundle.PreferredLocalizations[0];

Este valor será un código de idioma como en para inglés, es para español, ja para japonés, etc. El valor devuelto está restringido a una de las localización admitidas por la aplicación (mediante reglas de reserva para determinar la mejor coincidencia).

El código de la aplicación no siempre necesita comprobar este valor: en Xamarin e iOS se ofrecen características que ayudan a proporcionar automáticamente la cadena o el recurso correctos para el idioma del usuario. Estas características se describen en el resto de este documento.

Nota:

Use NSLocale.PreferredLanguages para determinar las preferencias de idioma del usuario, independientemente de las localizaciones admitidas por la aplicación. Los valores devueltos por este método han cambiado en iOS 9; vea Nota técnica TN2418 para más información.

Configuración regional

Los usuarios eligen su configuración regional en la aplicación Configuración. Este valor afecta al formato de fechas, horas, números y moneda.

Esto permite a los usuarios elegir si ven formatos de hora de 12 o 24 horas, si el separador decimal es una coma o un punto, y el orden del día, mes y año en la presentación de la fecha.

Con Xamarin tiene acceso a las clases de iOS (NSNumberFormatter) de Apple y a las clases de .NET en System.Globalization. Los desarrolladores deben evaluar qué es lo más adecuado para sus necesidades, ya que hay diferentes características disponibles en cada una. En concreto, si va a recuperar y mostrar precios de compra en la aplicación mediante StoreKit, debe usar las clases de formato de Apple para la información de precios devuelta.

La configuración regional actual se puede consultar de dos maneras:

  • NSLocale.CurrentLocale.LocaleIdentifier
  • NSLocale.AutoUpdatingCurrentLocale.LocaleIdentifier

El sistema operativo puede almacenar en caché el primer valor, por lo que es posible que no siempre refleje la configuración regional seleccionada actualmente del usuario. Use el segundo valor para obtener la configuración regional seleccionada actualmente.

Nota:

Mono (el entorno de ejecución de .NET en el que se basa Xamarin.iOS) y las API iOS de Apple no admiten conjuntos idénticos de combinaciones de idioma y región. Por este motivo, es posible seleccionar una combinación de idioma o región en la aplicación Configuración de iOS que no se asigna a un valor válido en Mono. Por ejemplo, si se establece el idioma de iPhone en inglés y su región en España, las siguientes API devuelven valores diferentes:

  • CurrentThead.CurrentCulture: en-US (API Mono)
  • CurrentThread.CurrentUICulture: en-US (API Mono)
  • NSLocale.CurrentLocale.LocaleIdentifier: en_ES (API Apple)

Como en Mono se usa CurrentThread.CurrentUICulture para seleccionar recursos y CurrentThread.CurrentCulture para dar formato a fechas y monedas, la localización basada en Mono (por ejemplo, con archivos .resx) puede no producir los resultados esperados para estas combinaciones de idioma y región. En estas situaciones, confíe en las API de Apple para la localización según sea necesario.

NSCurrentLocaleDidChangeNotification

iOS genera una instancia de NSCurrentLocaleDidChangeNotification cuando el usuario actualiza su configuración regional. Las aplicaciones pueden escuchar esta notificación mientras se ejecutan y pueden realizar los cambios adecuados en la interfaz de usuario.

Conceptos básicos de localización en iOS

Las siguientes características de iOS se aprovechan fácilmente en Xamarin para proporcionar recursos localizados y mostrarlos al usuario. Consulte el ejemplo TaskyL10n para ver cómo implementar estas ideas.

Especificación de idiomas predeterminados y admitidos en Info.plist

En Q&A TÉCNICO QA1828: Cómo iOS determina el idioma de la aplicación, Apple describe cómo iOS selecciona un idioma para usarlo en una aplicación. Los siguientes factores afectan al idioma que se muestra:

  • Idiomas preferidos del usuario (que se encuentran en la aplicación Configuración)
  • Localizaciones agrupadas con la aplicación (carpetas .lproj)
  • CFBundleDevelopmentRegion (valor Info.plist que especifica el idioma predeterminado para la aplicación)
  • CFBundleLocalizations (matriz Info.plist que especifica todas las localizaciones admitidas)

Como se indica en el Q&A técnico, CFBundleDevelopmentRegion representa la región y el idioma predeterminados de una aplicación. Si la aplicación no admite explícitamente ninguno de los idiomas preferidos de un usuario, usará el idioma especificado por este campo.

Importante

En iOS 11 se aplica este mecanismo de selección de idioma de manera más estricta que en versiones anteriores del sistema operativo. Por este motivo, cualquier aplicación de iOS 11 que no declare explícitamente sus localización admitidas, ya sea mediante la inclusión de carpetas .lproj o la configuración de un valor para CFBundleLocalizations, puede mostrar un idioma diferente en iOS 11 que en iOS 10.

Si CFBundleDevelopmentRegion no se ha especificado en el archivo Info.plist, las herramientas de compilación de Xamarin.iOS usan actualmente un valor predeterminado de en_US. Aunque esto puede cambiar en una versión futura, significa que el idioma predeterminado es inglés.

Para asegurarse de que la aplicación selecciona un idioma esperado, siga estos pasos:

  • Especifique un idioma predeterminado. Abra Info.plist y use la vista Origen a fin de establecer un valor para la clave CFBundleDevelopmentRegion; en XML, debe tener un aspecto similar al siguiente:
<key>CFBundleDevelopmentRegion</key>
<string>es</string>

En este ejemplo se usa "es" para especificar que, cuando no se admite ninguno de los idiomas preferidos de un usuario, el valor predeterminado es español.

  • Declare todas las localizaciones admitidas. En Info.plist, use la vista Origen a fin de establecer una matriz para la clave CFBundleLocalizations; en XML, debe tener un aspecto similar al siguiente:
<key>CFBundleLocalizations</key>
<array>
    <string>en</string>
    <string>es</string>
    ...
</array>

Las aplicaciones de Xamarin.iOS que se han localizado mediante mecanismos de .NET, como los archivos .resx, también deben proporcionar estos valores de Info.plist.

Para más información sobre estas claves de Info.plist, vea la referencia de claves de lista de propiedades de información de Apple.

GetLocalizedString (método)

El método NSBundle.MainBundle.GetLocalizedString busca texto localizado almacenado en archivos .strings en el proyecto. Estos archivos se organizan por idioma, en directorios con un nombre especial con un sufijo .lproj (tenga en cuenta que la primera letra de la extensión es una "L" minúscula).

Ubicaciones del archivo .strings

  • Base.lproj es el directorio que contiene recursos para el idioma predeterminado. A menudo se encuentra en la raíz del proyecto (pero también se puede colocar en la carpeta Resources).
  • Los directorios <language>.lproj se crean para cada idioma admitido, normalmente en la carpeta Resources.

Puede haber varios archivos .strings diferentes en cada directorio de idioma:

  • Localizable.strings: la lista principal de texto localizado.
  • InfoPlist.strings: se permiten determinadas claves específicas en este archivo para traducir aspectos como el nombre de la aplicación.
  • <nombre_guion_gráfico>.strings: archivo opcional que contiene traducciones para elementos de la interfaz de usuario en un guión gráfico.

La acción Compilar de estos archivos debe ser Agrupar recurso.

Formato del archivo .strings

La sintaxis de los valores de cadena localizados es:

/* comment */
"key"="localized-value";

Debes ejecutar el escape de los siguientes caracteres en cadenas:

  • Presupuesto de \"
  • \\ barra diagonal inversa
  • \n línea nueva

Este es un archivo es/Localizable.strings (es decir, Español) de muestra del ejemplo:

"<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";

Imágenes

Para localizar una imagen en iOS:

  1. Consulte la imagen en el código, por ejemplo:

    UIImage.FromBundle("flag");
    
  2. Coloque el archivo de imagen predeterminado flag.png en Base.lproj (el directorio del lenguaje de desarrollo nativo).

  3. Opcionalmente, coloque versiones localizadas de la imagen en carpetas .lproj para cada idioma (por ejemplo, es.lproj, ja.lproj). Use el mismo nombre de archivo flag.png en cada directorio de idioma.

Si una imagen no está presente para un idioma determinado, iOS recurrirá a la carpeta de idioma nativo predeterminada y cargará la imagen desde allí.

Imágenes de inicio

Use las convenciones de nomenclatura estándar para las imágenes de inicio (y XIB o Storyboard para los modelos iPhone 6) al colocarlas en los directorios .lproj para cada idioma.

Default.png
Default@2x.png
Default-568h@2x.png
LaunchScreen.xib

Nombre de la aplicación

La colocación de un archivo InfoPlist.stringsen un directorio .lproj le permite invalidar algunos valores de Info.plist de la aplicación, incluido el nombre de la aplicación:

"CFBundleDisplayName" = "LeónTodo";

Otras claves que puede usar para localizar cadenas específicas de la aplicación son las siguientes:

  • CFBundleName
  • CFBundleShortVersionString
  • NSHumanReadableCopyright

Fechas y horas

Aunque es posible usar las funciones integradas de fecha y hora de .NET (junto con la instancia actual de CultureInfo) para dar formato a las fechas y horas de una configuración regional, esto omitiría la configuración de usuario específica de la configuración regional (que se puede establecer independientemente del idioma).

Use NSDateFormatter de iOS para generar una salida que coincida con la preferencia de configuración regional del usuario. En el código de ejemplo siguiente se muestran las opciones básicas de formato de fecha y 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 inglés de 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 español de España:

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 la documentación Formateadores de fecha de Apple para más información. Al probar el formato de fecha y hora que depende de la configuración regional, compruebe los valores Idioma del iPhone y Región.

Diseño de derecha a izquierda (RTL)

iOS proporciona una serie de características que ayudan a crear aplicaciones compatibles con RTL:

  • Use los atributos leading y trailing del diseño automático para la alineación de los controles (que se corresponde a izquierda y derecha para inglés, pero se invierte para los idiomas RTL). El control UIStackView es especialmente útil para diseñar controles que sean compatibles con RTL.
  • Use TextAlignment = UITextAlignment.Natural para la alineación del texto (que será a la izquierda para la mayoría de los idiomas, pero a la derecha para RTL).
  • UINavigationController voltea automáticamente el botón Atrás e invierte la dirección del deslizamiento.

En las capturas de pantalla siguientes se muestra el ejemplo Tasky localizado en árabe y hebreo (aunque se haya escrito inglés en los campos):

Localization in Arabic

Localization in Hebrew

iOS invierte automáticamente UINavigationController y los demás controles se colocan dentro de UIStackView o se alinean con el diseño automático. El texto RTL se localiza mediante archivos .strings de la misma manera que el texto LTR.

Localización de la interfaz de usuario en el código

En el ejemplo Tasky (localizado en código) se muestra cómo localizar una aplicación en la que la interfaz de usuario se integrada en el código (en lugar de hacerlo en XIB o guiones gráficos).

Estructura del proyecto

Screenshot shows the resources tree for a sample including the location of localizable strings.

Localizable.strings (archivo)

Como se ha descrito antes, el formato del archivo Localizable.strings consta de pares clave-valor. La clave describe la intención de la cadena y el valor es el texto traducido que se usará en la aplicación.

A continuación se muestran las localizaciones en español (es) del ejemplo:

"<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";

Realización de la localización

En el código de la aplicación, siempre que se establezca el texto para mostrar de una interfaz de usuario (ya sea el texto de una etiqueta o el marcador de posición de una entrada, etc.), el código usa la función GetLocalizedString de iOS para recuperar la traducción correcta que se va a mostrar:

var localizedString = NSBundle.MainBundle.GetLocalizedString ("key", "optional");
someControl.Text = localizedString;

Localización de interfaces de usuario de guion gráfico

En el ejemplo Tasky (guion gráfico localizado) se muestra cómo localizar texto en controles de un guion gráfico.

Estructura de proyecto

El directorio Base.lproj contiene el guion gráfico y también debe contener las imágenes usadas en la aplicación.

Los demás directorios de lenguaje contienen un archivo Localizable.strings para los recursos de cadena a los que se hace referencia en el código, así como un archivo MainStoryboard.strings que contiene traducciones para el texto en el guion gráfico.

Screenshot shows the resources tree for a sample including the location of MainStoryboard strings.

Los directorios de idioma deben contener una copia de las imágenes localizadas para invalidar la presente en Base.lproj.

Id. de objeto e id. de localización

Al crear y editar controles en un guion gráfico, seleccione cada control y compruebe el identificador que se usará para la localización:

  • En Visual Studio para Mac, se encuentra en el Panel de propiedades y se denomina Id. de localización.
  • En Xcode, se denomina Id. de objeto.

Este valor de cadena suele tener un formato similar a "NF3-h8-xmR", como se muestra en la captura de pantalla siguiente:

Xcode view of Storyboard localization

Este valor se usa en el archivo .strings para asignar texto traducido automáticamente a cada control.

MainStoryboard.strings

El formato del archivo de traducción de guion gráfico es similar al archivo Localizable.strings, excepto que la clave (el valor de la izquierda) no la puede definir el usuario, sino que debe tener un formato muy específico: ObjectID.property.

En el archivo Mainstoryboard.strings de ejemplo siguiente puede ver instancias de UITextField con una propiedad de texto placeholder que se puede localizar; instancias de UILabel con una propiedad text y que el texto predeterminado de UIButton se establece mediante 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

El uso de un guion gráfico con clases de tamaño puede dar lugar a traducciones que no aparecen en la aplicación. En las notas de la versión de Xcode de Apple se indica que un guion gráfico o XIB no se localizará correctamente si se cumplen tres condiciones: se usan clases de tamaño, la localización base y el destino de compilación se establecen en Universal y la compilación tiene como destino iOS 7.0. La corrección consiste en duplicar el archivo de cadenas del guion gráfico en dos archivos idénticos: MainStoryboard~iphone.strings y MainStoryboard~ipad.strings, como se muestra en la captura de pantalla siguiente:

Strings files

Descripción en App Store

Siga las preguntas más frecuentes de Apple sobre la localización de App Store a fin de escribir traducciones para cada país en el que se venda la aplicación. Tenga en cuenta su advertencia de que las traducciones solo aparecerán si la aplicación también contiene un directorio .lproj localizado para el idioma.

Resumen

En este artículo se tratan los conceptos básicos de la localización de aplicaciones iOS mediante las características integradas de control de recursos y guion gráfico.

Puede obtener más información sobre i18n y L10n para aplicaciones iOS, Android y multiplataforma (incluido Xamarin.Forms) en esta guía multiplataforma.