Example #1
0
        /// <summary>
        ///   A new locale identifier with the all the empty subtags filled in
        ///   with a likely value.
        /// </summary>
        /// <returns>
        ///   A new locale identifier with all subtags filled in.
        /// </returns>
        public LocaleIdentifier MostLikelySubtags()
        {
            var result = (LocaleIdentifier)this.MemberwiseClone();

            // Remove the script code 'Zzzz' and the region code 'ZZ' if they occur.
            if (result.Script == "Zzzz")
            {
                result.Script = String.Empty;
            }
            if (result.Region == "ZZ")
            {
                result.Region = String.Empty;
            }

            // Short cut if all subtags have a value.
            if (result.Language != "" && result.Script != "" && result.Region != "")
            {
                return(result);
            }


            // Find the language in likely subtags.
            var likely = new[]
            {
                $"{result.Language}_{result.Script}_{result.Region}",
                $"{result.Language}_{result.Region}",
                $"{result.Language}_{result.Script}",
                $"{result.Language}",
                $"und_{result.Script}",
            }
            .Select(k => k.Replace("__", "_").Trim('_'))
            .Where(k => k != String.Empty)
            .Distinct()
            .Select(k => Cldr.Instance
                    .GetDocuments("common/supplemental/likelySubtags.xml")
                    .FirstElementOrDefault($"supplementalData/likelySubtags/likelySubtag[@from='{k}']")
                    )
            .FirstOrDefault(e => e != null);

            if (likely != null)
            {
                var defaults = LocaleIdentifier.ParseBcp47(likely.GetAttribute("to", ""));
                if (result.Language == "")
                {
                    result.Language = defaults.Language;
                }
                if (result.Script == "")
                {
                    result.Script = defaults.Script;
                }
                if (result.Region == "")
                {
                    result.Region = defaults.Region;
                }
            }

            return(result);
        }
Example #2
0
        /// <summary>
        ///   A new locale idenyifer with empty subtags that <see cref="MostLikelySubtags"/> would fill.
        /// </summary>
        /// <returns>
        ///   A new locale identifier.
        /// </returns>
        public LocaleIdentifier RemoveMostLikelySubtags()
        {
            var max = this.MostLikelySubtags();

            max.Variants = new string[0];
            var trials = new[] { max.Language, $"{max.Language}-{max.Region}", $"{max.Language}-{max.Script}" };

            foreach (var trial in trials)
            {
                var id = LocaleIdentifier.ParseBcp47(trial);
                if (max.ToUnicodeLanguage() == id.MostLikelySubtags().ToUnicodeLanguage())
                {
                    id.Variants = this.Variants;
                    return(id);
                }
            }

            max.Variants = this.Variants;
            return(max);
        }
Example #3
0
        /// <summary>
        ///   Convert BCP 47 tag to a valid Unicode locale identifier
        /// </summary>
        string TransformFromBcp47()
        {
            // 1. Canonicalize the language tag (afterwards, there will be no extlang subtag)

            // 2. Replace the BCP 47 primary language subtag "und" with "root" if no script, region,
            //    or variant subtags are present
            if (Language == "und" && Script == "" && Region == "" && Variants.Count() == 0)
            {
                Language = "root";
            }

            // 3. If the BCP 47 primary language subtag matches the type attribute of a languageAlias
            //    element in Supplemental Data, replace the language subtag with the replacement value.
            // 3.1 If there are additional subtags in the replacement value, add them to the result, but only
            //     if there is no corresponding subtag already in the tag.
            var languageAlias = Cldr.Instance
                                .GetDocuments("common/supplemental/supplementalMetadata.xml")
                                .FirstElementOrDefault($"supplementalData/metadata/alias/languageAlias[@type='{Language}']");

            if (languageAlias != null)
            {
                var replacement = LocaleIdentifier.ParseBcp47(languageAlias.GetAttribute("replacement", ""));
                Language = replacement.Language;
                if (Script == "")
                {
                    Script = replacement.Script;
                }
                if (Region == "")
                {
                    Region = replacement.Region;
                }
            }

            // 4. If the BCP 47 region subtag matches the type attribute of a territoryAlias
            //    element in Supplemental Data, replace the language subtag with the replacement value, as follows:
            var territoryAlias = Cldr.Instance
                                 .GetDocuments("common/supplemental/supplementalMetadata.xml")
                                 .FirstElementOrDefault($"supplementalData/metadata/alias/territoryAlias[@type='{Region}']");

            if (territoryAlias != null)
            {
                var replacements = territoryAlias.GetAttribute("replacement", "").Split(' ');
                //    4.1 If there is a single territory in the replacement, use it.
                var replacementValue = replacements[0];
                //    4.2 If there are multiple territories:
                //        4.2.1 Look up the most likely territory for the base language code(and script, if there is one).
                //        4.2.2 If that likely territory is in the list, use it.
                //        4.2.3 Otherwise, use the first territory in the list.
                if (replacements.Length > 1)
                {
                    var best = Cldr.Instance
                               .GetDocuments("common/supplemental/likelySubtags.xml")
                               .FirstElementOrDefault($"supplementalData/likelySubtags/likelySubtag[@from='{Language}']");
                    if (best != null)
                    {
                        var to = LocaleIdentifier.ParseBcp47(best.GetAttribute("to", ""));
                        if (replacements.Contains(to.Region))
                        {
                            replacementValue = to.Region;
                        }
                    }
                }
                Region = replacementValue;
            }

            // Verify that the subtags are defined.
            // TODO: Need StringRanges, see https://github.com/richardschneider/net-cldr/issues/2
            if (Language != "" && !Cldr.Instance.IsLanguageDefined(Language))
            {
                return($"Language '{Language}' is not defined.");
            }
            if (Script != "" && !Cldr.Instance.IsScriptDefined(Script))
            {
                return($"Script '{Script}' is not defined.");
            }
            if (Region != "" && !Cldr.Instance.IsRegionDefined(Region))
            {
                return($"Region '{Region}' is not defined.");
            }
            foreach (var variant in Variants)
            {
                if (!Cldr.Instance.IsVariantDefined(variant))
                {
                    return($"Language variant '{variant}' is not defined.");
                }
            }

            // TODO: U extensions
            // TODO: T extensions

            return(null);
        }