示例#1
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);
        }
示例#2
0
    static string[] getRowData(LocaleIdentifier locId)
    {
        var locStr = locId.ToString();
        var loc    = new Locale(locId);
        var values = new string[count];

        Func <string, string> normalize = (string str) => {
            // wrong i
            if (locStr == "be-Cyrl-BY")
            {
                str = str.Replace('i', 'і');
            }
            // convert \u00FF part of CLDR string to char
            return(decodeUnicodeLiteral(str));
        };

        // **** CALENDAR
        XPathNavigator gregorian;

        gregorian = loc.FindOrDefault("//calendar[@type=\"gregorian\"]//monthContext[@type=\"stand-alone\"]/monthWidth[@type=\"wide\"]");
        if (gregorian != null)
        {
            gregorian.Select("./*/text()").Cast <object>().Select(o => normalize(o.ToString())).ToArray(values, monthsIdx);
        }

        gregorian = loc.FindOrDefault("//calendar[@type=\"gregorian\"]//monthContext[@type=\"format\"]/monthWidth[@type=\"wide\"]");
        if (gregorian != null)
        {
            gregorian.Select("./*/text()").Cast <object>().Select(o => normalize(o.ToString())).ToArray(values, smonthsIdx);
        }

        gregorian = loc.FindOrDefault("//calendar[@type=\"gregorian\"]//dayContext[@type=\"stand-alone\"]/dayWidth[@type=\"wide\"]");
        if (gregorian != null && loc.ToString() != "lrc-Arab-IQ" && loc.ToString() != "lrc-Arab-IR" && loc.ToString() != "mzn-Arab-IR")
        {
            gregorian.Select("./*/text()").Cast <object>().Select(o => normalize(o.ToString())).ToArray(values, daysIdx);
        }

        gregorian = loc.FindOrDefault("//calendar[@type=\"gregorian\"]//dayContext[@type=\"format\"]/dayWidth[@type=\"wide\"]");
        if (gregorian != null && loc.ToString() != "lrc-Arab-IQ" && loc.ToString() != "lrc-Arab-IR" && loc.ToString() != "mzn-Arab-IR")
        {
            gregorian.Select("./*/text()").Cast <object>().Select(o => normalize(o.ToString())).ToArray(values, sdaysIdx);
        }


        // **** SPELL NUMBERS
        try {
            var spell = SpellingFormatter.Create(loc, new SpellingOptions {
                Style = SpellingStyle.Cardinal
            });
            numsSource.Select(n => normalize(spell.Format(n))).ToArray(values, numsIdx);
        } catch { }
        try {
            var spell = SpellingFormatter.Create(loc, new SpellingOptions {
                Style = SpellingStyle.Ordinal
            });
            numsSource.Select(n => normalize(spell.Format(n))).ToArray(values, snumsIdx);
        } catch { }

        return(values);
    }
示例#3
0
    static LangMatrixRow fromCldr(Locale loc, string path)
    {
        var finds = loc.FindOrDefault(path);

        if (finds == null)
        {
            return(null);
        }
        var res = new Dictionary <string, string>();

        foreach (var kv in finds.SelectChildren(XPathNodeType.Element).OfType <XPathNavigator>())
        {
            var key = kv.SelectSingleNode("./@type").Value;
            if (res.ContainsKey(key))
            {
                continue;
            }
            var value = kv.SelectSingleNode("./text()").Value;
            if (UnicodeBlocks.checkBlockNames(value, loc.Id.Script) != null)
            {
                continue;
            }
            res[key] = value;
        }
        return(new LangMatrixRow {
            lang = loc.Id.ToString(),
            row = res.Values.ToArray(),
            columnNames = res.Keys.ToArray(),
        });
    }
示例#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;
        }
示例#5
0
        NumberPattern FindPattern(decimal value, NumberLength?nl = null)
        {
            if (!nl.HasValue)
            {
                nl = Options.Length;
            }
            value = Math.Abs(value);

            // Determine the format length type.
            var flt = nl == NumberLength.Default
                ? "[not(@type)]"
                : $"[@type='{nl.ToString().ToLowerInvariant()}']";

            // Determine the path in the ldml to the pattern(s)
            var path = String.Empty;

            if (Options.Style == NumberStyle.Decimal)
            {
                path = $"ldml/numbers/decimalFormats[@numberSystem='{NumberingSystem.Id}']/decimalFormatLength{flt}/decimalFormat";
            }
            else if (Options.Style == NumberStyle.Percent)
            {
                path = $"ldml/numbers/percentFormats[@numberSystem='{NumberingSystem.Id}']/percentFormatLength{flt}/percentFormat";
            }
            else if (Options.Style == NumberStyle.Scientific)
            {
                path = $"ldml/numbers/scientificFormats[@numberSystem='{NumberingSystem.Id}']/scientificFormatLength{flt}/scientificFormat";
            }
            else if (Options.Style == NumberStyle.CurrencyStandard)
            {
                path = $"ldml/numbers/currencyFormats[@numberSystem='{NumberingSystem.Id}']/currencyFormatLength{flt}/currencyFormat[@type='standard']";
            }
            else if (Options.Style == NumberStyle.CurrencyAccounting)
            {
                path = $"ldml/numbers/currencyFormats[@numberSystem='{NumberingSystem.Id}']/currencyFormatLength{flt}/currencyFormat[@type='accounting']";
            }
            else
            {
                throw new NotImplementedException($"Unknown NumberStyle '{Options.Style}'.");
            }

            var xml = Locale.FindOrDefault(path);

            // Fall back to default number length;
            if (xml == null && nl != NumberLength.Default)
            {
                return(FindPattern(value, NumberLength.Default));
            }

            // Should not happen.
            if (xml == null)
            {
                throw new KeyNotFoundException($"Cannot find CLDR '{path}'.");
            }

            // Get the best pattern.
            var           category = Plural.Create(Locale).Category(value);
            NumberPattern best     = null;
            NumberPattern previous = null;
            var           pattern  = xml.SelectChildren("pattern", "");

            while (pattern.MoveNext())
            {
                var p = NumberPattern.Parse(pattern.Current);

                // If not a value range, then this is the best pattern.
                if (!p.MinValue.HasValue)
                {
                    best = p;
                    break;
                }

                // Only consider a pattern with the correct count.
                if (p.Count != category)
                {
                    continue;
                }

                // Get closest value in the range.
                if (p.MinValue.Value > value)
                {
                    best = previous;
                    break;
                }

                previous = p;
            }
            best = best ?? previous ?? new NumberPattern {
                FormatString = "0"
            };

            return(best);
        }
示例#6
0
        NumberFormatInfo NumberInfo(string currencyCode, int nDigits, NumberPattern pattern)
        {
            var nfi = new NumberFormatInfo
            {
                NaNSymbol              = Symbols.NotANumber,
                NegativeSign           = Symbols.MinusSign,
                NegativeInfinitySymbol = Symbols.MinusSign + Symbols.Infinity,
                NumberDecimalSeparator = Symbols.Decimal,
                NumberGroupSeparator   = Symbols.Group,
                // NativeDigits is NOT by used the C# formatter!!
                //NativeDigits = NumberingSystem.Digits,
                PercentDecimalSeparator = Symbols.Decimal,
                PercentSymbol           = Symbols.PercentSign,
                PerMilleSymbol          = Symbols.PerMille,
                PositiveInfinitySymbol  = Symbols.Infinity,
                PositiveSign            = Symbols.PlusSign
            };

            if (Options.Style == NumberStyle.Scientific && pattern.FormatString == "#E0")
            {
                pattern.FormatString = "0.0######E0";
            }

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

                // 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.FormatString = significantDigitsPattern.Replace(pattern.FormatString, "." + new String('0', significantDigits));
                }
            }

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

            if (useGrouping)
            {
                // Grouping digits, "#,##,##0" => [3, 2, 1]
                var parts = pattern.FormatString.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;

            return(nfi);
        }