Ejemplo n.º 1
0
        /// <summary>
        ///   Creates or reuses a numbering system for the specified <see cref="Locale"/>.
        /// </summary>
        /// <param name="locale">
        ///   The locale.
        /// </param>
        /// <returns>
        ///   A numbering system that is the best for the <paramref name="locale"/>.
        /// </returns>
        /// <remarks>
        ///   The locale identifier can use the "u-nu-XXX" extension to specify a numbering system.
        ///   If the extension's numbering system doesn't exist or is not specified,
        ///   then the default numbering system for the locale is used.
        ///   <para>
        ///   The <see href="http://unicode.org/reports/tr35/tr35-numbers.html#otherNumberingSystems">other numbering systems</see>
        ///   ("u-nu-native", "u-nu-finance" and "u-nu-traditio") are also allowed.
        ///   </para>
        /// </remarks>
        public static NumberingSystem Create(Locale locale)
        {
            string name;

            if (locale.Id.UnicodeExtension.Keywords.TryGetValue("nu", out name))
            {
                try
                {
                    if (Others.Contains(name))
                    {
                        // Consistency is the hobgoblin of small minds.
                        var other = name == "traditio"
                            ? "traditional"
                            : name;
                        name = locale.Find($"ldml/numbers/otherNumberingSystems/{other}").Value;
                    }
                    return(NumberingSystem.Create(name));
                }
                catch (KeyNotFoundException)
                {
                    // eat it, will fallback to default numbering system.
                }
            }

            // Find the default numbering system for the locale.
            var ns = locale.Find("ldml/numbers/defaultNumberingSystem/text()").Value;

            return(NumberingSystem.Create(ns));
        }
Ejemplo n.º 2
0
        string Transform(string s, string currencyCode, string pattern, NumberFormatInfo nfi)
        {
            var sb = new StringBuilder(s);

            // Replace digits with number system digits.
            for (int i = 0; i < 10; ++i)
            {
                sb.Replace(digits[i], NumberingSystem.Digits[i]);
            }

            // Replace currency symbol
            if (s.Contains("¤"))
            {
                if (currencyCode == null)
                {
                    currencyCode = Locale.CurrencyCode;
                }

                if (s.Contains("¤¤¤¤¤"))
                {
                    throw new NotImplementedException();
                }
                else if (s.Contains("¤¤¤¤"))
                {
                    throw new NotImplementedException();
                }
                else if (s.Contains("¤¤¤"))
                {
                    // Currency display name
                    throw new NotImplementedException();
                }
                else if (s.Contains("¤¤"))
                {
                    // ISO currency symbol
                    sb.Replace("¤¤", currencyCode);
                }
                else if (s.Contains("¤"))
                {
                    // Standard currency symbol
                    var symbol = $"ldml/numbers/currencies/currency[@type='{currencyCode}']/symbol";
                    sb.Replace("¤", Locale.Find(symbol).Value);
                }
            }

            return(sb.ToString());
        }
Ejemplo n.º 3
0
        /// <summary>
        ///   Creates the symbols for the specified <see cref="Locale"/>.
        /// </summary>
        /// <param name="locale">
        ///   The locale.
        /// </param>
        /// <returns>
        ///   The symbols that are the best for the <paramref name="locale"/>.
        /// </returns>
        public static NumberSymbols Create(Locale locale)
        {
            var ns      = NumberingSystem.Create(locale).Id;
            var path    = $"ldml/numbers/symbols[@numberSystem='{ns}']/";
            var symbols = new NumberSymbols
            {
                Decimal                = locale.Find(path + "decimal").Value,
                Exponential            = locale.Find(path + "exponential").Value,
                Group                  = locale.Find(path + "group").Value,
                Infinity               = locale.Find(path + "infinity").Value,
                List                   = locale.Find(path + "list").Value,
                MinusSign              = locale.Find(path + "minusSign").Value,
                NotANumber             = locale.Find(path + "nan").Value,
                PercentSign            = locale.Find(path + "percentSign").Value,
                PerMille               = locale.Find(path + "perMille").Value,
                PlusSign               = locale.Find(path + "plusSign").Value,
                SuperscriptingExponent = locale.Find(path + "superscriptingExponent").Value
            };

            var found = locale.FindOrDefault(path + "currencyDecimal");

            if (found != null)
            {
                symbols.CurrencyDecimal = found.Value;
            }

            found = locale.FindOrDefault(path + "currencyGroup");
            if (found != null)
            {
                symbols.CurrencyGroup = found.Value;
            }

            return(symbols);
        }
Ejemplo n.º 4
0
        void NumberInfo(string currencyCode, int nDigits, out string pattern, out NumberFormatInfo nfi)
        {
            nfi = new NumberFormatInfo
            {
                NaNSymbol              = Symbols.NotANumber,
                NegativeSign           = Symbols.MinusSign,
                NegativeInfinitySymbol = Symbols.MinusSign + Symbols.Infinity,
                NumberDecimalSeparator = Symbols.Decimal,
                NumberGroupSeparator   = Symbols.Group,
                // NativeDigits is NOT used the formatter!!
                //NativeDigits = NumberingSystem.Digits,
                PercentDecimalSeparator = Symbols.Decimal,
                PercentSymbol           = Symbols.PercentSign,
                PerMilleSymbol          = Symbols.PerMille,
                PositiveInfinitySymbol  = Symbols.Infinity,
                PositiveSign            = Symbols.PlusSign
            };

            pattern = null;
            if (Options.Style == NumberStyle.Decimal)
            {
                var path = $"ldml/numbers/decimalFormats[@numberSystem='{NumberingSystem.Id}']/decimalFormatLength[not(@type)]/decimalFormat/pattern";
                pattern = Locale.Find(path).Value;
            }

            else if (Options.Style == NumberStyle.Percent)
            {
                var path = $"ldml/numbers/percentFormats[@numberSystem='{NumberingSystem.Id}']/percentFormatLength[not(@type)]/percentFormat/pattern";
                pattern = Locale.Find(path).Value;
            }

            else if (Options.Style == NumberStyle.Scientific)
            {
                var path = $"ldml/numbers/scientificFormats[@numberSystem='{NumberingSystem.Id}']/scientificFormatLength[not(@type)]/scientificFormat/pattern";
                pattern = Locale.Find(path).Value;
                pattern = pattern == "#E0" ? "0.0######E0" : pattern;
            }

            else if (Options.Style == NumberStyle.CurrencyStandard || Options.Style == NumberStyle.CurrencyAccounting)
            {
                nfi.NumberDecimalSeparator = Symbols.CurrencyDecimal;
                nfi.NumberGroupSeparator   = Symbols.CurrencyGroup;

                string path = null;
                if (Options.Style == NumberStyle.CurrencyStandard)
                {
                    path = $"ldml/numbers/currencyFormats[@numberSystem='{NumberingSystem.Id}']/currencyFormatLength/currencyFormat[@type='standard']/pattern";
                }
                else if (Options.Style == NumberStyle.CurrencyAccounting)
                {
                    path = $"ldml/numbers/currencyFormats[@numberSystem='{NumberingSystem.Id}']/currencyFormatLength/currencyFormat[@type='accounting']/pattern";
                }
                pattern = Locale.Find(path).Value;

                // Apply currency decimal places
                if (currencyCode == null)
                {
                    currencyCode = Locale.CurrencyCode;
                }
                var digits = Cldr.Instance
                             .GetDocuments("common/supplemental/supplementalData.xml")
                             .FirstElementOrDefault($"supplementalData/currencyData/fractions/info[@iso4217='{currencyCode}']/@digits");
                if (digits != null)
                {
                    int significantDigits = Int32.Parse(digits.Value);
                    pattern = significantDigitsPattern.Replace(pattern, "." + new String('0', significantDigits));
                }
            }

            else
            {
                throw new NotImplementedException();
            }

            // Grouping of digits.
            var useGrouping = Options.UseGrouping;

            if (useGrouping)
            {
                // Grouping digits, "#,##,##0" => [3, 2, 1]
                var parts = pattern.Split(';');
                nfi.NumberGroupSizes = groupingPattern
                                       .Matches(parts[0])
                                       .Cast <Match>()
                                       .Skip(1)
                                       .Reverse()
                                       .Select(m => m.Length - 1)
                                       .DefaultIfEmpty(3)
                                       .ToArray();

                // Don't group if min grouping digits is not met.
                var minElement = Locale.FindOrDefault("ldml/numbers/minimumGroupingDigits");
                if (minElement != null)
                {
                    var minDigits = Int32.Parse(minElement.Value) + nfi.NumberGroupSizes[0];
                    useGrouping = nDigits > minDigits;
                }
            }

            if (!useGrouping)
            {
                nfi.NumberGroupSeparator = "";
            }
            nfi.PercentGroupSizes     = nfi.NumberGroupSizes;
            nfi.PercentGroupSeparator = nfi.NumberGroupSeparator;
        }