UNPKG

@fluent/bundle

Version:

Localization library for expressive translations.

139 lines (138 loc) 3.91 kB
/** * @overview * * The FTL resolver ships with a number of functions built-in. * * Each function take two arguments: * - args - an array of positional args * - opts - an object of key-value args * * Arguments to functions are guaranteed to already be instances of * `FluentValue`. Functions must return `FluentValues` as well. */ import { FluentNone, FluentNumber, FluentDateTime, } from "./types.js"; function values(opts, allowed) { const unwrapped = Object.create(null); for (const [name, opt] of Object.entries(opts)) { if (allowed.includes(name)) { unwrapped[name] = opt.valueOf(); } } return unwrapped; } const NUMBER_ALLOWED = [ "unitDisplay", "currencyDisplay", "useGrouping", "minimumIntegerDigits", "minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits", ]; /** * The implementation of the `NUMBER()` builtin available to translations. * * Translations may call the `NUMBER()` builtin in order to specify formatting * options of a number. For example: * * pi = The value of π is {NUMBER($pi, maximumFractionDigits: 2)}. * * The implementation expects an array of {@link FluentValue | FluentValues} representing the * positional arguments, and an object of named {@link FluentValue | FluentValues} representing the * named parameters. * * The following options are recognized: * * unitDisplay * currencyDisplay * useGrouping * minimumIntegerDigits * minimumFractionDigits * maximumFractionDigits * minimumSignificantDigits * maximumSignificantDigits * * Other options are ignored. * * @param args The positional arguments passed to this `NUMBER()`. * @param opts The named argments passed to this `NUMBER()`. */ export function NUMBER(args, opts) { let arg = args[0]; if (arg instanceof FluentNone) { return new FluentNone(`NUMBER(${arg.valueOf()})`); } if (arg instanceof FluentNumber) { return new FluentNumber(arg.valueOf(), { ...arg.opts, ...values(opts, NUMBER_ALLOWED), }); } if (arg instanceof FluentDateTime) { return new FluentNumber(arg.toNumber(), { ...values(opts, NUMBER_ALLOWED), }); } throw new TypeError("Invalid argument to NUMBER"); } const DATETIME_ALLOWED = [ "dateStyle", "timeStyle", "fractionalSecondDigits", "dayPeriod", "hour12", "weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName", ]; /** * The implementation of the `DATETIME()` builtin available to translations. * * Translations may call the `DATETIME()` builtin in order to specify * formatting options of a number. For example: * * now = It's {DATETIME($today, month: "long")}. * * The implementation expects an array of {@link FluentValue | FluentValues} representing the * positional arguments, and an object of named {@link FluentValue | FluentValues} representing the * named parameters. * * The following options are recognized: * * dateStyle * timeStyle * fractionalSecondDigits * dayPeriod * hour12 * weekday * era * year * month * day * hour * minute * second * timeZoneName * * Other options are ignored. * * @param args The positional arguments passed to this `DATETIME()`. * @param opts The named argments passed to this `DATETIME()`. */ export function DATETIME(args, opts) { let arg = args[0]; if (arg instanceof FluentNone) { return new FluentNone(`DATETIME(${arg.valueOf()})`); } if (arg instanceof FluentDateTime || arg instanceof FluentNumber) { return new FluentDateTime(arg, values(opts, DATETIME_ALLOWED)); } throw new TypeError("Invalid argument to DATETIME"); }