// ------------------------------------------------------------------------- // Static class methods. // ------------------------------------------------------------------------- /// <summary> /// Provides access to the predefined <c>PluralRules</c> for a given /// locale. /// </summary> /// /// <param name="locale">The locale for which a <c>PluralRules</c> object isreturned.</param> /// <returns>The predefined <c>PluralRules</c> object for this locale. /// If there's no predefined rules for this locale, the rules for the /// closest parent in the locale hierarchy that has one will be /// returned. The final fallback always returns the default rules.</returns> /// @draft ICU 3.8 /// @provisional This API might change or be removed in a future release. public static PluralRules ForLocale(ULocale locale) { PluralRules result = null; while (null == (result = (PluralRules)ILOG.J2CsMapping.Collections.Collections.Get(ruleMap, locale.GetName()))) { locale = locale.GetFallback(); if (locale == null) { return(DEFAULT); } } return(result); }
/// <exclude/> /// <summary> /// Attempt to parse the given string as a currency, either as a display name /// in the given locale, or as a 3-letter ISO 4217 code. If multiple display /// names match, then the longest one is selected. If both a display name and /// a 3-letter ISO code match, then the display name is preferred, unless /// it's length is less than 3. /// </summary> /// /// <param name="locale">the locale of the display names to match</param> /// <param name="text">the text to parse</param> /// <param name="pos">input-output position; on input, the position within text tomatch; must have 0 <= pos.getIndex() < text.length(); onoutput, the position after the last matched character. If theparse fails, the position in unchanged upon output.</param> /// <returns>the ISO 4217 code, as a string, of the best match, or null if /// there is no match</returns> public static String Parse(ULocale locale, String text, ILOG.J2CsMapping.Text.ParsePosition pos) { // TODO: There is a slight problem with the pseudo-multi-level // fallback implemented here. More-specific locales don't // properly shield duplicate entries in less-specific locales. // This problem will go away when real multi-level fallback is // implemented. We could also fix this by recording (in a // hash) which codes are used at each level of fallback, but // this doesn't seem warranted. int start = pos.GetIndex(); String fragment = text.Substring(start); String iso = null; int max = 0; // Look up the Currencies resource for the given locale. The // Currencies locale data looks like this: // |en { // | Currencies { // | USD { "US$", "US Dollar" } // | CHF { "Sw F", "Swiss Franc" } // | INR { "=0#Rs|1#Re|1<Rs", "=0#Rupees|1#Rupee|1<Rupees" } // | //... // | } // |} // In the future, resource bundles may implement multi-level // fallback. That is, if a currency is not found in the en_US // Currencies data, then the en Currencies data will be searched. // Currently, if a Currencies datum exists in en_US and en, the // en_US entry hides that in en. // We want multi-level fallback for this resource, so we implement // it manually. // Multi-level resource inheritance fallback loop while (locale != null) { UResourceBundle rb = IBM.ICU.Util.UResourceBundle.GetBundleInstance( IBM.ICU.Impl.ICUResourceBundle.ICU_BASE_NAME, locale); // We can't cast this to String[][]; the cast has to happen later try { UResourceBundle currencies = rb.Get("Currencies"); // Do a linear search for (int i = 0; i < currencies.GetSize(); ++i) { // String name = ((String[]) currencies[i][1])[0]; UResourceBundle item = currencies.Get(i); String name = item.GetString(0); if (name.Length < 1) { // Ignore zero-length names -- later, change this // when zero-length is used to mean something. continue; } else if (name[0] == '=') { name = name.Substring(1); if (name.Length > 0 && name[0] != '=') { ChoiceFormat choice = new ChoiceFormat(name); // Number n = choice.Parse(text, pos); int len = pos.GetIndex() - start; if (len > max) { iso = item.GetKey(); max = len; } pos.SetIndex(start); continue; } } if (name.Length > max && fragment.StartsWith(name)) { iso = item.GetKey(); max = name.Length; } } } catch (MissingManifestResourceException e) { } locale = locale.GetFallback(); } /* * 1. Look at the Currencies array from the locale 1a. Iterate through * it, and check each row to see if row[1] matches 1a1. If row[1] is a * pattern, use ChoiceFormat to attempt a parse 1b. Upon a match, return * the ISO code stored at row[0] 2. If there is no match, fall back to * "en" and try again 3. If there is no match, fall back to root and try * again 4. If still no match, parse 3-letter ISO {this code is probably * unchanged}. * * ICUResourceBundle rb = * (ICUResourceBundle)UResourceBundle.getBundleInstance * (UResourceBundle.ICU_BASE_NAME, locale); ICUResourceBundle currencies * = rb.get("Currencies"); */ // If display name parse fails or if it matches fewer than 3 // characters, try to parse 3-letter ISO. Do this after the // display name processing so 3-letter display names are // preferred. Consider /[A-Z]{3}/ to be valid ISO, and parse // it manually--UnicodeSet/regex are too slow and heavy. if (max < 3 && (text.Length - start) >= 3) { bool valid = true; for (int k = 0; k < 3; ++k) { char ch = text[start + k]; // 16-bit ok if (ch < 'A' || ch > 'Z') { valid = false; break; } } if (valid) { iso = text.Substring(start, (start + 3) - (start)); max = 3; } } pos.SetIndex(start + max); return(iso); }