zulip/docs/translating.md

124 lines
4.6 KiB
Markdown
Raw Normal View History

# Translating Zulip
Zulip has full support for unicode, so you can already use your
preferred language everywhere in Zulip.
To make Zulip even better for users around the world, the Zulip UI is
being translated into a number of major languages, including Spanish,
German, French, Chinese, Russian, and Japanese, with varying levels of
progress. If you speak a language other than English, your help with
translating Zulip would be greatly appreciated!
If you're interested in contributing translations to Zulip, join the
[Zulip project on Transifex](https://www.transifex.com/zulip/zulip/)
and ask to join any languages you'd like to contribute to (or add new
ones). Transifex's notification system sometimes fails to notify the
maintainers when you ask to join a project, so please send a quick
email to zulip-core@googlegroups.com when you request to join the
project or add a language so that we can be sure to accept your
request to contribute.
## Translation Tags
All user-facing text in the Zulip UI should be generated by a HTML
template so that it can be translated.
Zulip uses two types of templates: backend templates (powered by the
[Jinja2][] template engine, though the original [Django][] template
engine is still supported) and frontend templates (powered by
[Handlebars][]). At present, the frontend templates don't support
translation (though we're working on fixing this!), so the rest of
this discussion will be about the backend templates.
To mark a string for translation in the Jinja2 and Django template
engines, you can use the `_()` function in the templates like this:
```
{{ _("English text") }}
```
If a string contains both a literal string component and variables,
you can use a block translation, which makes use of placeholders to
help translators to translated an entire sentence. To translate a
block, Jinja2 uses the [trans][] tag while Django uses the
[blocktrans][] tag. So rather than writing something ugly and
confusing for translators like this:
```
# Don't do this!
{{ _("This string will have") }} {{ value }} {{ _("inside") }}
```
You can instead use:
```
# Jinja2 style
{% trans %}This string will have {{ value }} inside.{% endtrans %}
# Django style
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
```
Zulip expects all the error messages to be translatable. To ensure
this, the error message passed to `json_error` and `JsonableError`
should always be a literal string enclosed by `_()` function, e.g:
```
json_error(_('English Text'))
JsonableError(_('English Text'))
```
To ensure we always internationalize our JSON errors messages, the
Zulip linter (`tools/lint-all`) checks for correct usage.
## Frontend Translations
The first step in translating the frontend is to create the translation
files using `python manage makemessages`. This command will create
translation files under `static/locale`, the location can be changed by
passing an argument to the command, however make sure that the location is
2016-06-02 19:16:56 +02:00
publicly accessible since these files are loaded through XHR in the
frontend which will only work with publicly accessible resources.
The second step is to upload the translatable strings to Transifex using
`tx push -s -a`.
The final step is to get the translated files from Transifex using
`tx pull -a`.
[Django]: https://docs.djangoproject.com/en/1.9/topics/templates/#the-django-template-language
[Jinja2]: http://jinja.pocoo.org/
[Handlebars]: http://handlebarsjs.com/
[trans]: http://jinja.pocoo.org/docs/dev/templates/#i18n
[blocktrans]: https://docs.djangoproject.com/en/1.8/topics/i18n/translation/#std:templatetag-blocktrans
## Testing Translations
First of all make sure that you have compiled the translation strings
using `python manage.py compilemessages`.
Django figures out the effective language by going through the
following steps:
1. It looks for the language code in the url.
2. It loooks for the LANGUGE_SESSION_KEY key in the current user's
session.
3. It looks for the cookie named 'django_language'. You can set a
different name through LANGUAGE_COOKIE_NAME setting.
4. It looks for the `Accept-Language` HTTP header in the HTTP request.
Normally your browser will take care of this.
The easiest way to test translations is through the i18n urls e.g. if
you have German translations available you can access the German
version of a page by going to `/de/path_to_page`.
To test translations using other methods you will need an HTTP client
library like `requests`, `cURL` or `urllib`. Here is a sample code to
test `Accept-Language` header using requests:
```
import requests
headers = {"Accept-Language": "de"}
response = requests.get("http://localhost:9991/login/", headers=headers)
print(response.content)
```