relative-time-format
Version:
A convenient Intl.RelativeTimeFormat polyfill
278 lines (233 loc) • 7.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = extractRelativeTimeMessages;
exports.UNITS = void 0;
// import { isEqual } from 'lodash'
// Valid time units.
// Copy-pasted from `RelativeTimeFormat.js`.
var UNITS = ["second", "minute", "hour", "day", "week", "month", "quarter", "year"]; // Detects short and narrow flavours of labels (yr., mo., etc).
// E.g. there are "month", "month-short", "month-narrow".
// More on "narrow" vs "short":
// http://cldr.unicode.org/translation/plurals#TOC-Narrow-and-Short-Forms
exports.UNITS = UNITS;
var short = /-short$/;
var narrow = /-narrow$/; // Converts locale data from CLDR format to this library's format.
//
// CLDR locale data example:
//
// ```json
// {
// "main": {
// "en-US-POSIX": {
// "identity": {
// "language": "en",
// ...
// },
// "dates": {
// "fields": {
// "year": {
// "displayName": "year",
// "relative-type--1": "last year",
// "relative-type-0": "this year",
// "relative-type-1": "next year",
// "relativeTime-type-future": {
// "relativeTimePattern-count-one": "in {0} year",
// "relativeTimePattern-count-other": "in {0} years"
// },
// "relativeTime-type-past": {
// "relativeTimePattern-count-one": "{0} year ago",
// "relativeTimePattern-count-other": "{0} years ago"
// }
// },
// ...
// ```
//
// Parsed locale data example:
//
// ```json
// {
// "long":
// {
// ...
// "second": [
// {
// "one": "a second ago",
// "other": "{0} seconds ago"
// },
// {
// "one": "in a second",
// "other": "in {0} seconds"
// }
// ],
// ...
// },
// "short":
// {
// ...
// },
// ...
// }
// ```
function extractRelativeTimeMessages(localeData) {
// Extract `locale` from CLDR locale data.
var locale = Object.keys(localeData.main)[0];
var timeUnitsFormattingRules = localeData.main[locale].dates.fields;
return Object.keys(timeUnitsFormattingRules).filter(function (unit) {
// Take only the generic time measurement units
// (skip exotic ones like "fri" on "thu").
return UNITS.indexOf(parseUnit(unit).unit) >= 0;
}).reduce(function (localeData, _unit) {
var _parseUnit = parseUnit(_unit),
unit = _parseUnit.unit,
type = _parseUnit.type;
return setUnitRules(localeData, type, unit, extractTimeUnitFormattingRules(timeUnitsFormattingRules[_unit]));
}, {});
}
/**
* Parses CLDR time unit formatting rules.
* @param {object} - CLDR time unit formatting rules.
* @return {(object|string)}
*/
function extractTimeUnitFormattingRules(rulesCLDR) {
var rules = {}; // "relative" values aren't suitable for "ago" or "in a" cases,
// because "1 year ago" != "last year" (too vague for Jan 30th)
// and "in 0.49 years" != "this year" (it could be Nov 30th).
// Still including them here for `Intl.RelativeTimeFormat` polyfill.
// "yesterday".
//
// "the day before yesterday".
// For example, in German it's "Vorgestern".
//
// etc.
//
var previousIndex = 1;
while (rulesCLDR["relative-type--".concat(previousIndex)]) {
rules["previous".concat(previousIndex === 1 ? '' : '-' + previousIndex)] = rulesCLDR["relative-type--".concat(previousIndex)];
previousIndex++;
} // "today"
/* istanbul ignore else */
if (rulesCLDR['relative-type-0']) {
rules.current = rulesCLDR['relative-type-0'];
} // "tomorrow".
//
// "the day after tomorrow".
// For example, in German it's "Übermorgen".
//
// etc.
//
var nextIndex = 1;
while (rulesCLDR["relative-type-".concat(nextIndex)]) {
rules["next".concat(nextIndex === 1 ? '' : '-' + nextIndex)] = rulesCLDR["relative-type-".concat(nextIndex)];
nextIndex++;
} // Formatting past times.
//
// E.g.:
//
// "relativeTime-type-past":
// {
// "relativeTimePattern-count-one": "{0} mo. ago",
// "relativeTimePattern-count-other": "{0} mo. ago"
// }
//
/* istanbul ignore else */
if (rulesCLDR['relativeTime-type-past']) {
var past = rulesCLDR['relativeTime-type-past'];
rules.past = {}; // Populate all quantifiers ("one", "other", etc).
var _arr = Object.keys(past);
for (var _i = 0; _i < _arr.length; _i++) {
var quantifier = _arr[_i];
rules.past[quantifier.replace('relativeTimePattern-count-', '')] = past[quantifier];
} // Delete all duplicates of "other" rule.
var _arr2 = Object.keys(rules.past);
for (var _i2 = 0; _i2 < _arr2.length; _i2++) {
var _quantifier = _arr2[_i2];
if (_quantifier !== 'other' && rules.past[_quantifier] === rules.past.other) {
delete rules.past[_quantifier];
}
} // If only "other" rule is present then "rules" is not an object and is a string.
if (Object.keys(rules.past).length === 1) {
rules.past = rules.past.other;
}
} // Formatting future times.
//
// E.g.:
//
// "relativeTime-type-future":
// {
// "relativeTimePattern-count-one": "in {0} mo.",
// "relativeTimePattern-count-other": "in {0} mo."
// }
//
/* istanbul ignore else */
if (rulesCLDR['relativeTime-type-future']) {
var future = rulesCLDR['relativeTime-type-future'];
rules.future = {}; // Populate all quantifiers ("one", "other", etc).
var _arr3 = Object.keys(future);
for (var _i3 = 0; _i3 < _arr3.length; _i3++) {
var _quantifier2 = _arr3[_i3];
rules.future[_quantifier2.replace('relativeTimePattern-count-', '')] = future[_quantifier2];
} // Delete all duplicates of "other" rule.
var _arr4 = Object.keys(rules.future);
for (var _i4 = 0; _i4 < _arr4.length; _i4++) {
var _quantifier3 = _arr4[_i4];
if (_quantifier3 !== 'other' && rules.future[_quantifier3] === rules.future.other) {
delete rules.future[_quantifier3];
}
} // If only "other" rule is present then "rules" is not an object and is a string.
if (Object.keys(rules.future).length === 1) {
rules.future = rules.future.other;
}
} // // If `.past` === `.future` then replace them with `.other`.
// // (only eligible for "tiny" and "*-time" locale data which is not part of CLDR)
// if (isEqual(rules.past, rules.future)) {
// rules.other = rules.past
// delete rules.future
// }
// // If only "other" rule is defined for a time unit
// // then make "rules" a string rather than an object.
// if (Object.keys(rules).length === 1) {
// rules = rules.other
// }
return rules;
}
/**
* Sets time unit formatting rules in locale data.
* @param {object} localeData
* @param {string} type
* @param {string} unit
* @param {object} rules
* @return {object} Locale data.
*/
function setUnitRules(localeData, type, unit, rules) {
if (!localeData[type]) {
localeData[type] = {};
}
localeData[type][unit] = rules;
return localeData;
}
/**
* Parses CLDR time unit into `unit` and `type`.
* @param {string} CLDR_unit
* @return {object} `{ type, unit }`.
*/
function parseUnit(unit) {
if (narrow.test(unit)) {
return {
type: 'narrow',
unit: unit.replace(narrow, '')
};
}
if (short.test(unit)) {
return {
type: 'short',
unit: unit.replace(short, '')
};
}
return {
type: 'long',
unit: unit
};
}
//# sourceMappingURL=extractRelativeTimeMessages.js.map