program story

Android에서 RTL 언어 식별

inputbox 2021. 1. 9. 09:51
반응형

Android에서 RTL 언어 식별


모든 RTL 언어에 대해 언어 코드를 테스트하는 것 외에 RTL (오른쪽에서 왼쪽) 언어를 식별하는 방법이 있습니까?

API 17+는 RTL 및 LTR에 대한 여러 리소스를 허용하기 때문에 적어도 API 17에서 방법이 있어야한다고 생각합니다.


Configuration.getLayoutDirection () 에서 가져옵니다 .

Configuration config = getResources().getConfiguration();
if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
    //in Right To Left layout
}

@cyanide의 대답에는 올바른 접근 방식이 있지만 중요한 버그가 있습니다.

Character.getDirectionality는 양방향 (bidi) 문자 유형을 반환합니다 . 왼쪽에서 오른쪽 텍스트는 예측 가능한 유형 L이고 오른쪽에서 왼쪽은 예상 가능한 유형 R입니다. 그러나 아랍어 텍스트는 다른 유형 인 AL을 리턴합니다.

R 유형과 AL 유형 모두에 대한 검사를 추가 한 다음 Android와 함께 제공되는 모든 RTL 언어 인 히브리어 (이스라엘), 아랍어 (이집트) 및 아랍어 (이스라엘)를 수동으로 테스트했습니다.

보시다시피 다른 오른쪽에서 왼쪽으로 쓰는 언어는 제외되므로 Android가 이러한 언어를 추가함에 따라 유사한 문제가 발생할 수 있으며 바로 눈치 채지 못할 수 있습니다.

그래서 각 RTL ​​언어를 수동으로 테스트했습니다.

  • 아랍어 (العربية) = AL 유형
  • 쿠르드어 (کوردی) = 유형 AL
  • 페르시아어 (فارسی) = 유형 AL
  • 우르두어 (اردو) = AL 유형
  • 히브리어 (עברית) = 유형 R
  • 이디시어 (ייִדיש) = 유형 R

따라서 이것이 잘 작동 할 것 같습니다.

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

나에게 올바른 방향을 보내 주신 @cyanide에게 감사드립니다!


지원 라이브러리를 사용하는 경우 다음을 수행 할 수 있습니다.

if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL) {
    // The view has RTL layout
} else {
    // The view has LTR layout
}

지원 라이브러리에서 TextUtilsCompat사용할 수 있습니다 .

TextUtilsCompat.getLayoutDirectionFromLocale(locale)


보기의 레이아웃 방향을 확인하는 정말 간단한 방법이 있지만 API 17 이전 기기에서는 LTR로 돌아갑니다.

ViewUtils.isLayoutRtl(View view);

ViewUtils 클래스는 지원 v7 라이브러리와 함께 제공되므로 appcompat 라이브러리를 사용하는 경우 이미 사용할 수 있습니다.


나는 많은 정보를 모았고 마침내 내 자신의 RTLUtils 클래스를 만들었습니다.

주어진 Locale 또는 View가 '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;
    }
}

17 미만의 API를 확인하려면 이렇게 확인할 수 있습니다.

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

또는 API 17 이상

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

LTR 및 RTL 모드 모두에서 앱 UI를보다 정확하게 제어하기 위해 Android 4.2에는 View 구성 요소를 관리하는 데 도움이되는 다음과 같은 새로운 API가 포함되어 있습니다.

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

따라서 getLayoutDirectionFromLocale ()이 도움이 될 것입니다. 여기에서 샘플 코드를 참조하세요. https://android.googlesource.com/platform/frameworks/base.git/+/3fb824bae3322252a68c1cf8537280a5d2bd356d/core/tests/coretests/src/android/util/LocaleUtilTest.java


모두에게 감사합니다.

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

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.


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

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.


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
}

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

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());

ReferenceURL : https://stackoverflow.com/questions/18996183/identifying-rtl-language-in-android

반응형