Documentation
Feedback
Guides
Learning Center

Learning Center
Learning Center
Internationalization practices in VTEX IO
View in Portuguese
This content was migrated from the VTEX Learning Center and is no longer being actively maintained. For the most accurate and up-to-date information, please check the official documentation.

Introduction

With the customized block in the store, we need to learn to internationalize the content presented.

It is important to remember that blocks must always follow good localization practices, and must not show hardcoded strings, but ones that are sensitive to the language that the store operates.

Don't worry, you won't need to add translations of all texts for the various languages in which the Store Framework is used. Therefore, in this stage, will be presented concepts about the internationalization of apps and how to do it.

The Messages

The concept of messages makes it easy to add new languages ​​to the theme. The Messages centralize all translation services on the platform. Given a text to be translated, Messages will first check the user-defined context, then check the translations of the apps and, finally, go through the automatic translation system.

In the directory structure, you can see that there is a folder called messages, which has three main files: pt.json, en.json, andes.json, each responsible for the translations: Portuguese, English, and Spanish, respectively. In addition, in order to provide better automatic translations, the context.json file is used, which is responsible for avoiding ambiguities.

To use such definitions, the translation files mentioned above are JSON, whose keys are messages and values ​​are translations.

The context.json file is necessary and must contain all messages, besides offering automatic translations in exceptional cases.

Internationalizing your block

You must have learned how to use our builder messages, and it will be through it that internationalized strings will be added to the components.

  1. To do so, in the directory /messages, add now a message for the title of the component:

    messages/pt.json


    _10
    {
    _10
    ...,
    _10
    + "countdown.title": "Contagem Regressiva"
    _10
    }

    messages/en.json


    _10
    {
    _10
    ...,
    _10
    + "countdown.title": "Countdown"
    _10
    }

    messages/es.json


    _10
    {
    _10
    ...,
    _10
    + "countdown.title": "Cuenta Regresiva"
    _10
    }

    messages/context.json


    _10
    {
    _10
    ...,
    _10
    + "countdown.title": "Countdown"
    _10
    }

  2. After that, to render the title the component FormattedMessage of the lib react-intl must be used.

    The lib react-intl supports many ways of configuration and internationalization, it is worth checking it out.

  3. Now, add the lib using yarn add react-intl in the react directory. After doing that, in your component's code, Countdown.tsx, import the FormattedMessage:


    _10
    //react/Countdown.tsx
    _10
    import { FormattedMessage } from 'react-intl'

  4. And add a new prop to the interface CountdownProps:


    _10
    interface CountdownProps {
    _10
    + title: string
    _10
    targetDate: string
    _10
    }

  5. You'll also need to add a const that will be your title:


    _10
    //react/Countdown.tsx
    _10
    const titleText = title || <FormattedMessage id="countdown.title" />

  6. Now, join the title to the countdown to render. To do so, define a container outside. Besides, the text for the title will be passes using the prop title:


    _25
    //react/Countdown.tsx
    _25
    const Countdown: StorefrontFunctionComponent<CountdownProps> = ({
    _25
    title,
    _25
    targetDate,
    _25
    }) => {
    _25
    const [timeRemaining, setTime] = useState<TimeSplit>({
    _25
    hours: '00',
    _25
    minutes: '00',
    _25
    seconds: '00',
    _25
    })
    _25
    _25
    const titleText = title || <FormattedMessage id="countdown.title" />
    _25
    const handles = useCssHandles(CSS_HANDLES)
    _25
    _25
    tick(targetDate, setTime)
    _25
    _25
    return (
    _25
    <div className={`${handles.container} t-heading-2 fw3 w-100 c-muted-1`}>
    _25
    <div className={`${handles.title} db tc`}>{titleText}</div>
    _25
    <div className={`${handles.countdown} db tc`}>
    _25
    {`${timeRemaining.hours}:${timeRemaining.minutes}:${timeRemaining.seconds}`}
    _25
    </div>
    _25
    </div>
    _25
    )
    _25
    }

  7. Note that three new handles are used: container, countdown and title. Therefore, remember to declare them in the const CSS_HANDLES, seen in the previous step:


    _10
    const CSS_HANDLES = ['container', 'countdown', 'title']

  8. At last but not least, it is needed to add the title prop in the schema:


    _19
    //react/Countdown.tsx
    _19
    Countdown.schema = {
    _19
    title: 'editor.countdown.title',
    _19
    description: 'editor.countdown.description',
    _19
    type: 'object',
    _19
    properties: {
    _19
    + title: {
    _19
    + title: 'I am a title',
    _19
    + type: 'string',
    _19
    + default: null,
    _19
    + },
    _19
    targetDate: {
    _19
    title: 'Final date',
    _19
    description: 'Final date used in the countdown',
    _19
    type: 'string',
    _19
    default: null,
    _19
    },
    _19
    },
    _19
    }

Done! Now, to try out your store in other languages, you just need to add the query string /?cultureInfo=pt-br or /?cultureInfo=es-ar on the URL, for example. By using the first URL, the expected result is this one:

{"base64":"  ","img":{"width":1914,"height":979,"type":"png","mime":"image/png","wUnits":"px","hUnits":"px","length":606564,"url":"https://user-images.githubusercontent.com/19495917/80527977-99057880-896b-11ea-9305-8921d580a1f1.png"}}

Answer sheet

See answer sheet for Countdown.tsx
Countdown.tsx

_62
// store-block/react/Countdown.tsx
_62
import React, { useState } from 'react'
_62
import { TimeSplit } from './typings/global'
_62
import { tick, getTwoDaysFromNow } from './utils/time'
_62
import { useCssHandles } from 'vtex.css-handles'
_62
import { FormattedMessage } from 'react-intl'
_62
_62
interface CountdownProps {
_62
title: string
_62
targetDate: string
_62
}
_62
_62
const DEFAULT_TARGET_DATE = getTwoDaysFromNow()
_62
_62
const CSS_HANDLES = ['container', 'countdown', 'title']
_62
_62
const Countdown: StorefrontFunctionComponent<CountdownProps> = ({
_62
title,
_62
targetDate = DEFAULT_TARGET_DATE,
_62
}) => {
_62
const [timeRemaining, setTime] = useState<TimeSplit>({
_62
hours: '00',
_62
minutes: '00',
_62
seconds: '00',
_62
})
_62
_62
const titleText = title || <FormattedMessage id="countdown.title" />
_62
_62
const handles = useCssHandles(CSS_HANDLES)
_62
_62
tick(targetDate, setTime)
_62
_62
return (
_62
<div className={`${handles.container} t-heading-2 fw3 w-100 c-muted-1`}>
_62
<div className={`${handles.title} db tc`}>{titleText}</div>
_62
<div className={`${handles.countdown} db tc`}>
_62
{`${timeRemaining.hours}:${timeRemaining.minutes}:${timeRemaining.seconds}`}
_62
</div>
_62
</div>
_62
)
_62
}
_62
_62
Countdown.schema = {
_62
title: 'editor.countdown.title',
_62
description: 'editor.countdown.description',
_62
type: 'object',
_62
properties: {
_62
title: {
_62
title: 'I am a title',
_62
type: 'string',
_62
default: null,
_62
},
_62
targetDate: {
_62
title: 'Final date',
_62
description: 'Final date used in the countdown',
_62
type: 'string',
_62
default: null,
_62
},
_62
},
_62
}
_62
_62
export default Countdown

See answer sheet for context.json
context.json

_10
// store-block/messages/context.json
_10
{
_10
"editor.countdown.title": "Countdown",
_10
"editor.countdown.description": "Countdown component",
_10
"countdown.title": "Countdown"
_10
}

See answer sheet for en.json
en.json

_10
// store-block/messages/en.json
_10
{
_10
"editor.countdown.title": "Countdown",
_10
"editor.countdown.description": "Countdown component",
_10
"countdown.title": "Countdown"
_10
}

See answer sheet for es.json
es.json

_10
// store-block/messages/es.json
_10
{
_10
"editor.countdown.title": "Cuenta regresiva",
_10
"editor.countdown.description": "Cuenta regresiva component",
_10
"countdown.title": "Cuenta Regresiva"
_10
}

See answer sheet for pt.json
pt.json

_10
// store-block/messages/pt.json
_10
{
_10
"editor.countdown.title": "Contagem regressiva",
_10
"editor.countdown.description": "Componente de contagem regressiva",
_10
"countdown.title": "Contagem Regressiva"
_10
}

On this page