16

I'm trying to use react-intl package inside an app. The app is rendered on the server so I wrote some code to determine which language to use and serve into IntlProvider.

Translations were provided in messages.js file and they look like this:

export default {
  en: {
    message: '...some message',
    nested: {
      anotherMessage: '...another message',
    }
  }
  de: {
    // ...
  }
}

What I do is something like this:

// import messages from './messages.js'
// Check the locale for the user (based on cookies or other things)
const locale = ...
// Get the required messages
const messagesForLocale= = messages[locale];
// Supply the messages to the IntlProvider
<IntlProvider locale={locale} messages={messagesForLocale}>
  // ...
</IntlProvider>

Then when I use FormattedMessage component I can't access the nested message (anotherMessage) with code like this:

<FormattedMessage id="nested.anotherMessage" ... />

But message is accessible.

Any ideas where I made the mistake, or maybe I'm missing something in the whole concept?

Ancinek
  • 3,279
  • 3
  • 28
  • 70

3 Answers3

18

Since React Intl v2 no longer supports nested messages objects, the messages need to be flattening.

export const flattenMessages = ((nestedMessages, prefix = '') => {
  if (nestedMessages === null) {
    return {}
  }
  return Object.keys(nestedMessages).reduce((messages, key) => {
    const value       = nestedMessages[key]
    const prefixedKey = prefix ? `${prefix}.${key}` : key

    if (typeof value === 'string') {
      Object.assign(messages, { [prefixedKey]: value })
    } else {
      Object.assign(messages, flattenMessages(value, prefixedKey))
    }

    return messages
  }, {})
})

// Use flattenMessages
<IntlProvider locale={locale} messages={flattenMessages(messagesForLocale)}>

refs:

Soroush Chehresa
  • 3,630
  • 1
  • 10
  • 23
banyan
  • 2,881
  • 2
  • 22
  • 20
10

react-intl does not support nested messages anymore. If you still want to organize your messages that way, you can use the flat library to correct your messages structure beforehand.

import flatten from 'flat'

<IntlProvider locale={locale} messages={flatten(messagesForLocale)}>

A contributor of react-intl claims that the main reason for only supporting a flat message structure is:

Simplicity and flexibility is the main reason. With the flat object, people can write whatever message ids/keys they want and they won't be interpreted with special semantics.

View the issue Support nested messages-object comment on GitHub.

Camilo
  • 4,034
  • 24
  • 39
AHOYAHOY
  • 2,213
  • 4
  • 21
  • 34
1

Yes, customization using flattenMessages is the best way I found.

Here is the video demo for your reference.

https://egghead.io/lessons/react-convert-a-hard-coded-string-using-react-intl-formattedmessage

Krupal Patel
  • 396
  • 3
  • 12