Translating strings are done with the _t() function found in matrix-react-sdk/lib/languageHandler.js.
It is recommended to call this function wherever you introduce a string constant which should be translated.
However, translating can not be performed until after the translation system has been initialized.
Thus, sometimes translation must be performed at a different location in the source code than where the string is introduced.
This breaks some tooling and makes it difficult to find translatable strings.
Therefore, there is the alternative _td() function which is used to mark strings for translation,
without actually performing the translation (which must still be performed separately, and after the translation system has been initialized).
Basically, whenever a translatable string is introduced, you should call either _t() immediately OR _td() and later _t().
Example:
// Module-level constant
const COLORS = {
'#f8481c': _td('reddish orange'), // Can't call _t() here yet
'#fc2647': _td('pinky red') // Use _td() instead so the text is picked up for translation anyway
}
// Function that is called some time after i18n has been loaded
function getColorName(hex) {
return _t(COLORS[hex]); // Perform actual translation here
}
These rules are based on https://github.com/element-hq/element-x-android/blob/develop/tools/localazy/README.md At this time we are not trying to have a translation key per UI element as some methodologies use, whilst that would offer the greatest flexibility, it would also make reuse between projects nigh impossible. We are aiming for a set of common strings to be shared then some more localised translations per context they may appear in.
action_ if this is a verb, or common_ if nota11y_. Example: a11y_hide_passwordkeyboard_ for strings relating to keyboard shortcuts.. or | or . Try to balance string length against descriptiveness.import { _t } from 'matrix-react-sdk/src/languageHandler'; is present. If not add it to the other import statements. Also import _td if needed._t() to your string passing the translation key you come up with based on the rules above. If the string is introduced at a point before the translation system has not yet been initialized, use _td() instead, and call _t() at the appropriate time.yarn i18n to add the keys to src/i18n/strings/en_EN.jsonsrc/i18n/strings/en_EN.json with the English (UK) translations for the added keys.Edits to existing strings should be performed only via Localazy. There you can also require all translations to be redone if the meaning of the string has changed significantly.
_t() call. Instead of _t(TKEY) use _t(TKEY, {})_t for example _t(TKEY, {variable: this.variable})%(variable)s. Please note the s at the end. The name of the variable has to match the previous used name.count variable to choose between multiple versions of the same string, in order to get the correct pluralization. E.g. _t('You have %(count)s new messages', { count: 2 }) would show 'You have 2 new messages', while _t('You have %(count)s new messages', { count: 1 }) would show 'You have one new message' (assuming a singular version of the string has been added to the translation file. See above). Passing in count is much preferred over having an if-statement choose the correct string to use, because some languages have much more complicated plural rules than english (e.g. they might need a completely different form if there are three things rather than two)._t('<a>Click here!</a>', {}, { 'a': (sub) => <a>{sub}</a> }). If you don't do the tag substitution you will end up showing literally '' rather than making a hyperlink._t('Your email address is %(emailAddress)s', { emailAddress: <i>{userEmailAddress}</i> })._t() inside getDefaultProps: the translations aren't loaded when getDefaultProps is called, leading to missing translations. Use _td() to indicate that _t() will be called on the string later._td() instead and perform the actual translation later.