Translations
Gettextopen in new window is a localization framework for writing multi-lingual applications that can also be used in GNOME Shell extensions.
Preparing your extension for Gettext allows your users to contribute localized translations. More information and guides to translating can be found on the GNOME Translation Projectopen in new window wiki.
- Preparing an Extension
- Initializing Translations
- Marking Strings for Translation
- Packing an Extension with Translations
Preparing an Extension
Start by creating a po
directory for the translation template and translated languages:
$ cd ~/.local/share/gnome-shell/extensions
$ mkdir example@shell.gnome.org/po
2
Initializing Translations
Your extension must be configured to initialize translations when it's loaded. This only has to be done once, so the init()
function in extension.js
(and prefs.js
) is the perfect place to do this:
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
function init() {
// ExtensionUtils has a convenient function for doing this
ExtensionUtils.initTranslations(Me.metadata.uuid);
return new Extension();
}
2
3
4
5
6
7
8
9
Marking Strings for Translation
You also need to tell Gettext what strings need to be translated. Gettext functions retrieve the translation during run-time, but also mark strings as translatable for the scanner.
gettext()
This function is the most commonly used function, and is passed a single string.
ngettext()
This function is the other function you are likely to use, and is meant for strings that may or may not be plural like "1 Apple" and "2 Apples".
The
format()
function (seeprintf
open in new window) is available for all strings, but should only be used withngettext()
. In all other cases you should use JavaScript's Template Literalsopen in new window.
const Gettext = imports.gettext;
const St = imports.gi.St;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
// This creates an object with functions for marking strings as translatable.
// You must pass the same domain as `ExtensionUtils.initTranslations()`.
const Domain = Gettext.domain(Me.metadata.uuid);
// These are the two most commonly used Gettext functions. The `gettext()`
// function is often aliased as `_()`
const _ = Domain.gettext;
const ngettext = Domain.ngettext;
class Extension {
constructor() {
this._indicator = null;
this._count = 0;
}
_showNotification() {
this._count += 1;
// A regular translatable string is marked with the `_()` function
let title = _('A Notification');
// A "countable" string is marked with the `ngettext()` function
let body = ngettext(
'You have been notified %d time',
'You have been notified %d times',
this._count
).format(this._count);
Main.notify(title, body);
}
enable() {
let indicatorName = `${Me.metadata.name} Indicator`;
// Create a panel button
this._indicator = new PanelMenu.Button(0.0, indicatorName, false);
// Add an icon
let icon = new St.Icon({
icon_name: 'face-laugh-symbolic',
style_class: 'system-status-icon'
});
this._indicator.add_child(icon);
// Add a menu item that shows a notification.
this._indicator.menu.addAction(
_('Show Notification'),
this._showNotification.bind(this)
);
// Add the indicator to the panel
Main.panel.addToStatusArea(indicatorName, this._indicator);
}
disable() {
log(`disabling ${Me.metadata.name}`);
this._indicator.destroy();
this._indicator = null;
}
}
function init() {
log(`initializing ${Me.metadata.name}`);
// ExtensionUtils has a convenient function for doing this
ExtensionUtils.initTranslations(Me.metadata.uuid);
return new Extension();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Scanning for Translatable Strings
Gettext uses a POT file (portable object template) to store a list of all the translatable strings. You can generate the POT file by scanning your extension's source code with xgettext
:
$ cd ~/.local/share/gnome-shell/extensions/example@shell.gnome.org
$ xgettext --from-code=UTF-8 --output=po/example.pot *.js
2
Translators can use the .pot
file to create a .po
file translated for their language with a program like Gtranslatoropen in new window or POEditopen in new window.
Packing an Extension with Translations
Using the gnome-extensions
tool makes it easy to compile and include the translations with your extension. Simply pass the relative directory po
to the --podir
option when packing your extension:
$ gnome-extensions pack --podir=po example@shell.gnome.org