Stele - Context
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:
<pintl={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<Buttonintl={locale}intl-description="button to click to reveal an incoming message">Read</Button>// Second good example: same string, but different contextconst 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!