gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.3k stars 10.31k forks source link

How to extract translation messages? #13392

Closed onokje closed 5 years ago

onokje commented 5 years ago

Hi all, we have just begun to implement react-intl for i18n. Translations work fine, but so far we have been using a static json file with all translations.

Now i am looking for a way to extract all translation messages from all pages and components. I thought i could use babel-plugin-react-intl, but it is not working (nothing happens).

I have:

yarn develop works fine, but nothing is written to ./build I have various translations in my pages, for example: <FormattedMessage id="header.account.login" />

Any idea's?

jonniebigodes commented 5 years ago

@onokje i've picked up on your issue and first and foremost sorry for the late response.

From my testing i think i have a solution for you.

Below are the steps i took:

}

- Created a folder called `constants` and inside my locales file with the following content:
```javascript
module.exports = {
  en: {
    path: "en",
    locale: "English",
    default: true,
  },
  pt: {
    path: "pt",
    locale: "Português",
  },
  it: {
    path: "it",
    locale: "Italian",
  },
}

import LocalizedLink from "./LocalizedLink"

import locales from "../constants/locales"

const Header = ({ intl: { locale } }) => (

)

export default injectIntl(Header)

- `Layout.js` with the following content:
```javascript
import React, { Fragment } from "react"
import { IntlProvider, addLocaleData } from "react-intl"

// Locale data
import enData from "react-intl/locale-data/en"
import ptData from "react-intl/locale-data/pt"
import itData from "react-intl/locale-data/it"
// Messages
import en from "../i18n/en.json"
import pt from "../i18n/pt.json"
import it from '../i18n/it.json'
// Components
import Header from "./Header"

const messages = { en, pt, it }

addLocaleData([...enData, ...ptData, ...itData])

const Layout = ({ locale, children }) => (
  <IntlProvider locale={locale} messages={messages[locale]}>
    <Fragment>
      <Header />
      <div>{children}</div>
    </Fragment>
  </IntlProvider>
)

export default Layout

import locales from "../constants/locales"

const LocalizedLink = ({ to, intl: { locale }, ...props }) => { const path = locales[locale].default ? to : /${locale}${to}

return <Link {...props} to={path} /> }

export default injectIntl(LocalizedLink)

- Inside the pages folder i changed `index.js` to the following:
```javascript
import React from "react"
import { FormattedMessage } from "react-intl"

import Layout from "../components/Layout"
import LocalizedLink from "../components/LocalizedLink"

export default ({ pageContext: { locale } }) => (
  <Layout locale={locale}>
    <h1>
      <FormattedMessage id="hi" />
    </h1>
    <p>
      <FormattedMessage id="welcome" />
    </p>
    <LocalizedLink to="/about/">
      <FormattedMessage id="about" />
    </LocalizedLink>
  </Layout>
)

export default ({ pageContext: { locale } }) => (

)

- Modified `gatsby-node.js` to the following:
```javascript
const locales = require('./src/constants/locales')

exports.onCreatePage = ({ page, actions }) => {
  const { createPage, deletePage } = actions
  deletePage(page)
  Object.keys(locales).map(lang => {
    const localizedPath = locales[lang].default
      ? page.path
      : locales[lang].path + page.path

    createPage({
      ...page,
      path: localizedPath,
      context: {
        locale: lang
      }
    })
  })

module.exports={presets,plugins}

- Issued once more `gatsby clean && gatsby develop`, same result.
- Removed the file and moved the configuration to inside `package.json`, same result, nothing was being extracted. and no folders
- Took it even further, went back to my original setup with the `.babelrc` added `@babel-cli` and `@babel-core`, created a new script in the `package.json` with the following instructuctions:
```json
"extract-messages": "set NODE_ENV=test&& babel ./src --out-dir lib",

Ran it and now i'm presented with the following: onokje_folder_Tree

[
  {
    "id": "siteTitle",
    "defaultMessage": "Because it is sunny!"
  }
]

The content was extracted and the messages i have were added. Key thing to take from this, a lib folder will be created and that can be deleted, as it's basically Gatsby does "under the hood" to the components. Also add something to the defaultValues prop or nothing will be generated.

Feel free to provide feedback, so that we can close this issue, or continue to work on it till we have a solution for you.

onokje commented 5 years ago

Thank you for taking the time to write this essay, i really appreciate it ;)

After i tried your steps, it still didn't work for me at first, until i took a good look at our code, it turns out that we didn't use defaultMessage anywhere. That is the reason I didn't get any output, but it works now.

jonniebigodes commented 5 years ago

@onopko81 no need to thank, glad i was able to help you solve your issue.

gatsbot[bot] commented 5 years ago

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contributefor more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

gatsbot[bot] commented 5 years ago

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks again for being part of the Gatsby community!

fabianrios commented 4 years ago

does it work if the strings are put using {intl.formatMessage({ id: "online" })} instead of <FormattedMessage id="online" />?

onokje commented 4 years ago

You need to use defineMessages to define your messages first. And also add a default message. So like this:

const messages = defineMessages({
  placeholder: {
    id: 'search.bar.placeholder',
    defaultMessage: 'Search for a product...',
  },
});

And then where you actually want to use it: intl.formatMessage(messages.placeholder)