Search code examples
javascriptreactjsreact-intl

react-intl - accessing nested messages


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?


Solution

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

    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: