Another implementation of Internationalization for Python scripts in GIMP3

I came up with a new implementation to internationalize of Python scripts. With this implementation, I already made my scripts internationalize. In this method, programmers use plain text files as translation files instead of mo.files which are used in GIMP standard method.

The purpose of this implementation is to allow general end-users whose language files are not supplied to make their language files by themselves. Translation files are “locale” directory under this plug-in’s directory. If they cannot find their language file, can throw “defaut.txt” in locale directory to online AI translation service, and save the result as [your language code].txt in locale directory and they can easily localized my scripts.

You can download relatively simple sample file from here.

This program is constructed with two files. Main file (IN_sample_g3.py) and helper file (translate_smpl.py). Helper file recognizes language environment, reads each language translation file in “locale” directory. The format of translation files are as following. Each line of the file is…

MESSAGE KEY;translated scripts

For example

MNU_LBL;国際化UIサンプル (コンボボックス)
MNU_EXPLANATION;国際化UIのサンプルプログラム
DLG_TITLE;国際化のサンプル
LBL_COMBO_SEL;チャンネルを選択してください:

It is same format as ART / RawTherapee translation files. The helper file save the contents of the file into dictionary type list variable using these message keys. The name of translation file is [locale code].txt. In the case of Japanese, its file name is ja.txt.

Main file prepares this list variable with default value (English descriptions) in advance, and call helper file.

[default value preparation]

import translate_smpl
#------- for Internationalization -----
\# mTrans: list for message translation
mTrans = dict(
	MNU_LBL = "IN sample with Combo box",
	MNU_EXPLANATION ="sample program of Internationalization UI.",
	DLG_TITLE = "sample of Internationalization",
	LBL_COMBO_SEL = "Select the channel:",
	LBL_CHOICE1 = "Lightness",
	LBL_CHOICE2 = "Red",
	LBL_CHOICE3 = "Green",
	LBL_CHOICE4 = "Blue",
	TP_COMBO_SEL = "Select the channel where you can see \n" + \
		"the spots the most clearly.",
	LBL_RESULT = "Input Result:",
	LBL_BUTTON_C ="Cancel",
	LBL_BUTTON_O ="OK",
	MSG_ERR1 = "User canceled the operation."
	)

[call helper file]

def do_set_i18n (self, name):
	print("i18n name: ", name)
	global mTrans
	try:
		print("Read locale file Start")
		mTrans = translate_smpl.open_locale_file(mTrans)
	except:
		print("cannot read translation list")

	return True

If helper file successfully reads the language file, the contents of the list variable are replaced with the contents of the language file otherwise, they are kept. And actual messages are called with this list variable using Message Key, like…

channels = [
	mTrans["LBL_CHOICE1"],
	mTrans["LBL_CHOICE2"],
	mTrans["LBL_CHOICE3"],
	mTrans["LBL_CHOICE4"]
]

I prepared default.txt file. This file is not used in the operation. It is for end-users’ translation. If you are a programmer, you must make Message Key not to be translated with AI translation services. Because end-users may try to translate the default file using these translation services.

For example, if you make Message Key and actual message combination like…

RED;Red

it is easily translated as follows.

ROUGE;Rouge

In this case, end-users must fix Message Key back to the way it was.

If you make this combination like follows…

LBL_RED;Red

The Message Key will not be translated and only actual message will be translated like…

LBL_RED;Rouge

In this case, end-users can make immediately their translation file. Only they have to do is save the translated result as text file with appropriate file name, and place it in locale directory.

I admit the merit of using poedit to make translation files, however I think it is appropriate to make them for complicated system like GIMP main program. Translation files for each plug-in are relatively short and simple. It is hard for end-users to download and install poedit and to study using it to translate each short plug-in. And even if you adopt this implementation, it has no harmful effects to other plug-ins or GIMP’s eco-system.

Interesting, but I still prefer to use .po/ .mo files for my stuff.
Why should we reinvent the wheel?
Using poedit for translating isn’t too difficult.

As I have already written, this is to allow general end-users who are unfamiliar with poedit to translate plug-in files to their own language without the learning cost. I am not proposing to change the current whole GIMP translation system, which is supported by experienced volunteer translators. I think it is up to each plugin author to decide what kind of translation system to use.

And I would like to memorize here what I found during this programming.

If users set their GIMP3 UI language explicitly in preference, the setting is saved in environment variable “LANGUAGE”. However, if uses don’t set UI language explicitly and OS system language is used, “LANGUAGE” has no value (None). In this case, programmers must get UI language setting from “LANG” which is set by OS itself. There may be difference between values from “LANGUAGE” and “LANG”. For example, in Japanese Ubuntu like system, the value from “LANGUAGE” is “ja” but the value from “LANG” is “ja-JP.UTF-8”. In Japanese Windows, there is no difference between the values. GIMP 3.04 on Mac OS is more problematic. In Mac OS Japanese 15.6 + python-fu on GIMP 3.04, if users set explicitly their UI language in preference, they can get the value “ja” from “LANGUAGE”. However, if they don’t set UI language explicitly and use OS system language settings, they cannot get any language settings on python-fu: “LANG” and “LANGUAGE” have None. Therefor Mac OS users must set their GIMP UI language explicitly in preference to localize internationalized plug-ins. It is the same for using gettext.gettext() API to localize plug-ins.


And there are also some problems in flatpak.
Let’s assume you installed GIMP3 with flatpak, and put GIMP plug-ins under $HOME/.config/GIMP/3.0/plug-ins/ . If you try to get the plug-in directory name using os.path.dirname(__file__), the returned result is not the actual directory: the result is always $HOME/.var/app/org.gimp.GIMP/config/GIMP/3.0/plug-ins/[plug-in name].

I’m not sure the reason. Flatpak GIMP may copy the plug-ins to the directory or something. However if you put some files like translation files under the sub-directory of the plug-in directory, I found that sometimes the plug-in faults to get these files. I tried to get translation files in locale directory under the plug-in directory. They were in $HOME/.config/GIMP/3.0/plug-ins/[plug-in name]/locale . However using os.path.dirname(__file__), the plug-in tried to search $HOME/.var/app/org.gimp.GIMP/config/GIMP/3.0/plug-ins/[plug-in name]/locale directory which didn’t actually exist.

So I inserted following code to fix this problem.

if dirName.find("org.gimp.GIMP") != -1:
	dirName = \
	dirName.replace(".var/app/org.gimp.GIMP/config",".config")

This is a great solution – thank you for the detailed explanation.
Poedit is a great program, but it requires downloading, installing, and mastering the basics.
Furthermore, MO files can be problematic, as I’ve encountered various localization requirements, and there’s also the issue of the author not including a PO (or POT) file and wanting to change something in the translation.
You can convert MO to PO using the console (cmd) and the msgunfmt command, but that’s not something you’d expect from a typical user.
Your method eliminates these potential complications.

1 Like

Thank you!

I totally agree and support, the proposed method is much simpler.
For translations, you can use, for example. QTranslate

1 Like