-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix
/share
and cleanup and reorganize frontend locale loading (#25240)
- Loading branch information
Showing
25 changed files
with
152 additions
and
638 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export interface LocaleData { | ||
locale: string; | ||
messages: Record<string, string>; | ||
} | ||
|
||
let loadedLocale: LocaleData; | ||
|
||
export function setLocale(locale: LocaleData) { | ||
loadedLocale = locale; | ||
} | ||
|
||
export function getLocale() { | ||
if (!loadedLocale && process.env.NODE_ENV === 'development') { | ||
throw new Error('getLocale() called before any locale has been set'); | ||
} | ||
|
||
return loadedLocale; | ||
} | ||
|
||
export function isLocaleLoaded() { | ||
return !!loadedLocale; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export type { LocaleData } from './global_locale'; | ||
export { setLocale, getLocale, isLocaleLoaded } from './global_locale'; | ||
export { loadLocale } from './load_locale'; | ||
|
||
export { IntlProvider } from './intl_provider'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { useEffect, useState } from 'react'; | ||
|
||
import { IntlProvider as BaseIntlProvider } from 'react-intl'; | ||
|
||
import { getLocale, isLocaleLoaded } from './global_locale'; | ||
import { loadLocale } from './load_locale'; | ||
|
||
function onProviderError(error: unknown) { | ||
// Silent the error, like upstream does | ||
if (process.env.NODE_ENV === 'production') return; | ||
|
||
// This browser does not advertise Intl support for this locale, we only print a warning | ||
// As-per the spec, the browser should select the best matching locale | ||
if ( | ||
error && | ||
typeof error === 'object' && | ||
error instanceof Error && | ||
error.message.match('MISSING_DATA') | ||
) { | ||
console.warn(error.message); | ||
} | ||
|
||
console.error(error); | ||
} | ||
|
||
export const IntlProvider: React.FC< | ||
Omit<React.ComponentProps<typeof BaseIntlProvider>, 'locale' | 'messages'> | ||
> = ({ children, ...props }) => { | ||
const [localeLoaded, setLocaleLoaded] = useState(false); | ||
|
||
useEffect(() => { | ||
async function loadLocaleData() { | ||
if (!isLocaleLoaded()) { | ||
await loadLocale(); | ||
} | ||
|
||
setLocaleLoaded(true); | ||
} | ||
void loadLocaleData(); | ||
}, []); | ||
|
||
if (!localeLoaded) return null; | ||
|
||
const { locale, messages } = getLocale(); | ||
|
||
return ( | ||
<BaseIntlProvider | ||
locale={locale} | ||
messages={messages} | ||
onError={onProviderError} | ||
{...props} | ||
> | ||
{children} | ||
</BaseIntlProvider> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Semaphore } from 'async-mutex'; | ||
|
||
import type { LocaleData } from './global_locale'; | ||
import { isLocaleLoaded, setLocale } from './global_locale'; | ||
|
||
const localeLoadingSemaphore = new Semaphore(1); | ||
|
||
export async function loadLocale() { | ||
const locale = document.querySelector<HTMLElement>('html')?.lang || 'en'; | ||
|
||
// We use a Semaphore here so only one thing can try to load the locales at | ||
// the same time. If one tries to do it while its in progress, it will wait | ||
// for the initial load to finish before it is resumed (and will see that locale | ||
// data is already loaded) | ||
await localeLoadingSemaphore.runExclusive(async () => { | ||
// if the locale is already set, then do nothing | ||
if (isLocaleLoaded()) return; | ||
|
||
const localeData = (await import( | ||
/* webpackMode: "lazy" */ | ||
/* webpackChunkName: "locale/[request]" */ | ||
/* webpackInclude: /\.json$/ */ | ||
/* webpackPreload: true */ | ||
`mastodon/locales/${locale}.json` | ||
)) as LocaleData['messages']; | ||
|
||
setLocale({ messages: localeData, locale }); | ||
}); | ||
} |
Oops, something went wrong.