Supporting RTL languages in Android
Right-to-left support is not a cosmetic translation task. It affects reading order, navigation, alignment, gestures, icons and the way mixed-language content behaves inside an Android application.
Arabic, Hebrew, Persian and Urdu users need interfaces that feel native rather than reversed English screens. A resilient build follows the active locale, preserves logical text order and reuses the same components instead of maintaining a separate RTL app.
Make direction a foundation of the layout
Direction should follow the active app locale rather than a hardcoded visual choice. For an Arabic, Persian or Urdu build, the interface reads from right to left, while embedded English keeps its own direction. This is different from swapping the positions of a few controls.
| Layout concern | Left-to-right build | Right-to-left build |
|---|---|---|
| Reading progression | Left to right | Right to left |
| Leading interface edge | Left side | Right side |
| Start and end anchors | Resolve to left and right | Resolve to right and left |
| Directional resources | Remain unchanged where appropriate | Eligible assets mirror automatically |
| Non-directional artwork | Remains fixed | Remains fixed |
Per-app languages make this choice important. If the active locale is Arabic but labels remain English, forcing an RTL layout can leave English content aligned in an unfamiliar way. Let direction follow the app locale by default, and isolate exceptions on individual screens instead of reversing the entire hierarchy.
Enable RTL in the manifest and root view
Framework-level RTL support arrived in Android 4.2, API level 17. Declare support on the application so Android can apply relative layout rules and mirror eligible resources:
<application
xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsRtl="true">
Recent AndroidX AppCompat releases provide compatibility features for older devices, but the oldest supported Android version still needs dedicated testing.
The root container can inherit its direction or explicitly request the current locale:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layoutDirection="locale"
android:textDirection="locale">
Here, layoutDirection controls the arrangement of components, while textDirection controls text directionality. The locale value follows the active application configuration, including locales selected through AndroidX.
Use relative edges instead of physical sides
start and end describe logical leading and trailing edges. They resolve to left and right in an LTR layout, then right and left in an RTL layout:
<TextView
android:layout_marginStart="16dp"
android:paddingEnd="12dp"
android:gravity="start"
android:drawableStart="@drawable/ic_filter" />
Replace layout_alignParentLeft with layout_alignParentStart, layout_toRightOf with layout_toEndOf, and physical margin or padding attributes with their logical equivalents. In ConstraintLayout, use layout_constraintStartToStartOf and layout_constraintEndToEndOf.
The same principle applies in Kotlin. Framework-level APIs use Gravity.START and Gravity.END, while margins can be assigned with setMarginStart and setMarginEnd. These logical values let one layout work correctly in either direction.
Mirror visual assets by meaning
Android can mirror eligible drawables, but applying one blanket rule to every image is unsafe. A back arrow, forward arrow or list caret should follow the reading direction. A company logo, portrait, map, scientific symbol or chart normally should not be mirrored.
On API 19 and later, android:autoMirrored can flag a genuinely directional vector. Supply separate artwork when an asset needs complete visual control, and custom views should check the resolved layoutDirection before drawing. Code that assumes every coordinate increases from the left will produce incorrect or overlapping content in an RTL hierarchy.
Preserve logical order in mixed-language text
RTL text is bidirectional: an Arabic sentence may contain an English product name, number, email address or URL. Android applies the Unicode Bidirectional Algorithm when rendering text, so developers should store and provide strings in their natural logical order rather than reversing them manually.
The framework’s TextView already handles standard bidirectional text. BidiFormatter is useful when assembling dynamic content or drawing text outside a TextView:
val message = getString(R.string.order_summary, productName)
binding.orderSummary.text =
BidiFormatter.getInstance().unicodeWrap(message)
Do not manually swap brackets or reverse an entire string, because neutral characters such as punctuation can then move to the wrong end. Wrap independently inserted fragments when combining translated text and dynamic values. For a field containing unpredictable user-generated content, textDirection="firstStrong" can let the first strong directional character determine the run’s direction.
Localise content for Australian users
Writing direction is only one part of localisation. Use values-ar, values-fa and values-ur for translated resources, while values-en-rAU can hold Australian English spelling and wording. Australian English commonly uses “mobile” rather than “cell phone”, along with spellings such as “colour” and “organisation”.
Dates and numbers need separate locale-aware formatting. Australian English generally presents the day before the month, such as 31/12/2025, while Arabic-speaking users may expect different numerals, separators and regional conventions. Use DateFormat and NumberFormat with the active locale instead of hardcoded formats.
Language locale does not determine time zone. Australia spans several time zones, including different clocks in Perth, Adelaide, Brisbane, Sydney and Melbourne. Use the appropriate ZoneId and display the zone when an event’s timing could otherwise be ambiguous.
Australian Android distribution is dominated by Google Play, where public-facing transport, education, banking and commerce apps often serve multilingual customers. Translating the Play listing and screenshots supports that journey, but users will still reject an app whose controls or mixed-language messages remain awkward.
Test realistic flows and accessibility
RTL quality is easiest to judge with complete user journeys. Sydney and Melbourne have substantial Arabic-, Persian- and Urdu-speaking communities, and bilingual users may move between Australian English and another language within the same app. AndroidX AppCompat can exercise an app locale directly:
AppCompatDelegate.setApplicationLocales(
LocaleListCompat.forLanguageTags("ar-AU")
)
Run login, checkout, forms, dialogs, menus, navigation drawers and ListView or RecyclerView items under Arabic, Persian, Urdu and Australian English. Recreate activities after locale changes and confirm that unsaved input, selections and navigation state remain intact.
Finish with TalkBack, large fonts, large display sizes and hardware-keyboard navigation. Reading order, focus movement, touch targets and content descriptions must remain logical after the visual direction changes. That combination gives multilingual users in Australia the same dependable experience as English-speaking users without creating a fragile parallel application.