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

Polish i18n support #35

Closed
nicholaschiang opened this issue May 2, 2020 · 6 comments
Closed

Polish i18n support #35

nicholaschiang opened this issue May 2, 2020 · 6 comments
Assignees
Labels
p1 Urgent tasks type:bug Something isn't working in a story

Comments

@nicholaschiang
Copy link
Member

Goals

We want to be as global as possible which means supporting as many locales as we can find translators for. We need to de-couple the the translation text from our code (i.e. static content should be moved away from the codebase).

Options

I've researched some options for different i18n libraries but they all seem to have their own setbacks:

  • next-i18next
    • This seems like a super easy way to build i18n support because it was made with Next.js in mind.
    • This however, requires us to use a custom server.js which we do not want to do (we won't be able to statically pre-render anything).
  • react-intl
    • Recommended solution by this blog post and this Stack Overflow answer.
    • Seems like it has everything we'll need (but it'll require a tad bit more work to setup than next-i18next).
    • Note that this is the solution that I'm currently working with and I'm going to continue using it until I come against any blockers.
  • i18next
    • Appears to take a lot of configuration work and is more general than what we need (we want a React-specific solution ideally).
  • react-i18next
    • Also appears to take more configuration work than we want to deal with right now (although it does seem to be widely used).

For now, I'm going to keep using react-intl until I come up against any blocking issues. Note that react-intl also has a Slack workspace which will be good for support concerns, etc.

@nicholaschiang nicholaschiang added category:back-end p1 Urgent tasks type:bug Something isn't working in a story labels May 2, 2020
@nicholaschiang nicholaschiang added this to To Do in Tutorbook Roadmap via automation May 2, 2020
@nicholaschiang nicholaschiang moved this from To Do to Doing in Tutorbook Roadmap May 2, 2020
@nicholaschiang
Copy link
Member Author

This should also help with #31 once we get everything polished out.

@nicholaschiang nicholaschiang self-assigned this May 2, 2020
@nicholaschiang
Copy link
Member Author

nicholaschiang commented May 4, 2020

It looks like there's a lot of discussion for how to best implement i18n with Next.js (it's something that the creators of the framework have yet to describe official best practices for):

  • This discussion seems to have many possible ways to do it.
  • The Next.js team introduced redirects and rewrites in this RFC (Request for Comment) which seems to help a bit with i18n problems.
    • We'll want to use their redirects to redirect the user to their locale specific page (e.g. /search should redirect to /en/search or /fr/search based off the user's HTTP request Accept-Language headers).
    • Right now, that involves figuring out some RegExp to send all non-localized pages to an api/redirect endpoint that redirects based on that Accept-Language request header. For example:
      • /search should redirect to /api/redirect which should redirect to /en/search or /fr/search.
      • /end should also redirect to /api/redirect.
      • /en should not redirect anywhere (as it's already localized to English).
      • /fr/search also shouldn't redirect anywhere (it's localized in French).
  • Another painful way to implement i18n redirects would just to use placeholder or "redirect pages" like in this example where the home URL just sends you to the default locale (no language detection).

For now, I've got it setup to:

  • Statically pre-render all pages in our supported locales (designated in the src/intl folder).
  • Each page only imports it's own language files (e.g. /en/search only imports src/intl/locales/en.json).
  • Redirect to the requested locale based on the HTTP request Accept-Language header.
  • Put this code as high-level as possible so we don't have to add boilerplate to each new src/pages/ page.
  • Make adding translations and links (i.e. Links should automatically add the user's locale) as intuitive as possible.

@nicholaschiang
Copy link
Member Author

What we're doing now is:

  • If the user requests a page without specifying a locale (e.g. /search instead of /en/search) we rewrite them to the /api/redirect endpoint which redirects them to the correct locale based on their Accept-Language header (or the default locale en if there isn't an Accept-Language header).
  • Each locale's pages are SSG enabled (using getStaticPaths and getStaticProps). This, however, does add some boilerplate code that needs to be added to every page (but that's a small trade-off for SSG). We'll have to watch out for Next.js's native implementation of i18n for the future.

We still need to work on:

  • Putting the code as high-level as possible (see the above last bullet point).
  • Make adding translations and links (i.e. Links should automatically add the user's locale) as intuitive as possible.

@nicholaschiang
Copy link
Member Author

I'm re-opening this because:

  1. Our current i18n setup isn't very clean and requires a lot more boilerplate code in each file that needs translations (i.e. there is no t function, we have to define a helper for each component).
  2. next-translate is a lot more lightweight than react-intl so we'll probably want to switch over to using their stuff (and I emailed @aralroca about becoming a mentor; so it only makes sense that we'd use next-translate haha).

@nicholaschiang nicholaschiang reopened this Jun 3, 2020
Tutorbook Roadmap automation moved this from Done to Doing Jun 3, 2020
@vctormb
Copy link

vctormb commented Jun 4, 2020

@nicholaschiang are you currently using next-translate in production? Is it working good? I was thinking about to use next-i18next but after all the things that you wrote.. I don't know if I'll use it.

@nicholaschiang nicholaschiang changed the title feat: add i18n support Polish i18n support Jun 23, 2020
@nicholaschiang
Copy link
Member Author

Not yet @vctormb. Right now, we're still using react-intl as our i18n library. There are a lot of lighter weight options out there though (e.g. next-translate, Rosetta) that don't require so much boilerplate code so I'd look into one of those if I were you.

For instance, in react-intl an i18n-enabled component typically looks something like:

import { useIntl, defineMessages, IntlShape, MessageDescriptor } from 'react-intl';

const msgs: Record<string, MessageDescriptor> = defineMessages({
  header: {
    id: 'header',
    defaultMessage: 'Your profile',
    description: 'The header for the profile view.'
  },
});

export default function Profile(): JSX.Element {
  const intl: IntlShape = useIntl();
  return (
    <h1>{intl.formatMessage(msgs.header)}</h1>
  );
}

That's a lot of unnecessary boilerplate code IMHO haha.

On a slightly unrelated note, there seems to be an issue with our current static path generation setup where Next.js requires that you specify all paths. See this issue for more info on that.

nicholaschiang added a commit that referenced this issue Jul 27, 2020
Fixes #35 by replacing 'react-intl' with 'next-translate' (which is a
lot lighter weight and was made for use with Next.js).

Note that we still have an issue using the 'next-translate' <Link>
component and that we'll probably want to implement the "build step" as
a temporary workaround to enable automatic static optimization for our
dashboard pages.

We'll probably also add a redirect from '/en' to '/' and get rid of our
'/api/redirect' endpoint temporarily (while we don't support any other
locales). As soon as we get translations for other locales, however,
we'll add it back in.
Tutorbook Roadmap automation moved this from Doing to Done Jul 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p1 Urgent tasks type:bug Something isn't working in a story
Projects
No open projects
Development

No branches or pull requests

2 participants