poe-i18n
Version:
i18n utility for Path of Exile
96 lines (83 loc) • 2.65 kB
text/typescript
import formatMessage from '../format/message';
import { ICUMessageSyntax } from '../types/intl';
import { Formatter, UnaryFormatter } from '../types/StatDescription';
import { isRange, StatValue } from '../types/StatValue';
import { buildFormatter } from './formatters';
export interface FormatValuesOptions {
formatters: Formatter[];
message: ICUMessageSyntax;
}
export function formatValues(
values: StatValue[],
options: Partial<FormatValuesOptions> = {}
): string[] {
const { formatters, message } = options;
if (formatters === undefined) {
throw new Error('formatters not set');
}
const formatted: Array<StatValue | string> = [...values];
formatters.forEach((formatter, i) => {
if (typeof formatter !== 'string' && typeof formatter.arg === 'number') {
// base_chance_to_freeze% is the only exception
// see issues #25 and #33
const offset =
formatter.id === 'canonical_stat' &&
formatters.includes('canonical_line')
? 0
: -1;
const target_param = values[+formatter.arg + offset];
if (target_param !== undefined) {
formatted[+formatter.arg - 1] = formatValue(target_param, {
formatter,
message
});
} else {
throw new Error(`no param given for formatter '${formatter.id}'`);
}
}
});
return formatted.map(
value =>
typeof value === 'string' ? value : formatValue(value, { message })
);
}
export interface FormatValueOptions {
formatter: UnaryFormatter;
message: ICUMessageSyntax;
}
const DEFAULT_FORMATTER: UnaryFormatter = { id: 'id', arg: 1 };
export function formatValue(
value: StatValue,
options: Partial<FormatValueOptions> = {}
): string {
const { formatter = DEFAULT_FORMATTER, message = '{min}–{max}' } = options;
const { negates, format } = buildFormatter(formatter.id);
if (isRange(value)) {
const [min, max] = valueOrder(value, negates).map(n => format(n));
if (min === max) {
return min;
} else {
return formatMessage(message, { min, max });
}
} else {
return format(value);
}
}
/**
* orders the given values so that the smallest displayed is min
*
* reduced stats are given as negative values and then negated for display
* whichs results in [-30, -15] being displayed as "(30 - 15) reduced"
* @param param0
* @param negates - true if the values will be negated
*/
function valueOrder(
[left, right]: [number, number],
negates: boolean
): [number, number] {
if ((left < right && !negates) || (left > right && negates)) {
return [left, right];
} else {
return [right, left];
}
}