-
-
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
Use I18nextProvider with a components library #788
Comments
My guess it should work as long your component library does not export some bundles that bundle their own react version -> which in any case will break hooks and context But I never had the need for that - as most of the components we have in our component libraries are rather plain...where the text in most cases came via props...like eg. If your components are very complex doing something like: import i18next from 'i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
// import { initReactI18next } from 'react-i18next';
const i18n = i18next.createInstance();
i18n
// load translation using xhr -> see /public/locales
// learn more: https://github.com/i18next/i18next-xhr-backend
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
// .use(initReactI18next) // not use as it's a singleton pattern -> use I18nextProvider
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
});
export default i18n; And wrapping your components in that lib with the I18nextProvider might be an option. |
But you're using i18next
.use(initReactI18next) that should set i18n properly on every usage of react-i18next --> so really seems you bundle two react-i18next |
Thank you for your quick response it's clearly enjoyable ! So with your response I understand that my approach is not correct... All is ok for me --> Issue closed. |
I'm hitting this issue as well. I could open a new issue, but it exactly fits this, so I figured I'd add on to this closed issue and maybe have it reopened. My project topology looks like this; I have a "core" component library (We'll call it So the way it works is that The only way I can think to get around this is to have both libraries do their own I don't want to make the text props as the OP did though, since half the point of using my component library is it provides helpful instruction copy to users on how to complete tasks so you don't have to explain to them how to do something. If you've got any thoughts on this, would love some help! I could also link to the libraries themselves if that would help. |
@wbobeirne hard to tell what happens and why your code break - only thing i can say it's userland: I18nextProvider is a simple react context (zero magic) - all HOCs, render props and hook take i18n instance from the context if available - else the one instance passed using the i18n.use(...) Also if you pass me the links i won't have the time to dig through all your code - just not have the time for this -> if you can make a small codesandbox reproducing. |
Yep, that's totally fair. After doing some inspection of my rollup output, it looks like for some reason I was ending up with two outputs of Less than ideal, but I've had enough rollup configuration hell for one day. But as you said, it looks like this is a configuration issue, not anything inherent to |
If you like this module don’t forget to star this repo. Make a tweet, share the word or have a look at our https://locize.com to support the devs of this project -> there are many ways to help this project 🙏 |
I am facing a somewhat similar problem. I am working on a project that has three react frontends and only for one of them - the
|
@ndbeyer both works...it depends on what you prefer... |
Encountered the exact same problem, but I'm not sure I grasped the behaviour of Say I have the following structure:
The |
own instance of react...very bad idea |
I'm rather new to React Context. Is it better to just keep By "better" - I mean whether the |
you can transpile them...but exclude react from being included...there at anytime should be only one react instance...that's all |
You can use Here is my solution to refactoring the i18nInstance to a separate library (for a lerna monorepo for example) // utils-lib.js lives outside of the front-end/app project
import { initReactI18next } from "react-i18next";
export const i18nInstance = i18n
.use(otherThings)
.use(initReactI18next);
i18nInstance.init(generateI18nInitOptions(), error => {
// handle your errors
}); // App.tsx or App root
import { i18nInstance } from 'utils-lib';
const App = () =>
<I18nextProvider i18n={i18nInstance}>
<MyComp />
</I18nextProvider> import { useTranslation } from 'react-i18next';
const MyComp = () => {
const { t, i18n } = useTranslation();
return <div>{t('tag')}</div>
} |
I faced a similar issue when developing locally. The components library package is bridged in via Webpack aliasing hence it inevitably brought in its own instance of
I think as @jamuhl pointed out, it's crucial to have only one single INITIALIZED instance of |
Following #788 (comment) idea. What we have done is add package.json
webpack.config.js
|
Hello, From this comment
This is exactly what I have in mind, but I didn't manage to get it working. The Is there any detailed example how to perform this task. The documentation about I18nextProvider and how to use it is very limited. @ndbeyer how did you solve your 'problem' regards Frank |
|
@OmerShamay having multiple react instances bundled
|
@frudolph77 It's hard without more context on the implementation you followed. Have you tried #788 (comment)? |
hi, sr for reopening, but i am struggling with a similar problem.
the i18n instance lives in the library and should work shared to the remoteApps. The ContainerApp has the language switch button. so now i tried to use i18nProviders in the remoteApp and the containerApp to pass the instance from the library. i also tried this approach with not luck any idea how i can have this working? the example provided for a library does not work for me, as my apps are not nested in each others folder structure |
@eduardoacskimlinks If I do your suggestion on #788 (comment) my entire app crashes with Basically, my external package has
And my main package has both as deps (not peers). And then, on webpack I am manually adding those to externals:
|
I also had a similar problem, This is how I solved it. In my case, I was using "rollup" to create the react library, and i was using To solve this all I have to do was just provide libraries "react-i18next", "i18next" as external dependency
FYI using: |
Yes, in my case was to fix duplicated instances, as we needed to share instances between packages |
I would like to emphasize that if you are using different versions of the i18n package in your UI and your apps, the shared instance may not work seamlessly. In my case, I had a shared i18n instance, but it failed to detect language changes in the UI. Upon closer inspection, I realized that the package versions were mismatched. Subsequently, I ensured that both the UI and the apps were using the same versions. As a result, the language change is now successfully detected in the UI, and the translations work as intended. |
It's not clear how to get this working for people with UI libs that are "untranspiled" in a monorepo as their own project (nx). We just have ESM components in our ui lib and not bundling them at all. (no rollup etc) Then we add lib to transpile list ...
transpilePackages: [
'@company/react-components',
],
...
Result next-i18next.config.js const { DEFAULT_LOCALE, SUPPORTED_LOCALES } = require('@company/i18n')
const i18nConfig = {
debug: true,
i18n: {
defaultLocale: DEFAULT_LOCALE.code,
locales: SUPPORTED_LOCALES,
},
localePath:
typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/locales',
nsSeparator: false,
reloadOnPrerender: true,
}
module.exports = i18nConfig next.config.js const { i18n } = require('./next-i18next.config')
const nextConfig = {
i18n,
reactStrictMode: false,
compiler: {
styledComponents: true,
},
webpack: (config) => {
// this will override the experiments
config.experiments = { ...config.experiments, topLevelAwait: true }
config.module.rules.push({
test: /\.woff(2)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]-[sha512:hash:base64:7].[ext]',
outputPath: 'static/media/fonts/',
publicPath: '/_next/static/media/fonts/',
},
},
],
})
return config
},
}
module.exports = nextConfig |
Hi, I cannot give a definitive answer but what we learned on our side. The problem boils down to having the same instance for the lib and the rest of the app. My two cents to help you find a solution is to investigate how you import the Failing because there is no direct link to the global translation instance
Working because in runtime will pick the global translation instance
In addition to this specific issue, we encountered another problem related to table cells involving using useTranslation. This prevented us from using the function directly and instead required us to create a contextual object to pass the t function into the component for translation. While I don't recall all the specifics, the function lacked the context at the time of callback when used directly in the cell template, necessitating us to ensure the function was initialised correctly before use. I hope that helps by giving you some options to explore in your project. Please share your findings, as I would like to try |
Thanks @EduardoAC your additional issue seems to be the standard issue for us. |
Hi @iDVB, it's hard to know without the context on how the presentational layer integrates the components together, but it could be well related to the initialisation of the
Finally, regarding your question
Short answer: Yes, depending on the setup. |
Thanks @EduardoAC Doesn't seem like we're doing anything special... so it seems like there is just no way to get external libs to use the same instance in the app? |
Question about react-i18next
Hello,
I have a question about the utilization of I18nextProvider.
Here is my code :
And my component Toto is :
If my Toto is in the same project that my component App it works well.
But if my Toto component is in an external package, the translation doesn't works and I have the following message in the console :
I am currently developing a components library so I use npm link to make the link between my components library and my test project.
So my question is the following : There is a particular way to use I18nextProvider in this specific case ?
Generally, what is the best practice to use react-i18next with a components library ?
Thanks.
Damien
The text was updated successfully, but these errors were encountered: