Open olafurns7 opened 1 year ago
I tried to do the same concept and I thought it might work.
so I downloaded my translations from phrase app and cached them using next cache
so far everything was ok, until I got an error which seems the createI18nServer is expecting imports and does not accept an object
so far my implementation was like this
const locales = await prepareLocales()
export const { getI18n, getScopedI18n, getStaticParams } = createI18nServer(locales)
where locales variable would be
{
en: {
key:'translation'
},
de: {
key:'translation'
},
}
createI18nServer
/ createI18nClient
accepts an object where the values must be a function returning a promise of a locale object, because it's lazy-loaded on-demand. If you already have the values, you should easily be able to use the correct signature.
@QuiiBz Am I right in saying the idea behind the lib is to use static translation files right?
Using an API approach to load the translation data is not in scope.
createGetI18n
for example when it does return createT({ localeContent: flattenLocale((await locales[locale]()).default), ...
Is expecting the (await locales[]()).default
to be a file that is why it has .default
in there right?
If we are to switch the locale function from import to a fetch for example that returns a Promise that resolves to a JSON object will not work.
I guess we can hack around it and provide a default
namespace key for the entire thing and that will solve the issue.
But I wonder apart from TS safety is there any other reason why you would want local translations as a default?
In my use case the translations come from an endpoint generated by a CMS where you would want them to be able to be changed on the fly without the need of a build step.
Is expecting the (await locales[]()).default to be a file that is why it has .default in there right?
The file is a JavaScript module that has a default export (specifically the export default
, https://next-international.vercel.app/docs/writing-locales), so to get it after the import
we have to use the default
field. That will work the same if you have JSON files.
Thank you. Yeah I got that, perhaps my question was to complicated.
The point I was making is that the createT
function handles the way the data is loaded. And that forces you to use a JS module. That logic can be moved into user space and if we need to load a JS module we do the same, if we need to use fetch('htttp://some-translation-endpoint') we could do the same.
So this:
export const { getI18n, getScopedI18n, getStaticParams } = createI18nServer({
en: () => import('./en'),
fr: () => import('./fr')
})
could become this:
export const { getI18n, getScopedI18n, getStaticParams } = createI18nServer({
en: (await import(`./en`)).default,
fr: (await import(`./fr`)).default
})
Doing so enables us to use fetch() as an alternative to get translations from other sources behind a http call. Because the import is not handled in the core lib.
Hope it make more sense now and I'm guessing that was a conscious choice to only support JS modules for import.
You could totally do a fetch
instead of an import
- it just needs to return an object with a default
key. The issue with your 2nd code example is that we no longer have callbacks, which means all the locales aren't lazy-loaded when needed. This is particularly crucial for client-side rendering.
i have other question about dynamic translations like
const translatedCountryList = countryList.map((country) => {
return {
value: country?.value,
text: t(`countries.${country.text}`),
}
})
where it works but gives error of no matching overload or Expected 2 arguments, but got 1 in this case. Is there a way to fix that?
this seems to fix it, not sure if safe but works and no error:
const translatedCountryList = countryList.map((country) => {
const text: any = `countries.${country.text}`
return {
value: country?.value,
text: t(text, {}),
}
})
@QuiiBz can you provide an example of doing a fetch instead of an import ?
Why
Large commercial websites that serve visitors of multiple nationalities / locales can have a lot of translation strings.
In our case when these strings are created, they are done so in one locale in our CMS, then they are sent to a third party translation provider that in some cases takes time to return the localised versions of the strings.
I haven't tried how
next-international
handles what I'm suggesting belowConcept
Enable the functionality of dynamically updating the local
key:value
files, and reloading the translation provider so it has everything available.The functionality I'm looking for is basically somehow being able to force a reload of assets. I don't think logic that does the fetching and writing of the updated files is something that belongs within this library.
What we have done before, with other i18n libraries is to iterate through the set locales, fetch data from a CMS, and then map the values out and write to a
.json
. Then trigger a reload of the 18n library so it repopulates the strings.