Gettext: FileNotFoundError: [Errno 2] No translation file found for domain: 'base'

It seems that I am unable to get my GNU gettext utility to work properly, despite closely following both documentation and online resources.

My folder structure is the following:

/
|- src
|    |- __init__.py
|    |- main.py
|- locales
     |- ru
          |- LC_MESSAGES
               |- base.mo
               |- base.po

the top of my main.py reads like this (Windows machine):

import argparse
import gettext
from gettext import gettext as _

argparser = argparse.ArgumentParser()
argparser.add_argument("--language", required=False, default="en")
arguments = argparser.parse_args()
gettext.translation(
    "base", localedir=r".\locales", languages=[arguments.language[:2]]
).install()

And yet, when I try to run the script in either English or Russian, I still get an error:

FileNotFoundError: [Errno 2] No translation file found for domain: 'base'

What am I doing wrong?

I’ve tried putting locales dir inside the src folder and dropping the dot prefix (gettext.translation("base", localedir=r"locales", ...), but it doesn’t seem to have changed anything.

When you install isn’t _ added to builtins still ?

This is relative to where you run the program from.
Calculate the absolute path the locales.

It does, but PyCharm doesn’t know that, and I want to avoid annoying faux syntax errors.

This is relative to where you run the program from.
Calculate the absolute path the locales.

Being explicit about my path with Path(__file__).resolve().parents[1] / "locale" doesn’t seem to have changed anything. Why?:

what is the value of languages=? Is it ru?

In my app i do not set languages at all i let it use the default.
I also add fallback=True.

1 Like

Yes, the value that gets passed over to gettext.translation(languages=) is “ru”:

Weird - adding fallback=True makes the script run, but the translation doesn’t get processed properly at all…:

I suggest that you make a simple test app and generate the gettext files.
Maybe the problem is in your .pot, .po, and .mo files?
Have one message in en and its ru translation.
Can you make that work?

Post the script you use the make the gettext files.

1 Like

Okay, let’s go step by step.

On my Windows 11, 64 bit, English locale, Python 3.10, PyCharm machine.

Here is a sample script:

import gettext
from pathlib import Path
from gettext import gettext as _

gettext.translation(
    "translate",
    localedir=Path(__file__).resolve() / "locale",
    languages="ru",
    fallback=True,
).install()

print(_("Near the seaside, the oak is green"))

The path to the script is:

C:\Users\vladi\AppData\Roaming\JetBrains\PyCharmCE2022.2\scratches\scratch_38.py:

To create .pot file, I run this command in the command line:

python C:\Users\vladi\AppData\Local\Programs\Python\Python310\Tools\i18n\pygettext.py -d translate C:\Users\vladi\AppData\Roaming\JetBrains\PyCharmCE2022.2\scratches\scratch_38.py

Then, I open translate.pot in Poedit, and make the following configuration:

Source text Near the seaside, the oak is green → translation У лукоморья дуб зелёный

I save translate.mo and translate.mo files in the following newly made directory: C:\Users\vladi\AppData\Roaming\JetBrains\PyCharmCE2022.2\scratches\locale\ru\LC_MESSAGES:

translate.po reads as follows:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2022-11-08 09:29+0100\n"
"PO-Revision-Date: 2022-11-08 09:31+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 3.2\n"

#: C:\Users\vladi\AppData\Roaming\JetBrains\PyCharmCE2022.2\scratches\scratch_38.py:12
msgid "Near the seaside, the oak is green"
msgstr "У лукоморья дуб зелёный"

I run the file, and still, I do not receive the Russian translation:

What am I doing wrong?

Instead of languages="ru", have you tried languages=["ru"]?

Here’s how I do it in one of my programs:

Note that I chose to use a different name (something like base_ru.po) for each file so that they are easier to identify when using Poedit, but this should be irrelevant.

3 Likes

Aha, specifying it in a list AND removing the import seems to have worked, but now PyCharm screams as me. I guess I will have to trick PyCharm into thinking that this is okay:

Thank you all. So, the answer is, for any person looking this up into the future:

  1. Try specifying the absolute path

  2. Do not overwrite the underscore after install

  3. Keep in locale in a list.

2 Likes

That not the work flow.

  1. machine generate .pot
  2. machine generate new .po
  3. merge .po with your last translations with new .po
  4. edit merged .po and update translations as required
  5. commit update .po for use in the next interation
  6. generate .mo from merged .po

This is the code I use that sets up the special functions for gettext in my code.
I do not use the _ but setup my own setup of builtins:

        locale_path = wb_platform_specific.getLocalePath()
        self.translation = gettext.translation(
                '-'.join( [part.lower() for part in self.app_name_parts] ),
                str(locale_path),
                # language defaults
                fallback=True )

        import builtins
        # T_( 'non plural' )
        builtins.__dict__['T_'] = self.translation.gettext
        # S_( 'singular', 'plural', n )
        builtins.__dict__['S_'] = self.translation.ngettext
        # U_( 'static string' )
        # define here to keep mypy happy - humm  does not work...
        builtins.__dict__['U_'] = U_

Notice that I get then from the object that gettext.translation() returned to me.

2 Likes