diff --git a/README.md b/README.md index 045e6b5..53d67cd 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,10 @@ s.get(Strings.EXTENDED_AMOUNT) //=> Revenue Each method can also accept an additional options object supporting the following properties: - `plural` (boolean) or `count` (number): to more easily support conditional plurality using `get()` +- `suffix` (string): to customize what gets added to the value when auto-pluralization is used - `lc` (boolean) or `uc` (boolean): to transform the display value to lowercase or uppercase, respectively - `abbrev` (boolean): to abbreviate the display value to the first letter of each word in the string +- `strict` (boolean, default `true`): to use an empty string (strict=true) or key (strict=false) when key not found in strings or defaults - `locale` (string): to make sure case-sensitivity respects rules and characters for the user's language and region ## Primary API @@ -94,9 +96,11 @@ For convenience, the first two arguments are interchangeable. - `plural` (boolean): whether to use the plural form or not (mutually exclusive with `count`) - `count` (number): number of items that should be translated for plurality (mutually exclusive with `plural`) +- `suffix` (string): a custom suffix to add to the display string value when plurality is needed and no explicit plural value is defined - `lc` (boolean): transform the display string to lowercase (mutually exclusive with `uc`) - `uc` (boolean): transform the display string to uppercase (mutually exclusive with `lc`) - `abbrev` (boolean): transform the display string to its abbreviated form +- `strict` (boolean, default `true`): whether keys should be interpreted strictly (required in strings or defaults) or loosely (not required in strings or defaults) - in strict mode, an empty string will be returned when key is not found; in loose mode, the key will be used as the value when key is not found - `locale` (string): the user's locale e.g. `'en-US'` or `'en_US'` ### `Strings.getSingular(strings, key, opts)` @@ -155,7 +159,9 @@ Shortcut to get the plural value defined for `key`. If a singular value is defin ## Supported Keys +- `Strings.ADJUSTMENT` - `Strings.ANNUAL_CONTRACT_VALUE` +- `Strings.BATCH` - `Strings.CATEGORY` - `Strings.CLOSED` - `Strings.COMPENSATION` @@ -184,6 +190,10 @@ Abbreviate the given string by grabbing the first letter/character of each word, E.g. turns `'Annual Contract Value'` into `'ACV'` +### `Strings.formatInt(int, locale)` + +Attempts to format the given integer into a string per the given locale. + ### `Strings.isUpper(str, locale)` Returns a boolean indicating whether the given string is uppercase (in the given locale) or not. @@ -194,16 +204,30 @@ Naively attempts to normalize the given locale string into the language tag form E.g. turns `'en_US'` into `'en-US'` -### `Strings.pluralize(str, locale)` +### `Strings.pluralize(count, noun, opts)` -Attempts to apply pluralization to the given string in a case-sensitive manner. +Combine the given count and noun into a single formatted string, pluralizing the noun if necessary. -E.g. turns `'plan'` into `'plans'`, turns `'box'` into `'boxes'`, and turns `'fly'` into `'flies'` +Supported options include: + +- `suffix` (string): add this to the string instead of making a best-guess effort when pluralization is needed +- `locale` (string): to format the integer and respect case-sensitivity in a language-specific way ### `Strings.toLower(str, locale)` Attempts to safely transform the given string into lowercase. If a locale is given, it will be normalized. If the locale-specific operation fails, it will fall back to a locale-agnostic operation. +### `Strings.toPlural(str, opts)` + +Transforms the given string into its plural form, respecting case. + +E.g. turns `'plan'` into `'plans'`, turns `'box'` into `'boxes'`, and turns `'fly'` into `'flies'` + +Supported options include: + +- `suffix` (string): add this to the string instead of making a best-guess effort +- `locale` (string): to respect case-sensitivity in a language-specific way + ### `Strings.toUpper(str, locale)` Attempts to safely transform the given string into uppercase. If a locale is given, it will be normalized. If the locale-specific operation fails, it will fall back to a locale-agnostic operation. diff --git a/src/index.js b/src/index.js index 67d44b0..cf510da 100644 --- a/src/index.js +++ b/src/index.js @@ -27,18 +27,52 @@ class Strings { return String(c) !== Strings.toLower(c, locale) } - static pluralize (str, locale) { + // valid opts: + // - suffix (string, default based on str) to customize pluralization + // - locale (string, no default) to respect user's language + region + static toPlural (str, opts) { if (!str) return '' - let add = 's' + opts = opts || {} str = String(str) const last = str.slice(-1) - if (~['y', 'Y'].indexOf(last)) { - str = str.slice(0, -1) - add = 'ies' - } else if (~['j', 'o', 's', 'x', 'z', 'J', 'O', 'S', 'X', 'Z'].indexOf(last)) { - add = 'es' + let add + if (opts.suffix) add = opts.suffix + else { + add = 's' + if (~['y', 'Y'].indexOf(last)) { + str = str.slice(0, -1) + add = 'ies' + } else if (~['h', 'j', 'o', 's', 'x', 'z', 'H', 'J', 'O', 'S', 'X', 'Z'].indexOf(last)) { + add = 'es' + } } - return Strings.isUpper(last, locale) ? str + Strings.toUpper(add, locale) : str + add + return Strings.isUpper(last, opts.locale) ? str + Strings.toUpper(add, opts.locale) : str + add + } + + static formatInt (integer, locale) { + try { + return new Intl.NumberFormat(Strings.normalizeLocale(locale), { maximumFractionDigits: 0 }).format(integer) + } catch (_) {} + return String(integer) + } + + // valid opts: + // - suffix (string, default based on str) to customize pluralization + // - locale (string, no default) to respect user's language + region + static pluralize (count, noun, opts) { + if (!noun) return '' + noun = String(noun) + if (typeof count !== 'number') count = Number(count) + if (Number.isNaN(count)) count = 0 + let suffix, locale + if (typeof opts === 'string') { + suffix = opts + } else { + opts = opts || {} + suffix = opts.suffix + locale = opts.locale + } + return Strings.formatInt(count, locale) + ' ' + (count !== 1 ? Strings.toPlural(noun, { suffix, locale }) : noun) } static abbreviate (str) { @@ -46,7 +80,13 @@ class Strings { return String(str).split(/\s/).reduce((abbr, word) => abbr + word.slice(0, 1), '') } - // valid opts: plural (boolean), count (number), locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: + // - plural (boolean, no default) or count (number, no default) to determine whether singular or plural value should be used + // - suffix (string, default based on value) to customize auto-pluralization + // - lc (boolean, default false) or uc (boolean, default false) to transform value to lower or upper case before returning + // - abbrev (boolean, default false) to abbreviate the value before returning + // - strict (boolean, default true) to return empty string if key not in strings nor in DEFAULTS + // - locale (string, no default) to respect user's language + region static get (strings, key, opts) { // allow first two args to be interchangeable if (typeof strings === 'string') { @@ -66,24 +106,27 @@ class Strings { if (typeof opts === 'boolean') opts = { plural: opts } else if (typeof opts === 'number') opts = { count: opts } else opts = opts || {} - // check for locale - const locale = opts.locale || strings.locale + if (typeof opts.strict !== 'boolean') opts.strict = true // get value (object or singular string) let val = typeof strings.strings === 'object' ? strings.strings[key] : strings[key] if (val == null) val = Strings.DEFAULTS[key] - // if (val == null) val = key - if (val == null) return '' + if (val == null) { + if (opts.strict) return '' + val = key + } + // check for locale + const locale = opts.locale || strings.locale // determine plurality let usePlural = false if (typeof opts.plural === 'boolean') usePlural = opts.plural else if (typeof opts.count === 'number') usePlural = opts.count !== 1 // extract value if (usePlural) { - if (typeof val === 'string') val = Strings.pluralize(val, locale) + if (typeof val === 'string') val = Strings.toPlural(val, { locale, suffix: opts.suffix }) else if (val.plural || val.other) val = val.plural || val.other - else if (val.singular || val.one) val = Strings.pluralize(val.singular || val.one, locale) + else if (val.singular || val.one) val = Strings.toPlural(val.singular || val.one, { locale, suffix: opts.suffix }) } else if (typeof val !== 'string' && (val.singular || val.one)) { val = val.singular || val.one } @@ -94,12 +137,21 @@ class Strings { return opts.abbrev ? Strings.abbreviate(val) : val } - // valid opts: locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: + // - lc (boolean, default false) or uc (boolean, default false) to transform value to lower or upper case before returning + // - abbrev (boolean, default false) to abbreviate the value before returning + // - strict (boolean, default true) to return empty string if key not in strings nor in DEFAULTS + // - locale (string, no default) to respect user's language + region static getSingular (strings, key, opts) { return Strings.get(strings, key, Object.assign({}, opts, { plural: false })) } - // valid opts: locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: + // - suffix (string, default based on value) to customize auto-pluralization + // - lc (boolean, default false) or uc (boolean, default false) to transform value to lower or upper case before returning + // - abbrev (boolean, default false) to abbreviate the value before returning + // - strict (boolean, default true) to return empty string if key not in strings nor in DEFAULTS + // - locale (string, no default) to respect user's language + region static getPlural (strings, key, opts) { return Strings.get(strings, key, Object.assign({}, opts, { plural: true })) } @@ -112,17 +164,17 @@ class Strings { this.strings = strings } - // valid opts: plural (boolean), count (number), locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: plural (boolean), count (number), suffix (string), lc (boolean), uc (boolean), abbrev (boolean), strict (boolean), locale (string) get (key, opts) { return Strings.get(this.strings, key, opts) } - // valid opts: locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: lc (boolean), uc (boolean), abbrev (boolean), strict (boolean), locale (string) getSingular (key, opts) { return Strings.getSingular(this.strings, key, opts) } - // valid opts: locale (string), lc (boolean), uc (boolean), abbrev (boolean) + // valid opts: suffix (string), lc (boolean), uc (boolean), abbrev (boolean), strict (boolean), locale (string) getPlural (key, opts) { return Strings.getPlural(this.strings, key, opts) } @@ -148,6 +200,8 @@ Strings.DISPUTE = 'dispute' Strings.MEMBER = 'member' Strings.REP = 'rep' Strings.TEAM = 'team' +Strings.ADJUSTMENT = 'adjustment' +Strings.BATCH = 'batch' Strings.DEFAULTS = { [Strings.GROSS_MARGIN]: { @@ -196,7 +250,9 @@ Strings.DEFAULTS = { [Strings.DISPUTE]: 'Dispute', [Strings.MEMBER]: 'Member', [Strings.REP]: 'Rep', - [Strings.TEAM]: 'Team' + [Strings.TEAM]: 'Team', + [Strings.ADJUSTMENT]: 'Adjustment', + [Strings.BATCH]: 'Batch' } module.exports = Strings diff --git a/test.js b/test.js index 6e445e0..2501692 100644 --- a/test.js +++ b/test.js @@ -55,24 +55,169 @@ tap.test('isUpper', t => { t.end() }) +tap.test('toPlural', t => { + t.strictEqual(Strings.toPlural(), '') + t.strictEqual(Strings.toPlural(null), '') + t.strictEqual(Strings.toPlural(''), '') + t.strictEqual(Strings.toPlural('plan'), 'plans') + t.strictEqual(Strings.toPlural('PLAN'), 'PLANS') + t.strictEqual(Strings.toPlural('category'), 'categories') + t.strictEqual(Strings.toPlural('CATEGORY'), 'CATEGORIES') + t.strictEqual(Strings.toPlural('glass'), 'glasses') + t.strictEqual(Strings.toPlural('GLASS'), 'GLASSES') + t.strictEqual(Strings.toPlural('box'), 'boxes') + t.strictEqual(Strings.toPlural('BOX'), 'BOXES') + t.strictEqual(Strings.toPlural('batch'), 'batches') + t.strictEqual(Strings.toPlural('BATCH'), 'BATCHES') + + t.strictEqual(Strings.toPlural('plan', {}), 'plans') + t.strictEqual(Strings.toPlural('plan', { locale: undefined }), 'plans') + t.strictEqual(Strings.toPlural('plan', { locale: null }), 'plans') + + t.strictEqual(Strings.toPlural('plan', { locale: 'en-US' }), 'plans') + t.strictEqual(Strings.toPlural('plan', { locale: 'en_US' }), 'plans') + t.strictEqual(Strings.toPlural('plan', { locale: 'invalid locale' }), 'plans') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'en-US' }), 'PLANS') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'en_US' }), 'PLANS') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'invalid locale' }), 'PLANS') + + t.strictEqual(Strings.toPlural('plan', { suffix: 'tain' }), 'plantain') + t.strictEqual(Strings.toPlural('PLAN', { suffix: 'tain' }), 'PLANTAIN') + + t.strictEqual(Strings.toPlural('plan', { locale: 'en-US', suffix: 'tain' }), 'plantain') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'en-US', suffix: 'tain' }), 'PLANTAIN') + t.strictEqual(Strings.toPlural('plan', { locale: 'en_US', suffix: 'tain' }), 'plantain') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'en_US', suffix: 'tain' }), 'PLANTAIN') + t.strictEqual(Strings.toPlural('plan', { locale: 'invalid locale', suffix: 'tain' }), 'plantain') + t.strictEqual(Strings.toPlural('PLAN', { locale: 'invalid locale', suffix: 'tain' }), 'PLANTAIN') + + t.end() +}) + +tap.test('formatInt', t => { + t.strictEqual(Strings.formatInt(), 'NaN') + t.strictEqual(Strings.formatInt(null), '0') + t.strictEqual(Strings.formatInt(0), '0') + t.strictEqual(Strings.formatInt(1), '1') + t.strictEqual(Strings.formatInt(2), '2') + t.strictEqual(Strings.formatInt(1234567), '1,234,567') + t.strictEqual(Strings.formatInt('x'), 'NaN') + t.strictEqual(Strings.formatInt('9e10'), '90,000,000,000') + t.strictEqual(Strings.formatInt(Infinity), '∞') + + t.strictEqual(Strings.formatInt(null, 'en-US'), '0') + t.strictEqual(Strings.formatInt(0, 'en-US'), '0') + t.strictEqual(Strings.formatInt(1, 'en-US'), '1') + t.strictEqual(Strings.formatInt(2, 'en-US'), '2') + t.strictEqual(Strings.formatInt(1234567, 'en-US'), '1,234,567') + t.strictEqual(Strings.formatInt('x', 'en-US'), 'NaN') + t.strictEqual(Strings.formatInt('9e10', 'en-US'), '90,000,000,000') + t.strictEqual(Strings.formatInt(Infinity, 'en-US'), '∞') + + t.strictEqual(Strings.formatInt(null, 'en_US'), '0') + t.strictEqual(Strings.formatInt(0, 'en_US'), '0') + t.strictEqual(Strings.formatInt(1, 'en_US'), '1') + t.strictEqual(Strings.formatInt(2, 'en_US'), '2') + t.strictEqual(Strings.formatInt(1234567, 'en_US'), '1,234,567') + t.strictEqual(Strings.formatInt('x', 'en_US'), 'NaN') + t.strictEqual(Strings.formatInt('9e10', 'en_US'), '90,000,000,000') + t.strictEqual(Strings.formatInt(Infinity, 'en-US'), '∞') + + t.strictEqual(Strings.formatInt(null, 'invalid locale'), 'null') + t.strictEqual(Strings.formatInt(0, 'invalid locale'), '0') + t.strictEqual(Strings.formatInt(1, 'invalid locale'), '1') + t.strictEqual(Strings.formatInt(2, 'invalid locale'), '2') + t.strictEqual(Strings.formatInt(1234567, 'invalid locale'), '1234567') + t.strictEqual(Strings.formatInt('x', 'invalid locale'), 'x') + t.strictEqual(Strings.formatInt('9e10', 'invalid locale'), '9e10') + t.strictEqual(Strings.formatInt(Infinity, 'invalid locale'), 'Infinity') + + t.end() +}) + tap.test('pluralize', t => { t.strictEqual(Strings.pluralize(), '') t.strictEqual(Strings.pluralize(null), '') t.strictEqual(Strings.pluralize(''), '') - t.strictEqual(Strings.pluralize('plan'), 'plans') - t.strictEqual(Strings.pluralize('PLAN'), 'PLANS') - t.strictEqual(Strings.pluralize('category'), 'categories') - t.strictEqual(Strings.pluralize('CATEGORY'), 'CATEGORIES') - t.strictEqual(Strings.pluralize('glass'), 'glasses') - t.strictEqual(Strings.pluralize('GLASS'), 'GLASSES') - t.strictEqual(Strings.pluralize('box'), 'boxes') - t.strictEqual(Strings.pluralize('BOX'), 'BOXES') - t.strictEqual(Strings.pluralize('plan', 'en-US'), 'plans') - t.strictEqual(Strings.pluralize('plan', 'en_US'), 'plans') - t.strictEqual(Strings.pluralize('plan', 'invalid locale'), 'plans') - t.strictEqual(Strings.pluralize('PLAN', 'en-US'), 'PLANS') - t.strictEqual(Strings.pluralize('PLAN', 'en_US'), 'PLANS') - t.strictEqual(Strings.pluralize('PLAN', 'invalid locale'), 'PLANS') + t.strictEqual(Strings.pluralize(1), '') + t.strictEqual(Strings.pluralize(0), '') + t.strictEqual(Strings.pluralize(2), '') + + t.strictEqual(Strings.pluralize(1, null), '') + t.strictEqual(Strings.pluralize(1, ''), '') + + t.strictEqual(Strings.pluralize(1, 'guy'), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy'), '0 guies') + t.strictEqual(Strings.pluralize(2, 'guy'), '2 guies') + t.strictEqual(Strings.pluralize(1000, 'guy'), '1,000 guies') + t.strictEqual(Strings.pluralize(1, 'GUY'), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY'), '0 GUIES') + t.strictEqual(Strings.pluralize(2, 'GUY'), '2 GUIES') + t.strictEqual(Strings.pluralize(1000, 'GUY'), '1,000 GUIES') + + t.strictEqual(Strings.pluralize(1, 'guy', 's'), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', 's'), '0 guys') + t.strictEqual(Strings.pluralize(2, 'guy', 's'), '2 guys') + t.strictEqual(Strings.pluralize(1000, 'guy', 's'), '1,000 guys') + t.strictEqual(Strings.pluralize(1, 'GUY', 's'), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', 's'), '0 GUYS') + t.strictEqual(Strings.pluralize(2, 'GUY', 's'), '2 GUYS') + t.strictEqual(Strings.pluralize(1000, 'GUY', 's'), '1,000 GUYS') + + t.strictEqual(Strings.pluralize(1, 'guy', {}), '1 guy') + t.strictEqual(Strings.pluralize(2, 'guy', {}), '2 guies') + + t.strictEqual(Strings.pluralize(1, 'guy', { locale: 'en-US' }), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', { locale: 'en-US' }), '0 guies') + t.strictEqual(Strings.pluralize(2, 'guy', { locale: 'en-US' }), '2 guies') + t.strictEqual(Strings.pluralize(1000, 'guy', { locale: 'en-US' }), '1,000 guies') + t.strictEqual(Strings.pluralize(1, 'GUY', { locale: 'en-US' }), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', { locale: 'en-US' }), '0 GUIES') + t.strictEqual(Strings.pluralize(2, 'GUY', { locale: 'en-US' }), '2 GUIES') + t.strictEqual(Strings.pluralize(1000, 'GUY', { locale: 'en-US' }), '1,000 GUIES') + + t.strictEqual(Strings.pluralize(1, 'guy', { locale: 'en_US' }), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', { locale: 'en_US' }), '0 guies') + t.strictEqual(Strings.pluralize(2, 'guy', { locale: 'en_US' }), '2 guies') + t.strictEqual(Strings.pluralize(1000, 'guy', { locale: 'en_US' }), '1,000 guies') + t.strictEqual(Strings.pluralize(1, 'GUY', { locale: 'en_US' }), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', { locale: 'en_US' }), '0 GUIES') + t.strictEqual(Strings.pluralize(2, 'GUY', { locale: 'en_US' }), '2 GUIES') + t.strictEqual(Strings.pluralize(1000, 'GUY', { locale: 'en_US' }), '1,000 GUIES') + + t.strictEqual(Strings.pluralize(1, 'guy', { locale: 'invalid locale' }), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', { locale: 'invalid locale' }), '0 guies') + t.strictEqual(Strings.pluralize(2, 'guy', { locale: 'invalid locale' }), '2 guies') + t.strictEqual(Strings.pluralize(1000, 'guy', { locale: 'invalid locale' }), '1000 guies') + t.strictEqual(Strings.pluralize(1, 'GUY', { locale: 'invalid locale' }), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', { locale: 'invalid locale' }), '0 GUIES') + t.strictEqual(Strings.pluralize(2, 'GUY', { locale: 'invalid locale' }), '2 GUIES') + t.strictEqual(Strings.pluralize(1000, 'GUY', { locale: 'invalid locale' }), '1000 GUIES') + + t.strictEqual(Strings.pluralize(1, 'guy', { suffix: 's' }), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', { suffix: 's' }), '0 guys') + t.strictEqual(Strings.pluralize(2, 'guy', { suffix: 's' }), '2 guys') + t.strictEqual(Strings.pluralize(1000, 'guy', { suffix: 's' }), '1,000 guys') + t.strictEqual(Strings.pluralize(1, 'GUY', { suffix: 's' }), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', { suffix: 's' }), '0 GUYS') + t.strictEqual(Strings.pluralize(2, 'GUY', { suffix: 's' }), '2 GUYS') + t.strictEqual(Strings.pluralize(1000, 'GUY', { suffix: 's' }), '1,000 GUYS') + + t.strictEqual(Strings.pluralize(1, 'guy', { suffix: 's', locale: 'en-US' }), '1 guy') + t.strictEqual(Strings.pluralize(0, 'guy', { suffix: 's', locale: 'en-US' }), '0 guys') + t.strictEqual(Strings.pluralize(2, 'guy', { suffix: 's', locale: 'en-US' }), '2 guys') + t.strictEqual(Strings.pluralize(1000, 'guy', { suffix: 's', locale: 'en-US' }), '1,000 guys') + t.strictEqual(Strings.pluralize(1, 'GUY', { suffix: 's', locale: 'en-US' }), '1 GUY') + t.strictEqual(Strings.pluralize(0, 'GUY', { suffix: 's', locale: 'en-US' }), '0 GUYS') + t.strictEqual(Strings.pluralize(2, 'GUY', { suffix: 's', locale: 'en-US' }), '2 GUYS') + t.strictEqual(Strings.pluralize(1000, 'GUY', { suffix: 's', locale: 'en-US' }), '1,000 GUYS') + + t.strictEqual(Strings.pluralize(1000, 'guy', { suffix: 's', locale: 'invalid locale' }), '1000 guys') + t.strictEqual(Strings.pluralize(1000, 'GUY', { suffix: 's', locale: 'invalid locale' }), '1000 GUYS') + + t.strictEqual(Strings.pluralize('2', 'plan'), '2 plans') + t.strictEqual(Strings.pluralize('xyz', 'plan'), '0 plans') + t.end() }) @@ -85,6 +230,7 @@ tap.test('abbreviate', t => { t.strictEqual(Strings.abbreviate('one two three'), 'ott') t.strictEqual(Strings.abbreviate('One Two Three'), 'OTT') t.strictEqual(Strings.abbreviate('One Two Three'), 'OTT') + t.strictEqual(Strings.abbreviate(' One Two Three '), 'OTT') t.end() }) @@ -235,6 +381,18 @@ tap.test('static get', t => { t.strictEqual(Strings.get(strings, invalidKey, { uc: true, abbrev: true }), '') t.strictEqual(Strings.get(invalidKey, strings, { uc: true, abbrev: true }), '') + t.strictEqual(Strings.get(null, 'guy', { count: 2, suffix: 's', strict: false }), 'guys') + t.strictEqual(Strings.get('guy', null, { count: 2, suffix: 's', strict: false }), 'guys') + + const p = { + person: { + singular: 'person', + plural: 'people' + } + } + t.strictEqual(Strings.get(p, 'person', { count: 1, strict: false }), 'person') + t.strictEqual(Strings.get(p, 'person', { count: 2, strict: false }), 'people') + // strings object supports wrapper const wrapper = { locale: 'en_US', @@ -566,6 +724,10 @@ tap.test('defaults', t => { t.strictEqual(d.getPlural(Strings.REP), 'Reps') t.strictEqual(d.getSingular(Strings.TEAM), 'Team') t.strictEqual(d.getPlural(Strings.TEAM), 'Teams') + t.strictEqual(d.getSingular(Strings.ADJUSTMENT), 'Adjustment') + t.strictEqual(d.getPlural(Strings.ADJUSTMENT), 'Adjustments') + t.strictEqual(d.getSingular(Strings.BATCH), 'Batch') + t.strictEqual(d.getPlural(Strings.BATCH), 'Batches') t.end() })