diff --git a/src/components/hooks/dates.ts b/src/components/hooks/dates.ts index 898e245ecc..70ba421926 100644 --- a/src/components/hooks/dates.ts +++ b/src/components/hooks/dates.ts @@ -7,107 +7,21 @@ * {@link https://github.com/date-fns/date-fns/blob/main/docs/i18n.md} */ -import React from 'react' -import {formatDistance, type Locale} from 'date-fns' -import { - ca, - cy, - da, - de, - el, - enGB, - eo, - es, - eu, - fi, - fr, - fy, - gd, - gl, - hi, - hu, - id, - it, - ja, - km, - ko, - nl, - pl, - pt, - ptBR, - ro, - ru, - sv, - th, - tr, - uk, - vi, - zhCN, - zhHK, - zhTW, -} from 'date-fns/locale' +import {useCallback} from 'react' +import {formatDistance} from 'date-fns' -import {type AppLanguage} from '#/locale/languages' -import {useLanguagePrefs} from '#/state/preferences' - -/** - * {@link AppLanguage} - */ -const locales: Record = { - en: undefined, - an: undefined, - ast: undefined, - ca, - cy, - da, - de, - el, - ['en-GB']: enGB, - eo, - es, - eu, - fi, - fr, - fy, - ga: undefined, - gd, - gl, - hi, - hu, - ia: undefined, - id, - it, - ja, - km, - ko, - ne: undefined, - nl, - pl, - ['pt-PT']: pt, - ['pt-BR']: ptBR, - ro, - ru, - sv, - th, - tr, - uk, - vi, - ['zh-Hans-CN']: zhCN, - ['zh-Hant-HK']: zhHK, - ['zh-Hant-TW']: zhTW, -} +import {useDateLocale} from '#/locale/i18nProvider' /** * Returns a localized `formatDistance` function. * {@link formatDistance} */ export function useFormatDistance() { - const {appLanguage} = useLanguagePrefs() - return React.useCallback( + const locale = useDateLocale() + return useCallback( (date, baseDate, options) => { - const locale = locales[appLanguage as AppLanguage] - return formatDistance(date, baseDate, {...options, locale: locale}) + return formatDistance(date, baseDate, {...options, locale}) }, - [appLanguage], + [locale], ) } diff --git a/src/locale/i18n.ts b/src/locale/i18n.ts index 6e5a5d0de4..c063f30a4c 100644 --- a/src/locale/i18n.ts +++ b/src/locale/i18n.ts @@ -8,8 +8,9 @@ import '@formatjs/intl-pluralrules/locale-data/en' import '@formatjs/intl-numberformat/locale-data/en' import '@formatjs/intl-displaynames/locale-data/en' -import {useEffect} from 'react' +import {useEffect, useState} from 'react' import {i18n} from '@lingui/core' +import defaultLocale from 'date-fns/locale/en-US' import {sanitizeAppLanguageSetting} from '#/locale/helpers' import {AppLanguage} from '#/locale/languages' @@ -63,130 +64,144 @@ export async function dynamicActivate(locale: AppLanguage) { switch (locale) { case AppLanguage.an: { i18n.loadAndActivate({locale, messages: messagesAn}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/es'), import('@formatjs/intl-pluralrules/locale-data/an'), import('@formatjs/intl-numberformat/locale-data/es'), import('@formatjs/intl-displaynames/locale-data/es'), ]) - break + return dateLocale } case AppLanguage.ast: { i18n.loadAndActivate({locale, messages: messagesAst}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/es'), import('@formatjs/intl-pluralrules/locale-data/ast'), import('@formatjs/intl-numberformat/locale-data/ast'), import('@formatjs/intl-displaynames/locale-data/ast'), ]) - break + return dateLocale } case AppLanguage.ca: { i18n.loadAndActivate({locale, messages: messagesCa}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/ca'), import('@formatjs/intl-pluralrules/locale-data/ca'), import('@formatjs/intl-numberformat/locale-data/ca'), import('@formatjs/intl-displaynames/locale-data/ca'), ]) - break + return dateLocale } case AppLanguage.cy: { i18n.loadAndActivate({locale, messages: messagesCy}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/cy'), import('@formatjs/intl-pluralrules/locale-data/cy'), import('@formatjs/intl-numberformat/locale-data/cy'), import('@formatjs/intl-displaynames/locale-data/cy'), ]) - break + return dateLocale } case AppLanguage.da: { i18n.loadAndActivate({locale, messages: messagesDa}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/da'), import('@formatjs/intl-pluralrules/locale-data/da'), import('@formatjs/intl-numberformat/locale-data/da'), import('@formatjs/intl-displaynames/locale-data/da'), ]) - break + return dateLocale } case AppLanguage.de: { i18n.loadAndActivate({locale, messages: messagesDe}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/de'), import('@formatjs/intl-pluralrules/locale-data/de'), import('@formatjs/intl-numberformat/locale-data/de'), import('@formatjs/intl-displaynames/locale-data/de'), ]) - break + return dateLocale } case AppLanguage.el: { i18n.loadAndActivate({locale, messages: messagesEl}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/el'), import('@formatjs/intl-pluralrules/locale-data/el'), import('@formatjs/intl-numberformat/locale-data/el'), import('@formatjs/intl-displaynames/locale-data/el'), ]) - break + return dateLocale } case AppLanguage.en_GB: { i18n.loadAndActivate({locale, messages: messagesEn_GB}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/en-GB'), import('@formatjs/intl-pluralrules/locale-data/en'), import('@formatjs/intl-numberformat/locale-data/en-GB'), import('@formatjs/intl-displaynames/locale-data/en-GB'), ]) - break + return dateLocale } case AppLanguage.eo: { i18n.loadAndActivate({locale, messages: messagesEo}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/eo'), import('@formatjs/intl-pluralrules/locale-data/eo'), import('@formatjs/intl-numberformat/locale-data/eo'), // borked, see https://github.com/bluesky-social/social-app/pull/9574 // import('@formatjs/intl-displaynames/locale-data/eo'), ]) - break + return dateLocale } case AppLanguage.es: { i18n.loadAndActivate({locale, messages: messagesEs}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/es'), import('@formatjs/intl-pluralrules/locale-data/es'), import('@formatjs/intl-numberformat/locale-data/es'), import('@formatjs/intl-displaynames/locale-data/es'), ]) - break + return dateLocale } case AppLanguage.eu: { i18n.loadAndActivate({locale, messages: messagesEu}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/eu'), import('@formatjs/intl-pluralrules/locale-data/eu'), import('@formatjs/intl-numberformat/locale-data/eu'), import('@formatjs/intl-displaynames/locale-data/eu'), ]) - break + return dateLocale } case AppLanguage.fi: { i18n.loadAndActivate({locale, messages: messagesFi}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/fi'), import('@formatjs/intl-pluralrules/locale-data/fi'), import('@formatjs/intl-numberformat/locale-data/fi'), import('@formatjs/intl-displaynames/locale-data/fi'), ]) - break + return dateLocale } case AppLanguage.fr: { i18n.loadAndActivate({locale, messages: messagesFr}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/fr'), import('@formatjs/intl-pluralrules/locale-data/fr'), import('@formatjs/intl-numberformat/locale-data/fr'), import('@formatjs/intl-displaynames/locale-data/fr'), ]) - break + return dateLocale } case AppLanguage.fy: { i18n.loadAndActivate({locale, messages: messagesFy}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/fy'), import('@formatjs/intl-pluralrules/locale-data/fy'), import('@formatjs/intl-numberformat/locale-data/fy'), import('@formatjs/intl-displaynames/locale-data/fy'), ]) - break + return dateLocale } case AppLanguage.ga: { i18n.loadAndActivate({locale, messages: messagesGa}) @@ -195,43 +210,47 @@ export async function dynamicActivate(locale: AppLanguage) { import('@formatjs/intl-numberformat/locale-data/ga'), import('@formatjs/intl-displaynames/locale-data/ga'), ]) - break + return undefined } case AppLanguage.gd: { i18n.loadAndActivate({locale, messages: messagesGd}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/gd'), import('@formatjs/intl-pluralrules/locale-data/gd'), import('@formatjs/intl-numberformat/locale-data/gd'), import('@formatjs/intl-displaynames/locale-data/gd'), ]) - break + return dateLocale } case AppLanguage.gl: { i18n.loadAndActivate({locale, messages: messagesGl}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/gl'), import('@formatjs/intl-pluralrules/locale-data/gl'), import('@formatjs/intl-numberformat/locale-data/gl'), import('@formatjs/intl-displaynames/locale-data/gl'), ]) - break + return dateLocale } case AppLanguage.hi: { i18n.loadAndActivate({locale, messages: messagesHi}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/hi'), import('@formatjs/intl-pluralrules/locale-data/hi'), import('@formatjs/intl-numberformat/locale-data/hi'), import('@formatjs/intl-displaynames/locale-data/hi'), ]) - break + return dateLocale } case AppLanguage.hu: { i18n.loadAndActivate({locale, messages: messagesHu}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/hu'), import('@formatjs/intl-pluralrules/locale-data/hu'), import('@formatjs/intl-numberformat/locale-data/hu'), import('@formatjs/intl-displaynames/locale-data/hu'), ]) - break + return dateLocale } case AppLanguage.ia: { i18n.loadAndActivate({locale, messages: messagesIa}) @@ -240,52 +259,57 @@ export async function dynamicActivate(locale: AppLanguage) { import('@formatjs/intl-numberformat/locale-data/ia'), import('@formatjs/intl-displaynames/locale-data/ia'), ]) - break + return undefined } case AppLanguage.id: { i18n.loadAndActivate({locale, messages: messagesId}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/id'), import('@formatjs/intl-pluralrules/locale-data/id'), import('@formatjs/intl-numberformat/locale-data/id'), import('@formatjs/intl-displaynames/locale-data/id'), ]) - break + return dateLocale } case AppLanguage.it: { i18n.loadAndActivate({locale, messages: messagesIt}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/it'), import('@formatjs/intl-pluralrules/locale-data/it'), import('@formatjs/intl-numberformat/locale-data/it'), import('@formatjs/intl-displaynames/locale-data/it'), ]) - break + return dateLocale } case AppLanguage.ja: { i18n.loadAndActivate({locale, messages: messagesJa}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/ja'), import('@formatjs/intl-pluralrules/locale-data/ja'), import('@formatjs/intl-numberformat/locale-data/ja'), import('@formatjs/intl-displaynames/locale-data/ja'), ]) - break + return dateLocale } case AppLanguage.km: { i18n.loadAndActivate({locale, messages: messagesKm}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/km'), import('@formatjs/intl-pluralrules/locale-data/km'), import('@formatjs/intl-numberformat/locale-data/km'), import('@formatjs/intl-displaynames/locale-data/km'), ]) - break + return dateLocale } case AppLanguage.ko: { i18n.loadAndActivate({locale, messages: messagesKo}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/ko'), import('@formatjs/intl-pluralrules/locale-data/ko'), import('@formatjs/intl-numberformat/locale-data/ko'), import('@formatjs/intl-displaynames/locale-data/ko'), ]) - break + return dateLocale } case AppLanguage.ne: { i18n.loadAndActivate({locale, messages: messagesNe}) @@ -294,144 +318,164 @@ export async function dynamicActivate(locale: AppLanguage) { import('@formatjs/intl-numberformat/locale-data/ne'), import('@formatjs/intl-displaynames/locale-data/ne'), ]) - break + return undefined } case AppLanguage.nl: { i18n.loadAndActivate({locale, messages: messagesNl}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/nl'), import('@formatjs/intl-pluralrules/locale-data/nl'), import('@formatjs/intl-numberformat/locale-data/nl'), import('@formatjs/intl-displaynames/locale-data/nl'), ]) - break + return dateLocale } case AppLanguage.pl: { i18n.loadAndActivate({locale, messages: messagesPl}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/pl'), import('@formatjs/intl-pluralrules/locale-data/pl'), import('@formatjs/intl-numberformat/locale-data/pl'), import('@formatjs/intl-displaynames/locale-data/pl'), ]) - break + return dateLocale } case AppLanguage.pt_BR: { i18n.loadAndActivate({locale, messages: messagesPt_BR}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/pt-BR'), import('@formatjs/intl-pluralrules/locale-data/pt'), import('@formatjs/intl-numberformat/locale-data/pt'), import('@formatjs/intl-displaynames/locale-data/pt'), ]) - break + return dateLocale } case AppLanguage.pt_PT: { i18n.loadAndActivate({locale, messages: messagesPt_PT}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/pt'), import('@formatjs/intl-pluralrules/locale-data/pt-PT'), import('@formatjs/intl-numberformat/locale-data/pt-PT'), import('@formatjs/intl-displaynames/locale-data/pt-PT'), ]) - break + return dateLocale } case AppLanguage.ro: { i18n.loadAndActivate({locale, messages: messagesRo}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/ro'), import('@formatjs/intl-pluralrules/locale-data/ro'), import('@formatjs/intl-numberformat/locale-data/ro'), import('@formatjs/intl-displaynames/locale-data/ro'), ]) - break + return dateLocale } case AppLanguage.ru: { i18n.loadAndActivate({locale, messages: messagesRu}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/ru'), import('@formatjs/intl-pluralrules/locale-data/ru'), import('@formatjs/intl-numberformat/locale-data/ru'), import('@formatjs/intl-displaynames/locale-data/ru'), ]) - break + return dateLocale } case AppLanguage.sv: { i18n.loadAndActivate({locale, messages: messagesSv}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/sv'), import('@formatjs/intl-pluralrules/locale-data/sv'), import('@formatjs/intl-numberformat/locale-data/sv'), import('@formatjs/intl-displaynames/locale-data/sv'), ]) - break + return dateLocale } case AppLanguage.th: { i18n.loadAndActivate({locale, messages: messagesTh}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/th'), import('@formatjs/intl-pluralrules/locale-data/th'), import('@formatjs/intl-numberformat/locale-data/th'), import('@formatjs/intl-displaynames/locale-data/th'), ]) - break + return dateLocale } case AppLanguage.tr: { i18n.loadAndActivate({locale, messages: messagesTr}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/tr'), import('@formatjs/intl-pluralrules/locale-data/tr'), import('@formatjs/intl-numberformat/locale-data/tr'), import('@formatjs/intl-displaynames/locale-data/tr'), ]) - break + return dateLocale } case AppLanguage.uk: { i18n.loadAndActivate({locale, messages: messagesUk}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/uk'), import('@formatjs/intl-pluralrules/locale-data/uk'), import('@formatjs/intl-numberformat/locale-data/uk'), import('@formatjs/intl-displaynames/locale-data/uk'), ]) - break + return dateLocale } case AppLanguage.vi: { i18n.loadAndActivate({locale, messages: messagesVi}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/vi'), import('@formatjs/intl-pluralrules/locale-data/vi'), import('@formatjs/intl-numberformat/locale-data/vi'), import('@formatjs/intl-displaynames/locale-data/vi'), ]) - break + return dateLocale } case AppLanguage.zh_CN: { i18n.loadAndActivate({locale, messages: messagesZh_CN}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/zh-CN'), import('@formatjs/intl-pluralrules/locale-data/zh'), import('@formatjs/intl-numberformat/locale-data/zh'), import('@formatjs/intl-displaynames/locale-data/zh'), ]) - break + return dateLocale } case AppLanguage.zh_HK: { i18n.loadAndActivate({locale, messages: messagesZh_HK}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/zh-HK'), import('@formatjs/intl-pluralrules/locale-data/zh'), import('@formatjs/intl-numberformat/locale-data/zh'), import('@formatjs/intl-displaynames/locale-data/zh'), ]) - break + return dateLocale } case AppLanguage.zh_TW: { i18n.loadAndActivate({locale, messages: messagesZh_TW}) - await Promise.all([ + const [{default: dateLocale}] = await Promise.all([ + import('date-fns/locale/zh-TW'), import('@formatjs/intl-pluralrules/locale-data/zh'), import('@formatjs/intl-numberformat/locale-data/zh'), import('@formatjs/intl-displaynames/locale-data/zh'), ]) - break + return dateLocale } default: { i18n.loadAndActivate({locale, messages: messagesEn}) - break + return defaultLocale } } } export function useLocaleLanguage() { const {appLanguage} = useLanguagePrefs() + const [dateLocale, setDateLocale] = useState(defaultLocale) + useEffect(() => { - dynamicActivate(sanitizeAppLanguageSetting(appLanguage)) + dynamicActivate(sanitizeAppLanguageSetting(appLanguage)).then(locale => { + setDateLocale(locale ?? defaultLocale) + }) }, [appLanguage]) + + return dateLocale } diff --git a/src/locale/i18n.web.ts b/src/locale/i18n.web.ts index 23a866dc23..2b79ae7f29 100644 --- a/src/locale/i18n.web.ts +++ b/src/locale/i18n.web.ts @@ -1,5 +1,6 @@ -import {useEffect} from 'react' +import {useEffect, useState} from 'react' import {i18n} from '@lingui/core' +import defaultLocale from 'date-fns/locale/en-US' import {sanitizeAppLanguageSetting} from '#/locale/helpers' import {AppLanguage} from '#/locale/languages' @@ -10,62 +11,105 @@ import {useLanguagePrefs} from '#/state/preferences' */ export async function dynamicActivate(locale: AppLanguage) { let mod: any + let dateLocale: Locale = defaultLocale switch (locale) { case AppLanguage.an: { - mod = await import(`./locales/an/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/an/messages`), + import('date-fns/locale/es'), + ]) break } case AppLanguage.ast: { - mod = await import(`./locales/ast/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ast/messages`), + import('date-fns/locale/es'), + ]) break } case AppLanguage.ca: { - mod = await import(`./locales/ca/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ca/messages`), + import('date-fns/locale/ca'), + ]) break } case AppLanguage.cy: { - mod = await import(`./locales/cy/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/cy/messages`), + import('date-fns/locale/cy'), + ]) break } case AppLanguage.da: { - mod = await import(`./locales/da/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/da/messages`), + import('date-fns/locale/da'), + ]) break } case AppLanguage.de: { - mod = await import(`./locales/de/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/de/messages`), + import('date-fns/locale/de'), + ]) break } case AppLanguage.el: { - mod = await import(`./locales/el/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/el/messages`), + import('date-fns/locale/el'), + ]) break } case AppLanguage.en_GB: { - mod = await import(`./locales/en-GB/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/en-GB/messages`), + import('date-fns/locale/en-GB'), + ]) break } case AppLanguage.eo: { - mod = await import(`./locales/eo/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/eo/messages`), + import('date-fns/locale/eo'), + ]) break } case AppLanguage.es: { - mod = await import(`./locales/es/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/es/messages`), + import('date-fns/locale/es'), + ]) break } case AppLanguage.eu: { - mod = await import(`./locales/eu/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/eu/messages`), + import('date-fns/locale/eu'), + ]) break } case AppLanguage.fi: { - mod = await import(`./locales/fi/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/fi/messages`), + import('date-fns/locale/fi'), + ]) break } case AppLanguage.fr: { - mod = await import(`./locales/fr/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/fr/messages`), + import('date-fns/locale/fr'), + ]) break } case AppLanguage.fy: { - mod = await import(`./locales/fy/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/fy/messages`), + import('date-fns/locale/fy'), + ]) break } case AppLanguage.ga: { @@ -73,19 +117,31 @@ export async function dynamicActivate(locale: AppLanguage) { break } case AppLanguage.gd: { - mod = await import(`./locales/gd/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/gd/messages`), + import('date-fns/locale/gd'), + ]) break } case AppLanguage.gl: { - mod = await import(`./locales/gl/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/gl/messages`), + import('date-fns/locale/gl'), + ]) break } case AppLanguage.hi: { - mod = await import(`./locales/hi/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/hi/messages`), + import('date-fns/locale/hi'), + ]) break } case AppLanguage.hu: { - mod = await import(`./locales/hu/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/hu/messages`), + import('date-fns/locale/hu'), + ]) break } case AppLanguage.ia: { @@ -93,23 +149,38 @@ export async function dynamicActivate(locale: AppLanguage) { break } case AppLanguage.id: { - mod = await import(`./locales/id/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/id/messages`), + import('date-fns/locale/id'), + ]) break } case AppLanguage.it: { - mod = await import(`./locales/it/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/it/messages`), + import('date-fns/locale/it'), + ]) break } case AppLanguage.ja: { - mod = await import(`./locales/ja/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ja/messages`), + import('date-fns/locale/ja'), + ]) break } case AppLanguage.km: { - mod = await import(`./locales/km/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/km/messages`), + import('date-fns/locale/km'), + ]) break } case AppLanguage.ko: { - mod = await import(`./locales/ko/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ko/messages`), + import('date-fns/locale/ko'), + ]) break } case AppLanguage.ne: { @@ -117,59 +188,101 @@ export async function dynamicActivate(locale: AppLanguage) { break } case AppLanguage.nl: { - mod = await import(`./locales/nl/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/nl/messages`), + import('date-fns/locale/nl'), + ]) break } case AppLanguage.pl: { - mod = await import(`./locales/pl/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/pl/messages`), + import('date-fns/locale/pl'), + ]) break } case AppLanguage.pt_BR: { - mod = await import(`./locales/pt-BR/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/pt-BR/messages`), + import('date-fns/locale/pt-BR'), + ]) break } case AppLanguage.pt_PT: { - mod = await import(`./locales/pt-PT/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/pt-PT/messages`), + import('date-fns/locale/pt'), + ]) break } case AppLanguage.ro: { - mod = await import(`./locales/ro/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ro/messages`), + import('date-fns/locale/ro'), + ]) break } case AppLanguage.ru: { - mod = await import(`./locales/ru/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/ru/messages`), + import('date-fns/locale/ru'), + ]) break } case AppLanguage.sv: { - mod = await import(`./locales/sv/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/sv/messages`), + import('date-fns/locale/sv'), + ]) break } case AppLanguage.th: { - mod = await import(`./locales/th/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/th/messages`), + import('date-fns/locale/th'), + ]) break } case AppLanguage.tr: { - mod = await import(`./locales/tr/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/tr/messages`), + import('date-fns/locale/tr'), + ]) break } case AppLanguage.uk: { - mod = await import(`./locales/uk/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/uk/messages`), + import('date-fns/locale/uk'), + ]) break } case AppLanguage.vi: { - mod = await import(`./locales/vi/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/vi/messages`), + import('date-fns/locale/vi'), + ]) break } case AppLanguage.zh_CN: { - mod = await import(`./locales/zh-CN/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/zh-CN/messages`), + import('date-fns/locale/zh-CN'), + ]) break } case AppLanguage.zh_HK: { - mod = await import(`./locales/zh-HK/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/zh-HK/messages`), + import('date-fns/locale/zh-HK'), + ]) break } case AppLanguage.zh_TW: { - mod = await import(`./locales/zh-TW/messages`) + ;[mod, {default: dateLocale}] = await Promise.all([ + import(`./locales/zh-TW/messages`), + import('date-fns/locale/zh-TW'), + ]) break } default: { @@ -180,14 +293,22 @@ export async function dynamicActivate(locale: AppLanguage) { i18n.load(locale, mod.messages) i18n.activate(locale) + + return dateLocale } export function useLocaleLanguage() { const {appLanguage} = useLanguagePrefs() + const [dateLocale, setDateLocale] = useState(defaultLocale) + useEffect(() => { const sanitizedLanguage = sanitizeAppLanguageSetting(appLanguage) document.documentElement.lang = sanitizedLanguage - dynamicActivate(sanitizedLanguage) + dynamicActivate(sanitizedLanguage).then(locale => { + setDateLocale(locale) + }) }, [appLanguage]) + + return dateLocale } diff --git a/src/locale/i18nProvider.tsx b/src/locale/i18nProvider.tsx index 6af55fe0e1..f87822326d 100644 --- a/src/locale/i18nProvider.tsx +++ b/src/locale/i18nProvider.tsx @@ -1,10 +1,32 @@ +import {createContext, useContext} from 'react' import {i18n} from '@lingui/core' import {I18nProvider as DefaultI18nProvider} from '@lingui/react' +import {type Locale} from 'date-fns' import type React from 'react' import {useLocaleLanguage} from './i18n' +const DateLocaleContext = createContext(undefined) +DateLocaleContext.displayName = 'DateLocaleContext' + export default function I18nProvider({children}: {children: React.ReactNode}) { - useLocaleLanguage() - return {children} + const dateLocale = useLocaleLanguage() + return ( + + {children} + + ) +} + +/** + * Returns a `date-fns` locale corresponding to the current app language + */ +export function useDateLocale() { + const ctx = useContext(DateLocaleContext) + + if (!ctx) { + throw new Error('useDateLocale must be used within an I18nProvider') + } + + return ctx }