예제 #1
0
        public ReadOnlyDictionary <PluralCategories, ReadOnlyDictionary <int, NumberFormatPattern> > GetCompactNotationFormats(NumberCompactDisplayFormat style)
        {
            XElement decimalFormats = elements.FirstOrDefault(v => v.Name.LocalName == "decimalFormats");

            if (decimalFormats == null)
            {
                return(this.Parent.GetCompactNotationFormats(style));
            }
            if (CldrUtility.IsAlias(decimalFormats, out string numberSystem))
            {
                return(GetFormat(locale, numberSystem).GetCompactNotationFormats(style));
            }
            Dictionary <PluralCategories, Dictionary <int, NumberFormatPattern> > dict = new Dictionary <PluralCategories, Dictionary <int, NumberFormatPattern> >();

            foreach (PluralCategories kind in pluralRules.EnumerateCategories())
            {
                dict[kind] = new Dictionary <int, NumberFormatPattern>();
            }
            XElement decimalFormat = decimalFormats.XPathSelectElement(String.Format("decimalFormatLength[@type = '{0}']/decimalFormat", IntlProviderOptions.ToStringValue(style)));

            foreach (XElement pattern in decimalFormat.XPathSelectElements("pattern"))
            {
                PluralCategories count = IntlProviderOptions.ParseEnum <PluralCategories>(pattern.Attribute("count").Value);
                dict[count][pattern.Attribute("type").Value.Length - 1] = ParseNumberFormatPattern(pattern.Value);
            }
            if (decimalFormat.Attribute("inherits") != null)
            {
                ReadOnlyDictionary <PluralCategories, ReadOnlyDictionary <int, NumberFormatPattern> > parent = this.Parent.GetCompactNotationFormats(style);
                foreach (KeyValuePair <PluralCategories, ReadOnlyDictionary <int, NumberFormatPattern> > e in parent)
                {
                    CldrUtility.CopyPatternFromParent(dict[e.Key], e.Value);
                }
            }
            return(new ReadOnlyDictionary <PluralCategories, ReadOnlyDictionary <int, NumberFormatPattern> >(dict.ToDictionary(v => v.Key, v => new ReadOnlyDictionary <int, NumberFormatPattern>(v.Value))));
        }
예제 #2
0
 private CldrPluralRules(XElement rules)
 {
     this.PluralCategories = PluralCategories.Other;
     foreach (XElement node in rules.Elements("pluralRule"))
     {
         PluralCategories category = IntlProviderOptions.ParseEnum <PluralCategories>(node.Attribute("count").Value);
         if (category != PluralCategories.Other)
         {
             string textContent = node.Value;
             ruleset[category]      = ParseExpression(textContent);
             this.PluralCategories |= category;
         }
     }
 }
예제 #3
0
        public FormattedString Format(double value, NumberFormat formatter, RelativeTimeNumericFormat numeric, out string[] units)
        {
            FormattedString pattern;

            if (numeric == RelativeTimeNumericFormat.Auto)
            {
                double intValue = Math.Floor(value);
                if (intValue == value && intValue >= Int32.MinValue && intValue <= Int32.MaxValue)
                {
                    if (relative.TryGetValue((int)intValue, out pattern))
                    {
                        units = new string[1];
                        return(pattern);
                    }
                }
            }
            CldrPluralRules  pluralRules = CldrPluralRules.Resolve(PluralRuleType.Cardinal, locale);
            PluralCategories key         = pluralRules.Match(value);

            if ((value < 0 ? past : future).TryGetValue(key, out pattern))
            {
                FormattedString numParts = formatter.Format(Math.Abs(value));
                FormattedPart[] parts    = pattern.GetParts();
                int             index    = Array.FindIndex(parts, v => v.Type == FormattedPartType.Placeholder);
                string          unitStr  = IntlProviderOptions.ToStringValue(unit);
                if (numParts.PartCount > 1)
                {
                    List <FormattedPart> parts1 = new List <FormattedPart>(parts);
                    parts1.RemoveAt(index);
                    parts1.InsertRange(index, numParts);
                    units = new string[parts1.Count];
                    for (int j = 0, len2 = numParts.PartCount; j < len2; j++)
                    {
                        units[index + j] = unitStr;
                    }
                    return(new FormattedString(parts1));
                }
                else
                {
                    units        = new string[parts.Length];
                    units[index] = unitStr;
                    parts[index] = numParts[0];
                    return(new FormattedString(parts));
                }
            }
            units = new string[0];
            return(FormattedString.Empty);
        }
예제 #4
0
        public static CldrRelativeTimeFormat Resolve(string locale, string type)
        {
            string key = locale + "/" + type;

            if (resolvedPatterns.TryGetValue(key, out CldrRelativeTimeFormat cached))
            {
                return(cached);
            }
            CldrRelativeTimeFormat formatter = new CldrRelativeTimeFormat(locale, type);
            XElement field = xDocument.XPathSelectElement(String.Format("/root/fields[@locale = '{0}']/field[@type = '{1}']", locale, type));

            if (field == null)
            {
                throw new InvalidOperationException("Unknown locale or type");
            }
            if (CldrUtility.IsAlias(field, out string use))
            {
                return(resolvedPatterns.GetOrAdd(key, Resolve(locale, use)));
            }
            bool hasInheritedValues = field.Attribute("inherits") != null;

            foreach (XElement relative in field.Elements("relative"))
            {
                int amount = Int32.Parse(relative.Attribute("type").Value);
                formatter.relative[amount] = FormattedString.Parse(relative.Value);
            }
            foreach (XElement relativeTime in field.Elements("relativeTime"))
            {
                Dictionary <PluralCategories, FormattedString> dict = relativeTime.Attribute("type").Value == "future" ? formatter.future : formatter.past;
                foreach (XElement child in relativeTime.Elements())
                {
                    PluralCategories category = IntlProviderOptions.ParseEnum <PluralCategories>(child.Attribute("count").Value);
                    dict[category] = FormattedString.Parse(child.Value);
                }
                hasInheritedValues |= relativeTime.Attribute("inherits") != null;
            }
            if (hasInheritedValues)
            {
                CldrRelativeTimeFormat parent = CldrUtility.GetParentPatterns(locale, type, Resolve);
                CldrUtility.CopyPatternFromParent(formatter.relative, parent.relative);
                CldrUtility.CopyPatternFromParent(formatter.future, parent.future);
                CldrUtility.CopyPatternFromParent(formatter.past, parent.past);
            }
            return(resolvedPatterns.GetOrAdd(key, formatter));
        }
예제 #5
0
        private NumberFormatPattern GetCompactNotationPattern(double doubleValue, PluralCategories pluralCount, out double roundedValue)
        {
            ReadOnlyDictionary <int, NumberFormatPattern> dict = this.compactNotations[pluralCount];
            int exponent = (int)Math.Floor(Math.Log10(Math.Abs(doubleValue)));
            NumberFormatPattern pattern;

            if (dict.TryGetValue(exponent, out NumberFormatPattern notationFormats))
            {
                pattern = notationFormats;
            }
            else
            {
                pattern = exponent < dict.Keys.First() ? dict.Values.First() : dict.Values.Last();
            }
            int roundExp = exponent - pattern.PositivePattern.ToString().Count(v => v == '0') + 1;

            roundedValue = doubleValue / Math.Pow(10, roundExp);
            return(pattern.ToDisplayFormat(this));
        }
예제 #6
0
        public FormattedString Format(EcmaValue value)
        {
            EnsureInitialized();
            NumberFormatInfo formatter = formatProvider.FormatProvider;

            value = value.ToNumber();
            if (value.IsNaN || !value.IsFinite)
            {
                string str = value.ToDouble().ToString(formatter);
                return(new FormattedString(new[] { new FormattedPart(value.IsNaN ? FormattedPartType.NaN : FormattedPartType.Infinity, str) }));
            }

            double doubleValue = value.ToDouble();

            if (this.SignDisplay == SignDisplayFormat.Never)
            {
                doubleValue = Math.Abs(doubleValue);
            }
            if (this.Style == NumberStyle.Percent)
            {
                doubleValue *= 100;
            }
            PluralCategories    pluralCount     = pluralRules.Match(doubleValue);
            NumberFormatPattern notationFormats = this.Notation == NumberNotation.Compact ? GetCompactNotationPattern(doubleValue, pluralCount, out doubleValue) : this.notationFormats;
            NumberFormatPattern styleFormats    = this.styleFormats.Count == 1 ? this.styleFormats[PluralCategories.Other] : this.styleFormats[pluralCount];
            FormattedString     notationFormat  = null;
            FormattedString     styleFormat     = null;

            switch (doubleValue.CompareTo(0))
            {
            case -1:
                notationFormat = notationFormats.NegativePattern;
                styleFormat    = styleFormats.NegativePattern;
                break;

            case 0:
                notationFormat = notationFormats.ZeroPattern;
                styleFormat    = styleFormats.ZeroPattern;
                break;

            case 1:
                notationFormat = notationFormats.PositivePattern;
                styleFormat    = styleFormats.PositivePattern;
                break;
            }
            if (this.Digits.RoundingType == RoundingType.SignificantDigits)
            {
                doubleValue = RoundToSignificantDigits(doubleValue, this.Digits.MaximumSignificantDigits);
            }

            // format double value with corresponding notation (scienific, compact, ...)
            List <FormattedPart> numParts = new List <FormattedPart>(notationFormat);
            List <FormattedPart> subParts = new List <FormattedPart>();
            int    index     = numParts.FindIndex(v => v.Type == FormattedPartType.Placeholder);
            string formatted = doubleValue.ToString(numParts[index].Value, formatter);

            FormattedPartType integerType  = FormattedPartType.Integer;
            RoundingType      roundingType = this.Digits.RoundingType;
            int maxDigits   = roundingType == RoundingType.SignificantDigits ? this.Digits.MaximumSignificantDigits : -1;
            int numOfDigits = 0;

            foreach (Match m in Regex.Matches(formatted, "([0-9]+)|."))
            {
                FormattedPartType type = FormattedPartType.Literal;
                string            str  = m.Value;
                if (m.Groups[1].Success)
                {
                    type = integerType;
                    if (roundingType == RoundingType.SignificantDigits)
                    {
                        if (type != FormattedPartType.ExponentInteger)
                        {
                            numOfDigits += numOfDigits == 0 ? str.TrimStart('0').Length : str.Length;
                        }
                        if (type == FormattedPartType.Fraction && numOfDigits > maxDigits)
                        {
                            str = str.Substring(0, str.Length - numOfDigits + maxDigits);
                        }
                    }
                }
                else if (symbolType.TryGetValue(str, out type))
                {
                    if (type == FormattedPartType.Decimal)
                    {
                        integerType = FormattedPartType.Fraction;
                    }
                    else if (type == FormattedPartType.ExponentSeparator)
                    {
                        integerType = FormattedPartType.ExponentInteger;
                    }
                }
                subParts.Add(new FormattedPart(type, str));
            }
            numParts.RemoveAt(index);
            numParts.InsertRange(index, subParts);

            // format as curreny or unit with the formatted number
            List <FormattedPart> finalParts = new List <FormattedPart>(styleFormat);

            index = finalParts.FindIndex(v => v.Type == FormattedPartType.Placeholder);
            finalParts.RemoveAt(index);
            finalParts.InsertRange(index, numParts);
            return(new FormattedString(finalParts));
        }