diff options
| author | Trung Lê <8@tle.id.au> | 2026-06-10 17:32:15 +1000 |
|---|---|---|
| committer | Trung Lê <8@tle.id.au> | 2026-06-10 23:21:58 +1000 |
| commit | e845db5dc4f482f88d1562c0356cd1c65d5f538b (patch) | |
| tree | 0b1d9ca46ec459667e0a8f2b698e3708e06d84b2 /src/gsr-record-page.c | |
| parent | fbd27b7ba04c12eb080ccabec63938c2f05c75ec (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.c | 54 |
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"); |
