On Wed, 2000-12-06 at 15:24:58, Zbigniew Chyla wrote:

> (...)
> Thanks tor this! It should be no problem for translators - I have another
> patch, that doesn't _require_ modified translations. If you replace
> _("File") with Q_("!menu!File") in your code, old translations (containing
> only "File") will still work. I'll send improved patch tomorrow.

Attached patch implements new version of the Q_() macro. As I said before,
adding new prefixes to strings doesn't break existing translations.

This time I don't include whole po/Makefile.in.in but only small patch
adding "--keyword=Q_" to the list of xgettext options. Patch is being
applied by autogen.sh after running gettextize. Many GNOME apps
(eg. gnumeric) modify po/Makefile.in.in this way.


Zbigniew
diff -ruN /home/cyba/gcvs/gimp/ChangeLog gimp/ChangeLog
--- /home/cyba/gcvs/gimp/ChangeLog      Sun Dec  3 20:16:03 2000
+++ gimp/ChangeLog      Wed Dec  6 19:32:58 2000
@@ -1,3 +1,33 @@
+2000-12-06  Zbigniew Chyla  <[EMAIL PROTECTED]>
+
+       I18n improvement - added support for Q_() macro (replacement for _()
+       allowing to add a prefix of the form "!some_prefix!" to the
+       string and thus making it possible to translate it differently in
+       different contexts).
+
+       * libgimp/gimpintl.h, libgimp/libgimp-intl.h: included "gimputils.h",
+       defined Q_() macro.
+
+       * libgimp/gimputils.h: added functions declarations:
+       gimp_i18n_qualifier_prefix_gettext(),
+       gimp_i18n_qualifier_prefix_dgettext(),
+       gimp_i18n_qualifier_prefix_noop().
+
+       * libgimp/gimputils.c: included "gimpintl.h", added functions:
+       gimp_i18n_qualifier_prefix_gettext(),
+       gimp_i18n_qualifier_prefix_dgettext(),
+       gimp_i18n_qualifier_prefix_noop().
+
+       * autogen.sh: patching po/Makefile.in.in (with
+       po/Makefile.in.in.i18npatch) after running gettextize.
+
+       * po/Makefile.in.in.i18n: new file - patch for po/Makefile.in.in (file
+       provided by gettextize), adds "--keyword=Q_" to the list of xgettext
+       options.
+
+       * po-libgimp/Makefile.in.in, po-plug-ins/Makefile.in.in: added
+       "--keyword=Q_" to the list of xgettext options.
+
 2000-11-30  Andy Thomas <[EMAIL PROTECTED]>
 
        * app/curves.c
diff -ruN /home/cyba/gcvs/gimp/libgimp/gimputils.h gimp/libgimp/gimputils.h
--- /home/cyba/gcvs/gimp/libgimp/gimputils.h    Thu Nov 23 12:38:50 2000
+++ gimp/libgimp/gimputils.h    Wed Dec  6 19:32:58 2000
@@ -45,13 +45,12 @@
                          const gchar *exceptions);
 gchar * gimp_strcompress (const gchar *source);
 #endif  /* GLIB <= 1.3 */
-
+gchar *gimp_i18n_qualifier_prefix_gettext (const gchar *string);
+gchar *gimp_i18n_qualifier_prefix_dgettext (const gchar *domain, const gchar *string);
+gchar *gimp_i18n_qualifier_prefix_noop (const gchar *string);
 
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 
 #endif /* __GIMPUTILS_H__ */
-
-
-
diff -ruN /home/cyba/gcvs/gimp/libgimp/libgimp-intl.h gimp/libgimp/libgimp-intl.h
--- /home/cyba/gcvs/gimp/libgimp/libgimp-intl.h Thu Nov 23 12:38:50 2000
+++ gimp/libgimp/libgimp-intl.h Wed Dec  6 19:32:58 2000
@@ -22,10 +22,12 @@
 #ifndef __LIBGIMP_INTL_H__
 #define __LIBGIMP_INTL_H__
 
+#include "gimputils.h"
 
 #ifdef ENABLE_NLS
 #    include <libintl.h>
 #    define _(String) dgettext ("gimp-libgimp", String)
+#    define Q_(String) gimp_i18n_qualifier_prefix_dgettext ("gimp-libgimp", String)
 #    undef gettext
 #    define gettext(String) dgettext ("gimp-libgimp", String)
 #    ifdef gettext_noop
@@ -37,6 +39,7 @@
 /* Stubs that do something close enough.  */
 #    define gettext(String) (String)
 #    define _(String) (String)
+#    define Q_(String) gimp_i18n_qualifier_prefix_noop (String)
 #    define N_(String) (String)
 #endif
 
diff -ruN /home/cyba/gcvs/gimp/libgimp/gimpintl.h gimp/libgimp/gimpintl.h
--- /home/cyba/gcvs/gimp/libgimp/gimpintl.h     Thu Nov 23 12:38:48 2000
+++ gimp/libgimp/gimpintl.h     Wed Dec  6 19:32:58 2000
@@ -25,6 +25,8 @@
 #include <glib.h>
 #include <locale.h>
 
+#include "gimputils.h"
+
 /* Copied from gnome-i18n.h by Tom Tromey <[EMAIL PROTECTED]>
  * Heavily modified by Daniel Egger <[EMAIL PROTECTED]>
  * So be sure to hit me instead of him if something is wrong here
@@ -40,6 +42,7 @@
 #ifdef ENABLE_NLS
 #    include <libintl.h>
 #    define _(String) gettext (String)
+#    define Q_(String) gimp_i18n_qualifier_prefix_gettext (String)
 #    ifdef gettext_noop
 #        define N_(String) gettext_noop (String)
 #    else
@@ -53,6 +56,7 @@
 #    define dcgettext(Domain,Message,Type) (Message)
 #    define bindtextdomain(Domain,Directory) (Domain)
 #    define _(String) (String)
+#    define Q_(String) gimp_i18n_qualifier_prefix_noop (String)
 #    define N_(String) (String)
 #endif
 
diff -ruN /home/cyba/gcvs/gimp/libgimp/gimputils.c gimp/libgimp/gimputils.c
--- /home/cyba/gcvs/gimp/libgimp/gimputils.c    Thu Nov 23 12:38:50 2000
+++ gimp/libgimp/gimputils.c    Wed Dec  6 19:32:58 2000
@@ -23,8 +23,12 @@
 #include <string.h>
 #include <glib.h>
 
+#include "gimpintl.h"
 #include "gimputils.h"
 
+#define Q_PREFIX_START '!'
+#define Q_PREFIX_END   '!'
+
 /**
  * gimp_strescape:
  * @source: A string to escape special characters in.
@@ -197,3 +201,113 @@
   return dest;
 }
 #endif  /* GLIB <= 1.3 */
+
+/***
+ * gimp_i18n_qualifier_prefix_gettext
+ *
+ **/
+gchar *
+gimp_i18n_qualifier_prefix_gettext (const gchar *string)
+{
+       g_assert (string != NULL);
+
+       if (*string != Q_PREFIX_START) {
+               return gettext (string);
+       } else {
+               gchar *translation;
+
+               translation = gettext (string);
+               if (translation != string) {
+                       if (*translation != Q_PREFIX_START) {
+                               return translation;
+                       } else {
+                               gchar *real_translation;
+
+                               real_translation = strchr (translation + 1, 
+Q_PREFIX_END);
+                               if (real_translation != NULL) {
+                                       return real_translation + 1;
+                               } else {
+                                       g_warning ("Ivalid Q_() translation: \"%s\"", 
+translation);
+                                       return translation;
+                               }
+                       }
+               } else {
+                       gchar *real_string;
+
+                       real_string = strchr (string + 1, Q_PREFIX_END);
+                       if (real_string != NULL) {
+                               return gettext (real_string + 1);
+                       } else {
+                               g_warning ("Ivalid Q_() string: \"%s\"", string);
+                               return (gchar *) string;
+                       }
+               }
+       }
+}
+
+/***
+ * gimp_i18n_qualifier_prefix_dgettext
+ *
+ **/
+gchar *
+gimp_i18n_qualifier_prefix_dgettext (const gchar *domain, const gchar *string)
+{
+       g_assert (string != NULL);
+
+       if (*string != Q_PREFIX_START) {
+               return dgettext (domain, string);
+       } else {
+               gchar *translation;
+
+               translation = dgettext (domain, string);
+               if (translation != string) {
+                       if (*translation != Q_PREFIX_START) {
+                               return translation;
+                       } else {
+                               gchar *real_translation;
+
+                               real_translation = strchr (translation + 1, 
+Q_PREFIX_END);
+                               if (real_translation != NULL) {
+                                       return real_translation + 1;
+                               } else {
+                                       g_warning ("Ivalid Q_() translation: \"%s\"", 
+translation);
+                                       return translation;
+                               }
+                       }
+               } else {
+                       gchar *real_string;
+
+                       real_string = strchr (string + 1, Q_PREFIX_END);
+                       if (real_string != NULL) {
+                               return dgettext (domain, real_string + 1);
+                       } else {
+                               g_warning ("Ivalid Q_() string: \"%s\"", string);
+                               return (gchar *) string;
+                       }
+               }
+       }
+}
+
+/***
+ * gimp_i18n_qualifier_prefix_noop
+ *
+ **/
+gchar *
+gimp_i18n_qualifier_prefix_noop (const gchar *string)
+{
+       g_assert (string != NULL);
+
+       if (*string != Q_PREFIX_START) {
+               return (gchar *) string;
+       } else {
+               gchar *real_string;
+
+               real_string = strchr (string + 1, Q_PREFIX_END);
+               if (real_string != NULL) {
+                       return real_string + 1;
+               } else {
+                       g_warning ("Ivalid Q_() string: \"%s\"", string);
+                       return (gchar *) string;
+               }
+       }
+}
diff -ruN /home/cyba/gcvs/gimp/autogen.sh gimp/autogen.sh
--- /home/cyba/gcvs/gimp/autogen.sh     Sun Dec  3 20:18:06 2000
+++ gimp/autogen.sh     Wed Dec  6 19:42:30 2000
@@ -105,6 +105,14 @@
 # while making dist.
 echo "no" | gettextize --copy --force
 
+if [ -r po/Makefile.in.in.i18npatch ]; then
+       if grep 'keyword=Q_' po/Makefile.in.in >/dev/null; then
+               echo "no need for patching file \"Makefile.in.in\""
+       else
+               patch po/Makefile.in.in < po/Makefile.in.in.i18npatch
+       fi
+fi
+
 autogen_dirs="."
 #if test -z "$NO_GCG"; then
 #      autogen_dirs="$autogen_dirs tools/gcg"
diff -ruN /home/cyba/gcvs/gimp/po/Makefile.in.in.i18npatch 
gimp/po/Makefile.in.in.i18npatch
--- /home/cyba/gcvs/gimp/po/Makefile.in.in.i18npatch    Thu Jan  1 01:00:00 1970
+++ gimp/po/Makefile.in.in.i18npatch    Wed Dec  6 19:35:34 2000
@@ -0,0 +1,9 @@
+--- Makefile.in.in.clean       Wed Dec  6 19:33:55 2000
++++ Makefile.in.in     Wed Dec  6 19:32:58 2000
+@@ -87,5 +87,5 @@
+ $(srcdir)/$(PACKAGE).pot: $(POTFILES)
+       $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
+-        --add-comments --keyword=_ --keyword=N_ \
++        --add-comments --keyword=_ --keyword=N_ --keyword=Q_ \
+         --files-from=$(srcdir)/POTFILES.in \
+       && test ! -f $(PACKAGE).po \
diff -ruN /home/cyba/gcvs/gimp/po-libgimp/Makefile.in.in gimp/po-libgimp/Makefile.in.in
--- /home/cyba/gcvs/gimp/po-libgimp/Makefile.in.in      Thu Nov 23 12:39:17 2000
+++ gimp/po-libgimp/Makefile.in.in      Wed Dec  6 19:32:58 2000
@@ -84,7 +84,7 @@
 
 $(srcdir)/$(PACKAGE).pot: $(POTFILES)
        $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
-         --add-comments --keyword=_ --keyword=N_ \
+         --add-comments --keyword=_ --keyword=N_ --keyword=Q_ \
          --files-from=$(srcdir)/POTFILES.in \
        && test ! -f $(PACKAGE).po \
           || ( rm -f $(srcdir)/$(PACKAGE).pot \
diff -ruN /home/cyba/gcvs/gimp/po-plug-ins/Makefile.in.in 
gimp/po-plug-ins/Makefile.in.in
--- /home/cyba/gcvs/gimp/po-plug-ins/Makefile.in.in     Thu Nov 23 12:39:17 2000
+++ gimp/po-plug-ins/Makefile.in.in     Wed Dec  6 19:32:58 2000
@@ -84,7 +84,7 @@
 
 $(srcdir)/$(PACKAGE).pot: $(POTFILES)
        $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
-         --add-comments --keyword=_ --keyword=N_ \
+         --add-comments --keyword=_ --keyword=N_ --keyword=Q_ \
          --files-from=$(srcdir)/POTFILES.in \
        && test ! -f $(PACKAGE).po \
           || ( rm -f $(srcdir)/$(PACKAGE).pot \
diff -ru /home/cyba/gcvs/gimp/app/blend.c gimp/app/blend.c
--- /home/cyba/gcvs/gimp/app/blend.c    Sun Dec  3 20:16:03 2000
+++ gimp/app/blend.c    Wed Dec  6 21:39:01 2000
@@ -317,7 +317,7 @@
     (FALSE, gradient_type_callback,
      &options->gradient_type, (gpointer) options->gradient_type_d,
 
-     _("Linear"),                 (gpointer) LINEAR, NULL,
+     Q_("!gradient_type!Linear"), (gpointer) LINEAR, NULL,
      _("Bi-Linear"),              (gpointer) BILINEAR, NULL,
      _("Radial"),                 (gpointer) RADIAL, NULL,
      _("Square"),                 (gpointer) SQUARE, NULL,
diff -ru /home/cyba/gcvs/gimp/app/brush_select.c gimp/app/brush_select.c
--- /home/cyba/gcvs/gimp/app/brush_select.c     Sun Dec  3 20:16:03 2000
+++ gimp/app/brush_select.c     Wed Dec  6 21:39:01 2000
@@ -464,7 +464,7 @@
   util_box = gtk_hbox_new (FALSE, 0);
   gtk_box_pack_end (GTK_BOX (bsp->options_box), util_box, FALSE, FALSE, 4);
 
-  button =  gtk_button_new_with_label (_("New"));
+  button =  gtk_button_new_with_label (Q_("!brush-button!New"));
   gtk_signal_connect (GTK_OBJECT (button), "clicked",
                      GTK_SIGNAL_FUNC (brush_select_new_brush_callback),
                      bsp);
diff -ru /home/cyba/gcvs/gimp/app/gradient.c gimp/app/gradient.c
--- /home/cyba/gcvs/gimp/app/gradient.c Sun Dec  3 20:16:19 2000
+++ gimp/app/gradient.c Wed Dec  6 22:46:31 2000
@@ -529,7 +529,7 @@
 
 static const gchar *blending_types[] =
 {
-  N_("Linear"),
+  N_("!blending_type!Linear"),
   N_("Curved"),
   N_("Sinusoidal"),
   N_("Spherical (increasing)"),
@@ -906,7 +906,7 @@
   gtk_box_pack_start (GTK_BOX (gvbox), button, FALSE, FALSE, 0);
   gtk_widget_show (button);
 
-  button = ed_create_button (_("Save as POV-Ray"),
+  button = ed_create_button (Q_("!gradient-button!Save as POV-Ray"),
                             "dialogs/gradient_editor/save_as_pov_ray.html",
                             GTK_SIGNAL_FUNC (ed_save_pov_callback),
                             NULL);
@@ -1845,7 +1845,7 @@
   if (curr_gradient == NULL)
     return;
 
-  window = gtk_file_selection_new (_("Save as POV-Ray"));
+  window = gtk_file_selection_new (Q_("!gradient-dialog_title!Save as POV-Ray"));
   gtk_window_set_wmclass (GTK_WINDOW (window), "save_gradient", "Gimp");
   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
 
@@ -4617,7 +4617,7 @@
       else
        menuitem =
          gtk_radio_menu_item_new_with_label (group,
-                                             gettext (blending_types[i]));
+                                             Q_(blending_types[i]));
 
       group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
 
diff -ru /home/cyba/gcvs/gimp/app/palette.c gimp/app/palette.c
--- /home/cyba/gcvs/gimp/app/palette.c  Sun Dec  3 20:16:54 2000
+++ gimp/app/palette.c  Wed Dec  6 21:39:01 2000
@@ -1161,7 +1161,7 @@
 
   palette->popup_menu = menu = gtk_menu_new ();
 
-  menu_item = gtk_menu_item_new_with_label (_("New"));
+  menu_item = gtk_menu_item_new_with_label (Q_("!palette_color-menuitem!New"));
   gtk_menu_append (GTK_MENU (menu), menu_item);
   gtk_signal_connect (GTK_OBJECT (menu_item), "activate", 
                      GTK_SIGNAL_FUNC (palette_dialog_new_entry_callback),
@@ -2176,7 +2176,7 @@
       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), vbox,
                                gtk_label_new (_("Palette")));
       gtk_notebook_append_page (GTK_NOTEBOOK (hbox), scrolledwindow,
-                               gtk_label_new (_("Select")));
+                               gtk_label_new (Q_("!palette-notebook_tab!Select")));
     }
   else
     {
@@ -2216,7 +2216,7 @@
       gtk_container_add (GTK_CONTAINER (frame), vbox);
       gtk_widget_show (vbox);
       
-      button = gtk_button_new_with_label (_("New"));
+      button = gtk_button_new_with_label (Q_("!palette-button!New"));
       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
       gtk_signal_connect (GTK_OBJECT (button), "clicked",
@@ -2238,7 +2238,7 @@
                               "dialogs/palette_editor/delete_palette.html");
       gtk_widget_show (button);
       
-      button = gtk_button_new_with_label (_("Import"));
+      button = gtk_button_new_with_label (Q_("!palette-button!Import"));
       GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
       gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
       gtk_signal_connect (GTK_OBJECT (button), "clicked",
@@ -3093,7 +3093,7 @@
                     GTK_WIN_POS_NONE,
                     FALSE, TRUE, FALSE,
 
-                    _("Import"), palette_import_import_callback,
+                    Q_("!palette_import_dialog-button!Import"), 
+palette_import_import_callback,
                     palette, NULL, NULL, FALSE, FALSE,
                     _("Close"), palette_import_close_callback,
                     palette, NULL, NULL, TRUE, TRUE,
@@ -3107,7 +3107,7 @@
   gtk_widget_show (hbox);
 
   /*  The "Import" frame  */
-  frame = gtk_frame_new (_("Import"));
+  frame = gtk_frame_new (Q_("!palette_import_dialog-frame!Import"));
   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
   gtk_widget_show (frame);
 
@@ -3230,7 +3230,7 @@
   gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
   gtk_widget_show (image);
 
-  button = import_dialog->select = gtk_button_new_with_label (_("Select"));
+  button = import_dialog->select = gtk_button_new_with_label 
+(Q_("!palette_import-button!Select"));
   GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
   gtk_signal_connect (GTK_OBJECT (button), "clicked", 
                      GTK_SIGNAL_FUNC (palette_import_select_grad_callback),
diff -ru /home/cyba/gcvs/gimp/app/preferences_dialog.c gimp/app/preferences_dialog.c
--- /home/cyba/gcvs/gimp/app/preferences_dialog.c       Sun Dec  3 20:16:59 2000
+++ gimp/app/preferences_dialog.c       Wed Dec  6 21:39:01 2000
@@ -2109,9 +2109,9 @@
 
   /* Interface / Tool Options */
   vbox = prefs_notebook_append_page (GTK_NOTEBOOK (notebook),
-                                         _("Tool Options"),
+                                         Q_("!preferences_interface!Tool Options"),
                                          GTK_CTREE (ctree),
-                                         _("Tool Options"),
+                                         Q_("!preferences_interface!Tool Options"),
                                          
"dialogs/preferences/interface.html#tool_options",
                                          top_insert,
                                          &child_insert,
@@ -2246,7 +2246,7 @@
 
                           _("Nearest Neighbor (Fast)"),
                           (gpointer) NEAREST_NEIGHBOR_INTERPOLATION, NULL,
-                          _("Linear"),
+                          Q_("!interpolation_type!Linear"),
                           (gpointer) LINEAR_INTERPOLATION, NULL,
                           _("Cubic (Slow)"),
                           (gpointer) CUBIC_INTERPOLATION, NULL,
diff -ru /home/cyba/gcvs/gimp/app/tools.c gimp/app/tools.c
--- /home/cyba/gcvs/gimp/app/tools.c    Sun Dec  3 20:17:06 2000
+++ gimp/app/tools.c    Wed Dec  6 21:39:01 2000
@@ -1534,7 +1534,7 @@
 
   /*  The shell and main vbox  */
   options_shell =
-    gimp_dialog_new (_("Tool Options"), "tool_options",
+    gimp_dialog_new (Q_("!dialog_title!Tool Options"), "tool_options",
                     tools_help_func,
                     "dialogs/tool_options.html",
                     GTK_WIN_POS_NONE,
diff -ru /home/cyba/gcvs/gimp/modules/colorsel_water.c gimp/modules/colorsel_water.c
--- /home/cyba/gcvs/gimp/modules/colorsel_water.c       Thu Nov 23 12:38:51 2000
+++ gimp/modules/colorsel_water.c       Wed Dec  6 21:39:01 2000
@@ -626,7 +626,7 @@
   bbox = gtk_vbutton_box_new ();
   gtk_box_pack_end (GTK_BOX (hbox2), bbox, FALSE, FALSE, 0);
 
-  button = gtk_button_new_with_label (_("New"));
+  button = gtk_button_new_with_label (Q_("!color-button!New"));
   gtk_container_add (GTK_CONTAINER (bbox), button);
   gtk_signal_connect (GTK_OBJECT (button), "clicked",
                      (GtkSignalFunc) new_color_callback,

Reply via email to