Stele - Context

Components
HomeHow Stele Works
How To
Common Runtime RefactorsConfiguring Stele to be runtime or compile timeContextWhy we need contextWriting good contextmetadataPropNamesDevelopmentSimple CasesStele Awareness
LicenseTechdebt

Giving context to human translators

Usually machine translation (MT) like Google Translate is not the way to yield the best high quality translations, because machines lose things like tone and intent when doing automated translations. If you're using something like Google Translate to do your translations, then you can feel free to skip this section.

The easiest and most simple way to give context to translators would be to use the contextPropName option in your .babelrc. This string adds a prop you can use on any intl message to send to translators the context they need to make an accurate translation.

So if your .babelrc is:

[
"@patreon/stele/dist/plugin",
{
"propName": "intl",
"contextPropName": "intl-description"
}
]

You can then add context to a message like so:

<p
intl={locale}
intl-description="An excited welcome message displayed to new users"
>
Welcome to the site {userName}!
</p>

This then produces a special type of message that gets sent to translators:

{
"Welcome to the site {userName}!": {
"sourceContent": "Welcome to the site {userName}!",
"context": "An excited welcome message displayed to new users"
}
}

Why we need context

Translators aren't necessarily the ones using your product and the context where words appear matters. For instance does next March mean "the next month named March" or "the next time you go marching with your band"? Adding this prop is a way to give translators more context than what appears in the message to make it more simple to make quality translations.

Translate

The Translate function takes context as a fourth argument, so adding it is really easy and requires no extra configuration:

translate(
locale,
"Let's go to the mall, today!",
undefined,
"A line from the hit song 'Lets go to the mall', by Robin Sparkles",
)

Writing good context

When writing context, put yourself in the shoes of a human translator and try to encompass three different kinds of context that a translator would need in order to translate a message accurately:

  • Visual context: describe where the message shows up in the user interface, e.g. a button, a checkbox, a menu item, an input label, etc.
  • Usage context: outline the kind of activity a user might be performing in the product when they see the message, e.g. a nav bar, a tax form to fill out, a search, a table full of blocked users, etc.
  • Semantic context: clarify the meaning of an action, as well as the performer and target of that action, e.g. in the sentence "you give your supporters a token of appreciation", the verb "give" has a linguistic valency of 3. That is to say, if you think of "give" as a function, then it has three arguments: "you" (the subject), "your supporters" (the direct object), and "a token of appreciation" (the indirect object).
// Bad
<Button intl={locale}>Read</Button>
// Good, provides only visual context
<Button intl={locale} intl-description="button text">Read</Button>
// Better, provides all three kinds of context
<Button
intl={locale}
intl-description="button to click to reveal an incoming message"
>
Read
</Button>
// Second good example: same string, but different context
const STATUS_READ = translate(
locale,
'Read',
undefined,
'status of a sent message',
)

Note the second example above: sometimes, short messages can be misconstrued to mean something else! The first instance of "Read" is a call to action, but the second instance is the past tense of "to read", used as an adjective to describe the status of a message, along with other statuses like "Sent" or "Delivered". Use the context to clarify any potential ambiguities you can think of.

// Bad, could mean anything. Does it mean "the date on which someone was
// blocked"? "A cluster of dates consolidated into a single block"? "To block
// a person who is a potential date"? Nobody can tell without asking more
// questions.
const options = {
title: translate(locale, 'Block Date'),
}
// Good, provides visual context that this string will show up as the header of
// a column, presumably inside some layout, like a table.
const options = {
title: translate(locale, 'Block Date', undefined, 'column header'),
}
// Better, provides visual context, usage context, and implies that "block date"
// as a cohesive unit is a noun, meaning "the date on which someone was
// blocked".
const options = {
title: translate(
locale,
'Block Date',
undefined,
'blocked users table: column name',
),
}

metadataPropNames

Sometimes you need to add extra context to your messages in Stele. For this, we have metadataPropNames.

In Stele's Babel config, you can define a mapping, which causes Stele to extract prop values.

const steleConfig = [
'@patreon/stele/dist/plugin',
{
// ...
metadataPropNames: { 'my-metadata': 'myMetadata' },
// ...
},
]

Having configured metadataPropNames like the example above, you can now use my-metadata in your JSX:

<p intl={locale} my-metadata="greeting">
Good Afternoon!
</p>

and it will appear in the extracted message like so:

{
"sourceContent": "Good Afternoon!",
// ...
"productMetadata": {
"myMetadata": "greeting"
}
},

Why use metadataPropNames?

You may need to provide more context for your translations. Perhaps, you would like to flag certain translations for screenshots. Giving translators visual context can be essential in some cases.

Here's an explanation on how screenshots can help

To prepare your code for screenshots with Stele you might configure it like:

const steleConfig = [
'@patreon/stele/dist/plugin',
{
// ...
metadataPropNames: { 'intl-screenshot': 'intlScreenshot' },
// ...
},
]

Then, on every component that you would like to screenshot, add the prop

<p intl={locale} intl-screenshot="screenshotFilename">
Good Afternoon!
</p>

You've now laid the groundwork for taking screenshots of specific areas of your site. From here, you could use an automation software like Cypress to locate components with this metadata prop and take screenshots, for example. Unfortunately, the process of crawling your site and actually taking screenshots is outside the scope of this documentation.

metadataPropNames can be used for anything! Use your imagination!

© Patreon