예제 #1
0
        public InternalLocaleBuilder SetLocale(BaseLocale @base, LocaleExtensions extensions)
        {
            string language = @base.GetLanguage();
            string script   = @base.GetScript();
            string region   = @base.GetRegion();
            string variant  = @base.GetVariant();

            // ICU4N TODO: Remove ?
            if (JDKIMPL)
            {
                // Special backward compatibility support

                // Exception 1 - ja_JP_JP
                if (language.Equals("ja") && region.Equals("JP") && variant.Equals("JP"))
                {
                    // When locale ja_JP_JP is created, ca-japanese is always there.
                    // The builder ignores the variant "JP"
                    Debug.Assert("japanese".Equals(extensions.GetUnicodeLocaleType("ca")));
                    variant = "";
                }
                // Exception 2 - th_TH_TH
                else if (language.Equals("th") && region.Equals("TH") && variant.Equals("TH"))
                {
                    // When locale th_TH_TH is created, nu-thai is always there.
                    // The builder ignores the variant "TH"
                    Debug.Assert("thai".Equals(extensions.GetUnicodeLocaleType("nu")));
                    variant = "";
                }
                // Exception 3 - no_NO_NY
                else if (language.Equals("no") && region.Equals("NO") && variant.Equals("NY")) // ICU4N TODO: Fix this handling for .NET (no-NO is not reliable across platforms)
                {
                    // no_NO_NY is a valid locale and used by Java 6 or older versions.
                    // The build ignores the variant "NY" and change the language to "nn".
                    language = "nn";
                    variant  = "";
                }
            }

            // Validate base locale fields before updating internal state.
            // LocaleExtensions always store validated/canonicalized values,
            // so no checks are necessary.
            if (language.Length > 0 && !LanguageTag.IsLanguage(language))
            {
                throw new FormatException("Ill-formed language: " + language);
            }

            if (script.Length > 0 && !LanguageTag.IsScript(script))
            {
                throw new FormatException("Ill-formed script: " + script);
            }

            if (region.Length > 0 && !LanguageTag.IsRegion(region))
            {
                throw new FormatException("Ill-formed region: " + region); // ICU4N TODO: Port LocaleSyntaxException (instead of FormatException)
            }

            if (variant.Length > 0)
            {
                int errIdx = CheckVariants(variant, BaseLocale.SEP);
                if (errIdx != -1)
                {
                    throw new FormatException("Ill-formed variant: " + variant /*, errIdx*/);
                }
            }

            // The input locale is validated at this point.
            // Now, updating builder's internal fields.
            _language = language;
            _script   = script;
            _region   = region;
            _variant  = variant;
            ClearExtensions();

            var extKeys = (extensions == null) ? null : extensions.Keys;

            if (extKeys != null)
            {
                // map extensions back to builder's internal format
                foreach (char key in extKeys)
                {
                    Extension e = extensions.GetExtension(key);
                    if (e is UnicodeLocaleExtension)
                    {
                        UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
                        foreach (string uatr in ue.GetUnicodeLocaleAttributes())
                        {
                            if (_uattributes == null)
                            {
                                _uattributes = new HashSet <CaseInsensitiveString>(/*4*/);
                            }
                            _uattributes.Add(new CaseInsensitiveString(uatr));
                        }
                        foreach (string ukey in ue.GetUnicodeLocaleKeys())
                        {
                            if (_ukeywords == null)
                            {
                                _ukeywords = new Dictionary <CaseInsensitiveString, string>(4);
                            }
                            _ukeywords[new CaseInsensitiveString(ukey)] = ue.GetUnicodeLocaleType(ukey);
                        }
                    }
                    else
                    {
                        if (_extensions == null)
                        {
                            _extensions = new Dictionary <CaseInsensitiveChar, string>(4);
                        }
                        _extensions[new CaseInsensitiveChar(key)] = e.Value;
                    }
                }
            }
            return(this);
        }
예제 #2
0
        public static LanguageTag ParseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions)
        {
            LanguageTag tag = new LanguageTag();

            string language = baseLocale.GetLanguage();
            string script   = baseLocale.GetScript();
            string region   = baseLocale.GetRegion();
            string variant  = baseLocale.GetVariant();

            bool hasSubtag = false;

            string privuseVar = null;   // store ill-formed variant subtags

            if (language.Length > 0 && IsLanguage(language))
            {
                // Convert a deprecated language code used by Java to
                // a new code
                if (language.Equals("iw"))
                {
                    language = "he";
                }
                else if (language.Equals("ji"))
                {
                    language = "yi";
                }
                else if (language.Equals("in"))
                {
                    language = "id";
                }
                tag._language = language;
            }

            if (script.Length > 0 && IsScript(script))
            {
                tag._script = CanonicalizeScript(script);
                hasSubtag   = true;
            }

            if (region.Length > 0 && IsRegion(region))
            {
                tag._region = CanonicalizeRegion(region);
                hasSubtag   = true;
            }

            // ICU4N TODO: Remove ?
            if (JDKIMPL)
            {
                // Special handling for no_NO_NY - use nn_NO for language tag
                if (tag._language.Equals("no") && tag._region.Equals("NO") && variant.Equals("NY")) // ICU4N TODO: Fix this handling for .NET (no-NO is not reliable across platforms)
                {
                    tag._language = "nn";
                    variant       = "";
                }
            }

            if (variant.Length > 0)
            {
                List <string>         variants = null;
                StringTokenEnumerator varitr   = new StringTokenEnumerator(variant, BaseLocale.SEP);
                while (varitr.MoveNext())
                {
                    string var = varitr.Current;
                    if (!IsVariant(var))
                    {
                        break;
                    }
                    if (variants == null)
                    {
                        variants = new List <string>();
                    }
                    if (JDKIMPL)
                    {
                        variants.Add(var);  // Do not canonicalize!
                    }
                    else
                    {
                        variants.Add(CanonicalizeVariant(var));
                    }
                }
                if (variants != null)
                {
                    tag._variants = variants;
                    hasSubtag     = true;
                }
                if (!varitr.IsDone)
                {
                    // ill-formed variant subtags
                    StringBuilder buf = new StringBuilder();
                    while (!varitr.IsDone)
                    {
                        string prvv = varitr.Current;
                        if (!IsPrivateuseSubtag(prvv))
                        {
                            // cannot use private use subtag - truncated
                            break;
                        }
                        if (buf.Length > 0)
                        {
                            buf.Append(SEP);
                        }
                        if (!JDKIMPL)
                        {
                            prvv = AsciiUtil.ToLower(prvv);
                        }
                        buf.Append(prvv);
                        varitr.MoveNext();
                    }
                    if (buf.Length > 0)
                    {
                        privuseVar = buf.ToString();
                    }
                }
            }

            List <string> extensions = null;
            string        privateuse = null;

            var locextKeys = localeExtensions.Keys;

            foreach (char locextKey in locextKeys)
            {
                Extension ext = localeExtensions.GetExtension(locextKey);
                if (IsPrivateusePrefixChar(locextKey))
                {
                    privateuse = ext.Value;
                }
                else
                {
                    if (extensions == null)
                    {
                        extensions = new List <string>();
                    }
                    extensions.Add(locextKey.ToString() + SEP + ext.Value);
                }
            }

            if (extensions != null)
            {
                tag._extensions = extensions;
                hasSubtag       = true;
            }

            // append ill-formed variant subtags to private use
            if (privuseVar != null)
            {
                if (privateuse == null)
                {
                    privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar;
                }
                else
                {
                    privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX + SEP + privuseVar.Replace(BaseLocale.SEP, SEP);
                }
            }

            if (privateuse != null)
            {
                tag._privateuse = privateuse;
            }

            if (tag._language.Length == 0 && (hasSubtag || privateuse == null))
            {
                // use lang "und" when 1) no language is available AND
                // 2) any of other subtags other than private use are available or
                // no private use tag is available
                tag._language = UNDETERMINED;
            }

            return(tag);
        }