Skip to content

React intl translation examples

Gabriel Ramos Takeda edited this page Jun 30, 2017 · 5 revisions

Follow some examples that describes how to create an entry point to translate a text.

Translate simple text

Before

<h2>Escolha uma das suas comunidades</h2>

After

import { FormattedMessage } from 'react-intl'

<h2>
  <FormattedMessage
    id='page--community-list.subheader'
    defaultMessage='Escolha uma das suas comunidades'
  />
</h2>

In the pt-BR locale file

export default {
  ...
  'page--community-list.subheader': 'Escolha uma das suas comunidades',
  ...
}

Translate text with variable

Before

<h1>Olá {user.first_name},</h1>

After

import { FormattedMessage } from 'react-intl'

<h1>
  <FormattedMessage
    id='page--community-list.header'
    defaultMessage='Olá {name},'
    values={{ name: user.first_name }}
  />
</h1>

In the pt-BR locale file

export default {
  ...
  'page--community-list.header': 'Olá {name},',
  ...
}

Translate text that contains React component

Before

<p className='white center'>
  ou <Link to={paths.communityAdd()}>Crie uma nova comunidade</Link>
</p>

After

import { FormattedMessage } from 'react-intl'

<p className='white center'>
  <FormattedMessage
    id='page--community-list.community-add.text'
    defaultMessage='ou {link}'
    values={{
      link: (
        <Link to={paths.communityAdd()}>
          <FormattedMessage
            id='page--community-list.community-add.link'
            defaultMessage='Crie uma nova comunidade'
          />
        </Link>
      )
    }}
  />
</p>

In the pt-BR locale file

export default {
  ...
  'page--community-list.community-add.text': 'ou {link}',
  'page--community-list.community-add.link': 'Crie uma nova comunidade',
  ...
}

Translate text that contains HTML

Before

<p>
  Tem certeza que deseja remover o
  subdomínio <b>{this.state.deletedDNSRecord.value}</b>?
</p>

After

import { FormattedMessage } from 'react-intl'

<p>
  <FormattedMessage
    id='page--community-settings.domain'
    defaultMessage='Tem certeza que deseja remover o subdomínio {domain}?'
    values={{
      domain: <b>{this.state.deletedDNSRecord.value}</b>
    }}
  />
</p>

In the pt-BR locale file

export default {
  ...
  'page--community-settings.domain': 'Tem certeza que deseja remover o subdomínio {domain}?',
  ...
}

Translate html tag attribute

(or in cases that needs to returns a pure text instead of a component)

Before

<input
  type='text'
  name='first_name'
  placeholder='Insira aqui seu nome'
/>

After (stateless component)

import { injectIntl } from 'react-intl'

const ComponenteRaiz => ({ intl }) => (
  <input
    type='text'
    name='first_name'
    placeholder={
      intl.formatMessage({
        id: 'components--componente-raiz.input.first-name',
        defaultMessage: 'Insira aqui seu nome'
      })
    }
  />
)

export default injectIntl(ComponenteRaiz)

After (component w/ state)

import React, { Component } from 'react'
import { injectIntl } from 'react-intl'

class ComponenteRaiz extends Component {
  render() {
    const { intl } = this.props

    <input
      type='text'
      name='first_name'
      placeholder={
        intl.formatMessage({
          id: 'components--componente-raiz.input.first-name',
          defaultMessage: 'Insira aqui seu nome'
        })
      }
    />
  }
}

export default injectIntl(ComponenteRaiz)

In the pt-BR locale file

export default {
  ...
  'components--componente-raiz.input.first-name': 'Insira aqui seu nome',
  ...
}

Translate redux-form validate messages

Before

import { connect } from 'react-redux'
import { injectIntl } from 'react-intl'
import Page from './page'

const fields = ['first_name']

const validate = (values, { intl }) => {
  const errors = {}
  if (!values.first_name) {
    errors.first_name = 'Informe seu nome'
  }
  return errors
}

export default injectIntl(connect()(
  reduxForm({ form: 'exampleForm', fields, validate })(Page)
))

After

import { connect } from 'react-redux'
import { injectIntl } from 'react-intl'
import Page from './page'

const fields = ['first_name']

const validate = (values, { intl }) => {
  const errors = {}
  if (!values.first_name) {
    errors.first_name = intl.formatMessage({
      id: 'page--example.form.name.validation.required',
      defaultMessage: 'Informe seu nome'
    })
  }
  return errors
}

export default injectIntl(connect()(
  reduxForm({ form: 'exampleForm', fields, validate })(Page)
))

In the pt-BR locale file

export default {
  ...
  'page--example.form.name.validation.required': 'Informe seu nome',
  ...
}

Tests with intl object injection

  • You can execute the test files using the yarn test command like below, only replacing the relative path of the test file:
e.g.
yarn test routes/admin/authenticated/external/community-new/page.spec.js

It have two intl helper functions that allow tests of components that requires the intl object injection.

shallowWithIntl

import React from 'react'
- import { shallow } from 'enzyme'
+ import { shallowWithIntl } from '~root/intl/helpers'

import * as mock from '~client/utils/mock'
import Page from '~routes/admin/authenticated/external/community-new/page'

describe('routes/admin/authenticated/external/community-new/page', () => {
  const props = {
    fields: {
      name: {},
      city: {}
    },
    submitting: false,
    // Actions
    create: mock.noop
  }

  it('should render without crashed', () => {
-     shallow(<Page {...props} />)
+     shallowWithIntl(<Page {...props} />)
  })
})

mountWithIntl

import React from 'react'
import { expect } from 'chai'
- import { mount } from 'enzyme'
+ import { mountWithIntl } from '~root/intl/helpers'
import Page from '~routes/admin/not-authenticated/account-register/page'

const dummyField = field => ({
  name: field,
  onChange: () => {}
})

describe('~routes/admin/not-authenticated/account-register/page', () => {
  const props = {
    submit: () => {},
    fields: {
      name: dummyField('name'),
      last_name: dummyField('last_name'),
      email: dummyField('email'),
      password: dummyField('password'),
      password2: dummyField('password2')
    },
    handleSubmit: () => {}
  }

  it('should render without crashed', () => {
-    const page = mount(<Page {...props} />)
+    const page = mountWithIntl(<Page {...props} />)
    expect(page).to.be.ok
  })
})