-
Notifications
You must be signed in to change notification settings - Fork 134
l10n guide
We use traditional gettext-style localization, split in two repos.
Added in https://github.com/ansible/galaxy_ng/pull/882
We're using a _()
function, parameters are fine as long as the format string gets passed through _()
before interpolation. (That makes python f-strings unsuitable for l10n without modification.)
Do translate error messages in API responses, don't translate log messages.
+from django.utils.translation import gettext_lazy as _
- errmsg = 'Repository "{pulp_id}" not found while creating synclist'
+ errmsg = _('Repository "{pulp_id}" not found while creating synclist')
raise ValidationError(errmsg.format(pulp_id=repository_id))
except IntegrityError as exc:
- raise ValidationError("Synclist already exists: %s" % exc)
+ raise ValidationError(_("Synclist already exists: %s") % exc)
String extraction can be triggered using django-admin makemessages
(podman exec -it galaxy_ng_api_1 pulpcore-manager makemessages
), this creates the .po
files, then, those can be compiled to .mo
using django-admin compilemessages
. All these files live in ./galaxy_ng/locale/*/LC_MESSAGES/
.
More details in django translation docs.
Added in https://github.com/ansible/ansible-hub-ui/pull/810
We're using a t`...`
template string javascript-side, and a <Trans>
component for React JSX.
Current language is autodetected based on browser settings, and compared with the list of availableLanguages
in src/l10n.js
.
(It may be easier to install https://chrome.google.com/webstore/detail/locale-switcher/kngfjpghaokedippaapkfihdlmmlafcc for switching.)
import { t } from '@lingui/macro';
const data = "untranslated";
const string = t`Hello ${data}`;
(translators will see Hello {data}
, translate to something like Hola {data}
resulting in Hola untranslated
in the UI)
❗ Prefer using variables in string substition: t`Hello ${data.data}`
is using an expression, not a simple variable, so the translators will see Hello {0}
, they won't know what {0}
means without context.
import { Trans } from '@lingui/macro';
const data = "untranslated";
const MyComponent = () => (
<Trans>Hello <b>World</b>: {data}</Trans>
);
(translators will see Hello <0>World</0>: {data}
, translate to Hola <0>mundo</0>: {data}
resulting in Hola mundo: untranslated)
import { plural } from '@lingui/macro';
const myCount = 123;
const string = plural(myCount, {
one: '# byte',
other: '# bytes',
}); // yields 0 bytes, 1 byte, 2 bytes, ... depending on myCount
(translators will see {myCount, plural, one {# byte} other {# bytes}}
, translate to something like {myCount, plural, one {# byt} few {# byty} other {# bytů}}
, yielding 0 bytů, 1 byt, 2 byty, ..., 5 bytů
depending on myCount
)
More details in lingui docs; prefer the macro version for consistency.
- run
gettext:extract
to extract translatable strings fromsrc/
intolocale/*.po
- those
*.po
files get uploaded to a translation service (outside automation) - updated
*.po
files get downloaded from the service and merged in (usemsgmerge
to resolve conflicts if necessary) - run
gettext:compile
to createlocale/*.js
files for eachpo
counterpart - webpack automatically builds each locale js into a separate bundle
- using a dynamic import in
src/l10n.ts
to import the right one at runtime
Sponsored by Red Hat, Inc.