Here are the steps for re-creating a minimal example on Debian. I can't tell how portable this example actually is to other OS'es, but at least it's some starting point. Working with locales is not straight forward IMHO. Most of the mechanics in internationalization in GtkAda revolves around the package gtkada-intl.ads.
First of all I enabled the locales of interest by running
$ sudo dpkg-reconfigure locales
I wanted test translations for Dutch and French so I selected fr_FR.UTF-8 and nl_NL.UTF-8 in addition to those already selected (like, in my case, en_US.UTF-8). I also kept en_US.UTF-8 as the default locale. This was my locale configuration after the reconfiguration:
$ locale -a
C
C.UTF-8
en_US.utf8
fr_FR.utf8
nl_NL.utf8
POSIX
I then created a simple Glade UI file with a window (with title "English") containing one label (with text "Hello world!"). I made sure that all the texts were marked "translatable". This is a property attribute that can be enabled via the "Edit Text" dialog box. This dialog box can be accessed by clicking the button on the right side of the text area where you enter, for example, the label text.
example.glade (note in particular the translatable="yes" attributes)
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.16.1 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkWindow" id="Window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">English</property>
<property name="window_position">center</property>
<property name="default_width">300</property>
<property name="default_height">60</property>
<child>
<object class="GtkLabel" id="Label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Hello world!</property>
</object>
</child>
</object>
</interface>
I now created two translation files (.po files) as shown below: one for Dutch and one for French. Note how the msgid matches the window title text and label text.
translations_nl.po
msgid "English"
msgstr "Nederlands"
msgid "Hello world!"
msgstr "Hallo wereld!"
translations_fr.po
msgid "English"
msgstr "Français"
msgid "Hello world!"
msgstr "Bonjour le monde!"
These files must be converted to machine readable files using the msgfmt tool that ships with GtkAda (see GtkAda's bin directory), i.e.
$ msgfmt translations_nl.po -o messages.mo
I finally created a project and the required Ada sources using GNAT Studio CE 2020 (sources are at the end of this answer). I made sure all files were organized as follows:
example/
+- example.glade
+- default.gpr
+- obj/
| +- <various build files>
+- src/
| +- main.adb
| +- translation_demo.ads
| +- translation_demo.adb
| +- po/
| +- translations_nl.po
| +- translations_fr.po
+- locales/
+- nl_NL/
| +- LC_MESSAGES/
| +- messages.mo (generated using msgfmt)
+- fr_FR/
+- LC_MESSAGES/
+- messages.mo (generated using msgfmt)
If all goes well, then after building and running the executable, the proper translations will appear in the UI depending on the setting of the LANGUAGE environment variable.
Note that in this example I set the LANGUAGE environment variable from within the program using the Ada.Environment_Variables.Set procedure (see main.adb). This is only to show how to control the language from within your program at application startup (e.g. in case you want to control the language via a configuration file read at startup; an approach that might be needed on OS'es other than Linux). On Debian (and Linux in general), the LANGUAGE environment variable is typically set by the OS on behalf of the user (check output of the env command).
As an alternative, you might also try the example without setting the environment variable in main.adb and check the result if you start the program via
LANGUAGE=nl_NL ./obj/main
or
LANGUAGE=fr_FR ./obj/main.adb
In conclusion, note that the process of getting this to work is a precise process: Debian must know the locales nl_NL.UTF-8 and fr_FR.UTF-8, the .mo files must be available in the correct directories and the LANGUAGE environment variable must be set. Furthermore, because I use relative paths in the example code, the application must be started from project root directory, i.e.
$ ./obj/main
If something is wrong, then the translation will just not happen and no error and or warning will be provided.
main.adb
with Ada.Environment_Variables;
with Translation_Demo;
procedure Main is
NL : constant string := "nl_NL:nl";
FR : constant String := "fr_FR:fr";
begin
-- Set environment varianble.
Ada.Environment_Variables.Set ("LANGUAGE", NL);
Translation_Demo.Run;
end Main;
translation_demo.ads
package Translation_Demo is
procedure Run;
end Translation_Demo;
translation_demo.adb
with Ada.Text_IO;
with Gtk.Main;
with Gtk.Widget;
with Gtk.Builder;
with Gtk.Window;
with Gtk.Button;
with Gtkada.Intl;
with Glib; use Glib;
with Glib.Error; use Glib.Error;
package body Translation_Demo is
-- Name of the .mo file without extention.
Text_Domain : constant String := "messages";
-- (Relative) location of the <lang>/LC_MESSAGES/<domain>.mo files.
Text_Domain_Dir : constant String := "./locale";
-- (Relative) location of the Glade file.
Glade_File : constant String := "./example.glade";
Builder : Gtk.Builder.Gtk_Builder;
Window : Gtk.Window.Gtk_Window;
procedure Destroy_Event_Callback
(Widget : access Gtk.Widget.Gtk_Widget_Record'Class);
---------
-- Run --
---------
procedure Run is
use Gtk.Builder;
use Gtk.Window;
Success : GUint;
Error : aliased GError;
begin
-- Initialize GtkAda.
Gtk.Main.Init;
-- Setup the translation domain and directory where to find the .mo files.
Gtkada.Intl.Setlocale;
Gtkada.Intl.Text_Domain (Text_Domain);
Gtkada.Intl.Bind_Text_Domain (Text_Domain, Text_Domain_Dir);
-- Construct a Gtk_Builder instance and load our UI description.
Gtk_New (Builder);
-- Set the translation domain for the Glade file.
Builder.Set_Translation_Domain (Text_Domain);
-- Read the Glade file.
Success := Builder.Add_From_File (Glade_File, Error'Access);
if Success = 0 then
Ada.Text_IO.Put_Line ("failed to read Glade file");
Error_Free (Error);
Gtk.Main.Main_Quit;
end if;
-- Window
Window := Gtk_Window (Builder.Get_Object ("Window"));
Window.On_Destroy (Destroy_Event_Callback'Access);
Window.Show_All;
-- Start the main event loop
Gtk.Main.Main;
end Run;
----------------------------
-- Destroy_Event_Callback --
----------------------------
procedure Destroy_Event_Callback
(Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
is
begin
Gtk.Main.Main_Quit;
end Destroy_Event_Callback;
end Translation_Demo;
default.gpr
with "gtkada";
project Default is
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Main use ("main.adb");
end Default;