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

Non-nullable i18n instance #2079

Closed
MrDockal opened this issue Jan 18, 2023 · 3 comments
Closed

Non-nullable i18n instance #2079

MrDockal opened this issue Jan 18, 2023 · 3 comments
Labels

Comments

@MrDockal
Copy link

🚀 Feature Proposal

Add the ability to initialize the i18n instance manually. So you can easily call any method from i18n in the getServerSideProps lifecycle method.

Motivation

I have a use case where I want to dynamically add resource bundles by calling i18n.addResourceBundle method. However, on the initial render, the i18n instance isn't defined yet.

The example below demonstrates the current limitation because i18n might be null

export const getServerSideProps = async context => {
  i18n?.addResourceBundle('en', 'extras', { key: 'value' });
  return {
    props: {
      ...(await serverSideTranslations('en', ['common', 'extras'])), // extras weren't loaded when i18 is null
    },
  };
};

From your code, I can see i18n gets defined twice. First by appWithTranslation and createClient/node.ts

Example

This is my workaround:

// getI18nClient.ts
import { UserConfig } from 'next-i18next';
import { createConfig } from 'next-i18next/dist/commonjs/config/createConfig';
import createClient from 'next-i18next/dist/commonjs/createClient';
import { i18n as singletonI18n } from 'next-i18next';
import nextI18NextConfig from '../next-i18next.config';

// helper function to get around the nullable i18n limitation
export const getI18nClient = async (
  lng: string,
  userConfig: UserConfig = nextI18NextConfig,
): Promise<typeof singletonI18n> => {
  if (singletonI18n) {
    return singletonI18n;
  } else {
    const config = createConfig({
      ...userConfig,
      lng,
    });
    const { i18n, initPromise } = createClient({ ...config, lng });
    await initPromise;
    return i18n;
  }
};
// pages/index.tsx
export const getServerSideProps = async context => {
  const i18n = await getI18nClient(context.locale);
  i18n.addResourceBundle('en', 'extras', { key: 'value' });
  return {
    props: {
      ...(await serverSideTranslations('en', ['common', 'extras'])),
    },
  };
};

Another possible solution might be creating a wrapper around next.config.js file. Such as https://github.com/aralroca/next-translate#add-next-translate-plugin.

I'm happy to hear what you think of it. Cheers

@adrai
Copy link
Member

adrai commented Jan 18, 2023

The problem is, the i18next instance is not always the same and the initialization is asynchronous... and serverSideTranslations makes sure the correct language and namespaces are loaded...

Maybe alternatively there is the possibility to inject the onPreInitI18next option? => https://github.com/i18next/next-i18next/blob/master/src/createClient/node.ts#L37
https://github.com/i18next/next-i18next#options

I don't know if it makes sense to have a helper function (like your workaround) to be exposed as official api...

@MrDockal
Copy link
Author

Sure, the onPreInitI18next is a good place to do some of the things. However, you will lose the request context. This implies you can't do anything dynamic with the i18n instance based on the request parameters for example.

But I understand this might be quite an unusual use case.

@stale
Copy link

stale bot commented Mar 18, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants