static jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLanguageTag, jobject localeData) { ScopedUtfChars languageTag(env, javaLanguageTag); if (languageTag.c_str() == NULL) { return JNI_FALSE; } if (languageTag.size() >= ULOC_FULLNAME_CAPACITY) { return JNI_FALSE; // ICU has a fixed-length limit. } ScopedIcuLocale icuLocale(env, javaLanguageTag); if (!icuLocale.valid()) { return JNI_FALSE; } // Get the DateTimePatterns. UErrorCode status = U_ZERO_ERROR; bool foundDateTimePatterns = false; for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { if (getDateTimePatterns(env, localeData, it.Get())) { foundDateTimePatterns = true; break; } } if (!foundDateTimePatterns) { ALOGE("Couldn't find ICU DateTimePatterns for %s", languageTag.c_str()); return JNI_FALSE; } // Get the "Yesterday", "Today", and "Tomorrow" strings. bool foundYesterdayTodayAndTomorrow = false; for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { if (getYesterdayTodayAndTomorrow(env, localeData, icuLocale.locale(), it.Get())) { foundYesterdayTodayAndTomorrow = true; break; } } if (!foundYesterdayTodayAndTomorrow) { ALOGE("Couldn't find ICU yesterday/today/tomorrow for %s", languageTag.c_str()); return JNI_FALSE; } // Get the narrow "AM" and "PM" strings. bool foundAmPmMarkersNarrow = false; for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) { if (getAmPmMarkersNarrow(env, localeData, it.Get())) { foundAmPmMarkersNarrow = true; break; } } if (!foundAmPmMarkersNarrow) { ALOGE("Couldn't find ICU AmPmMarkersNarrow for %s", languageTag.c_str()); return JNI_FALSE; } status = U_ZERO_ERROR; UniquePtr<Calendar> cal(Calendar::createInstance(icuLocale.locale(), status)); if (U_FAILURE(status)) { return JNI_FALSE; } setIntegerField(env, localeData, "firstDayOfWeek", cal->getFirstDayOfWeek()); setIntegerField(env, localeData, "minimalDaysInFirstWeek", cal->getMinimalDaysInFirstWeek()); // Get DateFormatSymbols. status = U_ZERO_ERROR; DateFormatSymbols dateFormatSym(icuLocale.locale(), status); if (U_FAILURE(status)) { return JNI_FALSE; } // Get AM/PM and BC/AD. int32_t count = 0; const UnicodeString* amPmStrs = dateFormatSym.getAmPmStrings(count); setStringArrayField(env, localeData, "amPm", amPmStrs, count); const UnicodeString* erasStrs = dateFormatSym.getEras(count); setStringArrayField(env, localeData, "eras", erasStrs, count); const UnicodeString* longMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longMonthNames", longMonthNames, count); const UnicodeString* shortMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames, count); const UnicodeString* tinyMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); setStringArrayField(env, localeData, "tinyMonthNames", tinyMonthNames, count); const UnicodeString* longWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames, count); const UnicodeString* shortWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames, count); const UnicodeString* tinyWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); setStringArrayField(env, localeData, "tinyWeekdayNames", tinyWeekdayNames, count); const UnicodeString* longStandAloneMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames, count); const UnicodeString* shortStandAloneMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames, count); const UnicodeString* tinyStandAloneMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); setStringArrayField(env, localeData, "tinyStandAloneMonthNames", tinyStandAloneMonthNames, count); const UnicodeString* longStandAloneWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames, count); const UnicodeString* shortStandAloneWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames, count); const UnicodeString* tinyStandAloneWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); setStringArrayField(env, localeData, "tinyStandAloneWeekdayNames", tinyStandAloneWeekdayNames, count); status = U_ZERO_ERROR; // For numberPatterns and symbols. setNumberPatterns(env, localeData, icuLocale.locale()); setDecimalFormatSymbolsData(env, localeData, icuLocale.locale()); jstring countryCode = env->NewStringUTF(icuLocale.locale().getCountry()); jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode); env->DeleteLocalRef(countryCode); countryCode = NULL; jstring currencySymbol = NULL; if (internationalCurrencySymbol != NULL) { currencySymbol = ICU_getCurrencySymbol(env, NULL, javaLanguageTag, internationalCurrencySymbol); } else { internationalCurrencySymbol = env->NewStringUTF("XXX"); } if (currencySymbol == NULL) { // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN). currencySymbol = env->NewStringUTF("\xc2\xa4"); } setStringField(env, localeData, "currencySymbol", currencySymbol); setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol); return JNI_TRUE; }
static jboolean ICU_initLocaleDataImpl(JNIEnv* env, jclass, jstring locale, jobject localeData) { ScopedUtfChars localeName(env, locale); if (localeName.c_str() == NULL) { return JNI_FALSE; } // Get DateTimePatterns UErrorCode status; char currentLocale[ULOC_FULLNAME_CAPACITY]; int32_t localeNameLen = 0; if (localeName.size() >= ULOC_FULLNAME_CAPACITY) { return JNI_FALSE; // Exceed ICU defined limit of the whole locale ID. } strcpy(currentLocale, localeName.c_str()); do { status = U_ZERO_ERROR; ScopedResourceBundle root(ures_open(NULL, currentLocale, &status)); if (U_FAILURE(status)) { if (localeNameLen == 0) { break; // No parent locale, report this error outside the loop. } else { status = U_ZERO_ERROR; continue; // get parent locale. } } ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status)); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; // get parent locale. } ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status)); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; // get parent locale. } ScopedResourceBundle dateTimePatterns(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status)); if (U_SUCCESS(status)) { setStringField(env, localeData, "fullTimeFormat", dateTimePatterns.get(), 0); setStringField(env, localeData, "longTimeFormat", dateTimePatterns.get(), 1); setStringField(env, localeData, "mediumTimeFormat", dateTimePatterns.get(), 2); setStringField(env, localeData, "shortTimeFormat", dateTimePatterns.get(), 3); setStringField(env, localeData, "fullDateFormat", dateTimePatterns.get(), 4); setStringField(env, localeData, "longDateFormat", dateTimePatterns.get(), 5); setStringField(env, localeData, "mediumDateFormat", dateTimePatterns.get(), 6); setStringField(env, localeData, "shortDateFormat", dateTimePatterns.get(), 7); break; } else { status = U_ZERO_ERROR; // get parent locale. } } while((localeNameLen = uloc_getParent(currentLocale, currentLocale, sizeof(currentLocale), &status)) >= 0); if (U_FAILURE(status)) { ALOGE("Error getting ICU resource bundle: %s", u_errorName(status)); return JNI_FALSE; } status = U_ZERO_ERROR; Locale localeObj = getLocale(env, locale); UniquePtr<Calendar> cal(Calendar::createInstance(localeObj, status)); if (U_FAILURE(status)) { return JNI_FALSE; } setIntegerField(env, localeData, "firstDayOfWeek", cal->getFirstDayOfWeek()); setIntegerField(env, localeData, "minimalDaysInFirstWeek", cal->getMinimalDaysInFirstWeek()); // Get DateFormatSymbols status = U_ZERO_ERROR; DateFormatSymbols dateFormatSym(localeObj, status); if (U_FAILURE(status)) { return JNI_FALSE; } int32_t count = 0; // Get AM/PM marker const UnicodeString* amPmStrs = dateFormatSym.getAmPmStrings(count); setStringArrayField(env, localeData, "amPm", amPmStrs, count); const UnicodeString* erasStrs = dateFormatSym.getEras(count); setStringArrayField(env, localeData, "eras", erasStrs, count); const UnicodeString* longMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longMonthNames", longMonthNames, count); const UnicodeString* shortMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames, count); const UnicodeString* longWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames, count); const UnicodeString* shortWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames, count); const UnicodeString* longStandAloneMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames, count); const UnicodeString* shortStandAloneMonthNames = dateFormatSym.getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames, count); const UnicodeString* longStandAloneWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames, count); const UnicodeString* shortStandAloneWeekdayNames = dateFormatSym.getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames, count); status = U_ZERO_ERROR; // For numberPatterns and symbols. setNumberPatterns(env, localeData, locale); setDecimalFormatSymbolsData(env, localeData, locale); jstring countryCode = env->NewStringUTF(Locale::createFromName(localeName.c_str()).getCountry()); jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode); env->DeleteLocalRef(countryCode); countryCode = NULL; jstring currencySymbol = NULL; if (internationalCurrencySymbol != NULL) { currencySymbol = ICU_getCurrencySymbol(env, NULL, locale, internationalCurrencySymbol); } else { internationalCurrencySymbol = env->NewStringUTF("XXX"); } if (currencySymbol == NULL) { // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN). currencySymbol = env->NewStringUTF("\xc2\xa4"); } setStringField(env, localeData, "currencySymbol", currencySymbol); setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol); return JNI_TRUE; }