packages/babel-plugin-fbt/src/translate/IntlVariations.js (69 lines of code) (raw):

/** * (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. * * @emails oncall+i18n_fbt_js * @flow strict * @format */ export type IntlVariationsEnum = $IntlVariationsEnum; const invariant = require('invariant'); // Must match with `IntlVariations.js` const IntlNumberVariations = { // Cast below values to IntlVariationsEnum ZERO: ((16: $FlowExpectedError): IntlVariationsEnum), // 0b10000 ONE: ((4: $FlowExpectedError): IntlVariationsEnum), // 0b00100 TWO: ((8: $FlowExpectedError): IntlVariationsEnum), // 0b01000 FEW: ((20: $FlowExpectedError): IntlVariationsEnum), // 0b10100 MANY: ((12: $FlowExpectedError): IntlVariationsEnum), // 0b01100 OTHER: ((24: $FlowExpectedError): IntlVariationsEnum), // 0b11000 }; // Must match with `IntlVariations.js` const IntlGenderVariations = { // Cast below values to IntlVariationsEnum MALE: ((1: $FlowExpectedError): IntlVariationsEnum), FEMALE: ((2: $FlowExpectedError): IntlVariationsEnum), UNKNOWN: ((3: $FlowExpectedError): IntlVariationsEnum), }; // Two bitmasks for representing gender/number variations. Give a bit // between number/gender in case CLDR ever exceeds 7 options const IntlVariationMask: {| NUMBER: 0x1c, GENDER: 0x03, |} = { NUMBER: 0x1c, // 0b11100 GENDER: 0x03, // 0b00011 }; export type IntlVariationMaskValue = $Values<typeof IntlVariationMask>; const IntlFbtVariationType: $ReadOnly<{| GENDER: 1, NUMBER: 2, PRONOUN: 3, |}> = { GENDER: 1, NUMBER: 2, PRONOUN: 3, }; export type IntlFbtVariationTypeValue = $Values<typeof IntlFbtVariationType>; // Gender variation key used in JSFBT to represent any gender const GENDER_ANY: '*' = '*'; // Number variation key used in JSFBT to represent "many" (i.e. non-exactly one) const NUMBER_ANY: '*' = '*'; // This is not CLDR, but an fbt-specific marker that exists so that // singular phrases are not overwritten by multiplexed plural phrases // with a singular entry const EXACTLY_ONE: '_1' = '_1'; const SPECIALS = { // The default entry. When no entry exists, we fallback to this in the fbt // table access logic. '*': true, EXACTLY_ONE: true, }; function getType( n: $Values<typeof IntlVariationMask>, ): $Values<typeof IntlVariationMask> { invariant(isValidValue(n), 'Invalid NumberType: %s', n); /*eslint no-bitwise: 0*/ return n & IntlVariationMask.NUMBER ? IntlVariationMask.NUMBER : IntlVariationMask.GENDER; } function isValidValue(value: string | number): boolean { const num = Number(value); /*eslint no-bitwise: 0*/ return ( SPECIALS[value] || (num & IntlVariationMask.NUMBER && !(num & ~IntlVariationMask.NUMBER)) || (num & IntlVariationMask.GENDER && !(num & ~IntlVariationMask.GENDER)) ); } module.exports = { Number: IntlNumberVariations, Gender: IntlGenderVariations, Mask: IntlVariationMask, FbtVariationType: IntlFbtVariationType, isValidValue, getType, EXACTLY_ONE, VIEWING_USER: '__viewing_user__', SUBJECT: '__subject__', GENDER_ANY, NUMBER_ANY, };