I'm reading the django documentation for makemessages but the wording is not very clear:
Runs over the entire source tree of the current directory and pulls out all strings marked for translation. It creates (or updates) a message file in the conf/locale (in the Django tree) or locale (for project and application) directory. After making changes to the messages files you need to compile them with compilemessages for use with the builtin gettext support.
In the text above it doesn't seem clear to me what it means that makemessages would "pull out" strings marked for translation. (pull them out for what? where to?)
Meanwhile the compilemessages description makes sense as this simply compiles the messages once I've changed the language files.
When, if ever, should I use makemessages if compilemessages does the job I am seeking? What is the point of makemessages?
makemessages is used to scan through your apps looking for strings marked for translation. Once it has theses strings it puts them in a po file. If you then add further strings for translating to your app then you will need to run makemessages to generate an updated po file. compilemessages uses the contents of the po file to create a mo file, so the po file must be updated first.
makemessages accepts a param for the locale:
pipenv run django-admin makemessages --locale=de
This allows you to create a po file for each of the locales your app supports.
Related
I'm working with a current project that has existing .po files in "locale" directories in multiple installed app directories. Currently each locale directory is explicitly mentioned in the LOCALE_PATHS even though the docs state it will search for locale directories in each installed app. I wanted to remove the values in LOCALE_PATHS and just let normal discovery work, but it's not working.
If I clear out LOCALE_PATHS and run manage.py makemessages it appears like it's doing something (time is spent processing), but no file changes occur. If I do makemessages --keep-pot then I can see all the .pot files are actually being created, but it's not actually creating the .po files for each language. Only if I explicitly pass a -l de I then get an updated .po file for the language stated and a message stating "processing locale de". It SHOULD be able to look at the LANGUAGES setting or what files already exist and properly update them, but that appears to only happen if every locale directory is explicitly added into LOCALE_PATHS. If I have all the locale paths in LOCALE_PATHS then I can just run manage.py makemessages and all .po files are properly updated.
This is on Django 3.0
UPDATE: I upgraded to Django 3.2 LTS and still have the same issue except now I must add -a to makemessages or it does nothing. Previously it seemed to assume a -a if not provided.
I'm trying to translate a Django app. I created some strings with {% trans %} in my templates. However, when I execute the following command in my app folder, I receive an error message:
$ django-admin.py makemessages -l fr
CommandError: Unable to find a locale path to store translations for file __init__.py`
What did I do wrong?
Turns out you need to create a locale folder first using mkdir locale. If you are running the command from within an app folder, you need a locale folder within that app folder.
Actually you can configure where the locale folder is. In your settings.py add:
LOCALE_PATHS = (
PROJECT_ROOT + '/website/locale', )
Then create a folder for each of the languages you want to translate:
mkdir -p website/locale/de
The problem is that the command is not run from the app directory but from the project directory. This snippet from the docs explains it:
Turns out you need to create a locale folder first using mkdir locale.
./manage.py makemessages […] Runs over the entire source tree of the current directory and pulls out all strings marked for translation. It creates (or updates) a message file in the conf/locale (in the Django tree) or locale (for project and application) directory.
So, you either run the command from the app directory:
$ cd app
$ django-admin makemessages -l <locale>
… or you define a project wide locale directory using LOCALE_PATHS and you can run makemessages from the main directory from there on.
Either way, you should check that the ./locale/directory is present and create it using
$ mkdir locale
in case it's not.
If you want per-app locale dirs, simply create them in every app dir with translation strings (that has files with translation strings) before running makemessages. And django will find them. No need to cd.
If you want one project-wide locale dir, create it in the project dir before running makemessages.
For me, I had LOCALE_PATHS set correctly, but I did not have the environment variables set. When I set the environment variables, I ran python manage.py makemessages -l de and it ran correctly.
I can switch languages in my Django application by changing LANGUAGE_CODE in the Settings.py file for the application.
But I'm not sure where the actual text is coming from.
In path-to-django/contrib/auth/locale/, there are directories for many languages containing the translations of the text I'm displaying. But if I move an .mo file for a particular language to a new name, I still see text for that language -- even after I restart Django. So where does the text actually come from?
Also, for the 'en' locale, the translated text is always "" (empty string). Does ugettext_lazy just return its input string in that case? If not, where does the English text come from?
It is a difference, if you speak of translation in the django admin or within your application. The path you mentioned .../contrib/auth/locale refers to translations in the django admin.
For special translation within your application you should have a locale/ folder in your project. This folder is created when you run the django special script named "django-admin.py makemessages".
The script runs over your project source tree or your application
source tree and pulls out all strings marked for translation. It
creates (or updates) a message file in the directory
locale/LANG/LC_MESSAGES. In the de example, the file will be
locale/de/LC_MESSAGES/django.po.
For detailed explanation, please look at django i18n documentation
After you have created your message files (*.po) and after you have written your own translations in the message files, don't forget to compile them:
Compiling message files
After you create your message file -- and each
time you make changes to it -- you'll need to compile it into a more
efficient form, for use by gettext. Do this with the django-admin.py
compilemessages utility.
This tool runs over all available .po files and creates .mo files,
which are binary files optimized for use by gettext. In the same
directory from which you ran django-admin.py makemessages, run
django-admin.py compilemessages like this:
django-admin.py compilemessages
That's it. Your translations are ready for use.
It turns out there was a system-wide Django installation that was being used, rather than my local installation.
By creating a locale directory within my app, I'm able to override the strings used in the system-wide installation. I just modify the .po file there, and compile it.
I have an application located in one folder, and templates for it in another one...
I have added translation strings to the templates (which are stored in templates directory, I have one directory for all templates in my application)
When I go to the application folder and run a script there:
silver:articles oleg$ django-admin.py makemessages -l ru
processing language ru silver:articles
oleg$
I am getting empty
silver:articles oleg$ ls locale/ru/LC_MESSAGES/
silver:articles oleg$
And when I am running this command for example in project root, I am getting po file full made from python files (which seems strange to me because I thought it should be created from htmls)
makemessages always looks for strings marked for translation in python code files.
except for that, it looks in all .html files. maybe your templates have another extension? If that's the case you can use -e to specify other extension:
django-admin.py makemessages -l=ru -e=html,htm,txt
E.g. in my django source I have:
{% blocktrans %}You are a member since {{sincewhen}}{% endblocktrans %}
What should go into the .po file? (django docs don't explain this part as far as I could find)
Is .po format for placeholders universal for use in programs written in different programming languages?
edit: I've tried commands
django-admin.py makemessages -l de -e=html,py
django-admin.py compilemessages
This did not work because of a bug that I found and described here.
After this was fixed I could get the message files generated with the command above (if you have other file extensions - modify -e option accordingly.
Read this section: Message files
It explains how to generate .po files and gives an example:
django-admin.py makemessages -l de
Make sure you read that whole section to get an idea of how to generate/edit these files. Also, if you're looking for a great tool to help you manage your translations (and even use Google translations to use as a starting place), check out django-rosetta.
Use:
python manage.py makemessages -l <target_language>
(or makemessages -a for all languages)
That'll automatically create all the msgid's in the po's, all that's left for you is to fill out the msgstr's.
.po is the standard format used by the gettext library, which is available in virtually every modern programming language.