I want an elegant solution for adding styling like bold, italic, or a color for only a part of a translation.
Example
Let say that I have this i18n translation:
'my-page.confim-customer.popup.warning': 'All customer files must be authorized by the customer himself, please be sure to invite the customer to scan this QR code.'
Now i want that the words "must be authorized by the customer himself" will be in bold and in yellow. (Design requirement)
What can I do?
Solution 1 – Split in i18n
I can simply split the translation to three parts in i18n file:
// i18n/en.js
'my-page.confim-customer.popup.warning.part1': 'All customer files'
'my-page.confim-customer.popup.warning.part2': 'must be authorized by the customer himself,'
'my-page.confim-customer.popup.warning.part3': 'please be sure to invite the customer to scan this QR code.'
and then apply the css i want only on the "part2".
// MyComponent.jsx
const first = i18n.t('my-page.confim-customer.popup.warning.part1');
const second = i18n.t('my-page.confim-customer.popup.warning.part2');
const thrid = i18n.t('my-page.confim-customer.popup.warning.part3');
return (
<>
<div>
{first}
<span className="bold yellow">{second}</span>
{thrid}
</div>
</>
);
Pros
- It works
Cons
- Polute the i18n files with lots of partial string for each lines.
- When change is required it is a hassel to change the view and translation
Solution 2 – Split in code
I keep i18n in the same translation but I add seprator in it (let say $#$
):
'my-page.confim-customer.popup.warning': 'All customer files $#$must be authorized by the customer himself,$#$ please be sure to invite the customer to scan this QR code.'
And then in my component i split it:
// MyComponent.jsx
const [first, second, thrid] = i18n.t('my-page.confim-customer.popup.warning').split('$#$')
return (
<>
<div>
{first}
<span className="bold yellow">{second}</span>
{thrid}
</div>
</>
);
Pros
- It works
- Offload the headache to javascirpt, keep the translation in one i18n key
Cons
- Need to process the key before using it
- When change is needed (let say we add a new seperator for a section to be italic), we need to alter the way we process the key and change the view to match. not dynamic.
Note
I’m looking for a vanilla solution, as I’m not working with React or a popular framework.
2
Answers
i18next has a special component
Trans
. There you can use any components inside your string like:The strings split into separate keys are extremely not translator-friendly. It would be hard for translators to provide quality translations since they need to know where each part is used just not to break the UI.
In addition, the translation for some languages likely will have a different word order. The situation is even more complicated in RTL languages.
So, it’s definitely recommended to avoid such approaches with string splitting.
As a Vanilla JS solution that can work in your case, I would recommend the Lingui library.
In short, it allows developers to do the following thing by using the
@lingui/macro
package:Then you can extract all your localizable texts to the
.po
or.json
file by using the Lingui CLI.Components and HTML tags are replaced with dummy indexed tags (<0></0>) which has several advantages:
Further reading:
@lingui/macro
docs