Hi developers,

 as you might know that gettext solution works quite nice for
 GIMP itself but may cause trouble with plugins. To circumvent
 the problem that every plugin must have it's domain registered
 within the GIMP source, I'll offer you a new idea here:

 0. Foreword
 Basically we can't get away from gettext and switch to a better 
 system (which would have to be written first, too) that short before a 
 release like at the moment. Thus my goal was to change as little as
 possible. Like you'll see, we'll just have to add a line to every
 plugin outside the GIMP distribution to make this work; everything
 else stays the same like it is now, even the catalogs remain untouched.

 1. Ideas

 1.1 The config file
 The current system is a very static one i.e. nothing can be changed 
 neither without the sourcecode nor after compilation. What we need
 is a dynamic system to remove that deficiencies. A good way to bring
 some dynamic into a system is to make it configurable for example by
 having a config file.
 This configfile of course shouldn't have to be modified by an editor
 but automatically by the GIMP resp. libgimp.

 1.2 Plugins with libgimp
 To get this information in there we'll provide a funtion call in 
 libgimp which registers the domain from the name and path the plugin
 CAN provide. If the domain hasn't been registered yet it'll its way
 into the configfile
 
 1.3 The GIMP core
 The GIMP uses the information from this file to bind the necessary
 catalogs to itself. To actually use this bound domains we'll have to
 provide a function which won't look up a message in one catalog but
 recurse through all of them. This function will replace the gettext
 call just in places where the GIMP would lookup a menuentry which
 is sometimes not in its own catalog.

 2. Implementation

 2.1 The configfile
 Like all other configfiles this one will stay in ~/.gimp-<Version>.
 The first line contains ":gimp" to ensure that no one messed up this file.
 The next lines contain the name of the domain, a withespace and the
 location of the catalog. One catalog per line.

 2.2 Plugins with libgimp
 For the plugins we'll have two new functions in libgimp/gimpdomain.c
 which have the selfexplaining prototypes.

 gimp_domain_add (gchar *)
 and
 gimp_domain_add_with_path (gchar *, gchar *)

 Every plugin may register a domain but don't has to necessarily.
 The functions call another static one which checks whether the files
 already exists and whether the domain is already registerd. If so it
 won't be registered again else it will.

 2.3 The GIMP core
 GIMP will call initgettext() at startup which will initialise i18n
 if compiled with it and setup a default (and fallback) domain "gimp"
 and every domain that it'll read from localerc.
 Every occurence of gettext which had been used to translate menunames
 will be changed to gimpgettext which consists of a loop which checks 
 for a possible translation in all domains which were read from
 localerc.
 At the end GIMP'll call freegettext() to clean up everything.

 3. Conclusion
 This idea will cirumvent most of the problems which gettext alone
 just can't deal with. It's little and as such not very likely to 
 introduce many new bugs. It would allow us to ship GIMP 1.2 with
 the possibility to add plugins which will also benefit from
 localisation without any hassle.

 Patch against current CVS is appended. Please feel free to contribute
 further ideas and to comment this stuff.

-- 

Servus,
       Daniel
diff -P -r -u gimp/app/Makefile.am gimpnew/app/Makefile.am
--- gimp/app/Makefile.am        Mon Feb 21 23:26:00 2000
+++ gimpnew/app/Makefile.am     Tue Feb 22 00:11:35 2000
@@ -198,6 +198,8 @@
        gimpcontextpreview.h    \
        gimpdnd.c               \
        gimpdnd.h               \
+       gimpgettext.c           \
+       gimpgettext.h           \
        gimphelp.c              \
        gimphelp.h              \
        gimphelp_cmds.c         \
diff -P -r -u gimp/app/gimpgettext.c gimpnew/app/gimpgettext.c
--- gimp/app/gimpgettext.c      Thu Jan  1 01:00:00 1970
+++ gimpnew/app/gimpgettext.c   Tue Feb 22 01:02:10 2000
@@ -0,0 +1,188 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpgettext.c
+ * Copyright (C) 2000 Daniel Egger <[EMAIL PROTECTED]>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#ifdef ENABLE_NLS
+
+#include <gtk/gtkmain.h>
+#include <libgimp/gimpintl.h>
+#include <stdio.h>
+#include "gimpgettext.h"
+
+
+/* 128 bytes should be more than sufficient for now.
+ * This is used when parsing the file               */
+#define BUFFER_LENGTH 128
+
+/* Local data */
+
+static gchar *domains[100];
+static FILE *dbfile;
+
+/* Prototypes for local functions */
+
+static guint init_database();
+static gchar *fetch_entry_and_init();
+static void close_database();
+
+/* initgettext() initialises gettext for use with GIMP
+   and ONLY for GIMP. You must NOT call this function
+   elsewhere than in main.c!                           */
+
+void 
+initgettext()
+{
+       guint catalognum = 1;
+       gchar *domain;
+       
+       /* This makes it even safe if someone still uses
+          the normal gettext in gimp because the default
+          domain is still initialised to "gimp"         */
+
+       INIT_LOCALE("gimp");
+       domains[0]=g_strdup("gimp");
+
+       /* Try to init the database */
+       
+       if (!(init_database()))
+               return;
+       
+       /* Register all domains we find in the database */
+       
+       while ((domain = fetch_entry_and_init ()))
+       {
+               domains[catalognum]=domain;
+               catalognum++;
+       }
+
+       /* Close the database */
+       
+       close_database();
+}      
+
+/* This is a replacement for the normal gettext()
+   resp. dgettext("gimp",...) call. It will traverse through
+   all registers domains to find a translation.
+   The GIMP catalog is always the first one which will be
+   queried.                                                    */
+
+gchar *
+gimpgettext (gchar *msgid)
+{
+       guint catalognum = 0;
+       gchar *message;
+       
+       while (domains[catalognum]!=NULL)               
+       {
+               message = dgettext(domains[catalognum],msgid);
+               
+               /* If the new message is the not same as the old one
+                  then the catalog contained a translation, so
+                  we run away here...                              */
+               
+               if(strcmp(message,msgid))
+                       return message; 
+               
+               catalognum++;
+       }
+       
+       return msgid;
+}
+
+/* Internal function to initialise the database file which
+   contains the names of the catalogs to be queried.           */
+
+static guint
+init_database()
+{
+       gchar buffer[BUFFER_LENGTH];
+       gchar *dbfilename;
+       dbfilename = g_strdup_printf("%s/.gimp-1.1/localerc",g_get_home_dir());
+       
+       if (!(dbfile = fopen(dbfilename,"r")))
+       {
+               printf("Couldn't open file: %s\n", dbfilename);
+               goto error;
+       }
+       
+       if (strcmp(fgets(buffer,BUFFER_LENGTH,dbfile),":gimp\n"))
+       {
+               printf("No valid database: %s\n", dbfilename);
+               goto error;
+       }               
+       
+       return TRUE;
+
+error:
+       g_free(dbfilename);
+       return FALSE;
+}      
+
+/* Internal function which is called in order to get and register
+   the next domain in the database.                              */
+
+static gchar *
+fetch_entry_and_init()
+{
+       gchar *buffer;
+       gchar buffer2[BUFFER_LENGTH];
+ 
+       if ((fgetc(dbfile) != ':') && (!feof(dbfile)))
+       {
+               buffer = g_malloc(BUFFER_LENGTH);
+       
+               fseek(dbfile,-1,SEEK_CUR);
+               fscanf(dbfile,"%s %s\n",buffer,buffer2);
+
+               bindtextdomain(buffer,buffer2);
+               return buffer;
+       }
+       
+       return NULL;
+}      
+
+/* Internal function to close the database after use. */
+
+static void
+close_database()
+{
+       fclose(dbfile);
+}
+
+/* Public function to be called very late to free the which is used
+   to save the domainnames. You cannot use gimpgettext after this
+   call anymore!                                                   */
+
+void
+freegettext()
+{
+        guint catalognum = 0;
+
+        while (domains[catalognum]!=NULL)
+        {
+                g_free (domains[catalognum]);
+                catalognum++;
+        }
+}
+
+#endif  /*  ENABLE_NLS  */
+
diff -P -r -u gimp/app/gimpgettext.h gimpnew/app/gimpgettext.h
--- gimp/app/gimpgettext.h      Thu Jan  1 01:00:00 1970
+++ gimpnew/app/gimpgettext.h   Tue Feb 22 00:10:31 2000
@@ -0,0 +1,30 @@
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpgettext.h
+ * Copyright (C) 2000 Daniel Egger <[EMAIL PROTECTED]>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMPGETTEXT_H__
+#define __GIMPGETTEXT_H__
+
+void initgettext();
+gchar *gimpgettext(gchar *);
+void freegettext();
+
+#endif  /*  __GIMPGETTEXT_H__  */
+
diff -P -r -u gimp/app/main.c gimpnew/app/main.c
--- gimp/app/main.c     Mon Feb 21 23:26:12 2000
+++ gimpnew/app/main.c  Tue Feb 22 00:28:04 2000
@@ -44,6 +44,7 @@
 #include "app_procs.h"
 #include "errors.h"
 #include "install.h"
+#include "gimpgettext.h"
 
 #include "libgimp/gimpintl.h"
 
@@ -131,18 +132,27 @@
   prog_name = argv[0];
 
   /* Initialize i18n support */
+#ifdef BOGUS
+#ifdef ENABLE_NLS
   INIT_LOCALE ("gimp");
 
-#ifdef ENABLE_NLS
   bindtextdomain ("gimp-libgimp", LOCALEDIR);
 
   for (i = 0; i < n_plugin_domains; i++)
     bindtextdomain (plugin_domains[i], LOCALEDIR);
 #endif
+#endif
+#ifdef ENABLE_NLS
+
+   initgettext ();
+
+#endif
 
   gtk_init (&argc, &argv);
 
+#ifdef ENABLE_NLS  
   setlocale (LC_NUMERIC, "C");  /* gtk seems to zap this during init.. */
+#endif
 
 #ifdef HAVE_PUTENV
   display_env = g_strconcat ("DISPLAY=", gdk_get_display (), NULL);
diff -P -r -u gimp/app/menus.c gimpnew/app/menus.c
--- gimp/app/menus.c    Mon Feb 21 23:26:02 2000
+++ gimpnew/app/menus.c Tue Feb 22 01:12:26 2000
@@ -39,9 +39,11 @@
 #include "docindex.h"
 
 #include "config.h"
+#include "gimpgettext.h"
 #include "libgimp/gimpintl.h"
 #include "libgimp/gimpenv.h"
 
+
 #define MRU_MENU_ENTRY_SIZE (strlen ("/File/MRU00 ") + 1)
 #define MRU_MENU_ACCEL_SIZE sizeof ("<control>0")
 
@@ -1776,7 +1778,6 @@
   gchar *retval;
   gchar *factory;
   gchar *translation;
-  gint   i;
 
   factory = (gchar *) data;
 
@@ -1790,17 +1791,14 @@
       (strstr (path, "/MRU") != NULL))
     return retval;
 
-  /* 
-   * Work around a bug in GTK+ prior to 1.2.7 (similar workaround below)
-   */
-  translation = gettext (menupath);
+  translation = gimpgettext (menupath);
+
   if (*translation == '/')
     retval = translation;
   else
     g_warning ("bad translation for menupath: %s", menupath);
 
-  i = 0;
-  while (i < n_plugin_domains && !strcmp (path, retval) && factory)
+  if (!strcmp (path, retval) && factory)
     {
       g_free (menupath);
 
@@ -1812,14 +1810,14 @@
        * translated menu_entries which tend to crash the app due to bug in 
        * GTK+. 
        */
-      translation = dgettext (plugin_domains[i++], menupath);
+      translation = gimpgettext (menupath);
 
       if (strncmp (factory, translation, strlen (factory)) == 0)
        retval = translation + strlen (factory);
       else
        g_warning ("bad translation for menupath: %s", menupath);
     }
-
+  
   return retval;
 }
 
diff -P -r -u gimp/libgimp/Makefile.am gimpnew/libgimp/Makefile.am
--- gimp/libgimp/Makefile.am    Mon Feb 21 23:27:01 2000
+++ gimpnew/libgimp/Makefile.am Mon Feb 21 23:36:16 2000
@@ -33,6 +33,8 @@
        gimpcolorspace.c        \
        gimpdialog.c            \
        gimpdialog.h            \
+       gimpdomain.c            \
+       gimpdomain.h            \
        gimpfileselection.c     \
        gimpfileselection.h     \
        gimphelpui.c            \
@@ -82,6 +84,7 @@
        gimpcolorbutton.h       \
        gimpcolorspace.c        \
        gimpdisplay.c           \
+       gimpdomain.c            \
        gimpdrawable.c          \
        gimpenv.c               \
        gimpgradient.c          \
@@ -141,6 +144,7 @@
        gimpcolorspace.h        \
         gimpcompat.h           \
        gimpdialog.h            \
+       gimpdomain.h            \
        gimpenums.h             \
        gimpenv.h               \
        gimpexport.h            \
diff -P -r -u gimp/libgimp/gimpdomain.c gimpnew/libgimp/gimpdomain.c
--- gimp/libgimp/gimpdomain.c   Thu Jan  1 01:00:00 1970
+++ gimpnew/libgimp/gimpdomain.c        Tue Feb 22 00:01:57 2000
@@ -0,0 +1,111 @@
+/* gimpdomain.c - Part of the GIMP Library
+ *
+ * Copyright (C) 2000 Daniel Egger <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <glib.h>
+#include <stdio.h>
+
+#include "gimpenv.h"
+#include "gimpintl.h"
+
+#include "gimpdomain.h"
+
+
+static guint domain_add(gchar *domain, gchar *path);
+
+guint gimp_domain_add(gchar *domain)
+{
+       return (domain_add (domain, LOCALEDIR));
+}      
+
+guint gimp_domain_add_with_path(gchar *domain,
+                               gchar *path)
+{
+       return (domain_add (domain, path));
+}
+
+static guint domain_add(gchar *domain,
+                       gchar *path)
+{
+       FILE *dbfile;
+       gchar *dbfilename;
+       guint foundflag;
+       gchar buffer[128];
+       gchar buffer2[128];
+       
+       dbfilename = g_strdup_printf("%s/.gimp-1.1/localerc",g_get_home_dir());
+       
+       if (!(dbfile = fopen(dbfilename,"r+")))
+       {
+               printf("Couldn't open file %s\n", dbfilename);
+               if (!(dbfile = fopen(dbfilename,"a+")))
+               {
+                       printf("Couldn't even create one!\n");  
+                       g_free(dbfilename);
+                       return FALSE;
+               }       
+       }
+
+       rewind(dbfile);
+       if (!(fgetc(dbfile)==':'))
+       {
+               fseek(dbfile,0,SEEK_SET);
+               printf("No ':' found at start of file\n"
+                       "Assuming new file\n");
+               fputs(":gimp\n", dbfile);
+               fflush(dbfile);
+       }               
+       
+       fseek(dbfile,0,SEEK_SET);
+       fgets(buffer,128,dbfile);
+       printf("Got buffer: %s\n",buffer);
+       
+       if(!(strcmp(buffer,":gimp\n")))
+       {
+               printf("our file\n");
+       }
+       else
+       {
+               printf("not our file!\n");
+       }
+
+       foundflag = FALSE;
+       
+       while ((fgetc(dbfile) != ':') && (!feof(dbfile)))
+       {
+               fseek(dbfile,-1,SEEK_CUR);
+               fscanf(dbfile,"%s %s\n",buffer,buffer2);
+
+               if(!(strcmp(buffer,domain))) 
+               {
+                       foundflag = TRUE;
+                       break;
+               }
+       }
+
+       if(!foundflag)
+       {
+               fprintf(dbfile,"%s %s\n",domain,path);
+       }       
+       
+       fclose(dbfile);
+       g_free(dbfilename);
+       return TRUE;
+}
+
diff -P -r -u gimp/libgimp/gimpdomain.h gimpnew/libgimp/gimpdomain.h
--- gimp/libgimp/gimpdomain.h   Thu Jan  1 01:00:00 1970
+++ gimpnew/libgimp/gimpdomain.h        Tue Feb 22 00:00:03 2000
@@ -0,0 +1,40 @@
+/* gimpdomain.h
+ *
+ * Copyright (C) 2000 Daniel Egger <[EMAIL PROTECTED]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GIMPENV_H__
+#define __GIMPENV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <libgimp/gimpintl.h>
+#include <glib.h>
+#include <stdio.h>
+
+guint gimp_domain_add (gchar *domain);
+guint gimp_domain_add_with_path (gchar *domain, gchar *path);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /*  __GIMPENV_H__  */
+
diff -P -r -u gimp/libgimp/gimpintl.h gimpnew/libgimp/gimpintl.h
--- gimp/libgimp/gimpintl.h     Mon Feb 21 23:27:02 2000
+++ gimpnew/libgimp/gimpintl.h  Mon Feb 21 23:56:54 2000
@@ -1,7 +1,9 @@
-/* LIBGIMP - The GIMP Library                                                   
+/* gimpintl.h - Part of the GIMP Library                                              
+     
+ *
  * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball                
  *
- * libgimp-intl.h
+ * Copied from gnome-i18n.h by Tom Tromey <[EMAIL PROTECTED]>
+ * Copyright (C) 1999,2000 Daniel Egger <[EMAIL PROTECTED]>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,10 +25,7 @@
 
 #include <glib.h>
 #include <locale.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    */ 
+#include <libgimp/gimpenv.h>
 
 #ifndef LOCALEDIR
 #define LOCALEDIR g_strconcat (gimp_data_directory (), \

Reply via email to