i18n: add gettext support

parent 3a8b816a
...@@ -48,8 +48,9 @@ A component of the Ximper Shell. ...@@ -48,8 +48,9 @@ A component of the Ximper Shell.
%install %install
%meson_install %meson_install
%find_lang %name
%files %files -f %name.lang
%_bindir/%name %_bindir/%name
%_bindir/%name-client %_bindir/%name-client
......
...@@ -54,7 +54,7 @@ template $XimperShellNotificationCenterWidgetsNotifications: $XimperShellNotific ...@@ -54,7 +54,7 @@ template $XimperShellNotificationCenterWidgetsNotifications: $XimperShellNotific
} }
Label text_empty_label { Label text_empty_label {
label: "No Notifications"; label: _("No Notifications");
} }
}; };
} }
......
...@@ -6,6 +6,7 @@ project('ximper-shell-notification-center', ['c', 'vala'], ...@@ -6,6 +6,7 @@ project('ximper-shell-notification-center', ['c', 'vala'],
add_project_arguments(['-w'], language: 'c') add_project_arguments(['-w'], language: 'c')
add_project_arguments(['-Wno-error=int-conversion'], language: 'c') add_project_arguments(['-Wno-error=int-conversion'], language: 'c')
add_project_arguments(['-DGETTEXT_PACKAGE="' + meson.project_name() + '"'], language: 'c')
add_project_arguments(['--enable-gobject-tracing'], language: 'vala') add_project_arguments(['--enable-gobject-tracing'], language: 'vala')
add_project_arguments(['--enable-checking'], language: 'vala') add_project_arguments(['--enable-checking'], language: 'vala')
...@@ -15,6 +16,7 @@ cc = meson.get_compiler('c') ...@@ -15,6 +16,7 @@ cc = meson.get_compiler('c')
vala = meson.get_compiler('vala') vala = meson.get_compiler('vala')
gnome = import('gnome') gnome = import('gnome')
i18n = import('i18n')
app_resources = [] app_resources = []
...@@ -26,6 +28,7 @@ libdir = get_option('libdir') ...@@ -26,6 +28,7 @@ libdir = get_option('libdir')
protocol_dep = [] protocol_dep = []
subdir('protocols') subdir('protocols')
subdir('po')
subdir('data') subdir('data')
subdir('src') subdir('src')
......
src/main.vala
src/notification/notification.vala
src/configModel/configModel.vala
src/controlCenter/widgets/title/title.vala
src/controlCenter/widgets/dnd/dnd.vala
src/controlCenter/widgets/inhibitors/inhibitors.vala
src/controlCenter/widgets/volume/volume.vala
src/controlCenter/widgets/backlight/backlight.vala
src/controlCenter/widgets/slider/slider.vala
src/controlCenter/widgets/menubar/menubar.vala
src/controlCenter/widgets/powerProfiles/powerProfiles.vala
data/ui/notifications_widget.blp
i18n.gettext(meson.project_name(), preset: 'glib')
# Russian translation for ximper-shell-notification-center
# Copyright (C) 2026 Ximper Linux
# This file is distributed under the same license as the
# ximper-shell-notification-center package.
#
msgid ""
msgstr ""
"Project-Id-Version: ximper-shell-notification-center 0.1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-22 17:23+0300\n"
"PO-Revision-Date: 2026-03-22 17:23+0300\n"
"Last-Translator: \n"
"Language-Team: Russian\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<10 || n%100>=20) ? 1 : 2);\n"
#: src/notification/notification.vala:539
msgid "Enter Text"
msgstr "Введите текст"
#: src/notification/notification.vala:551
msgid "Reply"
msgstr "Ответить"
#: src/notification/notification.vala:579
#, c-format
msgid "COPY \"%s\""
msgstr "КОПИРОВАТЬ \"%s\""
#: src/notification/notification.vala:621
msgid "Now"
msgstr "Сейчас"
#: src/notification/notification.vala:625
#, c-format
msgid "%d min ago"
msgid_plural "%d mins ago"
msgstr[0] "%d мин. назад"
msgstr[1] "%d мин. назад"
msgstr[2] "%d мин. назад"
#: src/notification/notification.vala:629
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ч. назад"
msgstr[1] "%d ч. назад"
msgstr[2] "%d ч. назад"
#: src/notification/notification.vala:633
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d д. назад"
msgstr[1] "%d д. назад"
msgstr[2] "%d д. назад"
#: src/controlCenter/widgets/title/title.vala:19
msgid "Notifications"
msgstr "Уведомления"
#: src/controlCenter/widgets/title/title.vala:20
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:20
msgid "Clear All"
msgstr "Очистить"
#: src/controlCenter/widgets/dnd/dnd.vala:17
msgid "Do Not Disturb"
msgstr "Не беспокоить"
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:19
msgid "Inhibitors"
msgstr "Блокировки"
#: src/controlCenter/widgets/volume/volume.vala:53
msgid "No active sink input"
msgstr "Нет активного источника"
#: src/controlCenter/widgets/volume/volume.vala:58
msgid "Volume"
msgstr "Громкость"
#: src/controlCenter/widgets/backlight/backlight.vala:26
msgid "Brightness"
msgstr "Яркость"
#: src/controlCenter/widgets/slider/slider.vala:28
msgid "Slider"
msgstr "Ползунок"
#: src/controlCenter/widgets/menubar/menubar.vala:264
msgid "Menu"
msgstr "Меню"
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:149
msgid "Performance"
msgstr "Производительность"
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:150
msgid "Balanced"
msgstr "Баланс"
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:151
msgid "Power Saver"
msgstr "Энергосбережение"
#: src/controlCenter/widgets/notifications/notifications.vala:56
msgid "No Notifications"
msgstr "Нет уведомлений"
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-22 17:23+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: src/notification/notification.vala:539
msgid "Enter Text"
msgstr ""
#: src/notification/notification.vala:551
msgid "Reply"
msgstr ""
#: src/notification/notification.vala:579
#, c-format
msgid "COPY \"%s\""
msgstr ""
#: src/notification/notification.vala:621
msgid "Now"
msgstr ""
#: src/notification/notification.vala:625
#, c-format
msgid "%d min ago"
msgid_plural "%d mins ago"
msgstr[0] ""
msgstr[1] ""
#: src/notification/notification.vala:629
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] ""
msgstr[1] ""
#: src/notification/notification.vala:633
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] ""
msgstr[1] ""
#: src/controlCenter/widgets/title/title.vala:19
msgid "Notifications"
msgstr ""
#: src/controlCenter/widgets/title/title.vala:20
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:20
msgid "Clear All"
msgstr ""
#: src/controlCenter/widgets/dnd/dnd.vala:17
msgid "Do Not Disturb"
msgstr ""
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:19
msgid "Inhibitors"
msgstr ""
#: src/controlCenter/widgets/volume/volume.vala:53
msgid "No active sink input"
msgstr ""
#: src/controlCenter/widgets/volume/volume.vala:58
msgid "Volume"
msgstr ""
#: src/controlCenter/widgets/backlight/backlight.vala:26
msgid "Brightness"
msgstr ""
#: src/controlCenter/widgets/slider/slider.vala:28
msgid "Slider"
msgstr ""
#: src/controlCenter/widgets/menubar/menubar.vala:264
msgid "Menu"
msgstr ""
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:149
msgid "Performance"
msgstr ""
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:150
msgid "Balanced"
msgstr ""
#: src/controlCenter/widgets/powerProfiles/powerProfiles.vala:151
msgid "Power Saver"
msgstr ""
#: src/controlCenter/widgets/notifications/notifications.vala:56
msgid "No Notifications"
msgstr ""
public class Constants { public class Constants {
public const string VERSION = @VERSION@; public const string VERSION = @VERSION@;
public const string VERSIONNUM = @VERSION_NUM@; public const string VERSIONNUM = @VERSION_NUM@;
public const string GETTEXT_PACKAGE = @GETTEXT_PACKAGE@;
public const string LOCALEDIR = @LOCALEDIR@;
public const uint ANIMATION_DURATION = 400; public const uint ANIMATION_DURATION = 400;
} }
...@@ -23,7 +23,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -23,7 +23,7 @@ namespace XimperShellNotificationCenter.Widgets {
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
string ?label = get_prop<string> (config, "label"); string ?label = get_prop<string> (config, "label");
label_widget.set_label (label ?? "Brightness"); label_widget.set_label (label ?? _("Brightness"));
string device = (get_prop<string> (config, "device") ?? "intel_backlight"); string device = (get_prop<string> (config, "device") ?? "intel_backlight");
string subsystem = (get_prop<string> (config, "subsystem") ?? "backlight"); string subsystem = (get_prop<string> (config, "subsystem") ?? "backlight");
int min = int.max (0, get_prop<int> (config, "min")); int min = int.max (0, get_prop<int> (config, "min"));
......
...@@ -10,10 +10,11 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -10,10 +10,11 @@ namespace XimperShellNotificationCenter.Widgets {
Gtk.Switch dnd_button; Gtk.Switch dnd_button;
// Default config values // Default config values
string title = "Do Not Disturb"; string title;
public Dnd (string suffix) { public Dnd (string suffix) {
base (suffix); base (suffix);
title = _("Do Not Disturb");
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
......
...@@ -10,12 +10,14 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -10,12 +10,14 @@ namespace XimperShellNotificationCenter.Widgets {
Gtk.Button clear_all_button; Gtk.Button clear_all_button;
// Default config values // Default config values
string title = "Inhibitors"; string title;
bool has_clear_all_button = true; bool has_clear_all_button = true;
string button_text = "Clear All"; string button_text;
public Inhibitors (string suffix) { public Inhibitors (string suffix) {
base (suffix); base (suffix);
title = _("Inhibitors");
button_text = _("Clear All");
ximper_shell_notification_center_daemon.inhibited_changed.connect ((length) => { ximper_shell_notification_center_daemon.inhibited_changed.connect ((length) => {
if (!ximper_shell_notification_center_daemon.inhibited) { if (!ximper_shell_notification_center_daemon.inhibited) {
......
...@@ -261,7 +261,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -261,7 +261,7 @@ namespace XimperShellNotificationCenter.Widgets {
string ?label = get_prop<string> (obj, "label"); string ?label = get_prop<string> (obj, "label");
if (label == null) { if (label == null) {
label = "Menu"; label = _("Menu");
info ("No label for menu-object given using default"); info ("No label for menu-object given using default");
} }
......
...@@ -50,7 +50,10 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -50,7 +50,10 @@ namespace XimperShellNotificationCenter.Widgets {
notify["expanded-group"].connect (expanded_changed); notify["expanded-group"].connect (expanded_changed);
// TODO: Move this into notifications config! // TODO: Move this into notifications config!
text_empty_label.set_text (ConfigModel.instance.text_empty); string empty_text = ConfigModel.instance.text_empty;
text_empty_label.set_text (
empty_text == "No Notifications"
? _("No Notifications") : empty_text);
stack.set_visible_child_name (STACK_PLACEHOLDER_PAGE); stack.set_visible_child_name (STACK_PLACEHOLDER_PAGE);
......
...@@ -146,9 +146,9 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -146,9 +146,9 @@ namespace XimperShellNotificationCenter.Widgets {
private string get_default_label (string profile) { private string get_default_label (string profile) {
switch (profile) { switch (profile) {
case "performance": return "\xf0\x9f\x9a\x80 Performance"; case "performance": return _("Performance");
case "balanced": return "\xe2\x9a\x96 Balanced"; case "balanced": return _("Balanced");
case "power-saver": return "\xf0\x9f\x94\x8b Power Saver"; case "power-saver": return _("Power Saver");
default: return profile; default: return profile;
} }
} }
......
...@@ -25,7 +25,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -25,7 +25,7 @@ namespace XimperShellNotificationCenter.Widgets {
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
string ?label = get_prop<string> (config, "label"); string ?label = get_prop<string> (config, "label");
label_widget.set_label (label ?? "Slider"); label_widget.set_label (label ?? _("Slider"));
cmd_setter = get_prop<string> (config, "cmd_setter") ?? ""; cmd_setter = get_prop<string> (config, "cmd_setter") ?? "";
cmd_getter = get_prop<string> (config, "cmd_getter") ?? ""; cmd_getter = get_prop<string> (config, "cmd_getter") ?? "";
......
...@@ -10,12 +10,14 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -10,12 +10,14 @@ namespace XimperShellNotificationCenter.Widgets {
Gtk.Button clear_all_button; Gtk.Button clear_all_button;
// Default config values // Default config values
string title = "Notifications"; string title;
bool has_clear_all_button = true; bool has_clear_all_button = true;
string button_text = "Clear All"; string button_text;
public Title (string suffix) { public Title (string suffix) {
base (suffix); base (suffix);
title = _("Notifications");
button_text = _("Clear All");
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
......
...@@ -16,7 +16,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -16,7 +16,7 @@ namespace XimperShellNotificationCenter.Widgets {
Gtk.ToggleButton reveal_button; Gtk.ToggleButton reveal_button;
Gtk.Revealer revealer; Gtk.Revealer revealer;
Gtk.Label no_sink_inputs_label; Gtk.Label no_sink_inputs_label;
string empty_label = "No active sink input"; string empty_label;
string ?expand_label = null; string ?expand_label = null;
string ?collapse_label = null; string ?collapse_label = null;
...@@ -50,11 +50,12 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -50,11 +50,12 @@ namespace XimperShellNotificationCenter.Widgets {
public Volume (string suffix) { public Volume (string suffix) {
base (suffix); base (suffix);
empty_label = _("No active sink input");
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
string ?label = get_prop<string> (config, "label"); string ?label = get_prop<string> (config, "label");
label_widget.set_label (label ?? "Volume"); label_widget.set_label (label ?? _("Volume"));
bool show_per_app_found; bool show_per_app_found;
bool ?show_per_app = get_prop<bool> (config, "show-per-app", bool ?show_per_app = get_prop<bool> (config, "show-per-app",
......
...@@ -268,6 +268,11 @@ namespace XimperShellNotificationCenter { ...@@ -268,6 +268,11 @@ namespace XimperShellNotificationCenter {
} }
} }
Intl.setlocale (LocaleCategory.ALL, "");
Intl.bindtextdomain (Constants.GETTEXT_PACKAGE, Constants.LOCALEDIR);
Intl.bind_textdomain_codeset (Constants.GETTEXT_PACKAGE, "UTF-8");
Intl.textdomain (Constants.GETTEXT_PACKAGE);
print_startup_info (); print_startup_info ();
// Register custom Widgets so that they can be used in .ui template files // Register custom Widgets so that they can be used in .ui template files
......
...@@ -16,6 +16,8 @@ version = 'ximper-shell-notification-center @0@'.format(version) ...@@ -16,6 +16,8 @@ version = 'ximper-shell-notification-center @0@'.format(version)
const_config_data = configuration_data() const_config_data = configuration_data()
const_config_data.set_quoted('VERSION', version) const_config_data.set_quoted('VERSION', version)
const_config_data.set_quoted('VERSION_NUM', meson.project_version()) const_config_data.set_quoted('VERSION_NUM', meson.project_version())
const_config_data.set_quoted('GETTEXT_PACKAGE', meson.project_name())
const_config_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
constants = configure_file( constants = configure_file(
input : 'constants.vala.in', input : 'constants.vala.in',
output : 'constants.vala', output : 'constants.vala',
......
...@@ -536,7 +536,7 @@ namespace XimperShellNotificationCenter { ...@@ -536,7 +536,7 @@ namespace XimperShellNotificationCenter {
inline_reply_box.set_visible (true); inline_reply_box.set_visible (true);
inline_reply_entry.set_placeholder_text ( inline_reply_entry.set_placeholder_text (
param.inline_reply_placeholder ?? "Enter Text"); param.inline_reply_placeholder ?? _("Enter Text"));
// Set reply Button sensitivity to disabled if Entry text is empty // Set reply Button sensitivity to disabled if Entry text is empty
inline_reply_entry.bind_property ( inline_reply_entry.bind_property (
"text", "text",
...@@ -548,7 +548,7 @@ namespace XimperShellNotificationCenter { ...@@ -548,7 +548,7 @@ namespace XimperShellNotificationCenter {
}, },
null); null);
inline_reply_button.set_label (param.inline_reply.text ?? "Reply"); inline_reply_button.set_label (param.inline_reply.text ?? _("Reply"));
} }
private void set_actions () { private void set_actions () {
...@@ -576,7 +576,7 @@ namespace XimperShellNotificationCenter { ...@@ -576,7 +576,7 @@ namespace XimperShellNotificationCenter {
alt_actions_box.append (flowbox_child); alt_actions_box.append (flowbox_child);
Gtk.Button action_button = new Gtk.Button.with_label ( Gtk.Button action_button = new Gtk.Button.with_label (
"COPY \"%s\"".printf (code)); _("COPY \"%s\"").printf (code));
action_button.clicked.connect (() => { action_button.clicked.connect (() => {
// Copy to clipboard // Copy to clipboard
get_clipboard ().set_text (code); get_clipboard ().set_text (code);
...@@ -613,40 +613,25 @@ namespace XimperShellNotificationCenter { ...@@ -613,40 +613,25 @@ namespace XimperShellNotificationCenter {
} }
private string get_relative_time () { private string get_relative_time () {
string value = "";
double diff = (get_real_time () * 0.000001) - param.time; double diff = (get_real_time () * 0.000001) - param.time;
double secs = diff / 60; double mins = diff / 60;
double hours = secs / 60; double hours = mins / 60;
double days = hours / 24; double days = hours / 24;
if (secs < 1) { if (mins < 1) {
value = "Now"; return _("Now");
} else if (secs >= 1 && hours < 1) { } else if (hours < 1) {
// 1m - 1h int val = (int) Math.floor (mins);
var val = Math.floor (secs); return ngettext (
value = val.to_string () + " min"; "%d min ago", "%d mins ago", val).printf (val);
if (val > 1) { } else if (hours < 24) {
value += "s"; int val = (int) Math.floor (hours);
} return ngettext (
value += " ago"; "%d hour ago", "%d hours ago", val).printf (val);
} else if (hours >= 1 && hours < 24) {
// 1h - 24h
var val = Math.floor (hours);
value = val.to_string () + " hour";
if (val > 1) {
value += "s";
}
value += " ago";
} else { } else {
// Days int val = (int) Math.floor (days);
var val = Math.floor (days); return ngettext (
value = val.to_string () + " day"; "%d day ago", "%d days ago", val).printf (val);
if (val > 1) {
value += "s";
}
value += " ago";
} }
return value;
} }
private string get_iso8601_time () { private string get_iso8601_time () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment