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

avoid code duplication between different routes #12

Open
sedubois opened this issue Nov 15, 2017 · 22 comments
Open

avoid code duplication between different routes #12

sedubois opened this issue Nov 15, 2017 · 22 comments

Comments

@sedubois
Copy link
Contributor

Currently the gatsby-starter-default-i18n shows that one needs to create one separate source code file per language and per route (and even one extra for home redirection):

  • index.en.js
  • index.pt.js
  • page-2.en.js
  • page-2.pt.js

This is not really scalable; is there any way to avoid the duplication? Does this relate to the need to use Gatsby path prefixes?

@angeloocana
Copy link
Owner

Hi @sedubois

Good point!
Yes, we need that for path prefixes.

One thing I like about this is that you can use different queries and layouts.

What would you suggest?
If the plugin finds a page like test.js it would create routes for all the languages,
and If it finds a specific language like test.en.js it is going to override the automatic en version?

@sedubois
Copy link
Contributor Author

sedubois commented Nov 15, 2017

Yes, that sounds likes a reasonable behavior 🙂 just needs to be documented properly.

@pdrbrnd
Copy link

pdrbrnd commented Jan 10, 2018

Hi! Any news on this?

@danniehakan
Copy link

I'm wondering about this as well. I was looking into a client translation approach with react-i18next which would make it more DRY, but since I want google to be able to index the strings I suppose this plugin is more suitable? How are you going to maintain three index pages that look the same in 3 different languages with this approach? Maybe I'm missing something fundamental related to the philosophy behind this framework, GQL or something else.

@sedubois
Copy link
Contributor Author

My pages currently look like that:

// pages/about.en.js
export default from '../components/about'

export const pageQuery = graphql`
  query AboutEnQuery {
    ...AboutPageFragment
  }
`
// pages/about.fr.js
export default from '../components/about'

export const pageQuery = graphql`
  query AboutFrQuery {
    ...AboutPageFragment
  }
`
// components/about.js
export default class AboutPage extends React.Component {
  // whatever
}

export const aboutPageFragment = graphql`
  fragment AboutPageFragment on RootQueryType {
    // whatever
  }
`

So, as much as possible, code isn't duplicated. But it's still annoying that I need to create files just to re-export the generic component + need to duplicate the graphQL queries.

@danniehakan
Copy link

And in this query you fetch the strings related to the specific locale, I assume? It looks tedious.

What's your take on the approach from this blogpost https://www.gatsbyjs.org/blog/2017-10-17-building-i18n-with-gatsby/?

@sedubois
Copy link
Contributor Author

The aboutPageFragment query is unrelated to i18n. I just mention it here because as there are two separate pages, two separate GraphQL queries are needed: AboutEnQuery and AboutFrQuery. Otherwise the graphql templates extraction will fail.

The AboutPage class contains normal react-intl FormattedMessage components.

About that blog post I had those questions: https://twitter.com/semdubois/status/930688664224587776

Which ultimately led me to want to look at something other than i18next. I also preferred a plugin which would abstract away the complexity from my codebase if possible.

That being said I'm not so convinced by react-intl either. I found js-lingui whose v2 just came out, looks promising? What do you use?

@danniehakan
Copy link

I see. Thank you for the insight to the discussion regarding the blog post.

Were I'm confused is, while I'm getting SEO friendly routes by setting up the project with this plugin, how will the pages be properly indexed if the strings are XHR? Is that not a problem? Also I would need to connect the route created by gatsby to the specific language somehow, no?

Regarding what I'm using, I've not been setting up anything of the like before in the client. Prior to this I've been working with SSR frameworks like django and that's where I've put all the translations.

@sedubois
Copy link
Contributor Author

As Gatsby is a static site generator, your localized routes are generated at build time, i.e. you will have one HTML page per language which should then be trivial for search engines to pick up. Whatever localization system you use (react-intl, react-i18next, js-lingui, etc), you just need to check that those static HTML pages indeed contain the text that you expect. You can check what is generated in your public/ folder.

@danniehakan
Copy link

Regarding

you just need to check that those static HTML pages indeed contain the text that you expect

Are you saying the localized HTML files will actually have localized strings in them when google is crawling, meaning in the actual public/ folder? Because I don't see how that is true with the above said libraries (react-intl, react-i18next, js-lingui).

@danniehakan
Copy link

danniehakan commented Jan 28, 2018

I might be missing something, but those files in your build could as well not contain the actual strings(?).

I looked at the site that the gatsby i18n blog post was based on (doopoll.co) and I still saw the actual component translations being fetched after the initial page HTML had been loaded. So have you set it up differently with this plugin somehow?

@braco
Copy link

braco commented Jan 29, 2018

@sedubois make a gatsby/react-intl starter :)

js-lingui looks pretty great

@sedubois
Copy link
Contributor Author

sedubois commented Jan 29, 2018

@danniehakan I can confirm that those files contain the actual translated strings, both in the case of the blog's language-specific markdown files and in the case of JSX pages with FormattedMessage.

E.g.

$ grep "How do we take care of the planet?" en/about/index.html | wc -l
   1

Check the code of https://imagineclarity.com/en/about

@braco 👍 I might not have time for that but happy to have a look if you try out js-lingui (haven't done so yet).

@danniehakan
Copy link

danniehakan commented Jan 29, 2018

@sedubois That's exactly what I was looking for! Do you have any idea why this would work differently than react-i18next though(I set up the latter and cannot really get it to work like you have)? I just can't see how it's even possible for your markup to actually contain any localized strings.

@sedubois
Copy link
Contributor Author

I don’t know I guess that’s just the point of a static site generator, isn’t it? Gatsby generates static HTML files, so that the page contents are correct even before JavaScript takes over. For this to work you probably need to ensure that e.g the strings aren’t fetched after the React components get mounted.

@braco
Copy link

braco commented Jan 30, 2018

@angeloocana: agree this would be good:

If the plugin finds a page like test.js it would create routes for all the languages,
and If it finds a specific language like test.en.js it is going to override the automatic en version?

As long as the inline translation functions {t('...')} propagated to the different languages.

@mccrodp
Copy link

mccrodp commented Feb 11, 2018

make a gatsby/react-intl starter :)

Yea, I'd love to see some kind of starter for that and react-i18next with Gatsby. I felt not having a repo to look at with this post https://www.gatsbyjs.org/blog/2017-10-17-building-i18n-with-gatsby/ made things uncertain and I'd prefer to invest time in the gatsby-plugin-i18n at the moment instead of the alternatives, as at least I can see the plugin working locally, although I'm having issue with getting it to work with dynamic content such as from Contentful #31

Bit tricky to get a CMS driven Gatsby site working with i18n at the moment. Does this plugin work with dynamic routes generated on build, or only on the static routes mentioned?

Edit: I created a StackOverflow question to try to gain some attention to this as it's related to this issue at least indirectly: https://stackoverflow.com/questions/48757479/how-to-create-indexable-i18n-content-dynamically-from-a-cms-in-gatsby

If the plugin finds a page like test.js it would create routes for all the languages,
and If it finds a specific language like test.en.js it is going to override the automatic en version?

I like the sound of this also, if in the process we are able to have these routes be generated on build after the content is pulled from something dynamic like Contentful / another CMS.

@morgler
Copy link

morgler commented Feb 18, 2018

I'm currently also struggling with setting up a simple multi-language and SEO-friendly site with this. Using the approach of gatsby-plugin-i18n leads to unnecessary code duplication. It also does not extend nicely into translating components. But i18next on the other hand is not SEO-friendly.

I would love to see an approach where I could have language urls like example.com/en and example.com/de, but still only have to write one index.js or page-2.js file. These files would get the locale from the path as a prop and use it look up the correct translation strings in my i18next yml files.

I might be confused and missing the point here, but I'd assume it should be able to generate language-specific versions in the public folder by just pulling translations from yml files during build-time and inserting the into the index.js or page-2.js structure. Please tell me, if I'm totally missing the point.

@mccrodp
Copy link

mccrodp commented Feb 22, 2018

I'm not sure if this is related @angeloocana, @sedubois, but I'm wondering if we can learn anything to improve the code base by the following 2 comments here: gatsbyjs/gatsby#3853 (comment), the few comments above that on Kyle's suggestion and this repo also https://github.com/szimek/gatsby-react-intl-example

I think it's the same issue we're all talking about. Seems like a Layout component is suggested rather than any actual "layouts".

@romeboards
Copy link

Hey @sedubois - looking at your above code structure, have you found any caching problems with gatsby not loading new data into the fragment thats attached to the component? I found that I need to frequently be doing rm -r .cache with this format, unless its unrelated...

@sedubois
Copy link
Contributor Author

Sorry @romeboards, haven’t been having caching issues so far. If you have a way to repro you could always file an issue

@ghost
Copy link

ghost commented Jun 23, 2020

It doesn't feel this longstanding issue has gotten the attention it deserves from the Gatsby team. Ironic as their website suggests i18n is part of a great user experience. With static site generators like Hugo i18n is a solved problem.

Anyone looked at this project? It keeps routes DRY and sports Yarn workspaces containing a (1) theme (2) starter and (3) plugin: https://github.com/3nvi/gatsby-intl.

In addition the above also has a much more detailed write-up than that old 2017 blog post on the Gatsby site which, as time would tell, has earned Gatsby notariety for being i18n-unfriendly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants