Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy load language files to minimize download size #57

Open
jbaldivieso opened this issue Jun 5, 2024 · 2 comments
Open

Lazy load language files to minimize download size #57

jbaldivieso opened this issue Jun 5, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@jbaldivieso
Copy link

It appears that, despite having specified splitJson: true in the config, ultimately all translations get minified into the same file for my app. It would be ideal to lazily load languages only upon their activation. Once you have multiple languages with nontrivial amounts of content, the file size really starts to add up, with no benefit to your average single-language user.

@FlorianWerndl
Copy link

@jbaldivieso it may not fit to your needs/setup but I implemented it myself.
I have a nuxt application where gettext is initialized within a plugin and if I change the language the whole application is reloaded (I guess this is needed for this approach)

// plugins/translate.ts
await gettext(nuxtApp.$i18n.locale.value)

// gettext.js
...
export default async function gettext(lang) {
  const languageFile = await import(`../locales/dist/${lang}.json`);
  return createGettext({
    availableLanguages,
    silent: true,
    defaultLanguage: lang,
    translations: languageFile,
    provideDirective: false,
    provideComponent: false,
  });
}

@jbaldivieso
Copy link
Author

@FlorianWerndl–Thank you very much for sharing this! I took a closer look at the source code, and it appears that createGettext stores translations as a reactive variable, complete with a getter and setter. So one is able to hot-swap the translation file on the fly (dynamically importing it as you suggest) without having to reload the app.

Since this doesn't seem like an edge case (right? the average user only wants an app/website in a single language), I think this process could be smoother/better documented.

Here is what worked for me:

const availableLanguages = {
  en: "English",
  es: "Español",
  fr: "Francais",
}
const translations = {
  // This is fake; upon initial load, we call `updateLanguage` below to import
  // a *real* translation file. This prevents us from downloading the
  // English translation if that's not our browser's preferred language.
  en: { en: { stub: "stub" } }
}

export const gettext = createGettext({
  defaultLanguage: "en",
  availableLanguages,
  translations,
})

export async function updateLanguage(lang: string) {
  // Guard here against possible crazy imports
  if (lang in availableLanguages) {
    const trans = await import(`@/locales/translations/${lang}.json`)
    gettext.translations = trans
    gettext.current = lang
  }
}

And then when the app mounts, I call logic that looks up/infers the language (cookie, local storage, request headers) and calls updateLanguage asynchronously to set translations to a meaningful translation file. (In my case, I'm using code splitting with manually chunks in rollup, so I have to make sure that each translation file is represented there in a separate chunk.)

@lzurbriggen lzurbriggen added the enhancement New feature or request label Jun 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants