Las apps incluyen recursos que pueden ser específicos de una cultura en particular. Por ejemplo, una app puede incluir strings específicas de la cultura que se traducen al idioma de la configuración regional actual. Se recomienda mantener los recursos específicos de la cultura separados del resto de la app. Android determina los recursos específicos del idioma y de la cultura en función de la configuración regional del sistema. Puedes proporcionar compatibilidad con diferentes configuraciones regionales al usar el directorio de recursos en tu proyecto de Android.
Puedes especificar recursos adaptados a la cultura de las personas que usan tu app. Puedes proporcionar cualquier tipo de recurso que sea adecuado para el idioma y la cultura de tus usuarios. Por ejemplo, en la siguiente captura de pantalla, verás una app en la que se muestran una string y recursos de elementos de diseño en la configuración regional predeterminada (en_US
) del dispositivo y en la configuración regional en español (es_ES
)

Figura 1: Apps que usan diferentes recursos en función de la configuración regional actual
Si creaste tu proyecto con las herramientas del SDK de Android (consulta Cómo crear un proyecto de Android), las herramientas crean un directorio res/
en el nivel superior del proyecto. El directorio res/
contiene subdirectorios para distintos tipos de recursos. También hay algunos archivos predeterminados, como res/values/strings.xml
, que contienen los valores de tu string.
La compatibilidad con varios idiomas vas más allá del uso de recursos específicos de la configuración regional. Algunos usuarios eligen un idioma que usa escritura de derecha a izquierda (RTL), como el árabe o hebreo, para la configuración regional de su IU. Otros ven o generan contenido en un idioma que usa escritura de derecha a izquierda, aunque hayan establecido un idioma que usa la escritura de izquierda a derecha (por ejemplo, inglés) como configuración regional de su IU. Para brindar compatibilidad a ambos tipos de usuarios, tu app debe realizar lo siguiente:
- Debe usar un diseño de IU de derecha a izquierda para configuraciones regionales con escritura de derecha a izquierda.
- Debe detectar y especificar la dirección de los datos de texto que se muestran en los mensajes con formato. Por lo general, solo tienes que llamar a un método que determina la dirección de los datos de texto por ti.
Cómo crear archivos de recursos y directorios de configuraciones regionales
Para agregar compatibilidad con más configuraciones regionales, crea directorios adicionales dentro de res/
. El nombre de cada directorio debe tener el siguiente formato:
<resource type>-b+<language code>[+<country code>]
Por ejemplo, values-b+es/
contiene recursos de string para configuraciones regionales con el código de idioma es
. De manera similar, mipmap-b+es+ES/
contiene íconos para configuraciones regionales con el código de idioma es
y el código de país ES
.
Android carga los recursos correspondientes según la configuración regional del dispositivo durante el tiempo de ejecución. Para obtener más información, consulta Cómo proporcionar recursos alternativos.
Una vez que hayas decidido qué configuraciones regionales quieres admitir, crea los archivos y subdirectorios de recursos. Por ejemplo:
MyProject/ res/ values/ strings.xml values-b+es/ strings.xml mipmap/ country_flag.png mipmap-b+es+ES/ country_flag.png
Por ejemplo, a continuación, se muestran diferentes archivos de recursos para distintos idiomas:
Strings en inglés (configuración local predeterminada), /values/strings.xml
:
<resources> <string name="hello_world">Hello World!</string> </resources>
Strings en español (configuración regional de es
), /values-es/strings.xml
:
<resources> <string name="hello_world">¡Hola Mundo!</string> </resources>
Ícono de la bandera de Estados Unidos (configuración regional predeterminada), /mipmap/country_flag.png
:

Figura 2: Ícono que se usa para la configuración regional predeterminada (en_US)
Ícono de la bandera de España (configuración regional es_ES
), /mipmap-b+es+ES/country_flag.png
:

Figura 3: Ícono usado para la configuración regional de es_ES
Nota: Puedes usar un calificador de configuración regional (o cualquier calificador de configuración) en cualquier tipo de recurso, como lo harías si quisieras ofrecer versiones localizadas de elementos de diseño de tu mapa de bits. Para obtener más información, consulta Localización.
Cómo usar los recursos en tu app
Puedes hacer referencia a los recursos en el código fuente y a otros archivos XML mediante el atributo name
de cada recurso.
En el código fuente, puedes hacer referencia a un recurso mediante la sintaxis R.<resource type>.<resource name>
. Existen varios métodos que aceptan un recurso de esta manera.
Por ejemplo:
Kotlin
// Get a string resource from your app's Resources val hello = resources.getString(R.string.hello_world) // Or supply a string resource to a method that requires a string TextView(this).apply { setText(R.string.hello_world) }
Java
// Get a string resource from your app's Resources String hello = getResources().getString(R.string.hello_world); // Or supply a string resource to a method that requires a string TextView textView = new TextView(this); textView.setText(R.string.hello_world);
En otros archivos XML, puedes hacer referencia a un recurso con la sintaxis @<resource type>/<resource name>
siempre que el atributo XML acepte un valor compatible.
Por ejemplo:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/country_flag" />
Cómo dar formato al texto en mensajes
Una de las tareas más comunes en una app es dar formato al texto. Para dar formato a los mensajes localizados, tienes que insertar los datos numéricos y de texto en las posiciones correspondientes. Lamentablemente, cuando trabajas con una IU de derecha a izquierda o con datos de derecha a izquierda, el formato simple puede mostrar una salida de texto incorrecta o incluso ilegible.
Los idiomas como el árabe, el hebreo, el persa y el urdú, en general, se escriben en dirección de derecha a izquierda. Sin embargo, algunos elementos, como los números y el texto de izquierda a derecha incorporado, se escriben en dirección de izquierda a derecha dentro del texto de derecha a izquierda. Los idiomas que usan escrituras de izquierda a derecha, como el inglés, también son bidireccionales porque pueden contener escritura de derecha a izquierda incorporada que debe mostrarse en esa dirección.
La mayoría de las veces, las mismas apps generan esas instancias de texto en dirección opuesta incorporado. Estas insertan datos de texto de un idioma aleatorio (y en una dirección de texto aleatoria) en mensajes localizados. La mezcla de direcciones no suele indicar de manera clara dónde empieza y termina el texto en la dirección opuesta. Por lo tanto, estas características del texto generado por la app a menudo son las más problemáticas.
Si bien el control predeterminado de texto bidireccional del sistema suele procesar el texto de la forma esperada, es posible que este no se procese correctamente cuando tu app lo inserte en un mensaje localizado. A continuación, se presentan ejemplos de casos en los que es más probable que el texto no se muestre correctamente:
-
Cuando se inserta al principio del mensaje:
PERSON_NAME te está llamando
-
Cuando comienza con un número, como las direcciones o los números de teléfono:
987 654-3210
-
Cuando comienza con signos de puntuación, como en un número de teléfono:
+19876543210
-
Cuando finaliza con signos de puntuación:
¿Seguro?
-
Cuando ya incluye ambas direcciones:
La palabra בננה significa banana en hebreo.
Ejemplo
Por ejemplo, supongamos que una app a veces necesita mostrar el mensaje "¿Quisiste decir %s?", con una dirección insertada en el lugar de %s durante el tiempo de ejecución. Como la app admite diferentes configuraciones regionales de IU, el mensaje surge de un recurso específico de la configuración regional y usa la dirección de derecha a izquierda cuando se usa una configuración regional de derecha a izquierda. En el caso de una IU en hebreo, debería mostrarse de la siguiente manera:
האם התכוונת ל %s?
Sin embargo, es posible que la sugerencia provenga de una base de datos que no incluye texto en el idioma de la configuración regional. Por ejemplo, si la dirección en cuestión es para un lugar en California, esta aparece en la base de datos con texto en inglés. Si insertas la dirección "15 Bay Street, Laurel, CA" en el mensaje de derecha a izquierda sin proporcionar información sobre la dirección del texto, el resultado será incorrecto o inesperado:
האם התכוונת ל 15 Bay Street, Laurel, CA?
Observa que el número de la casa aparece del lado derecho de la dirección y no del izquierdo como se pretendía. Por lo tanto, parece un número de código postal extraño. Es posible que ocurra el mismo problema si incluyes texto de derecha a izquierda en un mensaje que usa la dirección de texto de izquierda a derecha.
Explicación y solución
El problema del ejemplo anterior se produce porque el formateador de texto no especifica que "15" forma parte de la dirección, de manera que el sistema no puede determinar si "15" es parte del texto de derecha a izquierda que lo precede o del texto de izquierda a derecha que lo sucede.
Para resolver este problema, usa el método unicodeWrap()
, que se encuentra en la clase BidiFormatter
, en cada fragmento de texto que insertes en el mensaje localizado.
Estos son algunos casos donde no debes usar unicodeWrap()
:
- Cuando el texto se inserta en una string legible por máquina, como un URI o una consulta de SQL.
- Cuando sabes que ese fragmento de texto ya está correctamente encapsulado.
El método unicodeWrap()
detecta la dirección de una string y la encapsula en caracteres con formato Unicode que especifican esa dirección. Como "15" ahora aparece dentro del texto que se declaró como de izquierda a derecha, se muestra en la posición correcta:
האם התכוונת ל 15 Bay Street, Laurel, CA?
En el siguiente fragmento de código, se muestra cómo usar unicodeWrap()
:
Kotlin
val mySuggestion = "15 Bay Street, Laurel, CA" val myBidiFormatter: BidiFormatter = BidiFormatter.getInstance() // The "did_you_mean" localized string resource includes // a "%s" placeholder for the suggestion. String.format(getString(R.string.did_you_mean), myBidiFormatter.unicodeWrap(mySuggestion))
Java
String mySuggestion = "15 Bay Street, Laurel, CA"; BidiFormatter myBidiFormatter = BidiFormatter.getInstance(); // The "did_you_mean" localized string resource includes // a "%s" placeholder for the suggestion. String.format(getString(R.string.did_you_mean), myBidiFormatter.unicodeWrap(mySuggestion));
Nota: Si tu app se orienta a Android 4.3 (API nivel 18) o versiones posteriores, usa la versión de BidiFormatter
que se encuentra en el marco de trabajo de Android. De lo contrario, usa la versión de BidiFormatter
que se encuentra en la biblioteca de compatibilidad.
Cómo dar formato a los números
Para convertir los números en strings en la lógica de tu app, debes usar strings de formato y no llamadas a métodos:
Kotlin
var myIntAsString = "$myInt"
Java
String myIntAsString = String.format("%d", myInt);
De esta manera, se asignará el formato correcto a los números para tu configuración regional, lo que podría implicar el uso de un conjunto de dígitos diferente.
Cuando usas String.format()
para crear una consulta de SQL en un dispositivo cuya configuración regional usa su propio conjunto de dígitos (como la configuración regional del persa y la mayoría de las configuraciones regionales del árabe) podrías tener problemas si alguno de los parámetros de la consulta consiste en números, porque a estos se les asigna el formato de los dígitos de la configuración regional, los cuales no son válidos en SQL.
Para mantener los números con formato ASCII y que la consulta de SQL siga siendo válida, en su lugar, debes usar la versión sobrecargada de String.format()
que incluye una configuración regional como primer parámetro. El argumento de configuración regional debe ser Locale.US
.
Compatibilidad con duplicación de diseño
Los usuarios que usan la escritura de derecha a izquierda prefieren una interfaz de usuario de derecha a izquierda, que incluye texto y menús alineados a la derecha, y flechas para avanzar que apuntan hacia la izquierda.
En la figura 4, se muestra la comparación entre la versión de izquierda a derecha de una pantalla con la app de Configuración y su equivalente de derecha a izquierda.


Cuando agregas compatibilidad con escritura de derecha a izquierda en tu app, es muy importante que tengas en cuenta lo siguiente:
- La duplicación de texto de derecha a izquierda solo se admite en apps que se ejecutan en dispositivos con Android 4.2 (nivel de API 17) o versiones posteriores. Para obtener más información sobre cómo agregar compatibilidad con la duplicación de texto en dispositivos anteriores, consulta Cómo proporcionar compatibilidad con apps heredadas.
- Para probar si tu app admite una dirección de texto de derecha a izquierda, pruébala con las opciones para desarrolladores y, luego, invita a usuarios que usan escrituras de derecha a izquierda a que usen tu app.
Nota: Para ver lineamientos de diseño adicionales relacionados con la duplicación de diseño, incluida una lista de los elementos que deben duplicarse y los que no, consulta los lineamientos de material design sobre el diseño bidireccional.
Para duplicar el diseño de IU en tu app de manera que aparezca la escritura de derecha a izquierda en una configuración regional de derecha a izquierda, completa los pasos de las siguientes secciones.
Cómo modificar los archivos de manifiesto y de compilación
Puedes modificar el archivo build.gradle
del módulo de tu app y el archivo de manifiesto de la app de la siguiente manera:
build.gradle (módulo: app)
android { ... defaultConfig { targetSdkVersion 17 // Or higher ... } }
AndroidManifest.xml
<manifest ... > ... <application ... android:supportsRtl="true"> </application> </manifest>
Nota: Si tu app se orienta a Android 4.1.1 (API nivel 16) o versiones anteriores, se omite el atributo android:supportsRtl
junto con cualquier otro valor de los atributos start
y end
que aparezca en los archivos de diseño de tu app. En este caso, la duplicación de diseño de derecha a izquierda no se realiza automáticamente.
Cómo actualizar recursos existentes
Convierte left
y right
en start
y end
, respectivamente, en cada uno de los archivos de recursos de diseño existentes.
Al hacerlo, permites que el marco de trabajo alinee los elementos de IU de tu app en función de la configuración de idioma del usuario.
Nota: Antes de actualizar tus recursos, obtén más información sobre cómo proporcionar compatibilidad con apps heredadas o apps que se orientan a Android 4.1.1 (API nivel 16) y versiones anteriores.
Para usar las capacidades de alineación de derecha a izquierda del marco de trabajo, cambia los atributos de los archivos de diseño que aparecen en la tabla 1.
Tabla 1: Atributos para usar cuando tu app sea compatible con varias direcciones de texto
En la tabla 2, se muestra cómo el sistema controla los atributos de alineación de IU en función de la versión del SDK de destino y de si se definieron los atributos left
y right
, y los atributos start
y end
.
Tabla 2: Comportamiento de la alineación de elementos de IU en función de la versión del SDK de destino y los atributos definidos
|
¿Se definieron los atributos left y right? | ¿Se definieron los atributos start y end? | Resultado |
---|---|---|---|
Sí | Sí | Sí | Se resuelven start y end , y se anulan left y right
|
Sí | Sí | No | Solo se usan left y right |
Sí | No | Sí | Solo se usan start y end |
No | Sí | Sí |
Se usan left y right (se ignoran start y end )
|
No | Sí | No | Solo se usan left y right |
No | No | Sí |
start y end se resuelven como left y right
|
Cómo agregar recursos específicos de idioma y dirección
Este paso consiste en agregar versiones específicas del diseño, los elementos de diseño y los archivos de recursos de valores que contienen valores personalizados para diferentes idiomas y direcciones de texto.
En Android 4.2 (nivel de API 17) y versiones posteriores, puedes usar los calificadores de recursos -ldrtl
(dirección-de-diseño-de-derecha-a-izquierda) y -ldltr
(dirección-de-diseño-de-izquierda-a-derecha). Para conservar la retrocompatibilidad con versiones anteriores con la carga de recursos existentes, las versiones anteriores de Android usan calificadores idioma de recursos que permiten inferir la dirección de texto correcta.
Supongamos que quieres agregar un archivo de diseño específico para admitir la escritura de derecha a izquierda, como los idiomas hebreo, árabe y persa. Para ello, agregas un directorio layout-ldrtl/
en res/
, como se muestra en el siguiente ejemplo:
res/ layout/ main.xml This layout file is loaded by default. layout-ldrtl/ main.xml This layout file is loaded for languages using an RTL text direction, including Arabic, Persian, and Hebrew.
Si quieres agregar una versión específica del diseño creada únicamente para texto en árabe, la estructura de tu directorio se verá de la siguiente manera:
res/ layout/ main.xml This layout file is loaded by default. layout-ar/ main.xml This layout file is loaded for Arabic text. layout-ldrtl/ main.xml This layout file is loaded only for non-Arabic languages that use an RTL text direction.
Nota: Los recursos específicos de idioma prevalecen sobre los recursos específicos de la dirección del diseño, los cuales prevalecen sobre los recursos predeterminados.
Cómo usar widgets compatibles
A partir de Android 4.2 (nivel de API 17), la mayoría de los elementos de IU del marco de trabajo admiten automáticamente la dirección de texto de derecha a izquierda. Sin embargo, muchos elementos del marco de trabajo, como ViewPager
, no la admiten.
Los widgets de la pantalla principal admiten la dirección de texto de derecha a izquierda siempre y cuando sus archivos de manifiesto correspondientes incluyan la asignación del atributo android:supportsRtl="true"
.
Cómo proporcionar compatibilidad con apps heredadas
Si tu app se orienta a Android 4.1.1 (nivel de API 16) o versiones anteriores, debes incluir los atributos left
y right
, además de start
y end
.
Para comprobar si tu diseño debe usar la dirección de texto de derecha a izquierda, usa la siguiente lógica:
Kotlin
private fun shouldUseLayoutRtl(): Boolean { return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { View.LAYOUT_DIRECTION_RTL == layoutDirection } else { false } }
Java
private boolean shouldUseLayoutRtl() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { return View.LAYOUT_DIRECTION_RTL == getLayoutDirection(); } else { return false; } }
Nota: Para evitar problemas de compatibilidad, usa la versión 23.0.1 o versiones posteriores de las Herramientas de desarrollo del SDK de Android.
Cómo realizar pruebas con las opciones para desarrolladores
En dispositivos que ejecutan Android 4.4 (API nivel 19) o versiones posteriores, puedes habilitar la función Forzar diseño der. a izq. en las opciones para desarrolladores en el dispositivo. Esta configuración te permite ver el texto que usa la escritura de izquierda a derecha (como el texto en inglés) en el modo de derecha a izquierda.
Cómo actualizar la lógica de la app
En esta sección, se describen los lugares específicos de la lógica de tu app que debes actualizar cuando la adaptas para controlar varias direcciones de texto.
Cambios en las propiedades
Para controlar un cambio en una propiedad relacionada con la dirección de derecha a izquierda (como la dirección del diseño, los parámetros del diseño, el relleno, la dirección del texto, la alineación del texto o el posicionamiento de los elementos de diseño), puedes usar la devolución de llamada onRtlPropertiesChanged()
, que te permite obtener la dirección de diseño actual y actualizar los objetos View
de la actividad según corresponda.
Vistas
Si quieres crear un widget de IU que no es una parte directa de la jerarquía de vistas de una actividad, como un diálogo o un elemento de IU similar a una notificación, debes establecer la dirección de diseño correcta en función del contexto. En el siguiente fragmento de código, se muestra cómo completar este proceso:
Kotlin
val config: Configuration = context.resources.configuration view.layoutDirection = config.layoutDirection
Java
final Configuration config = getContext().getResources().getConfiguration(); view.setLayoutDirection(config.getLayoutDirection());
Muchos métodos de la clase View
requieren consideraciones adicionales:
onMeasure()
- Las mediciones de vistas pueden variar en función de la dirección del texto.
onLayout()
- Si creas tu propia implementación de diseño, deberás llamar a
super()
en tu versión deonLayout()
y adaptar tu lógica personalizada para que admita escrituras de derecha a izquierda. onDraw()
- Si quieres implementar una vista personalizada o agregar funcionalidades avanzadas a un dibujo, deberás actualizar tu código para que admita escrituras de derecha a izquierda. Usa el siguiente código para determinar si tu widget está en modo de derecha a izquierda:
Kotlin
// On devices running Android 4.1.1 (API level 16) and lower, // you can call the isLayoutRtl() system method directly. fun isLayoutRtl(): Boolean = layoutDirection == LAYOUT_DIRECTION_RTL
Java
// On devices running Android 4.1.1 (API level 16) and lower, // you can call the isLayoutRtl() system method directly. public boolean isLayoutRtl() { return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); }
Elementos de diseño
Si tienes un elemento de diseño que necesita duplicarse para un diseño de derecha a izquierda, completa uno de estos pasos en función de la versión de Android que se ejecuta en el dispositivo:
- En dispositivos que ejecutan Android 4.3 (nivel de API 18) o versiones anteriores, debes agregar y definir los archivos de recursos
-ldrtl
. -
En Android 4.4 (nivel de API 19) o versiones posteriores, puedes usar
android:autoMirrored="true"
cuando definas tu elemento de diseño, que le permitirá al sistema controlar la duplicación del diseño de derecha a izquierda por ti.Nota: El atributo
android:autoMirrored
solo funciona para elementos de diseño sencillos cuya duplicación bidireccional es simplemente una duplicación gráfica de todo el elemento de diseño. Si tu elemento de diseño contiene varios elementos o si al reflejarlo se cambia su interpretación, tendrás que realizar la duplicación tú mismo. Siempre que sea posible, consulta a un experto en diseño bidireccional para determinar si los usuarios pueden comprender tus elementos de diseño duplicados.
Gravedad
Si el código de tu app es Gravity.LEFT
o Gravity.RIGHT
, tendrás que cambiar estos valores a Gravity.START
y Gravity.END
, respectivamente.
Por ejemplo, si usas el siguiente código:
Kotlin
when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) { Gravity.LEFT -> { // Handle objects that are left-aligned. } Gravity.RIGHT -> { // Handle objects that are right-aligned. } }
Java
switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.LEFT: // Handle objects that are left-aligned. break; case Gravity.RIGHT: // Handle objects that are right-aligned. break; }
Deberás modificarlo de la siguiente manera:
Kotlin
val absoluteGravity: Int = Gravity.getAbsoluteGravity(gravity, layoutDirection) when (absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK) { Gravity.LEFT -> { // Handle objects that are left-aligned. } Gravity.RIGHT -> { // Handle objects that are right-aligned. } }
Java
final int layoutDirection = getLayoutDirection(); final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection); switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.LEFT: // Handle objects that are left-aligned. break; case Gravity.RIGHT: // Handle objects that are right-aligned. break; }
De esta manera, puedes conservar el código existente que controla los valores alineados a la izquierda y a la derecha, incluso si usas start
y end
para tus valores de gravedad.
Nota: Cuando apliques tu configuración de gravedad, usa una versión sobrecargada de Gravity.apply()
que incluya un argumento layoutDirection
.
Margen y relleno
Para admitir escrituras de derecha a izquierda en tu app, sigue las prácticas recomendadas relacionadas con los valores de margen y relleno:
- Usa
getMarginStart()
ygetMarginEnd()
en lugar de los equivalentes de atributos específicos de la direcciónleftMargin
yrightMargin
. - Cuando uses
setMargins()
, intercambia los valores de los argumentosleft
yright
si tu app detecta escrituras de derecha a izquierda. -
Si tu app incluye una lógica de relleno personalizada, anula
setPadding()
ysetPaddingRelative()
.