Include check for untranslated text
authorColin Clark <colin.clark@cclark.uk>
Mon, 29 Apr 2024 15:53:40 +0000 (16:53 +0100)
committerColin Clark <colin.clark@cclark.uk>
Mon, 29 Apr 2024 15:53:40 +0000 (16:53 +0100)
- Meson check for untranslated text strings
- Fix some untranslated text strings

meson.build
scripts/untranslated-text.sh
src/dupe.cc
src/exif-common.cc
src/preferences.cc
src/search.cc
src/trash.cc

index 9d0e118..49ea1ba 100644 (file)
@@ -771,6 +771,21 @@ else
     summary({'Temporary Comments' : ['Test runs:', false]}, section : 'Testing', bool_yn : true)
 endif
 
+# Untranslated text checks
+untranslated_text_sh = find_program('untranslated-text.sh', dirs : scriptsdir, required : true)
+if untranslated_text_sh.found()
+        foreach source_file : main_sources + pan_view_sources + view_file_sources
+               if fs.name(source_file).endswith('.cc')
+                       source_file_name = fs.name(source_file)
+                       test('Untranslated Text_ ' + source_file_name, untranslated_text_sh, args : [source_file], timeout : 200)
+               endif
+       endforeach
+
+       summary({'Untranslated Text' : ['Test runs:', true]}, section : 'Testing', bool_yn : true)
+else
+       summary({'Untranslated Text' : ['Test runs:', false]}, section : 'Testing', bool_yn : true)
+endif
+
 # Lua test
 option = get_option('lua')
 if not option.disabled()
index a1587c7..ef6ef93 100755 (executable)
 #!/bin/sh
 
+#**********************************************************************
+# Copyright (C) 2024 - The Geeqie Team
+#
+# Author: Colin Clark
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#**********************************************************************
+
 ## @file
 ## @brief Locate strings not marked for translation
 ##
-## Checks all .c files under ./src
+## The check is not comprehensive - the exclusions make this
+## of limited value.
+##
+## @FIXME Strings starting with a space, or a lower-case alpha
+## or if there is more than one string per line, are not
+## checked for.
+##
+## The regex search is for a character sequence: \n
+## double quotes \n
+## upper-case alpha character \n
+## alpha character or space \n
+## printable character \n
+## previous character type repeated one or more times \n
+## double quotes
+##
+## The above sequence preceded by "_(" will not be a hit.
 ##
-## The check is not comprehensive - some errors are not detected
-## and there are some false hits.
+## $1 file to process
 ##
 
-for file in src/*.cc src/view-file/*.cc
+omit_text_array="
+ msg
+#define
+#include
+&lt
+@brief
+@param
+COPYRIGHT
+ColorSpace
+DEBUG
+Damien
+ERR
+EXIF
+Error
+Exif\.
+FIXME
+ImageLoaderType
+LUA_
+MonoSpace
+N_(
+NikonTag
+Pause
+PixbufRenderer
+PluginsMenu
+READ_
+Separator
+WRITE_
+Wrap
+\"Desktop\"
+\"Layout\"
+\"OK\"
+\"Xmp\.
+\.html
+\/\*
+\/\/
+\{\"
+_attribute
+action_group
+courier
+exif_get_item
+filter_add_if_missing
+font_name
+g_ascii_strcasecmp
+g_build_filename
+g_critical
+g_key_file_get_
+g_message
+g_object
+g_signal
+g_str_has_suffix
+g_strstr_len
+g_themed_icon_new
+g_warning
+getenv
+gtk_action_group_get_action
+gtk_container_child_get
+gtk_widget_add_accelerator
+layout_actions
+layout_toolbar_add
+luaL_
+lua_
+memcmp
+mouse_button_
+options->
+osd_template_insert
+pango_attr
+path_to_utf8
+primaries_name
+print_term
+printf
+return g_strdup
+runcmd
+setenv
+signal_
+signals_
+strcmp
+strncmp
+trc_name
+website-label
+write_char_option
+
+##cellrendericon.cc
+\"Background color as a GdkRGBA\"\,
+\"Background color\"\,
+\"Background set\"\,
+\"Draw focus indicator\"\,
+\"Fixed height\"\,
+\"Fixed width\"\,
+\"Focus\"\,
+\"Foreground color as a GdkRGBA\"\,
+\"Foreground color\"\,
+\"Foreground set\"\,
+\"GQvCellRendererIcon\"\,
+\"Height of icon excluding text\"\,
+\"Marks bit array\"\,
+\"Marks\"\,
+\"Number of marks\"\,
+\"Pixbuf Object\"\,
+\"Show marks\"\,
+\"Show text\"\,
+\"Text to render\"\,
+\"Text\"\,
+\"The pixbuf to render\"\,
+\"Toggled mark\"\,
+\"Whether the marks are displayed\"\,
+\"Whether the text is displayed\"\,
+\"Whether this tag affects the background color\"\,
+\"Whether this tag affects the foreground color\"\,
+\"Width of cell\"\,
+
+##pixbuf-renderer.cc
+\"Delay image update\"\,
+\"Display cache size MiB\"\,
+\"Expand image in autozoom.\"\,
+\"Fit window to image size\"\,
+\"Image actively loading\"\,
+\"Image rendering complete\"\,
+\"Limit size of image when autofitting\"\,
+\"Limit size of parent window\"\,
+\"New image scroll reset\"\,
+\"Number of tiles to retain in memory at any one time.\"\,
+\"Size increase limit of image when autofitting\"\,
+\"Size limit of image when autofitting\"\,
+\"Size limit of parent window\"\,
+\"Tile cache count\"\,
+\"Zoom maximum\"\,
+\"Zoom minimum\"\,
+\"Zoom quality\"\,
+
+##print.cc
+G_CALLBACK(print_set_font_cb)\, const_cast<char \*>(\"Image text font\"));
+G_CALLBACK(print_set_font_cb)\, const_cast<char \*>(\"Page text font\"));
+
+##remote.cc
+render_intent = g_strdup(\"Absolute Colorimetric\");
+render_intent = g_strdup(\"Absolute Colorimetric\");
+render_intent = g_strdup(\"Perceptual\");
+render_intent = g_strdup(\"Relative Colorimetric\");
+render_intent = g_strdup(\"Saturation\");
+"
+
+exclude_files_array="
+exif.cc
+format-canon.cc
+format-fuji.cc
+format-nikon.cc
+format-olympus.cc
+keymap-template.cc
+"
+
+filename_printed="no"
+
+omit="FILE_OK"
+while read -r omit_file
 do
-       for search_text in "label" "menu_item_add" "tooltip" "_button" "_text"
+       if [ -n "$omit_file" ]
+       then
+               if echo "$1" | grep --quiet "$omit_file"
+               then
+                       omit="omit"
+               fi
+       fi
+done << EOF
+$exclude_files_array
+EOF
+
+if [ "$omit" = "FILE_OK" ]
+then
+       while read -r infile_line
        do
-               cat -n "$file" | grep --extended-regexp --ignore-case "$search_text.*\(\"" | grep --invert-match "_(" | grep --invert-match "(\"\")" && printf '%s\n\n' "$file"
-       done
-done
+               if [ -n "$infile_line" ]
+               then
+                       omit="LINE_NOT_OK"
+                       while read -r omit_text
+                       do
+                               if [ -n "$omit_text" ]
+                               then
+                                       if echo "$infile_line" | grep --quiet "$omit_text"
+                                       then
+                                               omit="omit"
+                                       fi
+                               fi
+                       done << EOF
+$omit_text_array
+EOF
+                       if [ "$omit" = "LINE_NOT_OK" ]
+                       then
+                               if [ "$filename_printed" = "no" ]
+                               then
+                                       printf "\nfile: %s\n" "$1"
+                                       filename_printed="yes"
+                               fi
+
+                               no_tabs=$(echo "$infile_line" | tr -s '\t')
+                               printf "line: %s\n" "$no_tabs"
+                       fi
+               fi
+       done << EOF
+$(cat --number "$1" | grep --perl-regexp '(?<!_\()"[[:upper:]]([[:lower:]]|[[:space:]])[[:print:]]+"')
+EOF
+fi
+
+if [ "$filename_printed" = "yes" ]
+then
+       exit 1
+else
+       exit 0
+fi
index 68e553f..2716f8b 100644 (file)
@@ -4737,7 +4737,7 @@ DupeWindow *dupe_window_new()
        dw->controls_box = controls_box;
 
        dw->button_thumbs = gtk_check_button_new_with_label(_("Thumbnails"));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_thumbs), "Ctrl-T");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->button_thumbs), _("Ctrl-T"));
        dw->show_thumbs = options->duplicates_thumbnails;
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dw->button_thumbs), dw->show_thumbs);
        g_signal_connect(G_OBJECT(dw->button_thumbs), "toggled",
@@ -4757,7 +4757,7 @@ DupeWindow *dupe_window_new()
        gq_gtk_box_pack_start(GTK_BOX(controls_box), label, FALSE, FALSE, PREF_PAD_SPACE);
        gtk_widget_show(label);
        dw->custom_threshold = gtk_spin_button_new_with_range(1, 100, 1);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->custom_threshold), "Custom similarity threshold\n(Use tab key to set value)");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(dw->custom_threshold), _("Custom similarity threshold\n(Use tab key to set value)"));
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(dw->custom_threshold), options->duplicates_similarity_threshold);
        g_signal_connect(G_OBJECT(dw->custom_threshold), "value_changed", G_CALLBACK(dupe_window_custom_threshold_cb), dw);
        gq_gtk_box_pack_start(GTK_BOX(controls_box), dw->custom_threshold, FALSE, FALSE, PREF_PAD_SPACE);
@@ -4807,7 +4807,7 @@ DupeWindow *dupe_window_new()
        gtk_widget_show(button);
 
        button = pref_button_new(nullptr, GQ_ICON_CLOSE, _("Close"), G_CALLBACK(dupe_window_close_cb), dw);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(button), "Ctrl-W");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(button), _("Ctrl-W"));
        gq_gtk_container_add(GTK_WIDGET(hbox), button);
        gtk_widget_set_can_default(button, TRUE);
        gtk_widget_grab_default(button);
index 4dcdc4b..3c53802 100644 (file)
@@ -836,7 +836,7 @@ static gchar *exif_build_formatted_localtime(ExifData *exif)
 /**
  * @brief Gets timezone from GPS lat/long
  * @param[in] exif
- * @returns Timezone string in the form "Europe/London"
+ * @returns Timezone string in the form Europe/London
  *
  *
  */
index 15cd9d1..287cb1d 100644 (file)
@@ -2351,7 +2351,7 @@ static void config_tab_image(GtkWidget *notebook)
                                 100, 999, 1,
                                 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
        pref_checkbox_link_sensitivity(enlargement_button, spin);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("Enable this to allow Geeqie to increase the image size for images that are smaller than the current view area when the zoom is set to \"Fit image to window\". This value sets the maximum expansion permitted in percent i.e. 100% is full-size."));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("Enable this to allow Geeqie to increase the image size for images that are smaller than the current view area when the zoom is set to 'Fit image to window'. This value sets the maximum expansion permitted in percent i.e. 100% is full-size."));
 
        hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
        ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (%% of actual window):"),
@@ -2360,7 +2360,7 @@ static void config_tab_image(GtkWidget *notebook)
                                 10, 150, 1,
                                 options->image.max_autofit_size, &c_options->image.max_autofit_size);
        pref_checkbox_link_sensitivity(ct_button, spin);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value will set the virtual size of the window when \"Fit image to window\" is set. Instead of using the actual size of the window, the specified percentage of the window will be used. It allows one to keep a border around the image (values lower than 100%) or to auto zoom the image (values greater than 100%). It affects fullscreen mode too."));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value will set the virtual size of the window when 'Fit image to window' is set. Instead of using the actual size of the window, the specified percentage of the window will be used. It allows one to keep a border around the image (values lower than 100%) or to auto zoom the image (values greater than 100%). It affects fullscreen mode too."));
 
        group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
 
@@ -2478,7 +2478,7 @@ static void config_tab_windows(GtkWidget *notebook)
 
        widget = pref_checkbox_new_int(group, _("Hide window decorations"),
                              options->hide_window_decorations, &c_options->hide_window_decorations);
-       gtk_widget_set_tooltip_text(widget, "Remove borders and title bar from windows. A restart of Geeqie is required for this feature to take effect on the main layout window");
+       gtk_widget_set_tooltip_text(widget, _("Remove borders and title bar from windows. A restart of Geeqie is required for this feature to take effect on the main layout window"));
 
        pref_checkbox_new_int(group, _("Show window IDs"),
                              options->show_window_ids, &c_options->show_window_ids);
@@ -2993,7 +2993,7 @@ static void config_tab_metadata(GtkWidget *notebook)
        gtk_widget_set_tooltip_text(tmp_widget, _("See the Help file for a list of the tags used"));
 
        tmp_widget = pref_checkbox_new_int(group, _("Permit Keywords to be case-sensitive"), options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
-       gtk_widget_set_tooltip_text(tmp_widget, _("When selected, \"Place\" and \"place\" are two different keywords"));
+       gtk_widget_set_tooltip_text(tmp_widget, _("When selected, 'Place' and 'place' are two different keywords"));
 
        ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"), options->metadata.write_orientation, &c_options->metadata.write_orientation);
        gtk_widget_set_tooltip_text(ct_button, _("If checked, the results of orientation commands (Rotate, Mirror and Flip) issued on an image will be written to metadata\nNote: If this option is not checked, the results of orientation commands will be lost when Geeqie closes"));
@@ -3031,7 +3031,7 @@ static void config_tab_metadata(GtkWidget *notebook)
        group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
 
        ct_button = pref_checkbox_new_int(group, _("Read metadata in background"), options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
-       gtk_widget_set_tooltip_text(ct_button,"On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower");
+       gtk_widget_set_tooltip_text(ct_button,_("On folder change, read DateTimeOriginal, DateTimeDigitized and Star Rating in the idle loop.\nIf this is not selected, initial loading of the folder will be faster but sorting on these items will be slower"));
 }
 
 /* keywords tab */
@@ -3640,9 +3640,9 @@ static void config_tab_behavior(GtkWidget *notebook)
                                options->marks_save, &c_options->marks_save);
        gtk_widget_set_tooltip_text(marks,_("Note that marks linked to a keyword will be saved irrespective of this setting"));
 
-       with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
+       with_rename = pref_checkbox_new_int(group, _("Use 'With Rename' as default for Copy/Move dialogs"),
                                options->with_rename, &c_options->with_rename);
-       gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
+       gtk_widget_set_tooltip_text(with_rename,_("Change the default button for Copy/Move dialogs"));
 
        collections_on_top = pref_checkbox_new_int(group, _("Permit duplicates in Collections"),
                                options->collections_duplicates, &c_options->collections_duplicates);
@@ -3654,11 +3654,11 @@ static void config_tab_behavior(GtkWidget *notebook)
 
        hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
                                options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
-       gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
+       gtk_widget_set_tooltip_text(hide_window_in_fullscreen, _("When alt-tabbing, prevent Geeqie window showing twice"));
 
        hide_osd_in_fullscreen = pref_checkbox_new_int(group, _("Hide OSD in fullscreen"),
                                options->hide_osd_in_fullscreen, &c_options->hide_osd_in_fullscreen);
-       gtk_widget_set_tooltip_text(hide_osd_in_fullscreen,"Hide Overlay Screen Display in fullscreen mode");
+       gtk_widget_set_tooltip_text(hide_osd_in_fullscreen, _("Hide Overlay Screen Display in fullscreen mode"));
 
        pref_spin_new_int(group, _("Recent folder list maximum size"), nullptr,
                          1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
index 79625e6..7ef6da2 100644 (file)
@@ -2736,9 +2736,7 @@ static void search_start_cb(GtkWidget *, gpointer data)
                                                sd->search_lat < -90 || sd->search_lat > 90 ||
                                                sd->search_lon < -180 || sd->search_lon > 180)
                                {
-                               file_util_warning_dialog(_(
-                                               "Entry does not contain a valid lat/long value"),
-                                                       entry_text, GQ_ICON_DIALOG_WARNING, sd->window);
+                               file_util_warning_dialog(_("Entry does not contain a valid lat/long value"), entry_text, GQ_ICON_DIALOG_WARNING, sd->window);
                                return;
                                }
                        g_free(entry_text);
@@ -3449,7 +3447,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
        pref_checkbox_new_int(hbox, _("Match case"),
                              sd->search_name_match_case, &sd->search_name_match_case);
        pref_checkbox_new_int(hbox, _("Symbolic link"), sd->search_name_symbolic_link, &sd->search_name_symbolic_link);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(combo), "When set to \"contains\" or \"path contains\", this field uses Perl Compatible Regular Expressions.\ne.g. use \n.*\\.jpg\n and not \n*.jpg\n\nSee the Help file.");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(combo), _("When set to 'contains' or 'path contains', this field uses Perl Compatible Regular Expressions.\ne.g. use \n.*\\.jpg\n and not \n*.jpg\n\nSee the Help file."));
 
        /* Search for file size */
        hbox = menu_choice(sd->box_search, &sd->check_size, &sd->menu_size,
@@ -3558,7 +3556,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
        gtk_widget_show(sd->entry_comment);
        pref_checkbox_new_int(hbox, _("Match case"),
                              sd->search_comment_match_case, &sd->search_comment_match_case);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_comment), "This field uses Perl Compatible Regular Expressions.\ne.g. use \nabc.*ghk\n and not \nabc*ghk\n\nSee the Help file.");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->entry_comment), _("This field uses Perl Compatible Regular Expressions.\ne.g. use \nabc.*ghk\n and not \nabc*ghk\n\nSee the Help file."));
 
        /* Search for image rating */
        hbox = menu_choice(sd->box_search, &sd->check_rating, &sd->menu_rating,
@@ -3720,7 +3718,7 @@ void search_new(FileData *dir_fd, FileData *example_file)
 
        sd->button_thumbs = pref_checkbox_new(hbox, _("Thumbnails"), FALSE,
                                              G_CALLBACK(search_thumb_toggle_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_thumbs), "Ctrl-T");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_thumbs), _("Ctrl-T"));
 
        frame = gtk_frame_new(nullptr);
        DEBUG_NAME(frame);
@@ -3752,15 +3750,15 @@ void search_new(FileData *dir_fd, FileData *example_file)
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_start = pref_button_new(hbox, GQ_ICON_FIND, _("Find"),
                                           G_CALLBACK(search_start_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_start), "Ctrl-Return");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_start), _("Ctrl-Return"));
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_stop = pref_button_new(hbox, GQ_ICON_STOP, _("Stop"),
                                          G_CALLBACK(search_start_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_stop), "Ctrl-Return");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_stop), _("Ctrl-Return"));
        gtk_widget_set_sensitive(sd->button_stop, FALSE);
        pref_spacer(hbox, PREF_PAD_BUTTON_GAP);
        sd->button_close = pref_button_new(hbox, GQ_ICON_CLOSE, _("Close"), G_CALLBACK(search_window_close_cb), sd);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_close), "Ctrl-W");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(sd->button_close), _("Ctrl-W"));
        gtk_widget_set_sensitive(sd->button_close, TRUE);
 
        search_result_thumb_enable(sd, TRUE);
index 7daa656..44d5cb0 100644 (file)
@@ -202,7 +202,7 @@ gboolean file_util_safe_unlink(const gchar *path)
 
                if (!g_file_trash(tmp, FALSE, &error) )
                        {
-                       message = g_strconcat("See the Help file for a possible workaround.\n\n", error->message, NULL);
+                       message = g_strconcat(_("See the Help file for a possible workaround.\n\n"), error->message, NULL);
                        gd = warning_dialog(_("Move to trash failed\n\n"), message, GQ_ICON_DIALOG_ERROR, nullptr);
                        generic_dialog_add_button(gd, GQ_ICON_HELP, _("Help"), move_to_trash_failed_cb, FALSE);