We use Transifex to translate Sentry.
Other things that mean translating: localization, internationalization, i18n, l10n
If you need access to manage translations, translators, languages, or anything else, please talk to one of the following people:
- Ben Vinegar
- Vlad Cretu
General rules to follow when doing approvals.
- Don't approve new languages generally.
- Don't approve new languages that are duplicates of existing languages.
- Don't approve new team members unless they seem reliable (see security note below).
We have the ability to pay translators to come in and backfill a language. This has been done a number of times over the years, and is a good way to get an acceptable amount of coverage. There are caveats however:
- They often need "context" for a string, which we're usually missing in our code (or in the database). This means someone has to respond to their requests.
- The quality will be average - you given them a style to aim for, and they often do an ok-enough job.
- It's not free, though its cheap so it's not a big deal.
It's possible for translators to inject advertisements (links) or other bad content into translations. For this reason we don't accept translations implicitly - you get approved first - but it means we also need to do at least a minor bit of research on the translator themselves. Generally this is left to your own judgement, but take a look at their profile and ask yourself if they seem like a real human, or if this is a one-off account intended to use for abuse.
Translations have to be updated manually in Sentry.
To update untranslated strings in Transifex, open a terminal within the Sentry repo and run the following:
This will extract strings from the frontend using a webpack loader, as well as from the backend using
django makemessages -- which then gets merged together to create a
django.po file for the default (English) locale. This then gets propagated to our other supported locales.
It then uploads these PO files to Transifex to be translated. Ideally, this process is automated so that it is run on a schedule to ensure that new strings are synced with Transifex.
Note: You may need to go to Transifex and approve some previously reviewed translations. You can select a language and query for
reviewed:no origin:TM to find strings that have shifted around in the source code but have been previously translated. The
TM stands for Translation Memory.
The process of updating Sentry should be separate from updating Transifex as there needs to be time for translations and reviews to occur. In order to update Sentry run the following command in the Sentry repo:
This will pull translations from Transifex and use
django compilemessages to update the local translations. You should then commit the changes and submit a new Pull Request.
You may encounter some errors when running
LC_MESSAGES/django.po:4790: number of format specifications in 'msgid_plural' and 'msgstr' does not match
This means that we are using
tn() with an unbalanced set of string placeholders. For example,
tn('one user', '%s users', userCount); // This is bad because the first argument needs to also have %s // Instead do something like this userCount === 1 ? t('one user') : tn('%s users', '%s users', userCount); // Not great as the first arg to `tn()` is always ignored, but at least it will compile
Another common error you may see is
LC_MESSAGES/django.po:10824: 'msgstr' is not a valid Python format string, unlike 'msgid'. Reason: The character that terminates the directive number 1 is not a valid conversion specifier.
This generally means there is a literal
% that the parser is confusing for a string placeholder. For example,
#: static/app/views/dashboardsV2/manage/dashboardList.tsx:120 #, python-format msgid "100% of releases"
This can be resolved by removing
#, python-format (assuming you don't have any string formatting)