@phensley/cldr-core
Version:
Core library for @phensley/cldr
259 lines • 14.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var context_1 = require("./context");
var number_1 = require("../../parsing/patterns/number");
var cache_1 = require("../../utils/cache");
var util_1 = require("./util");
var render_1 = require("./render");
/**
* Number internal engine singleton, shared across all locales.
*/
var NumberInternalsImpl = /** @class */ (function () {
function NumberInternalsImpl(internals, cacheSize) {
if (cacheSize === void 0) { cacheSize = 50; }
this.internals = internals;
var schema = internals.schema;
this.currencies = schema.Currencies;
this.numbers = schema.Numbers;
this.numberPatternCache = new cache_1.Cache(number_1.parseNumberPattern, cacheSize);
}
NumberInternalsImpl.prototype.stringRenderer = function (params) {
return new render_1.StringNumberFormatter(params);
};
NumberInternalsImpl.prototype.partsRenderer = function (params) {
return new render_1.PartsNumberFormatter(params);
};
NumberInternalsImpl.prototype.getCurrencySymbol = function (bundle, code, width) {
var alt = width === 'narrow' ? 'narrow' : 'none';
return this.currencies.symbol.get(bundle, alt, code) || this.currencies.symbol.get(bundle, 'none', code);
};
NumberInternalsImpl.prototype.getCurrencyDisplayName = function (bundle, code) {
return this.currencies.displayName.get(bundle, code);
};
NumberInternalsImpl.prototype.getCurrencyPluralName = function (bundle, code, plural) {
return this.currencies.pluralName.get(bundle, plural, code);
};
NumberInternalsImpl.prototype.getNumberPattern = function (raw, negative) {
return this.numberPatternCache.get(raw)[negative ? 1 : 0];
};
NumberInternalsImpl.prototype.formatDecimal = function (bundle, renderer, n, options, params) {
// TODO: abstract away pattern selection defaulting
var style = options.style === undefined ? 'decimal' : options.style;
var result;
var plural = 'other';
var latnInfo = this.numbers.numberSystem.get('latn');
var info = this.numbers.numberSystem.get(params.numberSystemName) || latnInfo;
var decimalFormats = info.decimalFormats;
var latnDecimalFormats = this.numbers.numberSystem.get('latn').decimalFormats;
var standardRaw = decimalFormats.standard.get(bundle) || latnDecimalFormats.standard.get(bundle);
switch (style) {
case 'long':
case 'short':
{
var isShort = style === 'short';
var useLatn = decimalFormats.short.get(bundle, 'other', 4);
var patternImpl = isShort ? (useLatn ? latnInfo.decimalFormats.short : decimalFormats.short)
: (useLatn ? latnInfo.decimalFormats.long : decimalFormats.long);
var ctx = new context_1.NumberContext(options, true);
// Adjust the number using the compact pattern and divisor.
var _a = this.setupCompact(bundle, n, ctx, standardRaw, patternImpl), q2 = _a[0], ndigits = _a[1];
// Compute the plural category for the final q2.
var operands = q2.operands();
plural = this.internals.plurals.cardinal(bundle.language(), operands);
// Select the final pluralized compact pattern based on the integer
// digits of n and the plural category of the rounded / shifted number q2.
var raw = patternImpl.get(bundle, plural, ndigits)[0] || standardRaw;
if (raw === '0') {
raw = standardRaw;
}
// Re-select pattern as number may have changed sign due to rounding.
var pattern = this.getNumberPattern(raw, q2.isNegative());
result = renderer.render(q2, pattern, '', '', ctx.minInt, options.group);
break;
}
case 'percent':
case 'percent-scaled':
case 'permille':
case 'permille-scaled':
{
// Get percent pattern.
var raw = info.percentFormat.get(bundle) || latnInfo.percentFormat.get(bundle);
var pattern = this.getNumberPattern(raw, n.isNegative());
// Scale the number to a percent or permille form as needed.
if (style === 'percent') {
n = n.movePoint(2);
}
else if (style === 'permille') {
n = n.movePoint(3);
}
// Select percent or permille symbol.
var symbol = (style === 'percent' || style === 'percent-scaled') ?
params.symbols.percentSign : params.symbols.perMille;
// Adjust number using pattern and options, then render.
var ctx = new context_1.NumberContext(options, false, -1);
ctx.setPattern(pattern);
n = ctx.adjust(n);
var operands = n.operands();
plural = this.internals.plurals.cardinal(bundle.language(), operands);
// Re-select pattern as number may have changed sign due to rounding.
pattern = this.getNumberPattern(raw, n.isNegative());
result = renderer.render(n, pattern, '', symbol, ctx.minInt, options.group);
break;
}
case 'decimal':
{
// Get decimal pattern.
var pattern = this.getNumberPattern(standardRaw, n.isNegative());
// Adjust number using pattern and options, then render.
var ctx = new context_1.NumberContext(options, false, -1);
ctx.setPattern(pattern);
n = ctx.adjust(n);
var operands = n.operands();
plural = this.internals.plurals.cardinal(bundle.language(), operands);
// Re-select pattern as number may have changed sign due to rounding.
pattern = this.getNumberPattern(standardRaw, n.isNegative());
result = renderer.render(n, pattern, '', '', ctx.minInt, options.group);
break;
}
default:
result = renderer.empty();
break;
}
// No valid style matched
return [result, plural];
};
NumberInternalsImpl.prototype.formatCurrency = function (bundle, renderer, n, code, options, params) {
var fractions = util_1.getCurrencyFractions(code);
// TODO: display context support
// const width = options.symbolWidth === 'narrow' ? Alt.NARROW : Alt.NONE;
var width = options.symbolWidth === 'narrow' ? 'narrow' : 'none';
var style = options.style === undefined ? 'symbol' : options.style;
var latnInfo = this.numbers.numberSystem.get('latn');
var info = this.numbers.numberSystem.get(params.numberSystemName) || latnInfo;
var currencyFormats = info.currencyFormats;
var latnDecimalFormats = this.numbers.numberSystem.get('latn').decimalFormats;
var standardRaw = currencyFormats.standard.get(bundle) || latnDecimalFormats.standard.get(bundle);
switch (style) {
case 'code':
case 'name':
{
var raw = info.decimalFormats.standard.get(bundle) || latnInfo.decimalFormats.standard.get(bundle);
var pattern = this.getNumberPattern(raw, n.isNegative());
// Adjust number using pattern and options, then render.
var ctx = new context_1.NumberContext(options, false, fractions.digits);
ctx.setPattern(pattern);
n = ctx.adjust(n);
// Re-select pattern as number may have changed sign due to rounding.
pattern = this.getNumberPattern(raw, n.isNegative());
var num = renderer.render(n, pattern, '', '', ctx.minInt, options.group);
// Compute plural category and select pluralized unit.
var operands = n.operands();
var plural = this.internals.plurals.cardinal(bundle.language(), operands);
var unit = style === 'code' ? code : this.getCurrencyPluralName(bundle, code, plural);
// Wrap number and unit together.
var unitWrapper = currencyFormats.unitPattern.get(bundle, plural)
|| latnInfo.currencyFormats.unitPattern.get(bundle, plural);
return renderer.wrap(this.internals.wrapper, unitWrapper, num, renderer.make('unit', unit));
}
case 'short':
{
// The extra complexity here is to deal with rounding up and selecting the
// correct pluralized pattern for the final rounded form.
var patternImpl = currencyFormats.short;
var ctx = new context_1.NumberContext(options, true, fractions.digits);
var symbol = this.currencies.symbol.get(bundle, width, code);
// Adjust the number using the compact pattern and divisor.
var _a = this.setupCompact(bundle, n, ctx, standardRaw, patternImpl), q2 = _a[0], ndigits = _a[1];
// Compute the plural category for the final q2.
var operands = q2.operands();
var plural = this.internals.plurals.cardinal(bundle.language(), operands);
// Select the final pluralized compact pattern based on the integer
// digits of n and the plural category of the rounded / shifted number q2.
var raw = patternImpl.get(bundle, plural, ndigits)[0] || standardRaw;
if (raw === '0') {
raw = standardRaw;
}
var pattern = this.getNumberPattern(raw, q2.isNegative());
return renderer.render(q2, pattern, symbol, '', ctx.minInt, options.group);
}
case 'accounting':
case 'symbol':
{
// Select standard or accounting pattern based on style.
var styleArrow = style === 'symbol' ? currencyFormats.standard : currencyFormats.accounting;
var raw = styleArrow.get(bundle);
if (!raw) {
styleArrow = style === 'symbol' ? latnInfo.currencyFormats.standard : latnInfo.currencyFormats.accounting;
raw = styleArrow.get(bundle);
}
var pattern = this.getNumberPattern(raw, n.isNegative());
// Adjust number using pattern and options, then render.
var ctx = new context_1.NumberContext(options, false, fractions.digits);
ctx.setPattern(pattern);
n = ctx.adjust(n);
// Re-select pattern as number may have changed sign due to rounding.
pattern = this.getNumberPattern(raw, n.isNegative());
var symbol = this.currencies.symbol.get(bundle, width, code);
return renderer.render(n, pattern, symbol, '', ctx.minInt, options.group);
}
}
// No valid style matched
return renderer.empty();
};
/**
* Setup for a compact pattern. Returns the adjusted number and digits for
* selecting the pluralized pattern.
*
* The extra complexity here is to deal with rounding up and selecting the
* correct pluralized pattern for the final rounded form.
*/
NumberInternalsImpl.prototype.setupCompact = function (bundle, n, ctx, standardRaw, patternImpl) {
// Select the correct divisor based on the number of integer digits in n.
var negative = n.isNegative();
var ndigits = n.integerDigits();
// Select the initial compact pattern based on the integer digits of n.
// The plural category doesn't matter until the final pattern is selected.
var raw;
var ndivisor = 0;
_a = patternImpl.get(bundle, 'other', ndigits), raw = _a[0], ndivisor = _a[1];
var pattern = this.getNumberPattern(raw || standardRaw, negative);
var fracDigits = ctx.useSignificant ? -1 : 0;
// Move the decimal point of n, producing q1. We always strip trailing
// zeros on compact patterns.
var q1 = n;
if (ndivisor > 0) {
q1 = q1.movePoint(-ndivisor);
}
// Adjust q1 using the compact pattern's parameters, to produce q2.
var q1digits = q1.integerDigits();
ctx.setCompact(pattern, q1digits, ndivisor, fracDigits);
var q2 = ctx.adjust(q1);
var q2digits = q2.integerDigits();
// Check if the number rounded up, adding another integer digit.
if (q2digits > q1digits) {
// Select a new divisor and pattern.
ndigits++;
var divisor = 0;
_b = patternImpl.get(bundle, 'other', ndigits), raw = _b[0], divisor = _b[1];
pattern = this.getNumberPattern(raw || standardRaw, negative);
// If divisor changed we need to divide and adjust again. We don't divide,
// we just move the decimal point, since our Decimal type uses a radix that
// is a power of 10. Otherwise q2 is ready for formatting.
if (divisor > ndivisor) {
// We shift right before we move the decimal point. This triggers rounding
// of the number at its correct scale. Otherwise we would end up with
// 999,999 becoming 0.999999 and half-even rounding truncating the
// number to '0M' instead of '1M'.
q1 = n.shiftright(divisor);
q1 = q1.movePoint(-divisor);
ctx.setCompact(pattern, q1.integerDigits(), divisor, fracDigits);
q2 = ctx.adjust(q1);
}
}
return [q2, ndigits];
var _a, _b;
};
return NumberInternalsImpl;
}());
exports.NumberInternalsImpl = NumberInternalsImpl;
//# sourceMappingURL=internal.js.map