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

Provide i18n instance even when serverSideTranslations is not used #1049

Closed
jvcmanke opened this issue Mar 10, 2021 · 20 comments
Closed

Provide i18n instance even when serverSideTranslations is not used #1049

jvcmanke opened this issue Mar 10, 2021 · 20 comments

Comments

@jvcmanke
Copy link

Is your feature request related to a problem? Please describe.

When using getStaticPaths with fallback: true the fallback page does not run getStaticProps however I still want to render the translations for my _app or other components like loading spinner test using my i18next configuration.

I can do it using i18next-http-backend as I do with a few parts of my UI, however in this case the configuration is not loaded and i get the warning:

react-i18next:: You will need to pass in an i18next instance by unsing initReactI18next

Because next-i18next only adds the I18NextProvider if _nextI18Next is present in pageProps.

Describe the solution you'd like

Always wrap with the I18NextProvider just don't provide any server side translations.

Describe alternatives you've considered

I could wrap with my own instance but I don't see a reason next-i18next should't always provide the i18n instance.

Additional context

This would also mean that dynamic routes that don't want to use getStaticProps/getStaticPaths could still utilize the same i18n instance/configuration to fetch their translations client-side.

@jvcmanke
Copy link
Author

P.S.: I can come up with a PR if you agree.

@isaachinman
Copy link
Contributor

I'm not sure i18next-http-backend is the best solution for this.

Relevant documentation for fallback pages can be found here. In general, I wonder how the Vercel team expects users to translate fallback pages, or if this use case was overlooked entirely.

I would start by enquiring on the NextJs repo, rather than fetching translations on the client side, via HTTP.

@jvcmanke
Copy link
Author

Right, the fallback was just an example why it would be useful to have the i18n instance available at all times.

I don't see any reason where not having it there is better that having it there, while having it provided even without translations allows reuse of the same configuration everywhere.

I would start by enquiring on the NextJs repo, rather than fetching translations on the client side, via HTTP.

Translations through HTTP is necessary in certain situations. For example, I don't necessarily want to preload translations for parts of the app that my users might rarely access, dynamic options with translations for select components and authentication locked translations to name a few.

@isaachinman
Copy link
Contributor

Feel free to work on a PR. Just bear in mind it will need test coverage. Thanks!

@skrivanos
Copy link
Contributor

skrivanos commented Mar 14, 2021

+1. I'd like this for cases with dynamic routes where using getStaticPaths just isn't feasible and getServerSideProps causes unnecessary latency. For instance if you have a user specific dashboard (located at like /projects/[id]) where all data is loaded on the client.

There's one better solution and that is for Next.js to make it possible to use getStaticProps without getStaticPaths for dynamic routes but I don't see that happening anytime soon: vercel/next.js#14200

Edit: #993 seems like a dupe, but was closed.

@njarraud
Copy link

njarraud commented Mar 18, 2021

What is the current way of doing for dynamic routes that do not require getStaticProps or getServerSideProps other than for translations?

Nextjs requires to have getStaticPaths if getStaticProps is used for dynamic routes. I could use this solution with fallback: true but considering that serverSideTranslations is the only props in getStaticProps, it will build exactly the same file over and over again and I will end up with 1000s of identical pages. Am I missing something?

@dcodrin
Copy link

dcodrin commented Mar 18, 2021

Fetching translations client side is a huge requirement for us since we load components dynamically and they define the namespaces required. It was recommended to use i18next-http-middleware #1004 (comment) to achieve this however i was not able to make it work by simply including it in config.use. @isaachinman Would you be able to provide more details about how this needs to be wired up? Much appreciated!

@jvcmanke
Copy link
Author

@skrivanos and @njarraud There is currently not a possible solution for this, I didn't have time to work on a PR yet, however it probably would be necessary to use the overrideConfig parameter in appWithTranslation.

@dcodus You actually have to use i18next-http-backend not the middlware, you have to pass the config to appWithTranslation as overrideConfig, also don't forget to set partialBundledLanguages to true, to allow both server and client site translations, and to check typeof window !== "undefined" before including the backend to only include it on the client side.

@dcodrin
Copy link

dcodrin commented Mar 19, 2021

@jvcmanke Thank you! Everything works as expected now!

@saqbach
Copy link

saqbach commented Mar 20, 2021

Quick question, based on reading these issues + the documentation, I have the following set up. I feel like I'm close but I keep getting a react-i18next:: You will need to pass in an i18next instance by using initReactI18next -- am I missing something to get this working?

// next-i18next.config.js

const i18nextHttpBackend = require('i18next-http-backend').default;

module.exports = {
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'fr', 'es']
  },
  partialBundledLanguages: true,
  use: process.browser ? [i18nextHttpBackend] : []
};
// app.tsx 

import { appWithTranslation } from 'next-i18next';
const nextI18NextConfig = require('../../next-i18next.config');

export default appWithTranslation(App, nextI18NextConfig);
// index.tsx 

import { useTranslation } from 'next-i18next';

const { t } = useTranslation('homepage');

<h1>
  {t('heroTitle')}
</h1>

@isaachinman
Copy link
Contributor

@austinhale You are missing serverSideTranslations in your index.tsx file. The serverSideTranslations is the key function which reads translation data from the filesystem (or remote API, if specified), and passes it into your NextJs app as props.

@saqbach
Copy link

saqbach commented Mar 20, 2021

@isaachinman I’m new to the library so I’m still getting up to speed. Are you saying I should include the serverSideTranslations function and depending on the process.browser ternary, that will dictate whether the transaction actually occurs server side vs client side http?

@isaachinman
Copy link
Contributor

@austinhale Yes, if you want to use i18next-http-backend (not sure why you do), then that flow would make sense.

@AhsanNissar
Copy link

@isaachinman What if I am redirecting to another component from server.js or index.js file then how can I receive props in that component provided that I amj not passing any props on redirecting to the component but just using simple resirectTo: '/specificComponent'. How can I ensure that useTranslation can be utilized in the redirected component and it must be initialized with the translations that are in locales

@annbeemsterboer
Copy link

annbeemsterboer commented Apr 2, 2021

@austinhale You are missing serverSideTranslations in your index.tsx file. The serverSideTranslations is the key function which reads translation data from the filesystem (or remote API, if specified), and passes it into your NextJs app as props.

@isaachinman Hi, I have been searching hopelessly (in all closed/old issues) for any example of fetching translations from a remote API (server-side); I know it's not really to do with this lib but just documentation for i18next doesn't suffice either. Could you please point me in the right direction? You mention here it should be possible.

My current setup is as follows:

next-i18next.config.js
`const i18nextHttpBackend = require("i18next-http-backend").default;

module.exports = {
i18n: {
defaultLocale: "en",
locales: ["en", "nl"],
},
use: process.browser ? [i18nextHttpBackend] : [],
backend: {
loadPath:
// this is a mock for now
"https://virtserver.swaggerhub.com/translations/public/{{lng}}/{{ns}}",
},
serializeConfig: false,
};`

In _app I manually pass the config into appWithTranslation as described in the README.

From the docs for i18next-http-backend here it is not clear to me what options I should be passing in to load my translations. Could you please explain how this is compatible with serverSideTranslations ? Any tips would be highly appreciated.

I'd be more than happy to add to the ReadMe afterwards as I can image others struggle with this and have in the past (even though the setup of next-i18next was way different then.

@isaachinman
Copy link
Contributor

Hey @annbeemsterboer — I'm out of office until next week, but I believe @adrai has an example of using Locize as a backend?

@adrai
Copy link
Member

adrai commented Apr 2, 2021

@annbeemsterboer This next.js example with i18next-locize-backend may help: https://github.com/locize/next-i18next-locize
If you have i18next-http-backend, just replace i18next-locize-backend with i18next-http-backend and define your specific loadPath.

@annbeemsterboer
Copy link

@adrai thanks for the example! I keep getting the error TypeError: Cannot read property 'type' of undefined, which means the instance of class I18NextHttpBackend is undefined here.

module.exports = { i18n: { defaultLocale: "en", locales: ["en", "nl"], }, backend: { loadPath: "https://virtserver.swaggerhub.com/translations/public/{{lng}}/{{ns}}", crossDomain: true, }, use: [require("i18next-http-backend").default], ns: ["common", "getstarted"], debug: true, serializeConfig: false, };

my package.json contains

"next-i18next": "8.1.3", "next": "10.0.9", "i18next-http-backend": "^1.2.1"

Do you have any ideas?

@adrai
Copy link
Member

adrai commented Apr 7, 2021

instead of require("i18next-http-backend").default write require("i18next-http-backend/cjs")

@annbeemsterboer
Copy link

Thanks a million!

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

Successfully merging a pull request may close this issue.

9 participants