Stele - Common Runtime Refactors

Components
HomeHow Stele Works
How To
Common Runtime RefactorsJSXTranslateConfiguring Stele to be runtime or compile timeContextDevelopmentSimple CasesStele Awareness
LicenseTechdebt

Migrating more complicated strings

Strings that include some runtime logic are more difficult to translate. Since we need to convert messages to be statically known these types of strings will likely take the bulk of our time.

JSX

If statements and ternaries

Ternaries are very common in React code. So let's start with an example that isn't internationally friendly.

let buttonCopy
if (isCampaignConnected) {
buttonCopy = 'Disconnect'
} else {
buttonCopy = isCampaignSetup ? 'Complete Setup' : 'Connect'
}
return <Button>{buttonCopy} Now</Button>

Here we are trying to display some text to a user to help them know the status of their campaign. If we were to translate this in the simplest way we might get something like this:

let buttonCopy
if (isCampaignConnected) {
buttonCopy = translate(locale, 'Disconnect')
} else {
buttonCopy = isCampaignSetup
? translate(locale, 'Complete Setup')
: translate(locale, 'Connect')
}
return <Button intl={locale}>{buttonCopy} Now</Button>

This sends the following messages to your translator:

{
"Disconnect": "Disconnect",
"Complete Setup": "Complete Setup",
"Connect": "Connect",
"{buttonCopy} Now": "{buttonCopy} Now"
}

Unfortunately, we have just introduced a bug! We are sneakily embedding messages inside messages. Which as we learned earlier are not statically known strings. This can produce mistranslations in the future. Also the mesage "{buttonCopy} now" isn't incredibly meaningful.

Instead let's try a few different approaches, all of which are valid and up to you!

Using Select

If your booleans can easily be converted to strings, this is probably the best approach that gives your translators the most context. It would look something like this:

return (
<Button intl={locale}>
<Select
value={campaignState}
matches={{
connected: 'Disconnect',
setup: 'Complete Setup',
other: 'Connect',
}}
/>{' '}
Now
</Button>
)

This produces the message:

{
"{campaignState, select, connected {Disconnect} setup {Complete Setup} other {Connect}} Now": "{campaignState, select, connected {Disconnect} setup {Complete Setup} other {Connect}} Now"
}

Which, while much longer, gives the translator much more control and context over the entire string. Also, in my opinion, it's easier for the developer to see what the full messages are and how to reproduce them. Not to mention fewer words for your translator to translate.

Multiple returns

The other way to handle this would be to have multiple returns with the full strings in them

if (isCampaignConnected) {
return <Button intl={locale}>Disconnect Now</Button>
} else {
return isCampaignSetup ? (
<Button intl={locale}>Complete Setup Now</Button>
) : (
<Button intl={locale}>Connect Now</Button>
)
}

This allows us to maintain our original code structure and provide the entire string to our translators

Translate

© Patreon