How to Translate Strings#
How does it work?#
The NeoMutt program is written in English, but it has been through a process of Internationalization and Localization.
Internationalization (abbreviated to i18n):
is changing the source code of a program to allow it to look up strings that need translation
is done by programmers
Localization (abbreviated to l10n):
is providing a list of translated strings for a language
is done by translators
does not require programming skills
The translation team is currently managed by Rich Russon (flatcap).
It would be a great help to the project (and Rich) if someone volunteered to help with this.
State of the translations#
NeoMutt builds upon Mutt, so it has inherited its translations. Mutt hasn’t changed much (in years), so most of them are still correct.
Here are some recent statistics for the Swedish translation:
Count |
Description |
|---|---|
1321 |
Total number of strings to be translated |
998 |
Already translated |
219 |
Fuzzy – need checking by a human |
104 |
To do – need translating |
The “fuzzy” translations appear when the msgfmt tool finds a translation that
it thinks is correct. These translations are often wrong.
Is the job technical?#
No, it’s quite simple – you just need to be multi-lingual.
The translations are stored in “Portable Object” text files (.po)
Here’s a sample from the Japanese translation (ja.po)
#: main.c:905
msgid "Mailbox is empty."
msgstr "メールボックスが空。"
A comment, starting with a
#“msgid” – the string in English
“msgstr” – the string in Japanese
There are plenty of tools to help you with the translation process. One of them is “poedit” – it’s quite simple to use. This screenshot shows some translated, some fuzzy and some untranslated strings.
Notes:
Comments: “poedit” allows you to add comments to each translation. If you think that the comment should apply to all translations, then notify the NeoMutt project and they can add the comment to the source.
Context: The strings are sometimes hard to translate because they have no context. If you have any questions, ask the translations manager (at the top of the page).
More information#
The translation mechanism uses GNU’s “gettext”. Here are some of the relevant parts of their docs:
If you’re technical you could look at the NeoMutt source code:
git clone -b translate https://github.com/neomutt/neomutt
Translate-fu#
There’s a pretty good editor for translation files: ‘poedit’, but some of us are only really happy at the command line.
Here are some hints to improve your translate-fu!
msgattrib - Filter#
This tool will extract a subset of translations, e.g. fuzzy or untranslated:
msgattrib --no-wrap --only-fuzzy de.po > de-fuzzy.po
msgattrib --no-wrap --untranslated de.po > de-untrans.po
Now you can focus on just bits that need some work.
msggrep - Search#
This is a powerful search tool. You can find regexes in the msgid, msgstr or comments. Recently, I wanted to examine the overlap between the IDN messages, so I used:
msggrep --no-wrap --msgid -e IDN fr.po > fr-idn.po
msgcat - Combine#
Now that we’ve finished working, we want to re-combine the files. We can use msgcat to merge them:
msgcat --no-wrap --use-first de-fuzzy.po de.po > de-new.po
Note: Some reordering might occur, so --sort-by-file might help.
msgfmt - Stats#
To check the validity of your translation files, and to get some stats, we can use msgfmt. We don’t the save compiled message file, though.
msgfmt --statistics -c -o null.md fr.po
1087 translated messages, 185 fuzzy translations, 74 untranslated messages.
Viewing the Source#
Ideally, the L10n comments should be enough to tell the translator everything they need to know. Sometimes, though, looking at the source can make things much clearer much more quickly.
Each of the translations is preceded by a location line:
#: compose.c:118 compose.c:970 send.c:292
Vim users can use the gF (goto file) command which will open the file under the cursor and go to the exact source line you want.
Vim Tips#
Here are some tips from @mgedmin.
Find the next untranslated message with /msgstr ""\ze\n\n/e.
The \n\n avoids false matches from multiline translations, the \ze and /e position the cursor between the double quotes.
This can be wrapped up in a custom command: Find untranslated:
command! FindUntranslated normal /msgstr ""\ze\n\n/e<cr>
Find untranslated or fuzzy:
command! FindUntranslatedOrFuzzy normal /msgstr ""\ze\n\n\|^#.*, \zsfuzzy\>/e<cr>
Print stats:
command! -bar PoStats echo system("msgfmt --statistics -c -o null.md -", bufnr("%"))
Finally a function to remove the fuzzy flag: ftplugin/po.vim
Testing a Translation#
Developers can test a translation without installing it, with a small amount of setup.
This example is for the German locale:
Locale:
de_DE.utf-8Translation file:
po/de.po
Setup:
# Clone the source
cd
git clone https://github.com/neomutt/neomutt neomutt
# Edit translations
# Build source
# Link a message file into the source tree
cd
mkdir -p de_DE.utf-8/LC_MESSAGES
cd de_DE.utf-8/LC_MESSAGES
ln -s ~/neomutt/po/de.mo neomutt.mo
# Run NeoMutt using the locale
cd ~/neomutt
export LANG=de_DE.utf-8
export TEXTDOMAINDIR=$HOME
./neomutt
When run, NeoMutt will use the environment variables $LANG and
$TEXTDOMAINDIR to find the translation strings.