ICU-10736 Locale.isRightToLeft(), uloc_isRightToLeft(locale)

X-SVN-Rev: 36269
This commit is contained in:
Markus Scherer 2014-08-28 18:28:30 +00:00
parent 2572a84f50
commit 53dcbe6141
6 changed files with 155 additions and 52 deletions

View 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.
*
*******************************************************************************
@ -18,14 +18,18 @@
*/
#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

View 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

View 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.

View 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");
}
}

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

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