Stele - Common Runtime Refactors
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 buttonCopyif (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 buttonCopyif (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}><Selectvalue={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