intl_provider.tsx 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import { useEffect, useState } from 'react';
  2. import { IntlProvider as BaseIntlProvider } from 'react-intl';
  3. import { isProduction } from 'mastodon/utils/environment';
  4. import { getLocale, isLocaleLoaded } from './global_locale';
  5. import { loadLocale } from './load_locale';
  6. function onProviderError(error: unknown) {
  7. // Silent the error, like upstream does
  8. if (isProduction()) return;
  9. // This browser does not advertise Intl support for this locale, we only print a warning
  10. // As-per the spec, the browser should select the best matching locale
  11. if (
  12. error &&
  13. typeof error === 'object' &&
  14. error instanceof Error &&
  15. error.message.match('MISSING_DATA')
  16. ) {
  17. console.warn(error.message);
  18. }
  19. console.error(error);
  20. }
  21. export const IntlProvider: React.FC<
  22. Omit<React.ComponentProps<typeof BaseIntlProvider>, 'locale' | 'messages'>
  23. > = ({ children, ...props }) => {
  24. const [localeLoaded, setLocaleLoaded] = useState(false);
  25. useEffect(() => {
  26. async function loadLocaleData() {
  27. if (!isLocaleLoaded()) {
  28. await loadLocale();
  29. }
  30. setLocaleLoaded(true);
  31. }
  32. void loadLocaleData();
  33. }, []);
  34. if (!localeLoaded) return null;
  35. const { locale, messages } = getLocale();
  36. return (
  37. <BaseIntlProvider
  38. locale={locale}
  39. messages={messages}
  40. onError={onProviderError}
  41. textComponent='span'
  42. {...props}
  43. >
  44. {children}
  45. </BaseIntlProvider>
  46. );
  47. };