-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pre-fetch Locize API and make all translations available as static data
- Loading branch information
1 parent
604c57f
commit aad39ca
Showing
6 changed files
with
113 additions
and
7 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import fetchLocizeTranslations from '@/modules/core/i18n/fetchLocizeTranslations'; | ||
import preval from 'next-plugin-preval'; | ||
|
||
/** | ||
* Pre-fetches the Locize translations for all languages and stores the result in an cached internal JSON file. | ||
* Overall, this approach allows us to have some static app-wide data that will never update, and have real-time data wherever we want. | ||
* | ||
* This is very useful to avoid fetching the same data for each page during the build step. | ||
* By default, Next.js would call the Locize API once per page built. | ||
* This was a huge pain for many reasons, because our app uses mostly static pages and we don't want those static pages to be updated. | ||
* | ||
* Also, even considering built time only, it was very inefficient, because Next was triggering too many API calls: | ||
* - More than 40 fetch attempts (40+ demo pages) | ||
* - Our in-memory cache was helping but wouldn't completely conceal the over-fetching caused by Next.js | ||
* - Locize API has on-demand pricing, each call costs us money | ||
* | ||
* The shared/static dataset is accessible to: | ||
* - All components | ||
* - All pages (both getStaticProps and getStaticPaths, and even in getServerSideProps is you wish to!) | ||
* - All API endpoints | ||
* | ||
* XXX The data are therefore STALE, they're not fetched in real-time. | ||
* They won't update (the app won't display up-to-date data until the next deployment, for static pages). | ||
* | ||
* @example const allStaticLocizeTranslations = await getAllStaticLocizeTranslations(); | ||
* | ||
* @see https://github.com/ricokahler/next-plugin-preval | ||
*/ | ||
export const locizeTranslations = preval(fetchLocizeTranslations()); | ||
|
||
export default locizeTranslations; |
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,42 @@ | ||
import { supportedLocales } from '@/modules/core/i18n/i18nConfig'; | ||
import { | ||
fetchTranslations, | ||
I18nextResources, | ||
} from '@/modules/core/i18n/i18nextLocize'; | ||
import { I18nLocale } from '@/modules/core/i18n/types/I18nLocale'; | ||
import { createLogger } from '@/modules/core/logging/logger'; | ||
|
||
const fileLabel = 'modules/core/i18n/fetchLocizeTranslations'; | ||
const logger = createLogger({ | ||
fileLabel, | ||
}); | ||
|
||
export type LocizeTranslationByLang = { | ||
[lang: string]: I18nextResources; | ||
} | ||
|
||
/** | ||
* Fetches the Locize API. | ||
* Invoked by fetchLocizeTranslations.preval.preval.ts file at build time (during Webpack bundling). | ||
* | ||
* XXX Must be a single export file otherwise it can cause issues - See https://github.com/ricokahler/next-plugin-preval/issues/19#issuecomment-848799473 | ||
* | ||
* XXX We opinionately decided to use the "lang" (e.g: 'en') as Locize index, but it could also be the "name" (e.g: 'en-US'), it depends on your business requirements! | ||
* (lang is simpler) | ||
*/ | ||
export const fetchLocizeTranslations = async (): Promise<LocizeTranslationByLang> => { | ||
const translationsByLocale: LocizeTranslationByLang = {}; | ||
const promises: Promise<any>[] = []; | ||
|
||
supportedLocales.map((supportedLocale: I18nLocale) => { | ||
promises.push(fetchTranslations(supportedLocale?.lang)); | ||
}); | ||
|
||
// Run all promises in parallel and compute results into the dataset | ||
const results: I18nextResources[] = await Promise.all(promises); | ||
results.map((i18nextResources: I18nextResources, index) => translationsByLocale[supportedLocales[index]?.lang] = i18nextResources); | ||
|
||
return translationsByLocale; | ||
}; | ||
|
||
export default fetchLocizeTranslations; |
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,30 @@ | ||
import { LocizeTranslationByLang } from '@/modules/core/i18n/fetchLocizeTranslations'; | ||
import { I18nextResources } from '@/modules/core/i18n/i18nextLocize'; | ||
import { createLogger } from '@/modules/core/logging/logger'; | ||
|
||
const fileLabel = 'modules/core/i18n/getLocizeTranslations'; | ||
const logger = createLogger({ | ||
fileLabel, | ||
}); | ||
|
||
/** | ||
* Returns all translations (indexed by language), based on the app-wide static/shared/stale data fetched at build time. | ||
* | ||
* @example const allStaticLocizeTranslations = await getAllStaticLocizeTranslations(); | ||
*/ | ||
export const getAllStaticLocizeTranslations = async (): Promise<LocizeTranslationByLang> => { | ||
return (await import('@/modules/core/i18n/fetchLocizeTranslations.preval')) as unknown as LocizeTranslationByLang; | ||
}; | ||
|
||
/** | ||
* Returns all translations for one language, based on the app-wide static/shared/stale data fetched at build time. | ||
* | ||
* @example const i18nTranslations: I18nextResources = await getStaticLocizeTranslations(lang); | ||
* | ||
* @param lang | ||
*/ | ||
export const getStaticLocizeTranslations = async (lang: string): Promise<I18nextResources> => { | ||
const allStaticLocizeTranslations = await getAllStaticLocizeTranslations(); | ||
|
||
return allStaticLocizeTranslations?.[lang]; | ||
}; |
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