Identifying RTL language in Android
Asked Answered
A

17

60

Is there a way to identify RTL (right-to-left) language, apart from testing language code against all RTL languages?

Since API 17+ allows several resources for RTL and LTR, I assume, there should be a way, at least from API 17.

Assuan answered 25/9, 2013 at 4:23 Comment(0)
R
85

Get it from Configuration.getLayoutDirection():

Configuration config = getResources().getConfiguration();
if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
    //in Right To Left layout
}
Rexanna answered 25/9, 2013 at 4:37 Comment(5)
Unfortunately "Added in API level 17" so it wont work on older versions.Sardonyx
This solution works when you use "Force RTL layout direction" in developer options as well!Transcend
That's how you can do it for API levels below 17: https://mcmap.net/q/325222/-identifying-rtl-language-in-android.Nady
In Oreo it do not change the layout direction automatically(maybe its a bug) So this will not work in Oreo.Redo
@Sardonyx RTL isn't supported on 16 and below, so treat it as LTRDecompress
S
55

@cyanide's answer has the right approach but a critical bug.

Character.getDirectionality returns the Bi-directional (bidi) character type. Left-to-right text is a predictable type L and right-to-left is also predictably type R. BUT, Arabic text returns another type, type AL.

I added a check for both type R and type AL and then manually tested every RTL language Android comes with: Hebrew (Israel), Arabic (Egypt), and Arabic (Israel).

As you can see, this leaves out other right-to-left languages, so I was concerned that as Android adds these languages, there might have a similar issue and one might not notice right away.

So I tested manually each RTL language.

  • Arabic (العربية) = type AL
  • Kurdish (کوردی) = type AL
  • Farsi (فارسی) = type AL
  • Urdu (اردو) = type AL
  • Hebrew (עברית) = type R
  • Yiddish (ייִדיש) = type R

So it looks like this should work great:

public static boolean isRTL() {
    return isRTL(Locale.getDefault());
}

public static boolean isRTL(Locale locale) {
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
           directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
}

Thanks @cyanide for sending me the right direction!

Salsify answered 21/4, 2014 at 18:44 Comment(3)
This causes a StringIndexOutOfBoundsException from locale.getDisplayName().charAt(0). It seems that this is a known issue with Java 7. My current solution around this is something like final String language = application.getResources().getConfiguration().locale.getLanguage(); return Strings.equals(language, "iw") || Strings.equals(language, "ar") || Strings.equals(language, "he");Baerman
@Baerman interesting…is that something that affects real Android devices or just testing environments like Genymotion?Salsify
I need to change layout according to their local. I able to change strings. but I unable to change image. suppose in english image is in left side when i change to Arabic it should be right.I need to change on button click. if i go settings>language . its woking fine. but in code it is not working . I create only one layout. please let me know.Dominiquedominium
N
24

If you're using the support library, you can do the following:

if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) {
    // The view has RTL layout
} else {
    // The view has LTR layout
}
Nady answered 17/2, 2015 at 18:54 Comment(4)
I need to change layout according to their local. I able to change strings. but I unable to change image. suppose in english image is in left side when i change to Arabic it should be right.I need to change on button click. if i go settings>language . its woking fine. but in code it is not working . I create only one layout. please let me know.Dominiquedominium
Can we use this for pre API 17?Oddball
@Oddball yes, but it will always return LTROvereager
Just an FYI, this depends on the view being attached to a window, so if you do it in a constructor or onFinishInflate then it'll always treat it as LTR.Delgadillo
A
16

You can use TextUtilsCompat from the support library.

TextUtilsCompat.getLayoutDirectionFromLocale(locale)

Asyllabic answered 19/5, 2016 at 8:56 Comment(3)
Using the compat libraries is always a smart way to go but this is the one case where the Character.getDirectionality is available all the way to API 1. I would say both are acceptable.Region
Note that if your minSdk is at least 17, you can use the normal call instead: developer.android.com/reference/android/text/…Decompress
There is a difference between getLayoutDirectionFromLocale and Character.getDirectionality. getLayoutDirectionFromLocale does not consider Yiddish to be a RTL language, while Character.getDirectionality does.Alf
B
9

There's a really simple way to check the layout direction of a view, but it falls back to LTR on pre API 17 devices:

ViewUtils.isLayoutRtl(View view);

the ViewUtils class comes bundled with the support v7 library, so it should be available already if you're using the appcompat library.

Bedplate answered 6/8, 2015 at 10:17 Comment(2)
I need to change layout according to their local. I able to change strings. but I unable to change image. suppose in english image is in left side when i change to Arabic it should be right.I need to change on button click. if i go settings>language . its woking fine. but in code it is not working . I create only one layout. please let me know.Dominiquedominium
This just calls to ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL; , and this function isn't available for us to use (IDE shows error using it).Decompress
R
9

You can check like this if you want to check for API lower than 17

boolean isRightToLeft = TextUtilsCompat.getLayoutDirectionFromLocale(Locale
               .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;

OR for API 17 or above

boolean isRightToLeft = TextUtils.getLayoutDirectionFromLocale(Locale
               .getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;
Redo answered 23/11, 2017 at 10:39 Comment(0)
A
8

I gathered many information and finally made my own, hopefully complete, RTLUtils class.

It allows to know if a given Locale or View is 'RTL' :-)

package com.elementique.shared.lang;

import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import android.support.v4.view.ViewCompat;
import android.view.View;

public class RTLUtils
{

    private static final Set<String> RTL;

    static
    {
        Set<String> lang = new HashSet<String>();
        lang.add("ar"); // Arabic
        lang.add("dv"); // Divehi
        lang.add("fa"); // Persian (Farsi)
        lang.add("ha"); // Hausa
        lang.add("he"); // Hebrew
        lang.add("iw"); // Hebrew (old code)
        lang.add("ji"); // Yiddish (old code)
        lang.add("ps"); // Pashto, Pushto
        lang.add("ur"); // Urdu
        lang.add("yi"); // Yiddish
        RTL = Collections.unmodifiableSet(lang);
    }

    public static boolean isRTL(Locale locale)
    {
        if(locale == null)
            return false;

        // Character.getDirectionality(locale.getDisplayName().charAt(0))
        // can lead to NPE (Java 7 bug)
        // https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
        // using hard coded list of locale instead
        return RTL.contains(locale.getLanguage());
    }

    public static boolean isRTL(View view)
    {
        if(view == null)
            return false;

        // config.getLayoutDirection() only available since 4.2
        // -> using ViewCompat instead (from Android support library)
        if (ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL)
        {
            return true;
        }
        return false;
    }
}
Adjoint answered 24/2, 2015 at 8:38 Comment(4)
I need to change layout according to their local. I able to change strings. but I unable to change image. suppose in english image is in left side when i change to Arabic it should be right.I need to change on button click. if i go settings>language . its woking fine. but in code it is not working . I create only one layout. please let me know.Dominiquedominium
@Maid786 Not sure what you want to do. Have a look at developer.android.com/reference/android/widget/… and https://mcmap.net/q/259916/-android-flip-image-in-xmlAdjoint
@Adjoint How can I convert RTL string to double? eg: "‏‪41.12 ‬‏"Pelf
Sorry, I don't know how it's supposed to be done (I speak french and don't any of these RTL languages) maybe @ali-khaki can help?Adjoint
A
6

You can detect if a string is RTL/LTR with Bidi. Example:

import java.text.Bidi;

Bidi bidi = new Bidi( title, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT );

if( bidi.isLeftToRight() ) {
   // it's LTR
} else {
   // it's RTL
}
Afterlife answered 23/1, 2019 at 10:26 Comment(0)
O
4

Just use this code:

 public static boolean isRTL() {
   return isRTL(Locale.getDefault());
 }

 public static boolean isRTL(Locale locale) {
  final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
  return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
       directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
 }

 if (isRTL()) {
   // The view has RTL layout
 }
 else {
   // The view has LTR layout
 }

This will work for all Android API lavels.

Ossification answered 8/5, 2016 at 16:14 Comment(0)
S
3

For more precise control over your app UI in both LTR and RTL mode, Android 4.2 includes the following new APIs to help manage View components:

android:layoutDirection — attribute for setting the direction of a component's layout.
android:textDirection — attribute for setting the direction of a component's text.
android:textAlignment — attribute for setting the alignment of a component's text.
getLayoutDirectionFromLocale() — method for getting the Locale-specified direction

Thus getLayoutDirectionFromLocale() should help you out. Refer the sample code here : https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java

Sealed answered 25/9, 2013 at 5:18 Comment(1)
Is it possible to set layoutDirection to the value corresponding to the system locale? So, it can be either rtl or ltr.Xenocrates
A
2

Thanks to all.

If you look at the code of LayoutUtil.getLayoutDirectionFromLocale() (and, I assume Confuiguration.getLayoutDirection() as well), it ends up with analysing the starting letter of locale display name, using Character.getDirectionality.

Since Character.getDirectionality was around from Android 1, the following code will be compatible with all Android releases (even those, not supporting RTL correctly :)):

public static boolean isRTL() {
    return isRTL(Locale.getDefault());
}

public static boolean isRTL(Locale locale) {
     return
        Character.getDirectionality(locale.getDisplayName().charAt(0)) ==
            Character.DIRECTIONALITY_RIGHT_TO_LEFT; 
}
Assuan answered 26/9, 2013 at 1:57 Comment(0)
T
2

When building library you also always need to check if application is supporting RTL by using

(getApplicationInfo().flags &= ApplicationInfo.FLAG_SUPPORTS_RTL) != 0

When application is running on RTL locale, but it isn't declared in manifest android:supportsRtl="true" then it is running in LTR mode.

Touched answered 17/5, 2017 at 11:10 Comment(1)
Good point for a library! However, in the main app I know that supportsRtl is set, so checking seems to be redundant.Assuan
S
1

This will work in all SDKS:

private boolean isRTL() {
    Locale defLocale = Locale.getDefault();
    return  Character.getDirectionality(defLocale.getDisplayName(defLocale).charAt(0)) == Character.DIRECTIONALITY_RIGHT_TO_LEFT;
}
Spatiotemporal answered 27/2, 2014 at 9:23 Comment(0)
R
0

Native RTL support in Android 4.2

    public static ComponentOrientation getOrientation(Locale locale) 
    {
            // A more flexible implementation would consult a ResourceBundle
            // to find the appropriate orientation.  Until pluggable locales
            // are introduced however, the flexiblity isn't really needed.
            // So we choose efficiency instead.
            String lang = locale.getLanguage();
            if( "iw".equals(lang) || "ar".equals(lang)
                || "fa".equals(lang) || "ur".equals(lang) )
            {
                return RIGHT_TO_LEFT;
            } else {
                return LEFT_TO_RIGHT;
            }
    }
Ricebird answered 25/9, 2013 at 4:55 Comment(1)
Good! More complete answer here: #20815064 would you update yours?Adjoint
C
0

Easily you can use this :

 if (getWindow().getDecorView().getLayoutDirection()== View.LAYOUT_DIRECTION_RTL) {
        // The view has RTL layout
    } else {
        // The view has LTR layout
    }
Clarabelle answered 16/8, 2020 at 17:34 Comment(0)
N
0

You might have a specific requirement to test RTL explicitly but usually in android you don't need to.

All resources can be configured to any language by creating locale directories and resource files and together with using 'Start' and 'End' instead of 'Left' and 'Right' you can support RTL seamlessly.

e.g. android:layout_alignParentStart="true" instead of android:layout_alignParentLeft="true"

See here: https://developer.android.com/training/basics/supporting-devices/languages

Android makes it so easy, it's usually a waste of effort to code separate RTL/LTR logic.

Nikko answered 16/12, 2022 at 16:49 Comment(0)
B
-1

Because English language devices are supporting RTL, you can use this code in your MainActivity to change device language to english and you don't need to "supportRTL" code.

String languageToLoad  = "en"; // your language
Locale locale = new Locale(languageToLoad);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
Barbet answered 11/7, 2017 at 12:8 Comment(2)
Your code has a syntax error in the second last line.Emmie
The question was about identifying RTL and not about seting the locale.Maundy

© 2022 - 2024 — McMap. All rights reserved.