import BigNumber from 'bignumber.js'; import { BLANK_DIGIT, createBlankDigits, deconstructNumeric, groupDigits, NEGATIVE_SIGN, normalizeNumeric, Numeric, } from '../../../utils/numeric'; import getLatinPowerName from '../../../utils/common/latinPowers'; import {getGroupDigitsName} from '../../common/de'; const config = { thousandName: 'tausend', thousandOrdinalName: 'tausendste', millia: 'millia', illion: 'illion', illionth: 'illionste', illiard: 'illiarde', illiardth: 'illiardste', hundredsLatinNames: [ '', 'cen', 'duocen', 'trecen', 'quadringen', 'quingen', 'sescen', 'septingen', 'octingen', 'nongen', ], onesLatinNames: ['', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem'], tensLatinNames: [ '', 'dec', 'vigin', 'trigin', 'quadragin', 'quinquagin', 'sexagin', 'septuagin', 'octogin', 'nonagin', ], onesSpecialLatinNames: ['', 'm', 'b', 'tr', 'quadr', 'quin', 'sex', 'sep', 'oct', 'non'], negative: 'negative', grouping: 3, }; const getGroupIndexName = (index: BigNumber, digits: string, ordinal: boolean) => { if (index.eq(1)) { return ordinal ? config.thousandOrdinalName : config.thousandName; } const basicIndex = index.dividedToIntegerBy(2); const isOdd = index.mod(2).eq(1); const latinPowerName = getLatinPowerName(basicIndex, isOdd, ordinal, config); const latinPowerNameWithCase = latinPowerName.slice(0, 1).toUpperCase() + latinPowerName.slice(1); if (digits.padStart(config.grouping, BLANK_DIGIT) === '001' || ordinal) { return latinPowerNameWithCase; } if (latinPowerNameWithCase.endsWith('e')) { return latinPowerNameWithCase + 'n'; } return latinPowerNameWithCase + 'en'; }; const getGroupName = (g: [string, BigNumber], ordinal: boolean) => { const [digits, index] = g; if (index.lt(1)) { return getGroupDigitsName(digits, index, ordinal); } if (index.lt(2)) { return [getGroupDigitsName(digits, index, false), getGroupIndexName(index, digits, ordinal)].join(''); } return [getGroupDigitsName(digits, index, false), getGroupIndexName(index, digits, ordinal)].join(' '); }; type Options = { groupSeparator: string, ordinal: boolean, } const getLocalizedNumberName = (xRaw: Numeric, options = {} as Partial) => { const { groupSeparator = ' ', ordinal = false, } = options; const x = normalizeNumeric(xRaw); const {significandDigits, exponent} = deconstructNumeric(x); const blankDigits = createBlankDigits(config.grouping); const groups = groupDigits(significandDigits, exponent, config.grouping); if (groups.length === 1) { return getGroupName(groups[0], ordinal); } const base = groups .filter(([digits]) => digits !== blankDigits) .map((g, i, gg) => getGroupName(g, ordinal ? i === gg.length - 1 : false)) .join(groupSeparator); if (x.startsWith(NEGATIVE_SIGN)) { return [config.negative, base].join(' '); } return base; }; export default getLocalizedNumberName;