-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Is it really possible to access t()
from outside a React component the way it's described?
#1757
Comments
a) you can just b) your app is screaming at you because "someting IS WRONG" and enough devs in the past believed they did everything right (believing is not knowing) c) using outside of a component...would say best solution is avoiding it as much as possible @adrai idk...we get this question a lot. Devs reasonable struggle to solve the async nature challenge of i18next if using it outside of components. It is a challenge to solve - my guess it's even unsolvable 100% right without avoiding doing it and only translate in the UI renderer: first idea: use an async function const myTranslatedObject = await i18next.ready(t => ({ foo: t('bar') }));
We would have to do something like: #1058 (comment) import i18n from '../../../i18n';
const data = [
{
code: 'ew.bad-request#storageSettings#storage-full',
message: i18n.t('employee-details.messages.photo-update-error')
},
];
i18next.on('languageChanged', function(lng) {
data.message = i18n.t('employee-details.messages.photo-update-error')
})
export default data;
So I really struggle to suggest a solution to this beside telling don't do it - only use d) codesandbox...might be a deleted codesandbox (might be a result of introduced limit of free sandboxes)...thank you for reporting |
removed the codesandbox link in readme |
a) if there's no need to export it, I guess I can submit a PR simplifying that part of the example config? I mean, it must import the config file otherwise it won't even configure, but there's no need to import b) yep, I just mentioned the screaming error as a reference to what message I was talking about :) not complaing about it, I thought it would be clear from the grimacing emoji. Sorry for the misunderstanding on the joke. c) And yep, from my new understanding it looks impossible to use i18next outside of React if you don't have global await enabled, or all your use-cases are fine with promises. The biggest side effect of doing it that way, and that might take a while to notice, is that it won't update with language changes, given that's tied to events that are not mentioned in the React documentation (what makes sense, and what a React dev will mostly be reading, besides the raw i18next config). Overall, I would indeed suggest simply removing that info box from the docs, or replacing it with a warning of the side-effects of doing it that way. It's not just a problem with "simply importing", it is that importing and using that way will cause subtle and unexpected errors... Unless you use extra stuff that increase the time Bottom-line: people think they're doing everything right because the docs tell them to do something that won't really work as it seems so. d) sad on the codesandbox. It was really useful! And thanks for the fast response! |
a) it's the way we use to do it - as it's a matter of preference - neither option seems to be preferable I believe it should be simple enough to understand that: // File A
import i18n from 'i18next';
export default i18n;
// File B
import i18n1 from 'i18next';
import i18n2 from '.i18n';
i18n1 === i18n2
Sure it is an instance https://github.com/i18next/i18next/blob/master/src/i18next.js#L631 we decided 12 years ago that most devs only will need one instance -> so per default exported an instance instead of a function to create an instance b) No worry...did only want to make a point the console.log of i18next is doing what it is doing c) Agree...best to update that info box and eventually add an extra section beside the d) might come back if we find a codesandbox that is the pure initial sample (wanted to remove that deadlink and had no time to search) |
Just had your last comment in the email...and was thinking about the code posted there... let TAP = 'tap'
let CLICK = 'click'
i18next.on('languageChanged', () => {
TAP = i18next.t('tap')
CLICK = i18next.t('click')
})
//[...]
export function clickOrTap() {
return IS_MOBILE? TAP : CLICK
} First thought we could provide some helper like Then I realised - that is more or less what So your sample could just be: export function clickOrTap() {
return IS_MOBILE? i18next.t('tap') : i18next.t('click')
} I mean we do hundreds of calls to |
The way we are doing it over at Electricity Maps is by passing the Like this: function thatNeedT(t) {
return t('some.translation-string')
}
function ReactComponent(){
const {t} = useTranslation()
const translatedString = thatNeedT(t);
return (
<div>
{translatedString}
</div>
)
} Not sure if that is of any help here but it seems like a simple solution to, and if you have any feedback why we should not use it like this I'd be very interested in that as well. |
Documentation issue
I noticed a couple of issues with the config section of the Step-by-step guide:
i18n
which was got "raw" fromi18next
? Wouldn't it be simpler to justimport i18n from 'i18next'
everywhere you want that?i18next
and t()-away. But... that doesn't work that easy, giveni18next.init()
is async, right? What should be the correct way to do it outside React components - e.g. an API model class, or maybe a Redux action, in the (unlikely but possible) scenario of a race condition between the translation andinit()
resolving? Or, maybe, even using it raw like in the exact example (which is precisely what I do in a lot of places, as initially I thought it was fine).Motivation
Simply put, I wrote something stupid in my codebase and only realized it caused a mysterious bug quite later. Then I postponed it for, IDK, two years?? And now I'm looking into it.
I even tried creating a codesandbox (forking from an ancient one I had) to display the bug on i18next, but then, with the simpler codebase, I realized the bug was typed by my own keyboard: even IF there wasn't a race condition between
i18next.init()
async nature and my calls, further language changes would never change the translated text 🤡And here I am.
To be more specific about my main "problem", before I i18next'ed everything, there were some components with auxiliary text placed outside the component - e.g. tab titles used in actual tabs and a shortcuts sidebar. I'll try to move them all into the component, and maybe "lazify" it with a function call that can be awaited, somehow. I mean, there's no way to even fire a suspense event from outside a component, right? hahah
In case you want to see the stupid result of my codesandbox which cannot translate the title once the language changes, have a free laugh here. But it doesn't seem to cause the screaming warning I mentioned, probably because it doesn't
use(resourcesToBackend([...]))
, as in my scenario, soinit()
always wins the race.The text was updated successfully, but these errors were encountered: