]> granicus.if.org Git - icu/commitdiff
ICU-10736 Locale.isRightToLeft(), uloc_isRightToLeft(locale)
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 28 Aug 2014 18:28:30 +0000 (18:28 +0000)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 28 Aug 2014 18:28:30 +0000 (18:28 +0000)
X-SVN-Rev: 36269

icu4c/source/common/loclikely.cpp
icu4c/source/common/unicode/locid.h
icu4c/source/common/unicode/uloc.h
icu4c/source/test/cintltst/cloctst.c
icu4c/source/test/intltest/loctest.cpp
icu4c/source/test/intltest/loctest.h

index 6fbf873bdefd2daed0b30e17fc773994836f7230..aa4a95b85c41a812f71a87b5611cb673417b7828 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 1997-2012, International Business Machines
+*   Copyright (C) 1997-2014, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 */
 
 #include "unicode/utypes.h"
+#include "unicode/locid.h"
 #include "unicode/putil.h"
 #include "unicode/uloc.h"
 #include "unicode/ures.h"
+#include "unicode/uscript.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "ulocimp.h"
 #include "ustr_imp.h"
 
+#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
 /**
  * This function looks for the localeID in the likelySubtags resource.
  *
@@ -1273,3 +1277,59 @@ uloc_minimizeSubtags(const char*    localeID,
                     err);
     }    
 }
+
+// Pairs of (language subtag, + or -) for finding out fast if common languages
+// are LTR (minus) or RTL (plus).
+static const char* LANG_DIR_STRING =
+        "root-en-es-pt-zh-ja-ko-de-fr-it-ar+he+fa+ru-nl-pl-th-tr-";
+
+// Implemented here because this calls uloc_addLikelySubtags().
+U_CAPI UBool U_EXPORT2
+uloc_isRightToLeft(const char *locale) {
+    UErrorCode errorCode = U_ZERO_ERROR;
+    char script[8];
+    int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode);
+    if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
+            scriptLength == 0) {
+        // Fastpath: We know the likely scripts and their writing direction
+        // for some common languages.
+        errorCode = U_ZERO_ERROR;
+        char lang[8];
+        int32_t langLength = uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &errorCode);
+        if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
+                langLength == 0) {
+            return FALSE;
+        }
+        const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang);
+        if (langPtr != NULL) {
+            switch (langPtr[langLength]) {
+            case '-': return FALSE;
+            case '+': return TRUE;
+            default: break;  // partial match of a longer code
+            }
+        }
+        // Otherwise, find the likely script.
+        errorCode = U_ZERO_ERROR;
+        char likely[ULOC_FULLNAME_CAPACITY];
+        (void)uloc_addLikelySubtags(locale, likely, UPRV_LENGTHOF(likely), &errorCode);
+        if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) {
+            return FALSE;
+        }
+        scriptLength = uloc_getScript(likely, script, UPRV_LENGTHOF(script), &errorCode);
+        if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING ||
+                scriptLength == 0) {
+            return FALSE;
+        }
+    }
+    UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script);
+    return uscript_isRightToLeft(scriptCode);
+}
+
+U_NAMESPACE_BEGIN
+
+UBool
+Locale::isRightToLeft() const {
+    return uloc_isRightToLeft(getBaseName());
+}
+
+U_NAMESPACE_END
index 09ab5617a12b6a8bc149cc2db1565b3f035f93bf..96b8d2a6435d2ded3efe9e25aca24c0122d3f06f 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1996-2013, International Business Machines
+*   Copyright (C) 1996-2014, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -493,6 +493,21 @@ public:
      */
     uint32_t        getLCID(void) const;
 
+    /**
+     * Returns whether this locale's script is written right-to-left.
+     * If there is no script subtag, then the likely script is used, see uloc_addLikelySubtags().
+     * If no likely script is known, then FALSE is returned.
+     *
+     * A script is right-to-left according to the CLDR script metadata
+     * which corresponds to whether the script's letters have Bidi_Class=R or AL.
+     *
+     * Returns TRUE for "ar" and "en-Hebr", FALSE for "zh" and "fa-Cyrl".
+     *
+     * @return TRUE if the locale's script is written right-to-left
+     * @draft ICU 54
+     */
+    UBool isRightToLeft() const;
+
     /**
      * Fills in "dispLang" with the name of this locale's language in a format suitable for
      * user display in the default locale.  For example, if the locale's language code is
index fd9ddd83543511e79b378df78e0e3487bf1ec46c..5d9e1e7dc8881a1424d4bd6029a73b7f6531354a 100644 (file)
@@ -886,6 +886,23 @@ uloc_setKeywordValue(const char* keywordName,
                      char* buffer, int32_t bufferCapacity,
                      UErrorCode* status);
 
+/**
+ * Returns whether the locale's script is written right-to-left.
+ * If there is no script subtag, then the likely script is used, see uloc_addLikelySubtags().
+ * If no likely script is known, then FALSE is returned.
+ *
+ * A script is right-to-left according to the CLDR script metadata
+ * which corresponds to whether the script's letters have Bidi_Class=R or AL.
+ *
+ * Returns TRUE for "ar" and "en-Hebr", FALSE for "zh" and "fa-Cyrl".
+ *
+ * @param locale input locale ID
+ * @return TRUE if the locale's script is written right-to-left
+ * @draft ICU 54
+ */
+U_DRAFT UBool U_EXPORT2
+uloc_isRightToLeft(const char *locale);
+
 /**
  * enums for the  return value for the character and line orientation
  * functions.
index edd820fbec75334e44d2f98574b08dc2aa922578..d1fc2fff53652a424b1ed702aacd2d640c6bf610 100644 (file)
@@ -45,6 +45,8 @@ static void TestDisplayNameBrackets(void);
 
 static void TestUnicodeDefines(void);
 
+static void TestIsRightToLeft(void);
+
 void PrintDataTable();
 
 /*---------------------------------------------------
@@ -247,6 +249,7 @@ void addLocaleTest(TestNode** root)
     TESTCASE(TestUnicodeDefines);
     TESTCASE(TestEnglishExemplarCharacters);
     TESTCASE(TestDisplayNameBrackets);
+    TESTCASE(TestIsRightToLeft);
 }
 
 
@@ -5876,3 +5879,10 @@ static void TestUnicodeDefines(void) {
   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ASSIGN, ULOC_KEYWORD_ASSIGN_UNICODE);
   TEST_UNICODE_DEFINE(ULOC_KEYWORD_ITEM_SEPARATOR, ULOC_KEYWORD_ITEM_SEPARATOR_UNICODE);
 }
+
+static void TestIsRightToLeft() {
+    // API test only. More test cases in intltest/LocaleTest.
+    if(uloc_isRightToLeft("root") || !uloc_isRightToLeft("EN-HEBR")) {
+        log_err("uloc_isRightToLeft() failed");
+    }
+}
index 3e0d60e5caf1e2d9b0b622b496c0443d7e652cb1..2a247e304ca5279265ed13defa47160f10c739ac 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT:
- * Copyright (c) 1997-2013, International Business Machines Corporation and
+ * Copyright (c) 1997-2014, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -180,59 +180,50 @@ LocaleTest::~LocaleTest()
 
 void LocaleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
 {
-    switch (index) {
-        TESTCASE(0, TestBasicGetters);
-        TESTCASE(1, TestSimpleResourceInfo);
-        TESTCASE(2, TestDisplayNames);
-        TESTCASE(3, TestSimpleObjectStuff);
-        TESTCASE(4, TestPOSIXParsing);
-        TESTCASE(5, TestGetAvailableLocales);
-        TESTCASE(6, TestDataDirectory);
-        TESTCASE(7, TestISO3Fallback);
-        TESTCASE(8, TestGetLangsAndCountries);
-        TESTCASE(9, TestSimpleDisplayNames);
-        TESTCASE(10, TestUninstalledISO3Names);
-        TESTCASE(11, TestAtypicalLocales);
+    TESTCASE_AUTO_BEGIN;
+    TESTCASE_AUTO(TestBasicGetters);
+    TESTCASE_AUTO(TestSimpleResourceInfo);
+    TESTCASE_AUTO(TestDisplayNames);
+    TESTCASE_AUTO(TestSimpleObjectStuff);
+    TESTCASE_AUTO(TestPOSIXParsing);
+    TESTCASE_AUTO(TestGetAvailableLocales);
+    TESTCASE_AUTO(TestDataDirectory);
+    TESTCASE_AUTO(TestISO3Fallback);
+    TESTCASE_AUTO(TestGetLangsAndCountries);
+    TESTCASE_AUTO(TestSimpleDisplayNames);
+    TESTCASE_AUTO(TestUninstalledISO3Names);
+    TESTCASE_AUTO(TestAtypicalLocales);
 #if !UCONFIG_NO_FORMATTING
-        TESTCASE(12, TestThaiCurrencyFormat);
-        TESTCASE(13, TestEuroSupport);
+    TESTCASE_AUTO(TestThaiCurrencyFormat);
+    TESTCASE_AUTO(TestEuroSupport);
 #endif
-        TESTCASE(14, TestToString);
+    TESTCASE_AUTO(TestToString);
 #if !UCONFIG_NO_FORMATTING
-        TESTCASE(15, Test4139940);
-        TESTCASE(16, Test4143951);
+    TESTCASE_AUTO(Test4139940);
+    TESTCASE_AUTO(Test4143951);
 #endif
-        TESTCASE(17, Test4147315);
-        TESTCASE(18, Test4147317);
-        TESTCASE(19, Test4147552);
-        TESTCASE(20, TestVariantParsing);
+    TESTCASE_AUTO(Test4147315);
+    TESTCASE_AUTO(Test4147317);
+    TESTCASE_AUTO(Test4147552);
+    TESTCASE_AUTO(TestVariantParsing);
 #if !UCONFIG_NO_FORMATTING
-        TESTCASE(21, Test4105828);
+    TESTCASE_AUTO(Test4105828);
 #endif
-        TESTCASE(22, TestSetIsBogus);
-        TESTCASE(23, TestParallelAPIValues);
-        TESTCASE(24, TestKeywordVariants);
-        TESTCASE(25, TestKeywordVariantParsing);
-        TESTCASE(26, TestSetKeywordValue);
-        TESTCASE(27, TestGetBaseName);
+    TESTCASE_AUTO(TestSetIsBogus);
+    TESTCASE_AUTO(TestParallelAPIValues);
+    TESTCASE_AUTO(TestKeywordVariants);
+    TESTCASE_AUTO(TestKeywordVariantParsing);
+    TESTCASE_AUTO(TestSetKeywordValue);
+    TESTCASE_AUTO(TestGetBaseName);
 #if !UCONFIG_NO_FILE_IO
-        TESTCASE(28, TestGetLocale);
+    TESTCASE_AUTO(TestGetLocale);
 #endif
-        TESTCASE(29, TestVariantWithOutCountry);
-        TESTCASE(30, TestCanonicalization);
-        TESTCASE(31, TestCurrencyByDate);
-       TESTCASE(32, TestGetVariantWithKeywords);
-
-        // keep the last index in sync with the condition in default:
-
-        default:
-            if (index <= 28) { // keep this in sync with the last index!
-                name = "(test omitted by !UCONFIG_NO_FORMATTING)";
-            } else {
-                name = "";
-            }
-            break; //needed to end loop
-    }
+    TESTCASE_AUTO(TestVariantWithOutCountry);
+    TESTCASE_AUTO(TestCanonicalization);
+    TESTCASE_AUTO(TestCurrencyByDate);
+    TESTCASE_AUTO(TestGetVariantWithKeywords);
+    TESTCASE_AUTO(TestIsRightToLeft);
+    TESTCASE_AUTO_END;
 }
 
 void LocaleTest::TestBasicGetters() {
@@ -2546,3 +2537,15 @@ void LocaleTest::TestGetVariantWithKeywords(void)
   buffer[len] = '\0';
   test_assert(strcmp("value", buffer) == 0);
 }
+
+void LocaleTest::TestIsRightToLeft() {
+    assertFalse("root LTR", Locale::getRoot().isRightToLeft());
+    assertFalse("zh LTR", Locale::getChinese().isRightToLeft());
+    assertTrue("ar RTL", Locale("ar").isRightToLeft());
+    assertTrue("und-EG RTL", Locale("und-EG").isRightToLeft());
+    assertFalse("fa-Cyrl LTR", Locale("fa-Cyrl").isRightToLeft());
+    assertTrue("en-Hebr RTL", Locale("en-Hebr").isRightToLeft());
+    assertTrue("ckb RTL", Locale("ckb").isRightToLeft());  // Sorani Kurdish
+    assertFalse("fil LTR", Locale("fil").isRightToLeft());
+    assertFalse("he-Zyxw LTR", Locale("he-Zyxw").isRightToLeft());
+}
index a9172b920715ccad25ff43bcfc91b04397e22ab1..53f606d471120eb81d071783366701cbab68ddaf 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2010, International Business Machines Corporation and
+ * Copyright (c) 1997-2014, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -101,6 +101,7 @@ public:
     void TestCurrencyByDate(void);
 
     void TestGetVariantWithKeywords(void);
+    void TestIsRightToLeft();
 
 private:
     void _checklocs(const char* label,
@@ -169,6 +170,3 @@ private:
         DNAME_NO
     };
 };
-
-
-