Files
documentation/node_modules/@docusaurus/theme-common/lib/utils/usePluralForm.js
2024-03-22 03:47:51 +05:30

93 lines
3.4 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { useMemo } from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
// We want to ensurer a stable plural form order in all cases
// It is more convenient and natural to handle "small values" first
// See https://twitter.com/sebastienlorber/status/1366820663261077510
const OrderedPluralForms = [
'zero',
'one',
'two',
'few',
'many',
'other',
];
function sortPluralForms(pluralForms) {
return OrderedPluralForms.filter((pf) => pluralForms.includes(pf));
}
// Hardcoded english/fallback implementation
const EnglishPluralForms = {
locale: 'en',
pluralForms: sortPluralForms(['one', 'other']),
select: (count) => (count === 1 ? 'one' : 'other'),
};
function createLocalePluralForms(locale) {
const pluralRules = new Intl.PluralRules(locale);
return {
locale,
pluralForms: sortPluralForms(pluralRules.resolvedOptions().pluralCategories),
select: (count) => pluralRules.select(count),
};
}
/**
* Poor man's `PluralSelector` implementation, using an English fallback. We
* want a lightweight, future-proof and good-enough solution. We don't want a
* perfect and heavy solution.
*
* Docusaurus classic theme has only 2 deeply nested labels requiring complex
* plural rules. We don't want to use `Intl` + `PluralRules` polyfills + full
* ICU syntax (react-intl) just for that.
*
* Notes:
* - 2021: 92+% Browsers support `Intl.PluralRules`, and support will increase
* in the future
* - NodeJS >= 13 has full ICU support by default
* - In case of "mismatch" between SSR and Browser ICU support, React keeps
* working!
*/
function useLocalePluralForms() {
const { i18n: { currentLocale }, } = useDocusaurusContext();
return useMemo(() => {
try {
return createLocalePluralForms(currentLocale);
}
catch (err) {
console.error(`Failed to use Intl.PluralRules for locale "${currentLocale}".
Docusaurus will fallback to the default (English) implementation.
Error: ${err.message}
`);
return EnglishPluralForms;
}
}, [currentLocale]);
}
function selectPluralMessage(pluralMessages, count, localePluralForms) {
const separator = '|';
const parts = pluralMessages.split(separator);
if (parts.length === 1) {
return parts[0];
}
if (parts.length > localePluralForms.pluralForms.length) {
console.error(`For locale=${localePluralForms.locale}, a maximum of ${localePluralForms.pluralForms.length} plural forms are expected (${localePluralForms.pluralForms.join(',')}), but the message contains ${parts.length}: ${pluralMessages}`);
}
const pluralForm = localePluralForms.select(count);
const pluralFormIndex = localePluralForms.pluralForms.indexOf(pluralForm);
// In case of not enough plural form messages, we take the last one (other)
// instead of returning undefined
return parts[Math.min(pluralFormIndex, parts.length - 1)];
}
/**
* Reads the current locale and returns an interface very similar to
* `Intl.PluralRules`.
*/
export function usePluralForm() {
const localePluralForm = useLocalePluralForms();
return {
selectMessage: (count, pluralMessages) => selectPluralMessage(pluralMessages, count, localePluralForm),
};
}
//# sourceMappingURL=usePluralForm.js.map