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

SSR / Next.js example #6

Closed
willross opened this issue May 9, 2020 · 6 comments · Fixed by #7
Closed

SSR / Next.js example #6

willross opened this issue May 9, 2020 · 6 comments · Fixed by #7

Comments

@willross
Copy link
Contributor

willross commented May 9, 2020

Hi there!

What you are doing is amazing and you are solving a very big problem for apps that have a lot of strings. I'm really glad this exists now!

However, from the current examples it's not immediately obvious how this would work with isomorphic apps, using Next.js for example.

So if you could provide some pointers or maybe create a Next.js example, you'd save someone's life :)

Thanks!

@hjylewis
Copy link
Owner

hjylewis commented May 9, 2020

Thanks for the idea! You're right, a Next.js example would be helpful.

I'm not super familiar with nextjs but I'll give it a shot. In the meantime, if you get an example working can you make a pull request! :)

Let me know if you have any other questions getting set up

@hjylewis
Copy link
Owner

hjylewis commented May 9, 2020

@willross
Copy link
Contributor Author

willross commented May 10, 2020

@hjylewis, thanks for the quick response!

Your Next.js example has some issues from the Next.js project structure logic point of view, but they are easily fixed.

The main problem is that en locale is hardcoded in the .babelrc, therefore the locale doesn't change even when you provide a different locale prop to IntlProvider.

I see that in your react-intl-example you are exporting a dedicated webpack config for each locale to solve that. To be honest, I don't really understand your approach to configuring webpack like that, but I'm not very good with webpack/babel magic.

So far I'm unable to successfully reproduce this approach in next.config.js, which is where webpack is configured in Next. I'm not sure if it even is possible to export multiple webpack configs in Next.

Here's my repo, hope you'll have an opportunity to take a look: https://github.com/willross/nextjs-example. In it's current state it's working with the hardcoded locale, but doesn't allow changing languages.

@willross
Copy link
Contributor Author

Apparently, currently you can't return an array of webpack configs in Next.js (vercel/next.js#1306). Do you think there's a way to achieve multi-locale functionality some other way?

@hjylewis
Copy link
Owner

Hmm, that's what I was worried about.

Your Next.js example has some issues from the Next.js project structure logic point of view, but they are easily fixed.

PRs are welcome :)

Apparently, currently you can't return an array of webpack configs in Next.js (vercel/next.js#1306)

Yeah, that's how the other examples work. You are basically building a version of your application for each locale.

Do you think there's a way to achieve multi-locale functionality some other way?

You could set it up so that all locales are loaded. This would be suboptimal since it would increase bundle size but works with Next.js. It would also have the added benefit of allowing locale switching without a refresh

To get that to work, your getMessage function should ignore the locale argument and return an object containing the message in every locale (instead of just a string). Then you'll want to modify your addMessages function to accept these objects.

// getMessage

const fs = require("fs");
const path = require("path");

module.exports = function getMessage(key, locale, defaultMessage) {
  const en = JSON.parse(fs.readFileSync(
    path.resolve(process.cwd(), `./i18n/messages/en.json`)
  ));
  const es = JSON.parse(fs.readFileSync(
    path.resolve(process.cwd(), `./i18n/messages/es.json`)
  ));

  return {
    en: en[key] || defaultMessage,
    es: es[key] || defaultMessage,
  }
};
// addMessages
const messages = {
  en: {},
  es: {},
};

export function getMessages(locale) {
  return messages[locale];
}

export function addMessages(idAndMessages) {
  idAndMessages.forEach(([id, messageObject]) => {
    Object.keys(messageObject).forEach(locale => {
      messages[locale][id] = messageObject[locale];
    });
  });
}
// App.js

...

<IntlProvider locale={locale} messages={getMessages(locale)}/>

...

Unfortunately, since Nextjs doesn't make it easy to build multiple outputs there isn't a way to build per-locale bundles without ditching Nextjs. That said, you should be able to SSR per-locale bundles, just not with Nextjs.

Does that help? Let me know if you have any questions

@willross
Copy link
Contributor Author

Yup, this approach works!

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.

2 participants