aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gsr-record-page.c
diff options
context:
space:
mode:
authorTrung Lê <8@tle.id.au>2026-06-10 17:32:15 +1000
committerTrung Lê <8@tle.id.au>2026-06-10 23:21:58 +1000
commite845db5dc4f482f88d1562c0356cd1c65d5f538b (patch)
tree0b1d9ca46ec459667e0a8f2b698e3708e06d84b2 /src/gsr-record-page.c
parentfbd27b7ba04c12eb080ccabec63938c2f05c75ec (diff)
feat: add gettext i18n with translations (vi, de, fr, it, es, pt)
Wire up internationalization for the app and ship six translations. Infrastructure: - meson: import i18n, define GETTEXT_PACKAGE/GSR_LOCALEDIR, add po/ subdir, and translate the .desktop and AppStream metainfo via i18n.merge_file (renamed to .desktop.in / .metainfo.xml.in). - main.c: setlocale + bindtextdomain/textdomain so the catalog is loaded. - po/: LINGUAS, POTFILES.in, meson.build (glib preset). String marking: - Wrap every user-visible string with _() across main.c, gsr-window.c, the four pages and the shortcut dialog (titles, subtitles, labels, buttons, combo display names, notifications, toasts, dialogs, menu items). - Leave ids/keys untranslated: codec/container/service ids, GAction/icon/CSS names, GVariant/format strings, accelerators, etc. Linting: - Re-enable gobject-linter's untranslated_string rule (now that i18n exists) as an error so new user-visible strings must be wrapped. Translations (141 messages each, %s/%d/markup placeholders preserved): - Vietnamese (vi), German (de), French (fr), Italian (it), Spanish (es), Portuguese (pt). Codec names, "OK", proper nouns and the product name are intentionally left in English. Verified: msgfmt --check-format passes and the compiled catalogs resolve (e.g. "Record" -> "Ghi hình" / "Aufnahme" / "Enregistrement").
Diffstat (limited to 'src/gsr-record-page.c')
-rw-r--r--src/gsr-record-page.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/src/gsr-record-page.c b/src/gsr-record-page.c
index 745bdcf..40b28bb 100644
--- a/src/gsr-record-page.c
+++ b/src/gsr-record-page.c
@@ -3,6 +3,8 @@
#include <signal.h>
#include <time.h>
+#include <glib/gi18n.h>
+
#include "gsr-window.h"
#ifdef HAVE_X11
@@ -131,7 +133,7 @@ on_save_dir_activated(AdwActionRow *row G_GNUC_UNUSED,
{
GsrRecordPage *self = GSR_RECORD_PAGE(user_data);
g_autoptr(GtkFileDialog) dialog = gtk_file_dialog_new();
- gtk_file_dialog_set_title(dialog, "Select save directory");
+ gtk_file_dialog_set_title(dialog, _("Select save directory"));
if (self->save_directory) {
g_autoptr(GFile) initial = g_file_new_for_path(self->save_directory);
@@ -247,7 +249,7 @@ on_x11_start_stop_activated(AdwActionRow *row G_GNUC_UNUSED,
{
GsrRecordPage *self = GSR_RECORD_PAGE(user_data);
GsrShortcutAccelDialog *dialog = gsr_shortcut_accel_dialog_new(
- "Start/Stop recording", self->x11_start_stop_accel);
+ _("Start/Stop recording"), self->x11_start_stop_accel);
g_signal_connect(dialog, "shortcut-set",
G_CALLBACK(on_x11_start_stop_shortcut_set), self);
adw_dialog_present(ADW_DIALOG(dialog), GTK_WIDGET(self));
@@ -278,7 +280,7 @@ on_x11_pause_activated(AdwActionRow *row G_GNUC_UNUSED,
{
GsrRecordPage *self = GSR_RECORD_PAGE(user_data);
GsrShortcutAccelDialog *dialog = gsr_shortcut_accel_dialog_new(
- "Pause/Unpause recording", self->x11_pause_accel);
+ _("Pause/Unpause recording"), self->x11_pause_accel);
g_signal_connect(dialog, "shortcut-set",
G_CALLBACK(on_x11_pause_shortcut_set), self);
adw_dialog_present(ADW_DIALOG(dialog), GTK_WIDGET(self));
@@ -289,7 +291,7 @@ static void
build_hotkey_group(GsrRecordPage *self)
{
self->hotkey_group = ADW_PREFERENCES_GROUP(adw_preferences_group_new());
- adw_preferences_group_set_title(self->hotkey_group, "Hotkeys");
+ adw_preferences_group_set_title(self->hotkey_group, _("Hotkeys"));
GsrDisplayServer ds = self->info->system_info.display_server;
@@ -297,8 +299,8 @@ build_hotkey_group(GsrRecordPage *self)
if (ds == GSR_DISPLAY_SERVER_WAYLAND) {
/* "Not supported" label — initially hidden, shown if portal fails */
self->hotkey_not_supported_label = gtk_label_new(
- "Your Wayland compositor doesn't support global hotkeys.\n"
- "Use X11 or KDE Plasma on Wayland if you want to use hotkeys.");
+ _("Your Wayland compositor doesn't support global hotkeys.\n"
+ "Use X11 or KDE Plasma on Wayland if you want to use hotkeys."));
gtk_label_set_wrap(GTK_LABEL(self->hotkey_not_supported_label), TRUE);
gtk_widget_add_css_class(self->hotkey_not_supported_label, "dim-label");
gtk_widget_set_margin_top(self->hotkey_not_supported_label, 6);
@@ -312,32 +314,32 @@ build_hotkey_group(GsrRecordPage *self)
self->hotkey_info_row = GTK_WIDGET(info_row);
if (is_kde_wayland()) {
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(info_row),
- "Hotkeys are managed by KDE Plasma");
+ _("Hotkeys are managed by KDE Plasma"));
adw_action_row_set_subtitle(info_row,
- "Click to configure hotkeys in system settings");
+ _("Click to configure hotkeys in system settings"));
GtkButton *change_btn = GTK_BUTTON(
- gtk_button_new_with_label("Change hotkeys"));
+ gtk_button_new_with_label(_("Change hotkeys")));
gtk_widget_set_valign(GTK_WIDGET(change_btn), GTK_ALIGN_CENTER);
g_object_set_data(G_OBJECT(info_row), "change-button", change_btn);
adw_action_row_add_suffix(info_row, GTK_WIDGET(change_btn));
} else {
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(info_row),
- "Hotkeys are managed by your compositor");
+ _("Hotkeys are managed by your compositor"));
adw_action_row_set_subtitle(info_row,
- "Go to system settings to change hotkeys");
+ _("Go to system settings to change hotkeys"));
}
adw_preferences_group_add(self->hotkey_group, GTK_WIDGET(info_row));
/* Hotkey labels (shown after portal succeeds) */
AdwActionRow *start_row = ADW_ACTION_ROW(adw_action_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(start_row),
- "Start/Stop recording");
+ _("Start/Stop recording"));
adw_action_row_set_subtitle(start_row, "");
adw_preferences_group_add(self->hotkey_group, GTK_WIDGET(start_row));
AdwActionRow *pause_row = ADW_ACTION_ROW(adw_action_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(pause_row),
- "Pause/Unpause recording");
+ _("Pause/Unpause recording"));
adw_action_row_set_subtitle(pause_row, "");
adw_preferences_group_add(self->hotkey_group, GTK_WIDGET(pause_row));
@@ -353,7 +355,7 @@ build_hotkey_group(GsrRecordPage *self)
/* X11: interactive shortcut rows */
self->x11_start_stop_row = ADW_ACTION_ROW(adw_action_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(self->x11_start_stop_row),
- "Start/Stop recording");
+ _("Start/Stop recording"));
gtk_list_box_row_set_activatable(GTK_LIST_BOX_ROW(self->x11_start_stop_row), TRUE);
self->x11_start_stop_label = GTK_SHORTCUT_LABEL(
@@ -372,7 +374,7 @@ build_hotkey_group(GsrRecordPage *self)
/* Pause/Unpause row */
self->x11_pause_row = ADW_ACTION_ROW(adw_action_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(self->x11_pause_row),
- "Pause/Unpause recording");
+ _("Pause/Unpause recording"));
gtk_list_box_row_set_activatable(GTK_LIST_BOX_ROW(self->x11_pause_row), TRUE);
self->x11_pause_label = GTK_SHORTCUT_LABEL(
@@ -399,13 +401,13 @@ static void
build_output_group(GsrRecordPage *self)
{
self->output_group = ADW_PREFERENCES_GROUP(adw_preferences_group_new());
- adw_preferences_group_set_title(self->output_group, "Output");
+ adw_preferences_group_set_title(self->output_group, _("Output"));
/* Save directory */
self->save_directory = get_default_videos_dir();
self->save_dir_row = ADW_ACTION_ROW(adw_action_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(self->save_dir_row),
- "Save directory");
+ _("Save directory"));
adw_action_row_set_subtitle(self->save_dir_row, self->save_directory);
gtk_list_box_row_set_activatable(GTK_LIST_BOX_ROW(self->save_dir_row), TRUE);
@@ -421,7 +423,7 @@ build_output_group(GsrRecordPage *self)
/* Container format */
self->container_row = ADW_COMBO_ROW(adw_combo_row_new());
adw_preferences_row_set_title(ADW_PREFERENCES_ROW(self->container_row),
- "Container");
+ _("Container"));
GtkStringList *ct_model = gtk_string_list_new(NULL);
const char *containers[] = {
@@ -453,7 +455,7 @@ build_action_group(GsrRecordPage *self)
gtk_widget_set_margin_bottom(GTK_WIDGET(box), 6);
self->start_button = GTK_BUTTON(
- gtk_button_new_with_label("Start recording"));
+ gtk_button_new_with_label(_("Start recording")));
gtk_widget_set_hexpand(GTK_WIDGET(self->start_button), TRUE);
gtk_widget_add_css_class(GTK_WIDGET(self->start_button), "suggested-action");
g_signal_connect(self->start_button, "clicked",
@@ -461,7 +463,7 @@ build_action_group(GsrRecordPage *self)
gtk_box_append(box, GTK_WIDGET(self->start_button));
self->pause_button = GTK_BUTTON(
- gtk_button_new_with_label("Pause recording"));
+ gtk_button_new_with_label(_("Pause recording")));
gtk_widget_set_hexpand(GTK_WIDGET(self->pause_button), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(self->pause_button), FALSE);
g_signal_connect(self->pause_button, "clicked",
@@ -628,7 +630,7 @@ void
gsr_record_page_set_active(GsrRecordPage *self, gboolean active)
{
if (active) {
- gtk_button_set_label(self->start_button, "Stop recording");
+ gtk_button_set_label(self->start_button, _("Stop recording"));
gtk_widget_remove_css_class(GTK_WIDGET(self->start_button), "suggested-action");
gtk_widget_add_css_class(GTK_WIDGET(self->start_button), "destructive-action");
gtk_widget_set_sensitive(GTK_WIDGET(self->pause_button), TRUE);
@@ -636,11 +638,11 @@ gsr_record_page_set_active(GsrRecordPage *self, gboolean active)
gtk_widget_add_css_class(GTK_WIDGET(self->record_icon), "recording-active");
gtk_widget_remove_css_class(GTK_WIDGET(self->record_icon), "recording-paused");
} else {
- gtk_button_set_label(self->start_button, "Start recording");
+ gtk_button_set_label(self->start_button, _("Start recording"));
gtk_widget_remove_css_class(GTK_WIDGET(self->start_button), "destructive-action");
gtk_widget_add_css_class(GTK_WIDGET(self->start_button), "suggested-action");
gtk_widget_set_sensitive(GTK_WIDGET(self->pause_button), FALSE);
- gtk_button_set_label(self->pause_button, "Pause recording");
+ gtk_button_set_label(self->pause_button, _("Pause recording"));
gtk_widget_set_opacity(GTK_WIDGET(self->status_box), 0.5);
gtk_label_set_text(self->timer_label, "00:00:00");
gtk_image_set_from_icon_name(self->record_icon, "media-record-symbolic");
@@ -658,12 +660,12 @@ void
gsr_record_page_set_paused(GsrRecordPage *self, gboolean paused)
{
if (paused) {
- gtk_button_set_label(self->pause_button, "Unpause recording");
+ gtk_button_set_label(self->pause_button, _("Unpause recording"));
gtk_image_set_from_icon_name(self->record_icon, "media-playback-pause-symbolic");
gtk_widget_remove_css_class(GTK_WIDGET(self->record_icon), "recording-active");
gtk_widget_add_css_class(GTK_WIDGET(self->record_icon), "recording-paused");
} else {
- gtk_button_set_label(self->pause_button, "Pause recording");
+ gtk_button_set_label(self->pause_button, _("Pause recording"));
gtk_image_set_from_icon_name(self->record_icon, "media-record-symbolic");
gtk_widget_remove_css_class(GTK_WIDGET(self->record_icon), "recording-paused");
gtk_widget_add_css_class(GTK_WIDGET(self->record_icon), "recording-active");
@@ -697,7 +699,7 @@ gsr_record_page_new(const GsrInfo *info)
GsrRecordPage *self = g_object_new(GSR_TYPE_RECORD_PAGE, NULL);
self->info = info;
- adw_preferences_page_set_title(ADW_PREFERENCES_PAGE(self), "Record");
+ adw_preferences_page_set_title(ADW_PREFERENCES_PAGE(self), _("Record"));
adw_preferences_page_set_icon_name(ADW_PREFERENCES_PAGE(self),
"media-record-symbolic");