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

useTranslation - override language #1637

Closed
joekur opened this issue May 18, 2023 · 10 comments
Closed

useTranslation - override language #1637

joekur opened this issue May 18, 2023 · 10 comments

Comments

@joekur
Copy link

joekur commented May 18, 2023

🚀 Feature Proposal

Allow useTranslation to take an optional lng prop to override the language passed to getFixedT (link).

Motivation

In a server-side rendering (SSR) environment, there is no single language, since a single server could handle different requests in different languages. This requires you to manage multiple i18n instances, one per language, in order for a useTranslation somewhere down the react tree to work. While something like next-i18next may handle this for you, we have use-cases for shared component libraries that may execute in both SSR and client-side environments, which requires to hand-roll some code for synchronizing language between app and library, and initializing an i18n instance (or multiple) for the component library to use (with its own translation files).

To correctly support SSR in the component library, this seems to require creating an i18n instance per supported language, and initializing each of them with the translation files, so that the correct one for the given request's language can be passed down via context. However if we could instead just pass down, say, the current language via context, we could have just a single i18n instance, and we could wrap useTranslation in a hook that passes that language to it.

Example

Simple example:

const { t } = useTranslation('ns1', { lng: 'es' });

How this might be used in a component lib (let's keep it simple and say our component takes a lng prop itself):

const i18n = i18next.createInstance(...);

const MySharedComponent = ({ lng }) => {
  cons { t } = useTranslation('ns1', { i18n, lng });
  return t('foo');
};
@adrai
Copy link
Member

adrai commented May 18, 2023

workaround:

const { i18n } = useTranslation('ns1');
const t = i18n.getFixedT('en');

Does this work for you?
fyi: that would return the appropriate t function, but the translation resources needs to be loaded before... maybe use the preload option in the init call.

if that's ok, we could adapt the useTranslation like that:
image

@joekur
Copy link
Author

joekur commented May 18, 2023

I had actually thought about that - my uncertainty was around if that t would inherit the other properties that are being passed to the getFixedT inside useTranslation - namely the namespaces and keyPrefix as shown in your code screenshot?

@joekur
Copy link
Author

joekur commented May 18, 2023

And yeah as far as we're currently concerned, we would load translation files upfront - we wouldn't be using any other special backends for these component libraries.

@adrai
Copy link
Member

adrai commented May 18, 2023

ok, try v12.3.0

this should work:

const i18n = i18next.createInstance(...);

const MySharedComponent = ({ lng }) => {
  cons { t } = useTranslation('ns1', { i18n, lng });
  return t('foo');
};

@jamuhl
Copy link
Member

jamuhl commented May 18, 2023

not a fan of that change...might work for this scenario...but all others (using this not serverside with backends) will complain:

cons { t } = useTranslation('ns1', { lng });

// -> i get missings....why useTranslation does not assert lng get loaded?!?

adrai added a commit that referenced this issue May 18, 2023
@adrai
Copy link
Member

adrai commented May 18, 2023

not a fan of that change...might work for this scenario...but all others (using this not serverside with backends) will complain:

cons { t } = useTranslation('ns1', { lng });

// -> i get missings....why useTranslation does not assert lng get loaded?!?

react-i18next v12.3.1 + i18next v22.5.0 should also address that

@adrai adrai closed this as completed May 18, 2023
@Kamahl19
Copy link

@adrai the result of these changes is that the resolvedLanguage is now string | undefined instead of always string

const { i18n } = useTranslation();
i18n.resolvedLanguage // string | undefined

Is this intentional change? I thought resolvedLanguage is always supposed to be resolved

@adrai
Copy link
Member

adrai commented May 19, 2023

There is no guarantee resolvedLanguage is always defined, but can you please provide a minimal reproducible example showing resolvedLanguage to be undefined? Just tested in a normal client side environment, and at least there it seems to be defined.

@adrai
Copy link
Member

adrai commented May 19, 2023

Or do you mean this? i18next/i18next#1960
for 'cimode' or 'dev' resolvedLanguage is not "set"

@Kamahl19
Copy link

Yes, sorry about that

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

No branches or pull requests

4 participants