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 <cyba@xxxxxxxx> + + 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 <alt@xxxxxxxx> * 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 <tromey@xxxxxxxxxxxxxxxxx> * Heavily modified by Daniel Egger <Daniel.Egger@xxxxxxxxxxx> * 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,