unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* i18n, gettext support
@ 2004-08-20 20:26 Bruno Haible
  2004-08-23  0:58 ` Kevin Ryde
  2004-09-01 16:25 ` Jan Nieuwenhuizen
  0 siblings, 2 replies; 28+ messages in thread
From: Bruno Haible @ 2004-08-20 20:26 UTC (permalink / raw)
  Cc: Jan Nieuwenhuizen

[-- Attachment #1: Type: text/plain, Size: 1983 bytes --]

Hello,

Jan Nieuwenhuizen asked me (the GNU gettext maintainer) for how to support
Guile programs in gettext.

The idea would be to make libintl bindings at the C level, and add support
for Scheme to xgettext and msgfmt. Common Lisp support has already been done
long ago; the guile support would therefore be a simple clone of it.

I plan to use this sample "hello world" program as an example. Is this OK
with you, the guile developers?

=============================== hello.scm ==================================
#!@GUILE@ -s
!#
;;; Example for use of GNU gettext.
;;; Copyright (C) 2004 Free Software Foundation, Inc.
;;; This file is in the public domain.

;;; Source code of the GNU guile program.

(use-modules (i18n))
(use-modules (ice-9 format))

(set! (i18n:textdomain) "hello-guile")
(set! (i18n:textdomaindir "hello-guile") "@localedir@/")
(define _ i18n:gettext)

(display (_ "Hello, world!"))
(newline)
(format #t (_ "This program is running as process number ~D.") (getpid))
(newline)
=============================================================================

Attached you find my proposal for the libintl binding module. It is based
on the existing interface in GNU clisp, and adapted for guile. Please
comment on it. You can use this proposal as a base for the documentation
of this interface.

Technically, this binding could be distributed with guile or with gettext.
I would much prefer if it were part of guile, because this frees the
guile user from checking whether the guile-libintl interface is installed
or not.

The ice-9 format string facility with its ~n@* facility is sufficient for
i18n. Is it true that most guile programs use format, not printf, for
formatted string output?

> without guile properly understanding multi-byte strings it's a bit limited

Without proper multibyte or Unicode string support, programs can not
do surgery (truncation, uppercase conversion etc.) on strings returned
from i18n:gettext, but it can output them.

Bruno


[-- Attachment #2: guile-gettext.html --]
[-- Type: text/html, Size: 17344 bytes --]

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-08-20 20:26 i18n, gettext support Bruno Haible
@ 2004-08-23  0:58 ` Kevin Ryde
  2004-09-01 16:25 ` Jan Nieuwenhuizen
  1 sibling, 0 replies; 28+ messages in thread
From: Kevin Ryde @ 2004-08-23  0:58 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

Bruno Haible <bruno@clisp.org> writes:
>
> (use-modules (i18n))

It's probably important enough to have in the core.

> (set! (i18n:textdomain) "hello-guile")

I'd just call the functions plain "textdomain" etc.

> (define _ i18n:gettext)

Could provide that binding by default, to encourage its use.

> The ice-9 format string facility with its ~n@* facility is sufficient for
> i18n.

Many programs probably use only the core `simple-format' version of
format, which lacks ~*.  Might be worth adding there.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-08-20 20:26 i18n, gettext support Bruno Haible
  2004-08-23  0:58 ` Kevin Ryde
@ 2004-09-01 16:25 ` Jan Nieuwenhuizen
  2004-09-01 20:57   ` Bruno Haible
  2004-09-01 21:44   ` Kevin Ryde
  1 sibling, 2 replies; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-01 16:25 UTC (permalink / raw)
  Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 323 bytes --]

Bruno Haible writes:

> I plan to use this sample "hello world" program as an example. Is this OK
> with you, the guile developers?

Attached is a patch with gettext C bindings for GUILE (which I tried
to avoid before).

When this gets included in GUILE, we can make the final changes to
hello-guile.scm.

Greetings,
Jan.


[-- Attachment #2: guile-1.7.1.jcn1.diff --]
[-- Type: text/plain, Size: 9687 bytes --]

? debug
? doconf
? guile-config/libtool.m4
? guile-config/ltdl.m4
? guile-readline/ice-9
? guile-readline/libtool.m4
? libguile/i18n.c
? libguile/i18n.h
? libguile/init.loT
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.444
diff -p -u -r1.444 ChangeLog
--- ChangeLog	27 Aug 2004 01:10:20 -0000	1.444
+++ ChangeLog	1 Sep 2004 16:17:14 -0000
@@ -1,3 +1,7 @@
+2004-09-01  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* configure.in: Add i18n checks.
+
 2004-08-27  Kevin Ryde  <user42@zip.com.au>
 
 	* configure.in (AC_CHECK_MEMBERS): Add struct sockaddr.sin_len and
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.251
diff -p -u -r1.251 configure.in
--- configure.in	27 Aug 2004 01:09:48 -0000	1.251
+++ configure.in	1 Sep 2004 16:17:14 -0000
@@ -637,6 +637,14 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AC_CHECK_HEADERS([gettext.h libintl.h])
+AC_CHECK_FUNCS(gettext)
+if test $ac_cv_func_gettext = no; then
+   AC_CHECK_LIB(intl, gettext)
+fi
+AC_CHECK_FUNCS([bindtextdomain textdomain])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2137
diff -p -u -r1.2137 ChangeLog
--- libguile/ChangeLog	27 Aug 2004 12:46:11 -0000	1.2137
+++ libguile/ChangeLog	1 Sep 2004 16:17:17 -0000
@@ -1,3 +1,8 @@
+2004-09-01  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h:
+	* i18n.c: New file.
+
 2004-08-27  Marius Vollmer  <marius.vollmer@uni-dortmund.de>
 
 	* strings.c (SCM_STRINGP): Accept all strings.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	1 Sep 2004 16:17:17 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	1 Sep 2004 16:17:17 -0000
@@ -477,6 +477,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/numbers.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/numbers.c,v
retrieving revision 1.260
diff -p -u -r1.260 numbers.c
--- libguile/numbers.c	24 Aug 2004 16:43:50 -0000	1.260
+++ libguile/numbers.c	1 Sep 2004 16:17:18 -0000
@@ -5848,8 +5848,8 @@ scm_init_numbers ()
       scm_dblprec[10-2] = (DBL_DIG > 20) ? 20 : DBL_DIG;
 #endif
 
-#ifdef GUILE_DEBUG
-  check_sanity ();
+#ifdef FIXME__GUILE_DEBUG
+   check_sanity ();
 #endif
 
   exactly_one_half = scm_permanent_object (scm_divide (SCM_I_MAKINUM (1),
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-01 18:12:57 +0200
@@ -0,0 +1,43 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+\f
+
+#include "libguile/__scm.h"
+
+\f
+
+
+\f
+
+SCM_API SCM scm_gettext (SCM string);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-01 17:38:29 +0200
@@ -0,0 +1,116 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef HAVE_GETEXT_H
+#  include <gettext.h>
+#endif
+
+#ifdef HAVE_LIBINTL_H
+#  include <libintl.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/discouraged.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+
+\f
+
+#ifdef HAVE_GETTEXT
+SCM_DEFINE (scm_gettext, "gettext", 1, 0, 0,
+	    (SCM string),
+	    "Return gettext lookup of @var{string}.")
+#define FUNC_NAME s_scm_gettext
+{
+  SCM_VALIDATE_STRING (1, string);
+  return scm_makfrom0str (gettext (SCM_STRING_CHARS (string)));
+}
+#undef FUNC_NAME
+#endif /* HAVE_GETTEXT */
+
+#ifdef HAVE_TEXTDOMAIN
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+            (SCM domainname),
+	    "If optional argument @var{domainname} is supplied, "
+	    "set textdomain."
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *rv;
+  char *n;
+
+  if (SCM_UNBNDP (domainname))
+    n = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      n = SCM_STRING_CHARS (domainname);
+    }
+  rv = textdomain (n);
+  if (rv == NULL)
+    SCM_SYSERROR;
+  return scm_makfrom0str (rv);
+}
+#undef FUNC_NAME
+#endif /* HAVE_TEXTDOMAIN */
+
+#ifdef HAVE_BINDTEXTDOMAIN
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+            (SCM domainname, SCM directory),
+	    "Set message catalogs for domain @var{domainname} "
+	    "to directory @{directory}."
+	    "Return the bound directory.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *rv;
+  char *d;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    d = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      d = SCM_STRING_CHARS (directory);
+    }
+  rv = bindtextdomain (SCM_STRING_CHARS (domainname), d);
+  if (rv == NULL)
+    SCM_SYSERROR;
+  return scm_makfrom0str (rv);
+}
+#undef FUNC_NAME
+#endif /* HAVE_BINDTEXTDOMAIN */
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-01 16:25 ` Jan Nieuwenhuizen
@ 2004-09-01 20:57   ` Bruno Haible
  2004-09-02  9:38     ` Jan Nieuwenhuizen
  2004-09-01 21:44   ` Kevin Ryde
  1 sibling, 1 reply; 28+ messages in thread
From: Bruno Haible @ 2004-09-01 20:57 UTC (permalink / raw)
  Cc: guile-devel

Jan Nieuwenhuizen wrote:
> Attached is a patch with gettext C bindings for GUILE (which I tried
> to avoid before).

Thanks; this is a good start. The patch is not complete however: it implements
only half of the proposed API; the autoconf text for libintl is broken; and
the use of gettext.h is useless since gettext.h should never be installed in
public directories.

I'll send an updated patch tomorrow.

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-01 16:25 ` Jan Nieuwenhuizen
  2004-09-01 20:57   ` Bruno Haible
@ 2004-09-01 21:44   ` Kevin Ryde
  1 sibling, 0 replies; 28+ messages in thread
From: Kevin Ryde @ 2004-09-01 21:44 UTC (permalink / raw)
  Cc: Bruno Haible, guile-devel

Jan Nieuwenhuizen <janneke@gnu.org> writes:
>
> +SCM_API SCM scm_gettext (SCM string);

dgettext is good too, and may as well have dcgettext at the same time.

> +SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);

bind_textdomain_codeset will be good too until guile gets a strong
grip on coding matters.  (I would use it for instance to force utf8
for strings for gtk.)


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-01 20:57   ` Bruno Haible
@ 2004-09-02  9:38     ` Jan Nieuwenhuizen
  2004-09-02 16:06       ` Bruno Haible
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-02  9:38 UTC (permalink / raw)
  Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 580 bytes --]

Bruno Haible writes:

> Thanks; this is a good start. The patch is not complete however: it
> implements only half of the proposed API;

I have implemented the minimal functionality; the biggest hurdle is
probably getting this included (I can hardly imagine how a software in
2004 could still lack gettext -- and be widely used).

> the autoconf text for libintl is broken; and the use of gettext.h is
> useless since gettext.h should never be installed in public
> directories.

Thanks, these should be fixed, see attached.

> I'll send an updated patch tomorrow.

Great.

Jan.


[-- Attachment #2: guile-1.7.1.jcn2.diff --]
[-- Type: text/plain, Size: 9922 bytes --]

? debug
? do-diff
? doconf
? guile-1.7.1.jcn1.diff
? guile-1.7.1.jcn2.diff
? guile-config/libtool.m4
? guile-config/ltdl.m4
? guile-readline/ice-9
? guile-readline/libtool.m4
? libguile/'
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.444
diff -p -u -r1.444 ChangeLog
--- ChangeLog	27 Aug 2004 01:10:20 -0000	1.444
+++ ChangeLog	2 Sep 2004 09:27:59 -0000
@@ -1,3 +1,7 @@
+2004-09-01  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* configure.in: Add i18n tests.
+
 2004-08-27  Kevin Ryde  <user42@zip.com.au>
 
 	* configure.in (AC_CHECK_MEMBERS): Add struct sockaddr.sin_len and
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.251
diff -p -u -r1.251 configure.in
--- configure.in	27 Aug 2004 01:09:48 -0000	1.251
+++ configure.in	2 Sep 2004 09:27:59 -0000
@@ -637,6 +637,14 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AC_CHECK_HEADERS([libintl.h])
+AC_CHECK_FUNCS(gettext)
+if test $ac_cv_func_gettext = no; then
+   AC_CHECK_LIB(intl, gettext)
+fi
+AC_CHECK_FUNCS([bindtextdomain textdomain])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2137
diff -p -u -r1.2137 ChangeLog
--- libguile/ChangeLog	27 Aug 2004 12:46:11 -0000	1.2137
+++ libguile/ChangeLog	2 Sep 2004 09:28:02 -0000
@@ -1,3 +1,11 @@
+2004-09-02  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h:
+	* i18n.c: New file.
+
+	* init.c:
+	* Makefile.am: Add it.
+
 2004-08-27  Marius Vollmer  <marius.vollmer@uni-dortmund.de>
 
 	* strings.c (SCM_STRINGP): Accept all strings.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	2 Sep 2004 09:28:02 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	2 Sep 2004 09:28:02 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/numbers.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/numbers.c,v
retrieving revision 1.260
diff -p -u -r1.260 numbers.c
--- libguile/numbers.c	24 Aug 2004 16:43:50 -0000	1.260
+++ libguile/numbers.c	2 Sep 2004 09:28:03 -0000
@@ -5848,8 +5848,8 @@ scm_init_numbers ()
       scm_dblprec[10-2] = (DBL_DIG > 20) ? 20 : DBL_DIG;
 #endif
 
-#ifdef GUILE_DEBUG
-  check_sanity ();
+#ifdef FIXME__GUILE_DEBUG
+   check_sanity ();
 #endif
 
   exactly_one_half = scm_permanent_object (scm_divide (SCM_I_MAKINUM (1),
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-01 18:12:57 +0200
@@ -0,0 +1,43 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+\f
+
+#include "libguile/__scm.h"
+
+\f
+
+
+\f
+
+SCM_API SCM scm_gettext (SCM string);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-02 11:24:39 +0200
@@ -0,0 +1,113 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#if HAVE_LIBINTL_H
+#  include <libintl.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+
+\f
+
+#if ! HAVE_GETTEXT
+#  define gettext(x) (x)
+#endif
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 0, 0,
+	    (SCM string),
+	    "Return gettext lookup of @var{string}.")
+#define FUNC_NAME s_scm_gettext
+{
+  SCM_VALIDATE_STRING (1, string);
+  return scm_from_locale_string (gettext (SCM_STRING_CHARS (string)));
+}
+#undef FUNC_NAME
+
+#if HAVE_TEXTDOMAIN
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+            (SCM domainname),
+	    "If optional argument @var{domainname} is supplied, "
+	    "set textdomain."
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *rv;
+  char *n;
+
+  if (SCM_UNBNDP (domainname))
+    n = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      n = SCM_STRING_CHARS (domainname);
+    }
+  rv = textdomain (n);
+  if (rv == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (rv);
+}
+#undef FUNC_NAME
+#endif /* HAVE_TEXTDOMAIN */
+
+#if HAVE_BINDTEXTDOMAIN
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+            (SCM domainname, SCM directory),
+	    "Set message catalogs for domain @var{domainname} "
+	    "to directory @{directory}."
+	    "Return the bound directory.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *rv;
+  char *d;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    d = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      d = SCM_STRING_CHARS (directory);
+    }
+  rv = bindtextdomain (SCM_STRING_CHARS (domainname), d);
+  if (rv == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (rv);
+}
+#undef FUNC_NAME
+#endif /* HAVE_BINDTEXTDOMAIN */
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]



-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-02  9:38     ` Jan Nieuwenhuizen
@ 2004-09-02 16:06       ` Bruno Haible
  2004-09-02 16:21         ` Bruno Haible
  2004-09-02 17:32         ` Jan Nieuwenhuizen
  0 siblings, 2 replies; 28+ messages in thread
From: Bruno Haible @ 2004-09-02 16:06 UTC (permalink / raw)
  Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1072 bytes --]

Jan Nieuwenhuizen wrote:
> Thanks, these should be fixed, see attached.

The autoconf test is still broken: AC_CHECK_LIB(intl, gettext) doesn't work.
Also your patch uses SCM_STRING_CHARS, which is deprecated and (as far as
I can test) doesn't work (probably because it returns a not NUL terminated
string).

Find here an extended patch. It implements the complete functionality,
including plural handling, different locale categories and access to
bind_textdomain_codeset (which will probably be important for Gtk/GNOME
applications).


ChangeLog:
2004-09-02  Bruno Haible  <bruno@clisp.org>

	* configure.in: Add AM_GNU_GETTEXT invocation.

libguile/ChangeLog:
2004-09-02  Jan Nieuwenhuizen  <janneke@gnu.org>
            Bruno Haible  <bruno@clisp.org>

	* i18n.h: New file.
	* i18n.c: New file.
	* init.c: Include libguile/i18n.h.
	(scm_init_guile_1): Add call to scm_init_i18n().
	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
	(DOT_X_FILES): Add i18n.x.
	(DOT_DOC_FILES): Add i18n.doc.
	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
	(modinclude_HEADERS): Add i18n.h.


[-- Attachment #2: guile-diffs --]
[-- Type: text/x-diff, Size: 17890 bytes --]

diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/configure.in guile-1.7.1/configure.in
*** guile-1.7.1.orig/configure.in	2004-08-26 16:23:34.000000000 +0200
--- guile-1.7.1/configure.in	2004-09-01 22:05:51.000000000 +0200
***************
*** 637,642 ****
--- 637,645 ----
              [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
    [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
  
+ dnl i18n tests
+ AM_GNU_GETTEXT([external], [need-ngettext])
+ 
  ### Some systems don't declare some functions.  On such systems, we
  ### need to at least provide our own K&R-style declarations.
  
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/init.c guile-1.7.1/libguile/init.c
*** guile-1.7.1.orig/libguile/init.c	2004-08-25 11:45:13.000000000 +0200
--- guile-1.7.1/libguile/init.c	2004-09-02 13:43:11.000000000 +0200
***************
*** 63,68 ****
--- 63,69 ----
  #include "libguile/hash.h"
  #include "libguile/hashtab.h"
  #include "libguile/hooks.h"
+ #include "libguile/i18n.h"
  #include "libguile/iselect.h"
  #include "libguile/ioext.h"
  #include "libguile/keywords.h"
***************
*** 477,482 ****
--- 478,484 ----
    scm_init_properties ();
    scm_init_hooks ();            /* Requires smob_prehistory */
    scm_init_gc ();		/* Requires hooks, async */
+   scm_init_i18n ();
    scm_init_ioext ();
    scm_init_keywords ();
    scm_init_list ();
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/Makefile.am guile-1.7.1/libguile/Makefile.am
*** guile-1.7.1.orig/libguile/Makefile.am	2004-08-25 11:45:10.000000000 +0200
--- guile-1.7.1/libguile/Makefile.am	2004-09-02 17:47:55.000000000 +0200
***************
*** 97,103 ****
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
--- 97,103 ----
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
***************
*** 113,119 ****
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
--- 113,119 ----
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
***************
*** 132,139 ****
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
!     keywords.doc lang.doc list.doc load.doc macros.doc			    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
--- 132,139 ----
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
!     ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
***************
*** 172,178 ****
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
--- 172,178 ----
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
***************
*** 187,193 ****
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
--- 187,193 ----
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.h	2004-09-02 14:05:22.000000000 +0200
***************
*** 0 ****
--- 1,41 ----
+ /* classes: h_files */
+ 
+ #ifndef SCM_I18N_H
+ #define SCM_I18N_H
+ 
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ #include "libguile/__scm.h"
+ 
+ SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+ SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+ SCM_API SCM scm_get_textdomain (void);
+ SCM_API SCM scm_set_textdomain (SCM domainname);
+ SCM_API SCM scm_get_textdomain_dir (SCM domainname);
+ SCM_API SCM scm_set_textdomain_dir (SCM domainname, SCM directory);
+ SCM_API SCM scm_get_textdomain_codeset (SCM domainname);
+ SCM_API SCM scm_set_textdomain_codeset (SCM domainname, SCM encoding);
+ SCM_API void scm_init_i18n (void);
+ 
+ #endif  /* SCM_I18N_H */
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.c	2004-09-02 17:39:25.000000000 +0200
***************
*** 0 ****
--- 1,334 ----
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ 
+ #if HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+ 
+ #include "libguile/_scm.h"
+ #include "libguile/discouraged.h"
+ #include "libguile/feature.h"
+ #include "libguile/i18n.h"
+ #include "libguile/strings.h"
+ #include "gettext.h"
+ #include <locale.h>
+ 
+ 
+ SCM_SYMBOL (scm_sym_LC_MESSAGES, "LC_MESSAGES");
+ SCM_SYMBOL (scm_sym_LC_CTYPE, "LC_CTYPE");
+ SCM_SYMBOL (scm_sym_LC_TIME, "LC_TIME");
+ SCM_SYMBOL (scm_sym_LC_COLLATE, "LC_COLLATE");
+ SCM_SYMBOL (scm_sym_LC_MONETARY, "LC_MONETARY");
+ 
+ 
+ static int
+ scm_validate_category (SCM category, const char *subr, int pos)
+ {
+   if (scm_is_eq (category, scm_sym_LC_MESSAGES))
+     return LC_MESSAGES;
+   else if (scm_is_eq (category, scm_sym_LC_CTYPE))
+     return LC_CTYPE;
+   else if (scm_is_eq (category, scm_sym_LC_TIME))
+     return LC_TIME;
+   else if (scm_is_eq (category, scm_sym_LC_COLLATE))
+     return LC_COLLATE;
+   else if (scm_is_eq (category, scm_sym_LC_MONETARY))
+     return LC_MONETARY;
+   else
+     scm_wrong_type_arg (subr, pos, category);
+ }
+ 
+ 
+ SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+ 	    (SCM msgid, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid} in the message domain "
+ 	    "@var{domain}. @var{domain} is optional and defaults to the "
+ 	    "domain set through (textdomain). @var{category} is optional "
+ 	    "and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_gettext
+ {
+   char *c_msgid;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 1 argument case.  */
+       result = gettext (c_msgid);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (2, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 2 argument case.  */
+ 	  result = dgettext (c_domain, c_msgid);
+ 	}
+       else
+ 	{
+ 	  /* 3 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 3);
+ 	  result = dcgettext (c_domain, c_msgid, c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid);
+       return msgid;
+     }
+   else
+     {
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+ 	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+ 	    "message domain @var{domain}, with the plural form being chosen "
+ 	    "appropriately for the number @var{n}. @var{domain} is optional "
+ 	    "and defaults to the domain set through (textdomain). "
+ 	    "@var{category} is optional and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_ngettext
+ {
+   char *c_msgid;
+   char *c_msgid_plural;
+   unsigned long c_n;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   SCM_VALIDATE_STRING (2, msgid_plural);
+   c_msgid_plural = scm_to_locale_string (msgid_plural);
+   SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 3 argument case.  */
+       result = ngettext (c_msgid, c_msgid_plural, c_n);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (4, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 4 argument case.  */
+ 	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+ 	}
+       else
+ 	{
+ 	  /* 5 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 5);
+ 	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+ 			       c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid;
+     }
+   else if (result == c_msgid_plural)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid_plural;
+     }
+   else
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain, "textdomain", 0, 0, 0,
+ 	    (void),
+ 	    "Return the current message domain.")
+ #define FUNC_NAME s_scm_get_textdomain
+ {
+   const char *result;
+ 
+   result = textdomain (NULL);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain, "set!-textdomain", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Change the current message domain.")
+ #define FUNC_NAME s_scm_set_textdomain
+ {
+   char *c_domain;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   if (textdomain (c_domain) == NULL)
+     SCM_SYSERROR;
+   free (c_domain);
+   return domain;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_dir, "textdomaindir", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_get_textdomain_dir
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bindtextdomain (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_dir, "set!-textdomaindir", 2, 0, 0,
+ 	    (SCM domain, SCM directory),
+ 	    "Change the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_set_textdomain_dir
+ {
+   char *c_domain;
+   char *c_directory;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, directory);
+   c_domain = scm_to_locale_string (domain);
+   c_directory = scm_to_locale_string (directory);
+   if (bindtextdomain (c_domain, c_directory) == NULL)
+     SCM_SYSERROR;
+   free (c_directory);
+   free (c_domain);
+   return directory;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_codeset, "textdomain-codeset", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_get_textdomain_codeset
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bind_textdomain_codeset (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_codeset, "set!-textdomain-codeset", 2, 0, 0,
+ 	    (SCM domain, SCM encoding),
+ 	    "Change the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_set_textdomain_codeset
+ {
+   char *c_domain;
+   char *c_encoding;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, encoding);
+   c_domain = scm_to_locale_string (domain);
+   c_encoding = scm_to_locale_string (encoding);
+   if (bind_textdomain_codeset (c_domain, c_encoding) == NULL)
+     SCM_SYSERROR;
+   free (c_encoding);
+   free (c_domain);
+   return encoding;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ void 
+ scm_init_i18n ()
+ {
+   SCM gettersym, settersym;
+ 
+   scm_add_feature ("i18n");
+ #include "libguile/i18n.x"
+ 
+   gettersym = scm_c_lookup ("textdomain");
+   settersym = scm_c_lookup ("set!-textdomain");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomaindir");
+   settersym = scm_c_lookup ("set!-textdomaindir");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomain-codeset");
+   settersym = scm_c_lookup ("set!-textdomain-codeset");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ }
+ 
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-02 16:06       ` Bruno Haible
@ 2004-09-02 16:21         ` Bruno Haible
  2004-09-03  1:34           ` Kevin Ryde
  2004-09-02 17:32         ` Jan Nieuwenhuizen
  1 sibling, 1 reply; 28+ messages in thread
From: Bruno Haible @ 2004-09-02 16:21 UTC (permalink / raw)
  Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

Oops. Same thing once again, with gettext.h added.


ChangeLog:
2004-09-02  Bruno Haible  <bruno@clisp.org>

	* configure.in: Add AM_GNU_GETTEXT invocation.

libguile/ChangeLog:
2004-09-02  Jan Nieuwenhuizen  <janneke@gnu.org>
            Bruno Haible  <bruno@clisp.org>

	* i18n.h: New file.
	* i18n.c: New file.
	* gettext.h: New file, taken from GNU gettext.
	* init.c: Include libguile/i18n.h.
	(scm_init_guile_1): Add call to scm_init_i18n().
	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
	(DOT_X_FILES): Add i18n.x.
	(DOT_DOC_FILES): Add i18n.doc.
	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
	(modinclude_HEADERS): Add i18n.h.


[-- Attachment #2: guile-diffs --]
[-- Type: text/x-diff, Size: 21239 bytes --]

diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/configure.in guile-1.7.1/configure.in
*** guile-1.7.1.orig/configure.in	2004-08-26 16:23:34.000000000 +0200
--- guile-1.7.1/configure.in	2004-09-01 22:05:51.000000000 +0200
***************
*** 637,642 ****
--- 637,645 ----
              [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
    [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
  
+ dnl i18n tests
+ AM_GNU_GETTEXT([external], [need-ngettext])
+ 
  ### Some systems don't declare some functions.  On such systems, we
  ### need to at least provide our own K&R-style declarations.
  
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/init.c guile-1.7.1/libguile/init.c
*** guile-1.7.1.orig/libguile/init.c	2004-08-25 11:45:13.000000000 +0200
--- guile-1.7.1/libguile/init.c	2004-09-02 13:43:11.000000000 +0200
***************
*** 63,68 ****
--- 63,69 ----
  #include "libguile/hash.h"
  #include "libguile/hashtab.h"
  #include "libguile/hooks.h"
+ #include "libguile/i18n.h"
  #include "libguile/iselect.h"
  #include "libguile/ioext.h"
  #include "libguile/keywords.h"
***************
*** 477,482 ****
--- 478,484 ----
    scm_init_properties ();
    scm_init_hooks ();            /* Requires smob_prehistory */
    scm_init_gc ();		/* Requires hooks, async */
+   scm_init_i18n ();
    scm_init_ioext ();
    scm_init_keywords ();
    scm_init_list ();
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/Makefile.am guile-1.7.1/libguile/Makefile.am
*** guile-1.7.1.orig/libguile/Makefile.am	2004-08-25 11:45:10.000000000 +0200
--- guile-1.7.1/libguile/Makefile.am	2004-09-02 17:47:55.000000000 +0200
***************
*** 97,103 ****
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
--- 97,103 ----
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
***************
*** 113,119 ****
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
--- 113,119 ----
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
***************
*** 132,139 ****
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
!     keywords.doc lang.doc list.doc load.doc macros.doc			    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
--- 132,139 ----
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
!     ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
***************
*** 172,178 ****
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
--- 172,178 ----
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
***************
*** 187,193 ****
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
--- 187,193 ----
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.h	2004-09-02 14:05:22.000000000 +0200
***************
*** 0 ****
--- 1,41 ----
+ /* classes: h_files */
+ 
+ #ifndef SCM_I18N_H
+ #define SCM_I18N_H
+ 
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ #include "libguile/__scm.h"
+ 
+ SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+ SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+ SCM_API SCM scm_get_textdomain (void);
+ SCM_API SCM scm_set_textdomain (SCM domainname);
+ SCM_API SCM scm_get_textdomain_dir (SCM domainname);
+ SCM_API SCM scm_set_textdomain_dir (SCM domainname, SCM directory);
+ SCM_API SCM scm_get_textdomain_codeset (SCM domainname);
+ SCM_API SCM scm_set_textdomain_codeset (SCM domainname, SCM encoding);
+ SCM_API void scm_init_i18n (void);
+ 
+ #endif  /* SCM_I18N_H */
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.c	2004-09-02 17:39:25.000000000 +0200
***************
*** 0 ****
--- 1,334 ----
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ 
+ #if HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+ 
+ #include "libguile/_scm.h"
+ #include "libguile/discouraged.h"
+ #include "libguile/feature.h"
+ #include "libguile/i18n.h"
+ #include "libguile/strings.h"
+ #include "gettext.h"
+ #include <locale.h>
+ 
+ 
+ SCM_SYMBOL (scm_sym_LC_MESSAGES, "LC_MESSAGES");
+ SCM_SYMBOL (scm_sym_LC_CTYPE, "LC_CTYPE");
+ SCM_SYMBOL (scm_sym_LC_TIME, "LC_TIME");
+ SCM_SYMBOL (scm_sym_LC_COLLATE, "LC_COLLATE");
+ SCM_SYMBOL (scm_sym_LC_MONETARY, "LC_MONETARY");
+ 
+ 
+ static int
+ scm_validate_category (SCM category, const char *subr, int pos)
+ {
+   if (scm_is_eq (category, scm_sym_LC_MESSAGES))
+     return LC_MESSAGES;
+   else if (scm_is_eq (category, scm_sym_LC_CTYPE))
+     return LC_CTYPE;
+   else if (scm_is_eq (category, scm_sym_LC_TIME))
+     return LC_TIME;
+   else if (scm_is_eq (category, scm_sym_LC_COLLATE))
+     return LC_COLLATE;
+   else if (scm_is_eq (category, scm_sym_LC_MONETARY))
+     return LC_MONETARY;
+   else
+     scm_wrong_type_arg (subr, pos, category);
+ }
+ 
+ 
+ SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+ 	    (SCM msgid, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid} in the message domain "
+ 	    "@var{domain}. @var{domain} is optional and defaults to the "
+ 	    "domain set through (textdomain). @var{category} is optional "
+ 	    "and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_gettext
+ {
+   char *c_msgid;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 1 argument case.  */
+       result = gettext (c_msgid);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (2, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 2 argument case.  */
+ 	  result = dgettext (c_domain, c_msgid);
+ 	}
+       else
+ 	{
+ 	  /* 3 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 3);
+ 	  result = dcgettext (c_domain, c_msgid, c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid);
+       return msgid;
+     }
+   else
+     {
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+ 	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+ 	    "message domain @var{domain}, with the plural form being chosen "
+ 	    "appropriately for the number @var{n}. @var{domain} is optional "
+ 	    "and defaults to the domain set through (textdomain). "
+ 	    "@var{category} is optional and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_ngettext
+ {
+   char *c_msgid;
+   char *c_msgid_plural;
+   unsigned long c_n;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   SCM_VALIDATE_STRING (2, msgid_plural);
+   c_msgid_plural = scm_to_locale_string (msgid_plural);
+   SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 3 argument case.  */
+       result = ngettext (c_msgid, c_msgid_plural, c_n);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (4, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 4 argument case.  */
+ 	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+ 	}
+       else
+ 	{
+ 	  /* 5 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 5);
+ 	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+ 			       c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid;
+     }
+   else if (result == c_msgid_plural)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid_plural;
+     }
+   else
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain, "textdomain", 0, 0, 0,
+ 	    (void),
+ 	    "Return the current message domain.")
+ #define FUNC_NAME s_scm_get_textdomain
+ {
+   const char *result;
+ 
+   result = textdomain (NULL);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain, "set!-textdomain", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Change the current message domain.")
+ #define FUNC_NAME s_scm_set_textdomain
+ {
+   char *c_domain;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   if (textdomain (c_domain) == NULL)
+     SCM_SYSERROR;
+   free (c_domain);
+   return domain;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_dir, "textdomaindir", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_get_textdomain_dir
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bindtextdomain (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_dir, "set!-textdomaindir", 2, 0, 0,
+ 	    (SCM domain, SCM directory),
+ 	    "Change the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_set_textdomain_dir
+ {
+   char *c_domain;
+   char *c_directory;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, directory);
+   c_domain = scm_to_locale_string (domain);
+   c_directory = scm_to_locale_string (directory);
+   if (bindtextdomain (c_domain, c_directory) == NULL)
+     SCM_SYSERROR;
+   free (c_directory);
+   free (c_domain);
+   return directory;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_codeset, "textdomain-codeset", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_get_textdomain_codeset
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bind_textdomain_codeset (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_codeset, "set!-textdomain-codeset", 2, 0, 0,
+ 	    (SCM domain, SCM encoding),
+ 	    "Change the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_set_textdomain_codeset
+ {
+   char *c_domain;
+   char *c_encoding;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, encoding);
+   c_domain = scm_to_locale_string (domain);
+   c_encoding = scm_to_locale_string (encoding);
+   if (bind_textdomain_codeset (c_domain, c_encoding) == NULL)
+     SCM_SYSERROR;
+   free (c_encoding);
+   free (c_domain);
+   return encoding;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ void 
+ scm_init_i18n ()
+ {
+   SCM gettersym, settersym;
+ 
+   scm_add_feature ("i18n");
+ #include "libguile/i18n.x"
+ 
+   gettersym = scm_c_lookup ("textdomain");
+   settersym = scm_c_lookup ("set!-textdomain");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomaindir");
+   settersym = scm_c_lookup ("set!-textdomaindir");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomain-codeset");
+   settersym = scm_c_lookup ("set!-textdomain-codeset");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ }
+ 
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/gettext.h	2002-05-10 13:20:06.000000000 +0200
***************
*** 0 ****
--- 1,69 ----
+ /* Convenience header for conditional use of GNU <libintl.h>.
+    Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+ 
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published
+    by the Free Software Foundation; either version 2, 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
+    Library General Public License for more details.
+ 
+    You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+ #define _LIBGETTEXT_H 1
+ 
+ /* NLS can be disabled through the configure --disable-nls option.  */
+ #if ENABLE_NLS
+ 
+ /* Get declarations of GNU message catalog functions.  */
+ # include <libintl.h>
+ 
+ #else
+ 
+ /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+    chokes if dcgettext is defined as a macro.  So include it now, to make
+    later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+    as well because people using "gettext.h" will not include <libintl.h>,
+    and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+    is OK.  */
+ #if defined(__sun)
+ # include <locale.h>
+ #endif
+ 
+ /* Disabled NLS.
+    The casts to 'const char *' serve the purpose of producing warnings
+    for invalid uses of the value returned from these functions.
+    On pre-ANSI systems without 'const', the config.h file is supposed to
+    contain "#define const".  */
+ # define gettext(Msgid) ((const char *) (Msgid))
+ # define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+ # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+ # define ngettext(Msgid1, Msgid2, N) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define dngettext(Domainname, Msgid1, Msgid2, N) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define textdomain(Domainname) ((const char *) (Domainname))
+ # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+ # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+ 
+ #endif
+ 
+ /* A pseudo function call that serves as a marker for the automated
+    extraction of messages, but does not call gettext().  The run-time
+    translation is done at a different place in the code.
+    The argument, String, should be a literal string.  Concatenated strings
+    and other string expressions won't work.
+    The macro's expansion is not parenthesized, so that it is suitable as
+    initializer for static 'char[]' or 'const char[]' variables.  */
+ #define gettext_noop(String) String
+ 
+ #endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-02 16:06       ` Bruno Haible
  2004-09-02 16:21         ` Bruno Haible
@ 2004-09-02 17:32         ` Jan Nieuwenhuizen
  1 sibling, 0 replies; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-02 17:32 UTC (permalink / raw)
  Cc: guile-devel

Bruno Haible writes:

> The autoconf test is still broken: AC_CHECK_LIB(intl, gettext) doesn't work.

Hmm, that's strange, I just copied the socket/connect; probably should
have tested it.

> Also your patch uses SCM_STRING_CHARS, which is deprecated

We used that in LilyPond, but it's just been deprecated so it seems.

> Find here an extended patch.

Thanks, please apply.

Jan.

-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-02 16:21         ` Bruno Haible
@ 2004-09-03  1:34           ` Kevin Ryde
  2004-09-04 17:25             ` Bruno Haible
  2004-09-07  8:20             ` Jan Nieuwenhuizen
  0 siblings, 2 replies; 28+ messages in thread
From: Kevin Ryde @ 2004-09-03  1:34 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

Bruno Haible <bruno@clisp.org> writes:
>
> + SCM_API SCM scm_get_textdomain (void);
> + SCM_API SCM scm_set_textdomain (SCM domainname);

I think these could be a single textdomain func taking an optional
argument.  That's what's done for setlocale for instance, and it
matches the C routines.

> + SCM_API SCM scm_get_textdomain_dir (SCM domainname);
> + SCM_API SCM scm_set_textdomain_dir (SCM domainname, SCM directory);
> + SCM_API SCM scm_get_textdomain_codeset (SCM domainname);
> + SCM_API SCM scm_set_textdomain_codeset (SCM domainname, SCM encoding);

And I'd call these bindtextdomain, again for similarity to the C
routines they wrap.

> + static int
> + scm_validate_category (SCM category, const char *subr, int pos)
> + {
> +   if (scm_is_eq (category, scm_sym_LC_MESSAGES))
> +     return LC_MESSAGES;

LC_MESSAGES and friends already exist as variables.

> +   SCM_VARIABLE_SET (gettersym,
> + 		    scm_make_procedure_with_setter (
> + 			SCM_VARIABLE_REF (gettersym),
> + 			SCM_VARIABLE_REF (settersym)));

Procedures with setters are not much used in the core.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-03  1:34           ` Kevin Ryde
@ 2004-09-04 17:25             ` Bruno Haible
  2004-09-07  0:13               ` Kevin Ryde
  2004-09-07  8:20             ` Jan Nieuwenhuizen
  1 sibling, 1 reply; 28+ messages in thread
From: Bruno Haible @ 2004-09-04 17:25 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]

Kevin Ryde wrote:

> LC_MESSAGES and friends already exist as variables.

OK. Find attached a revised patch which takes this into account.

> > + SCM_API SCM scm_get_textdomain (void);
> > + SCM_API SCM scm_set_textdomain (SCM domainname);
>
> I think these could be a single textdomain func taking an optional
> argument.  That's what's done for setlocale for instance, and it
> matches the C routines.
>
> > + SCM_API SCM scm_get_textdomain_dir (SCM domainname);
> > + SCM_API SCM scm_set_textdomain_dir (SCM domainname, SCM directory);
> > + SCM_API SCM scm_get_textdomain_codeset (SCM domainname);
> > + SCM_API SCM scm_set_textdomain_codeset (SCM domainname, SCM encoding);
>
> And I'd call these bindtextdomain, again for similarity to the C
> routines they wrap.
>
> > +   SCM_VARIABLE_SET (gettersym,
> > + 		    scm_make_procedure_with_setter (
> > + 			SCM_VARIABLE_REF (gettersym),
> > + 			SCM_VARIABLE_REF (settersym)));
>
> Procedures with setters are not much used in the core.

That's your point of view, not mine. I would find it irresponsible if I
were to submit a patch which includes destructive functions that don't
bear a '!' in their name.

You and/or Jan can of course spend 15 minutes to modify my patch to fit your
point of view.

In the GNU 'xgettext' extractor and associated example I will support
whatever API you provide in guile.

Bruno

[-- Attachment #2: guile-diffs --]
[-- Type: text/x-diff, Size: 21513 bytes --]

ChangeLog:
2004-09-02  Bruno Haible  <bruno@clisp.org>

	* configure.in: Add AM_GNU_GETTEXT invocation.

libguile/ChangeLog:
2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
            Bruno Haible  <bruno@clisp.org>

	* i18n.h: New file.
	* i18n.c: New file.
	* gettext.h: New file, taken from GNU gettext.
	* init.c: Include libguile/i18n.h.
	(scm_init_guile_1): Add call to scm_init_i18n().
	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
	(DOT_X_FILES): Add i18n.x.
	(DOT_DOC_FILES): Add i18n.doc.
	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
	(modinclude_HEADERS): Add i18n.h.

diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/configure.in guile-1.7.1/configure.in
*** guile-1.7.1.orig/configure.in	2004-08-26 16:23:34.000000000 +0200
--- guile-1.7.1/configure.in	2004-09-01 22:05:51.000000000 +0200
***************
*** 637,642 ****
--- 637,645 ----
              [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
    [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
  
+ dnl i18n tests
+ AM_GNU_GETTEXT([external], [need-ngettext])
+ 
  ### Some systems don't declare some functions.  On such systems, we
  ### need to at least provide our own K&R-style declarations.
  
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/init.c guile-1.7.1/libguile/init.c
*** guile-1.7.1.orig/libguile/init.c	2004-08-25 11:45:13.000000000 +0200
--- guile-1.7.1/libguile/init.c	2004-09-02 13:43:11.000000000 +0200
***************
*** 63,68 ****
--- 63,69 ----
  #include "libguile/hash.h"
  #include "libguile/hashtab.h"
  #include "libguile/hooks.h"
+ #include "libguile/i18n.h"
  #include "libguile/iselect.h"
  #include "libguile/ioext.h"
  #include "libguile/keywords.h"
***************
*** 477,482 ****
--- 478,484 ----
    scm_init_properties ();
    scm_init_hooks ();            /* Requires smob_prehistory */
    scm_init_gc ();		/* Requires hooks, async */
+   scm_init_i18n ();
    scm_init_ioext ();
    scm_init_keywords ();
    scm_init_list ();
diff -r -c3 --exclude=Makefile --exclude='*.texi' --exclude='*.info*' --exclude=configure --exclude=Makefile.in guile-1.7.1.orig/libguile/Makefile.am guile-1.7.1/libguile/Makefile.am
*** guile-1.7.1.orig/libguile/Makefile.am	2004-08-25 11:45:10.000000000 +0200
--- guile-1.7.1/libguile/Makefile.am	2004-09-02 17:47:55.000000000 +0200
***************
*** 97,103 ****
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
--- 97,103 ----
      gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
  	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
      gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
!     hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
      lang.c list.c							    \
      load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
      options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
***************
*** 113,119 ****
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
--- 113,119 ----
      error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
      futures.x								 \
      gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
!     gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
      keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
      numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
      procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
***************
*** 132,139 ****
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
!     keywords.doc lang.doc list.doc load.doc macros.doc			    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
--- 132,139 ----
      extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
      gc.doc goops.doc							    \
      gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
!     guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
!     ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
      mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
      options.doc pairs.doc ports.doc print.doc procprop.doc		    \
      procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
***************
*** 172,178 ****
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
--- 172,178 ----
  
  libguile_la_DEPENDENCIES = @LIBLOBJS@
  libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
! libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
  
  # These are headers visible as <guile/mumble.h>
  pkginclude_HEADERS = gh.h
***************
*** 187,193 ****
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
--- 187,193 ----
      error.h eval.h							      \
      evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
      gc.h gdb_interface.h gdbint.h					      \
!     goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
      inline.h ioext.h							      \
      iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
      net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.h	2004-09-02 14:05:22.000000000 +0200
***************
*** 0 ****
--- 1,41 ----
+ /* classes: h_files */
+ 
+ #ifndef SCM_I18N_H
+ #define SCM_I18N_H
+ 
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ #include "libguile/__scm.h"
+ 
+ SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+ SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+ SCM_API SCM scm_get_textdomain (void);
+ SCM_API SCM scm_set_textdomain (SCM domainname);
+ SCM_API SCM scm_get_textdomain_dir (SCM domainname);
+ SCM_API SCM scm_set_textdomain_dir (SCM domainname, SCM directory);
+ SCM_API SCM scm_get_textdomain_codeset (SCM domainname);
+ SCM_API SCM scm_set_textdomain_codeset (SCM domainname, SCM encoding);
+ SCM_API void scm_init_i18n (void);
+ 
+ #endif  /* SCM_I18N_H */
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/i18n.c	2004-09-04 19:10:24.000000000 +0200
***************
*** 0 ****
--- 1,323 ----
+ /* Copyright (C) 2004 Free Software Foundation, Inc.
+  *
+  * 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.1 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
+  */
+ 
+ 
+ #if HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+ 
+ #include "libguile/_scm.h"
+ #include "libguile/discouraged.h"
+ #include "libguile/feature.h"
+ #include "libguile/i18n.h"
+ #include "libguile/strings.h"
+ #include "gettext.h"
+ #include <locale.h>
+ 
+ 
+ static int
+ scm_validate_category (SCM category, const char *subr, int pos)
+ {
+   if (scm_is_eq (category, scm_from_int (LC_MESSAGES))
+       || scm_is_eq (category, scm_from_int (LC_CTYPE))
+       || scm_is_eq (category, scm_from_int (LC_TIME))
+       || scm_is_eq (category, scm_from_int (LC_COLLATE))
+       || scm_is_eq (category, scm_from_int (LC_MONETARY)))
+     return scm_to_int (category);
+   else
+     scm_wrong_type_arg (subr, pos, category);
+ }
+ 
+ 
+ SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+ 	    (SCM msgid, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid} in the message domain "
+ 	    "@var{domain}. @var{domain} is optional and defaults to the "
+ 	    "domain set through (textdomain). @var{category} is optional "
+ 	    "and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_gettext
+ {
+   char *c_msgid;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 1 argument case.  */
+       result = gettext (c_msgid);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (2, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 2 argument case.  */
+ 	  result = dgettext (c_domain, c_msgid);
+ 	}
+       else
+ 	{
+ 	  /* 3 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 3);
+ 	  result = dcgettext (c_domain, c_msgid, c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid);
+       return msgid;
+     }
+   else
+     {
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+ 	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+ 	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+ 	    "message domain @var{domain}, with the plural form being chosen "
+ 	    "appropriately for the number @var{n}. @var{domain} is optional "
+ 	    "and defaults to the domain set through (textdomain). "
+ 	    "@var{category} is optional and defaults to LC_MESSAGES.")
+ #define FUNC_NAME s_scm_ngettext
+ {
+   char *c_msgid;
+   char *c_msgid_plural;
+   unsigned long c_n;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, msgid);
+   c_msgid = scm_to_locale_string (msgid);
+   SCM_VALIDATE_STRING (2, msgid_plural);
+   c_msgid_plural = scm_to_locale_string (msgid_plural);
+   SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+   if (SCM_UNBNDP (domain))
+     {
+       /* 3 argument case.  */
+       result = ngettext (c_msgid, c_msgid_plural, c_n);
+     }
+   else
+     {
+       char *c_domain;
+ 
+       SCM_VALIDATE_STRING (4, domain);
+       c_domain = scm_to_locale_string (domain);
+       if (SCM_UNBNDP (category))
+ 	{
+ 	  /* 4 argument case.  */
+ 	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+ 	}
+       else
+ 	{
+ 	  /* 5 argument case.  */
+ 	  int c_category;
+ 
+ 	  c_category = scm_validate_category (category, FUNC_NAME, 5);
+ 	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+ 			       c_category);
+ 	}
+       free (c_domain);
+     }
+ 
+   if (result == c_msgid)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid;
+     }
+   else if (result == c_msgid_plural)
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return msgid_plural;
+     }
+   else
+     {
+       free (c_msgid_plural);
+       free (c_msgid);
+       return scm_makfrom0str (result);
+     }
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain, "textdomain", 0, 0, 0,
+ 	    (void),
+ 	    "Return the current message domain.")
+ #define FUNC_NAME s_scm_get_textdomain
+ {
+   const char *result;
+ 
+   result = textdomain (NULL);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain, "set!-textdomain", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Change the current message domain.")
+ #define FUNC_NAME s_scm_set_textdomain
+ {
+   char *c_domain;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   if (textdomain (c_domain) == NULL)
+     SCM_SYSERROR;
+   free (c_domain);
+   return domain;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_dir, "textdomaindir", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_get_textdomain_dir
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bindtextdomain (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_dir, "set!-textdomaindir", 2, 0, 0,
+ 	    (SCM domain, SCM directory),
+ 	    "Change the base directory for message catalogs for the given "
+ 	    "message domain.")
+ #define FUNC_NAME s_scm_set_textdomain_dir
+ {
+   char *c_domain;
+   char *c_directory;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, directory);
+   c_domain = scm_to_locale_string (domain);
+   c_directory = scm_to_locale_string (directory);
+   if (bindtextdomain (c_domain, c_directory) == NULL)
+     SCM_SYSERROR;
+   free (c_directory);
+   free (c_domain);
+   return directory;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_get_textdomain_codeset, "textdomain-codeset", 1, 0, 0,
+ 	    (SCM domain),
+ 	    "Return the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_get_textdomain_codeset
+ {
+   char *c_domain;
+   const char *result;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   c_domain = scm_to_locale_string (domain);
+   result = bind_textdomain_codeset (c_domain, NULL);
+   free (c_domain);
+   if (result == NULL)
+     return SCM_BOOL_F;
+   else
+     return scm_makfrom0str (result);
+ }
+ #undef FUNC_NAME
+ 
+ 
+ SCM_DEFINE (scm_set_textdomain_codeset, "set!-textdomain-codeset", 2, 0, 0,
+ 	    (SCM domain, SCM encoding),
+ 	    "Change the encoding for message catalogs for the given message "
+ 	    "domain.")
+ #define FUNC_NAME s_scm_set_textdomain_codeset
+ {
+   char *c_domain;
+   char *c_encoding;
+ 
+   SCM_VALIDATE_STRING (1, domain);
+   SCM_VALIDATE_STRING (2, encoding);
+   c_domain = scm_to_locale_string (domain);
+   c_encoding = scm_to_locale_string (encoding);
+   if (bind_textdomain_codeset (c_domain, c_encoding) == NULL)
+     SCM_SYSERROR;
+   free (c_encoding);
+   free (c_domain);
+   return encoding;
+ }
+ #undef FUNC_NAME
+ 
+ 
+ void 
+ scm_init_i18n ()
+ {
+   SCM gettersym, settersym;
+ 
+   scm_add_feature ("i18n");
+ #include "libguile/i18n.x"
+ 
+   gettersym = scm_c_lookup ("textdomain");
+   settersym = scm_c_lookup ("set!-textdomain");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomaindir");
+   settersym = scm_c_lookup ("set!-textdomaindir");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ 
+   gettersym = scm_c_lookup ("textdomain-codeset");
+   settersym = scm_c_lookup ("set!-textdomain-codeset");
+   SCM_VARIABLE_SET (gettersym,
+ 		    scm_make_procedure_with_setter (
+ 			SCM_VARIABLE_REF (gettersym),
+ 			SCM_VARIABLE_REF (settersym)));
+ }
+ 
+ 
+ /*
+   Local Variables:
+   c-file-style: "gnu"
+   End:
+ */
*** /dev/null	1970-01-01 01:00:00.000000000 +0100
--- guile-1.7.1/libguile/gettext.h	2002-05-10 13:20:06.000000000 +0200
***************
*** 0 ****
--- 1,69 ----
+ /* Convenience header for conditional use of GNU <libintl.h>.
+    Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+ 
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published
+    by the Free Software Foundation; either version 2, 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
+    Library General Public License for more details.
+ 
+    You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+ #define _LIBGETTEXT_H 1
+ 
+ /* NLS can be disabled through the configure --disable-nls option.  */
+ #if ENABLE_NLS
+ 
+ /* Get declarations of GNU message catalog functions.  */
+ # include <libintl.h>
+ 
+ #else
+ 
+ /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+    chokes if dcgettext is defined as a macro.  So include it now, to make
+    later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+    as well because people using "gettext.h" will not include <libintl.h>,
+    and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+    is OK.  */
+ #if defined(__sun)
+ # include <locale.h>
+ #endif
+ 
+ /* Disabled NLS.
+    The casts to 'const char *' serve the purpose of producing warnings
+    for invalid uses of the value returned from these functions.
+    On pre-ANSI systems without 'const', the config.h file is supposed to
+    contain "#define const".  */
+ # define gettext(Msgid) ((const char *) (Msgid))
+ # define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+ # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+ # define ngettext(Msgid1, Msgid2, N) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define dngettext(Domainname, Msgid1, Msgid2, N) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+     ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+ # define textdomain(Domainname) ((const char *) (Domainname))
+ # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+ # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+ 
+ #endif
+ 
+ /* A pseudo function call that serves as a marker for the automated
+    extraction of messages, but does not call gettext().  The run-time
+    translation is done at a different place in the code.
+    The argument, String, should be a literal string.  Concatenated strings
+    and other string expressions won't work.
+    The macro's expansion is not parenthesized, so that it is suitable as
+    initializer for static 'char[]' or 'const char[]' variables.  */
+ #define gettext_noop(String) String
+ 
+ #endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-04 17:25             ` Bruno Haible
@ 2004-09-07  0:13               ` Kevin Ryde
  2004-09-07 12:38                 ` Bruno Haible
  0 siblings, 1 reply; 28+ messages in thread
From: Kevin Ryde @ 2004-09-07  0:13 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

Bruno Haible <bruno@clisp.org> writes:
>
> That's your point of view, not mine. I would find it irresponsible if I
> were to submit a patch which includes destructive functions that don't
> bear a '!' in their name.

Well, I guess the conventions for system stuff are described at the
start of the posix interface chapter in the manual.  I think ! is just
meant for changes to scheme level data, not system things.

But actually it was the procedure-with-setter I was more concerned
about, being almost never used in the core, and in fact a rather
controversial concept, as I understand it.

> In the GNU 'xgettext' extractor and associated example I will support
> whatever API you provide in guile.

That'll be (_ "foo") won't it?  Being nice and compact, and already
used.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-03  1:34           ` Kevin Ryde
  2004-09-04 17:25             ` Bruno Haible
@ 2004-09-07  8:20             ` Jan Nieuwenhuizen
  2004-09-07 14:16               ` Jan Nieuwenhuizen
  1 sibling, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-07  8:20 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 317 bytes --]

Kevin Ryde writes:

> I think these could be a single textdomain func taking an optional
> argument.

> And I'd call these bindtextdomain, again for similarity to the C
> routines they wrap.

Ok.  In this next iteration, the wrapper functions are [once again]
similar to the C functions they wrap.

Greetings,

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn.diff --]
[-- Type: text/plain, Size: 18693 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	7 Sep 2004 08:14:16 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	7 Sep 2004 08:14:17 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	7 Sep 2004 08:14:20 -0000
@@ -1,3 +1,23 @@
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bindtextdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	7 Sep 2004 08:14:20 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	7 Sep 2004 08:14:20 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-07 10:09:45 +0200
@@ -0,0 +1,38 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bindtextdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-07 10:11:29 +0200
@@ -0,0 +1,266 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/discouraged.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+static int
+scm_validate_category (SCM category, const char *subr, int pos)
+{
+  if (scm_is_eq (category, scm_from_int (LC_MESSAGES))
+      || scm_is_eq (category, scm_from_int (LC_CTYPE))
+      || scm_is_eq (category, scm_from_int (LC_TIME))
+      || scm_is_eq (category, scm_from_int (LC_COLLATE))
+      || scm_is_eq (category, scm_from_int (LC_MONETARY)))
+    return scm_to_int (category);
+  else
+    scm_wrong_type_arg (subr, pos, category);
+}
+
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_validate_category (category, FUNC_NAME, 3);
+	  result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  else
+    {
+      free (c_msgid);
+      return scm_makfrom0str (result);
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_validate_category (category, FUNC_NAME, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  else
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return scm_makfrom0str (result);
+    }
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+  c_result = textdomain (c_domain);
+  if (c_domain != NULL)
+    free (c_domain);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+  if (c_directory != NULL)
+    free (c_directory);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain_codeset, "bindtextdomain_codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_encoding);
+  free (c_domain);
+  if (c_encoding != NULL)
+    free (c_encoding);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-07  0:13               ` Kevin Ryde
@ 2004-09-07 12:38                 ` Bruno Haible
  2004-09-08  1:10                   ` Kevin Ryde
  0 siblings, 1 reply; 28+ messages in thread
From: Bruno Haible @ 2004-09-07 12:38 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

Kevin Ryde wrote:
> > In the GNU 'xgettext' extractor and associated example I will support
> > whatever API you provide in guile.
>
> That'll be (_ "foo") won't it?  Being nice and compact, and already
> used.

The 'xgettext' extractor will recognize 'gettext', 'ngettext'. I can also
make it recognize '_' by default, no problem.

However, I don't think the _ should be built-in. Rather, applications will
define it differently than libraries: For an application, which typically
calls set!-textdomain, a programmer does

   (define _ gettext)

For a library, which must not interfere with the main application,
a programmer does

   (define (_ msgid) (gettext msgid "my-domain"))

[I hope Scheme has a package system or environment system that makes it
possible to distinguish _ in the application from _ in the library!]

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-07  8:20             ` Jan Nieuwenhuizen
@ 2004-09-07 14:16               ` Jan Nieuwenhuizen
  2004-09-08  1:15                 ` Kevin Ryde
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-07 14:16 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 96 bytes --]

Jan Nieuwenhuizen writes:

Find a new version with some silly bugs fixed (thanks Bruno).

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn-2.diff --]
[-- Type: text/plain, Size: 18778 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	7 Sep 2004 13:19:33 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	7 Sep 2004 13:19:33 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	7 Sep 2004 13:19:36 -0000
@@ -1,3 +1,23 @@
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	7 Sep 2004 13:19:36 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	7 Sep 2004 13:19:36 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-07 15:18:07 +0200
@@ -0,0 +1,38 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-07 15:18:54 +0200
@@ -0,0 +1,270 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/discouraged.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+static int
+scm_validate_category (SCM category, const char *subr, int pos)
+{
+  if (scm_is_eq (category, scm_from_int (LC_MESSAGES))
+      || scm_is_eq (category, scm_from_int (LC_CTYPE))
+      || scm_is_eq (category, scm_from_int (LC_TIME))
+      || scm_is_eq (category, scm_from_int (LC_COLLATE))
+      || scm_is_eq (category, scm_from_int (LC_MONETARY)))
+    return scm_to_int (category);
+  else
+    scm_wrong_type_arg (subr, pos, category);
+}
+
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_validate_category (category, FUNC_NAME, 3);
+	  result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  else
+    {
+      free (c_msgid);
+      return scm_makfrom0str (result);
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_validate_category (category, FUNC_NAME, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  else
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return scm_makfrom0str (result);
+    }
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+  c_result = textdomain (c_domain);
+  if (c_domain != NULL)
+    free (c_domain);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+  if (c_directory != NULL)
+    free (c_directory);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+  free (c_domain);
+  if (c_encoding != NULL)
+    free (c_encoding);
+  if (c_result == NULL)
+    {
+      if (SCM_UNBNDP (encoding))
+	return SCM_BOOL_F;
+      SCM_SYSERROR;
+    }
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-07 12:38                 ` Bruno Haible
@ 2004-09-08  1:10                   ` Kevin Ryde
  0 siblings, 0 replies; 28+ messages in thread
From: Kevin Ryde @ 2004-09-08  1:10 UTC (permalink / raw)
  Cc: guile-devel, Jan Nieuwenhuizen

Bruno Haible <bruno@clisp.org> writes:
>
> However, I don't think the _ should be built-in. Rather, applications will
> define it differently than libraries:

Oops, yep.

> [I hope Scheme has a package system or environment system that makes it
> possible to distinguish _ in the application from _ in the library!]

Not as standard, but yes in most, including guile.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-07 14:16               ` Jan Nieuwenhuizen
@ 2004-09-08  1:15                 ` Kevin Ryde
  2004-09-08  8:58                   ` Jan Nieuwenhuizen
  2004-09-08 10:39                   ` Bruno Haible
  0 siblings, 2 replies; 28+ messages in thread
From: Kevin Ryde @ 2004-09-08  1:15 UTC (permalink / raw)
  Cc: Bruno Haible, guile-devel

Jan Nieuwenhuizen <janneke@gnu.org> writes:
>
> +static int
> +scm_validate_category (SCM category, const char *subr, int pos)

Could call that scm_to_lc_category or similar to match the new api
style I guess.  scm_setlocale (in posix.c) could use it too.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08  1:15                 ` Kevin Ryde
@ 2004-09-08  8:58                   ` Jan Nieuwenhuizen
  2004-09-08 10:39                   ` Bruno Haible
  1 sibling, 0 replies; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-08  8:58 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 203 bytes --]

Kevin Ryde writes:

>> +scm_validate_category (SCM category, const char *subr, int pos)
>
> Could call that scm_to_lc_category
[..]
> scm_setlocale could use it too.

Done.  New version attached.

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn-3.diff --]
[-- Type: text/plain, Size: 21382 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	8 Sep 2004 08:55:37 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	8 Sep 2004 08:55:37 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	8 Sep 2004 08:55:40 -0000
@@ -1,3 +1,33 @@
+2004-09-08  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
+	LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.
+
+	* i18n.c (scm_to_lc_category): New name and export.  Support all
+	LC categories.
+
+	* posix.c (s_scm_setlocale): Use it.
+
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	8 Sep 2004 08:55:41 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	8 Sep 2004 08:55:41 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/posix.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/posix.c,v
retrieving revision 1.147
diff -p -u -r1.147 posix.c
--- libguile/posix.c	7 Sep 2004 00:26:48 -0000	1.147
+++ libguile/posix.c	8 Sep 2004 08:55:41 -0000
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_to_lc_category (category, FUNC_NAME, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@ scm_init_posix ()
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-08 09:37:48 +0200
@@ -0,0 +1,39 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+int scm_to_lc_category (SCM category, const char *subr, int pos);
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-08 10:50:54 +0200
@@ -0,0 +1,303 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_to_lc_category (SCM category, const char *subr, int pos)
+{
+  if (0
+#ifdef LC_COLLATE
+      || scm_is_eq (category, scm_from_int (LC_COLLATE))
+#endif
+#ifdef LC_CTYPE
+      || scm_is_eq (category, scm_from_int (LC_CTYPE))
+#endif
+#ifdef LC_MONETARY
+      || scm_is_eq (category, scm_from_int (LC_MONETARY))
+#endif
+#ifdef LC_NUMERIC
+      || scm_is_eq (category, scm_from_int (LC_NUMERIC))
+#endif
+#ifdef LC_TIME
+      || scm_is_eq (category, scm_from_int (LC_TIME))
+#endif
+#ifdef LC_MESSAGES
+      || scm_is_eq (category, scm_from_int (LC_MESSAGES))
+#endif
+#ifdef LC_ALL
+      || scm_is_eq (category, scm_from_int (LC_ALL))
+#endif
+#ifdef LC_PAPER
+      || scm_is_eq (category, scm_from_int (LC_PAPER))
+#endif
+#ifdef LC_NAME
+      || scm_is_eq (category, scm_from_int (LC_NAME))
+#endif
+#ifdef LC_ADDRESS
+      || scm_is_eq (category, scm_from_int (LC_ADDRESS))
+#endif
+#ifdef LC_TELEPHONE
+      || scm_is_eq (category, scm_from_int (LC_TELEPHONE))
+#endif
+#ifdef LC_MEASUREMENT
+      || scm_is_eq (category, scm_from_int (LC_MEASUREMENT))
+#endif
+#ifdef LC_IDENTIFICATION
+      || scm_is_eq (category, scm_from_int (LC_IDENTIFICATION))
+#endif
+      )
+    return scm_to_int (category);
+  scm_wrong_type_arg (subr, pos, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, FUNC_NAME, 3);
+	  result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  else
+    {
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, FUNC_NAME, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  else
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+  c_result = textdomain (c_domain);
+  if (c_domain != NULL)
+    free (c_domain);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+  if (c_directory != NULL)
+    free (c_directory);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+  free (c_domain);
+  if (c_encoding != NULL)
+    free (c_encoding);
+  if (c_result == NULL)
+    {
+      if (SCM_UNBNDP (encoding))
+	return SCM_BOOL_F;
+      SCM_SYSERROR;
+    }
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08  1:15                 ` Kevin Ryde
  2004-09-08  8:58                   ` Jan Nieuwenhuizen
@ 2004-09-08 10:39                   ` Bruno Haible
  2004-09-08 14:37                     ` Jan Nieuwenhuizen
  2004-09-08 21:53                     ` Jan Nieuwenhuizen
  1 sibling, 2 replies; 28+ messages in thread
From: Bruno Haible @ 2004-09-08 10:39 UTC (permalink / raw)
  Cc: guile-devel

Kevin Ryde wrote:
> scm_setlocale (in posix.c) could use it too.

setlocale(), however, must accept LC_ALL, which is forbidden in dcgettext()
and dcngettext(). Therefore either the test for LC_ALL should be moved to
s_scm_setlocale, or the function scm_to_lc_category should take a bool
argument telling whether to consider LC_ALL as valid.

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 10:39                   ` Bruno Haible
@ 2004-09-08 14:37                     ` Jan Nieuwenhuizen
  2004-09-08 16:37                       ` Bruno Haible
  2004-09-08 21:53                     ` Jan Nieuwenhuizen
  1 sibling, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-08 14:37 UTC (permalink / raw)
  Cc: guile-devel

Bruno Haible writes:

> setlocale(), however, must accept LC_ALL, which is forbidden in dcgettext()
> and dcngettext(). Therefore either the test for LC_ALL should be moved to
> s_scm_setlocale, or the function scm_to_lc_category should take a bool
> argument telling whether to consider LC_ALL as valid.

I don't understand.  If that's forbidden, d*gettext will tell you that,
why add an extra check?

Jan.

-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 14:37                     ` Jan Nieuwenhuizen
@ 2004-09-08 16:37                       ` Bruno Haible
  0 siblings, 0 replies; 28+ messages in thread
From: Bruno Haible @ 2004-09-08 16:37 UTC (permalink / raw)
  Cc: guile-devel

Jan Nieuwenhuizen wrote:
> I don't understand.  If that's forbidden, d*gettext will tell you that,

It's forbidden. dcgettext will not do what people expect when they try to use
it.

> why add an extra check?

In order to tell people that they are writing buggy code when they write
(gettext string LC_ALL). There's no difference between LC_ALL and -761 in
this respect: both are invalid.

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 10:39                   ` Bruno Haible
  2004-09-08 14:37                     ` Jan Nieuwenhuizen
@ 2004-09-08 21:53                     ` Jan Nieuwenhuizen
  2004-09-08 22:45                       ` Kevin Ryde
  1 sibling, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-08 21:53 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 170 bytes --]

Bruno Haible writes:

> or the function scm_to_lc_category should take a bool argument
> telling whether to consider LC_ALL as valid.

Ok, then this should be it.

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn-4.diff --]
[-- Type: text/plain, Size: 21445 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	8 Sep 2004 21:47:50 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	8 Sep 2004 21:47:50 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	8 Sep 2004 21:47:53 -0000
@@ -1,3 +1,33 @@
+2004-09-08  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
+	LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.
+
+	* i18n.c (scm_to_lc_category): New name and export.  Support all
+	LC categories.
+
+	* posix.c (s_scm_setlocale): Use it.
+
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	8 Sep 2004 21:47:54 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	8 Sep 2004 21:47:54 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/posix.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/posix.c,v
retrieving revision 1.147
diff -p -u -r1.147 posix.c
--- libguile/posix.c	7 Sep 2004 00:26:48 -0000	1.147
+++ libguile/posix.c	8 Sep 2004 21:47:54 -0000
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_to_lc_category (category, 1, FUNC_NAME, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@ scm_init_posix ()
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-08 23:44:13 +0200
@@ -0,0 +1,39 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+int scm_to_lc_category (SCM category, int allow_lc_all, const char *subr, int pos);
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-08 23:45:35 +0200
@@ -0,0 +1,303 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_to_lc_category (SCM category, int allow_lc_all, const char *subr, int pos)
+{
+  if (0
+#ifdef LC_COLLATE
+      || scm_is_eq (category, scm_from_int (LC_COLLATE))
+#endif
+#ifdef LC_CTYPE
+      || scm_is_eq (category, scm_from_int (LC_CTYPE))
+#endif
+#ifdef LC_MONETARY
+      || scm_is_eq (category, scm_from_int (LC_MONETARY))
+#endif
+#ifdef LC_NUMERIC
+      || scm_is_eq (category, scm_from_int (LC_NUMERIC))
+#endif
+#ifdef LC_TIME
+      || scm_is_eq (category, scm_from_int (LC_TIME))
+#endif
+#ifdef LC_MESSAGES
+      || scm_is_eq (category, scm_from_int (LC_MESSAGES))
+#endif
+#ifdef LC_ALL
+      || (allow_lc_all && scm_is_eq (category, scm_from_int (LC_ALL)))
+#endif
+#ifdef LC_PAPER
+      || scm_is_eq (category, scm_from_int (LC_PAPER))
+#endif
+#ifdef LC_NAME
+      || scm_is_eq (category, scm_from_int (LC_NAME))
+#endif
+#ifdef LC_ADDRESS
+      || scm_is_eq (category, scm_from_int (LC_ADDRESS))
+#endif
+#ifdef LC_TELEPHONE
+      || scm_is_eq (category, scm_from_int (LC_TELEPHONE))
+#endif
+#ifdef LC_MEASUREMENT
+      || scm_is_eq (category, scm_from_int (LC_MEASUREMENT))
+#endif
+#ifdef LC_IDENTIFICATION
+      || scm_is_eq (category, scm_from_int (LC_IDENTIFICATION))
+#endif
+      )
+    return scm_to_int (category);
+  scm_wrong_type_arg (subr, pos, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, FUNC_NAME, 3);
+	  result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  else
+    {
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, FUNC_NAME, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  else
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+  c_result = textdomain (c_domain);
+  if (c_domain != NULL)
+    free (c_domain);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+  if (c_directory != NULL)
+    free (c_directory);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+  free (c_domain);
+  if (c_encoding != NULL)
+    free (c_encoding);
+  if (c_result == NULL)
+    {
+      if (SCM_UNBNDP (encoding))
+	return SCM_BOOL_F;
+      SCM_SYSERROR;
+    }
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]



-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 21:53                     ` Jan Nieuwenhuizen
@ 2004-09-08 22:45                       ` Kevin Ryde
  2004-09-08 23:46                         ` Jan Nieuwenhuizen
  0 siblings, 1 reply; 28+ messages in thread
From: Kevin Ryde @ 2004-09-08 22:45 UTC (permalink / raw)
  Cc: Bruno Haible, guile-devel

Jan Nieuwenhuizen <janneke@gnu.org> writes:
>
> +int
> +scm_to_lc_category (SCM category, int allow_lc_all, const char *subr, int pos)

The other scm_to_foo's haven't been taking a subr argument.  (That's
supposed to show up in the backtrace, or something.)

> +      || scm_is_eq (category, scm_from_int (LC_COLLATE))

Maybe a C "switch", to save some code.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 22:45                       ` Kevin Ryde
@ 2004-09-08 23:46                         ` Jan Nieuwenhuizen
  2004-09-09 16:25                           ` Jan Nieuwenhuizen
  0 siblings, 1 reply; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-08 23:46 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 276 bytes --]

Kevin Ryde writes:

> The other scm_to_foo's haven't been taking a subr argument.  (That's
> supposed to show up in the backtrace, or something.)

Ok, I see.

>> +      || scm_is_eq (category, scm_from_int (LC_COLLATE))

> Maybe a C "switch", to save some code.

Done.

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn-5.diff --]
[-- Type: text/plain, Size: 20988 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	8 Sep 2004 23:44:11 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	8 Sep 2004 23:44:12 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	8 Sep 2004 23:44:17 -0000
@@ -1,3 +1,33 @@
+2004-09-08  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
+	LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.
+
+	* i18n.c (scm_to_lc_category): New name and export.  Support all
+	LC categories.
+
+	* posix.c (s_scm_setlocale): Use it.
+
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	8 Sep 2004 23:44:17 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	8 Sep 2004 23:44:17 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/posix.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/posix.c,v
retrieving revision 1.147
diff -p -u -r1.147 posix.c
--- libguile/posix.c	7 Sep 2004 00:26:48 -0000	1.147
+++ libguile/posix.c	8 Sep 2004 23:44:17 -0000
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_to_lc_category (category, 1, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@ scm_init_posix ()
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-09 01:34:13 +0200
@@ -0,0 +1,39 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+int scm_to_lc_category (SCM category, int allow_lc_all, int pos);
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-09 01:37:21 +0200
@@ -0,0 +1,307 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_to_lc_category (SCM category, int allow_lc_all, int pos)
+{
+  int c_category = scm_to_int (category);
+  switch (c_category)
+    {
+#ifdef LC_CTYPE
+    case LC_CTYPE:
+#endif
+#ifdef LC_NUMERIC
+    case LC_NUMERIC:
+#endif
+#ifdef LC_COLLATE
+    case LC_COLLATE:
+#endif
+#ifdef LC_TIME
+    case LC_TIME:
+#endif
+#ifdef LC_MONETARY
+    case LC_MONETARY:
+#endif
+#ifdef LC_MESSAGES
+    case LC_MESSAGES:
+#endif
+#ifdef LC_PAPER
+    case LC_PAPER:
+#endif
+#ifdef LC_NAME
+    case LC_NAME:
+#endif
+#ifdef LC_ADDRESS
+    case LC_ADDRESS:
+#endif
+#ifdef LC_TELEPHONE
+    case LC_TELEPHONE:
+#endif
+#ifdef LC_MEASUREMENT
+    case LC_MEASUREMENT:
+#endif
+#ifdef LC_IDENTIFICATION
+    case LC_IDENTIFICATION:
+#endif
+      return c_category;
+#ifdef LC_ALL
+    case LC_ALL:
+      if (allow_lc_all)
+	return c_category;
+#endif  
+    }
+  scm_wrong_type_arg (0, pos, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, 3);
+	  result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  else
+    {
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  else
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return scm_from_locale_string (result);
+    }
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+  c_result = textdomain (c_domain);
+  if (c_domain != NULL)
+    free (c_domain);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+  if (c_directory != NULL)
+    free (c_directory);
+  if (c_result == NULL)
+    SCM_SYSERROR;
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+  free (c_domain);
+  if (c_encoding != NULL)
+    free (c_encoding);
+  if (c_result == NULL)
+    {
+      if (SCM_UNBNDP (encoding))
+	return SCM_BOOL_F;
+      SCM_SYSERROR;
+    }
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-08 23:46                         ` Jan Nieuwenhuizen
@ 2004-09-09 16:25                           ` Jan Nieuwenhuizen
  2004-09-15 11:20                             ` Bruno Haible
  2004-09-22  0:42                             ` Marius Vollmer
  0 siblings, 2 replies; 28+ messages in thread
From: Jan Nieuwenhuizen @ 2004-09-09 16:25 UTC (permalink / raw)
  Cc: Bruno Haible

[-- Attachment #1: Type: text/plain, Size: 170 bytes --]

Jan Nieuwenhuizen writes:

New and improved.  This version not only compiles, but has also been
tested; it should now work even with --disable-nls.  Thanks Bruno!

Jan.


[-- Attachment #2: guile-1.7.1-bh-jcn-6.diff --]
[-- Type: text/plain, Size: 21518 bytes --]

? ABOUT-NLS
? do-diff
? doconf
? libguile/gettext.h
? libguile/i18n.c
? libguile/i18n.h
Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.445
diff -p -u -r1.445 ChangeLog
--- ChangeLog	3 Sep 2004 19:45:34 -0000	1.445
+++ ChangeLog	9 Sep 2004 15:13:38 -0000
@@ -1,3 +1,7 @@
+2004-09-02  Bruno Haible  <bruno@clisp.org>
+
+	* configure.in: Add AM_GNU_GETTEXT invocation.
+
 2004-09-03  Stefan Jahn  <stefan@lkcc.org>
 
 	* configure.in (isinf): Let configure find the isinf() function
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.252
diff -p -u -r1.252 configure.in
--- configure.in	3 Sep 2004 19:45:35 -0000	1.252
+++ configure.in	9 Sep 2004 15:13:38 -0000
@@ -637,6 +637,9 @@ AC_TRY_LINK([#include <gmp.h>],
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2140
diff -p -u -r1.2140 ChangeLog
--- libguile/ChangeLog	7 Sep 2004 00:34:38 -0000	1.2140
+++ libguile/ChangeLog	9 Sep 2004 15:13:41 -0000
@@ -1,3 +1,37 @@
+2004-09-09  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.c: Handle --disable-nls (thanks Bruno).
+
+2004-09-08  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
+	LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.
+
+	* i18n.c (scm_to_lc_category): New name and export.  Support all
+	LC categories.
+
+	* posix.c (s_scm_setlocale): Use it.
+
+2004-09-07  Jan Nieuwenhuizen  <janneke@gnu.org>
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+2004-09-04  Jan Nieuwenhuizen  <janneke@gnu.org>
+            Bruno Haible  <bruno@clisp.org>
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
 2004-09-07  Kevin Ryde  <user42@zip.com.au>
 
 	* numbers.c (scm_integer_expt): Reject exponent +/-inf.
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.191
diff -p -u -r1.191 Makefile.am
--- libguile/Makefile.am	24 Aug 2004 22:11:35 -0000	1.191
+++ libguile/Makefile.am	9 Sep 2004 15:13:41 -0000
@@ -97,7 +97,7 @@ libguile_la_SOURCES = alist.c arbiters.c
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@ DOT_X_FILES = alist.x arbiters.x async.x
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@ DOT_DOC_FILES = alist.doc arbiters.doc a
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@ noinst_HEADERS = convert.i.c	\
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@ modinclude_HEADERS = __scm.h alist.h arb
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -p -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	9 Sep 2004 15:13:42 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@ scm_init_guile_1 (SCM_STACKITEM *base)
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/posix.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/posix.c,v
retrieving revision 1.147
diff -p -u -r1.147 posix.c
--- libguile/posix.c	7 Sep 2004 00:26:48 -0000	1.147
+++ libguile/posix.c	9 Sep 2004 15:13:42 -0000
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_to_lc_category (category, 1, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@ scm_init_posix ()
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif
--- ../ugh-cvs/libguile/libguile.h	1970-01-01 01:00:00 +0100
+++ libguile/i18n.h	2004-09-09 01:34:13 +0200
@@ -0,0 +1,39 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+int scm_to_lc_category (SCM category, int allow_lc_all, int pos);
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/libguile.c	1970-01-01 01:00:00 +0100
+++ libguile/i18n.c	2004-09-09 17:00:15 +0200
@@ -0,0 +1,334 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_to_lc_category (SCM category, int allow_lc_all, int pos)
+{
+  int c_category = scm_to_int (category);
+  switch (c_category)
+    {
+#ifdef LC_CTYPE
+    case LC_CTYPE:
+#endif
+#ifdef LC_NUMERIC
+    case LC_NUMERIC:
+#endif
+#ifdef LC_COLLATE
+    case LC_COLLATE:
+#endif
+#ifdef LC_TIME
+    case LC_TIME:
+#endif
+#ifdef LC_MONETARY
+    case LC_MONETARY:
+#endif
+#ifdef LC_MESSAGES
+    case LC_MESSAGES:
+#endif
+#ifdef LC_PAPER
+    case LC_PAPER:
+#endif
+#ifdef LC_NAME
+    case LC_NAME:
+#endif
+#ifdef LC_ADDRESS
+    case LC_ADDRESS:
+#endif
+#ifdef LC_TELEPHONE
+    case LC_TELEPHONE:
+#endif
+#ifdef LC_MEASUREMENT
+    case LC_MEASUREMENT:
+#endif
+#ifdef LC_IDENTIFICATION
+    case LC_IDENTIFICATION:
+#endif
+      return c_category;
+#ifdef LC_ALL
+    case LC_ALL:
+      if (allow_lc_all)
+	return c_category;
+#endif  
+    }
+  scm_wrong_type_arg (0, pos, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      c_result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (2, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  c_result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, 3);
+	  c_result = dcgettext (c_domain, c_msgid, c_category);
+	}
+      free (c_domain);
+    }
+
+  if (c_result == c_msgid)
+    {
+      free (c_msgid);
+      return msgid;
+    }
+  
+  free (c_msgid);
+  return scm_from_locale_string (c_result);
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *result;
+
+  SCM_VALIDATE_STRING (1, msgid);
+  c_msgid = scm_to_locale_string (msgid);
+  SCM_VALIDATE_STRING (2, msgid_plural);
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  SCM_VALIDATE_ULONG_COPY (3, n, c_n);
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      SCM_VALIDATE_STRING (4, domain);
+      c_domain = scm_to_locale_string (domain);
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_to_lc_category (category, 0, 5);
+	  result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+			       c_category);
+	}
+      free (c_domain);
+    }
+
+  if (result == c_msgid)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid;
+    }
+  else if (result == c_msgid_plural)
+    {
+      free (c_msgid_plural);
+      free (c_msgid);
+      return msgid_plural;
+    }
+  
+  free (c_msgid_plural);
+  free (c_msgid);
+  return scm_from_locale_string (result);
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char const *c_result;
+  char *c_domain;
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (1, domainname);
+      c_domain = scm_to_locale_string (domainname);
+    }
+
+  c_result = textdomain (c_domain);
+  if (c_result != NULL)
+    {
+      SCM result = scm_from_locale_string (c_result);
+      if (c_domain != NULL)
+	free (c_domain);
+      return result;
+    }
+  else if (!SCM_UNBNDP (domainname))
+    {
+      if (c_domain != NULL)
+	free (c_domain);
+      SCM_SYSERROR;
+    }
+
+  return SCM_BOOL_F;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, directory);
+      c_directory = scm_to_locale_string (directory);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bindtextdomain (c_domain, c_directory);
+  free (c_domain);
+
+  if (c_result != NULL)
+    {
+      SCM result = scm_from_locale_string (c_result);
+      if (c_directory != NULL)
+	free (c_directory);
+      return result;
+    }
+  else if (!SCM_UNBNDP (directory))
+    {
+      if (c_directory != NULL)
+	free (c_directory);
+      SCM_SYSERROR;
+    }
+
+  return SCM_BOOL_F;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+
+  SCM_VALIDATE_STRING (1, domainname);
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      SCM_VALIDATE_STRING (2, encoding);
+      c_encoding = scm_to_locale_string (encoding);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+  free (c_domain);
+
+  if (c_result != NULL)
+    {
+      SCM result = scm_from_locale_string (c_result);
+      if (c_encoding != NULL)
+	free (c_encoding);
+      return result;
+    }
+  else if (!SCM_UNBNDP (encoding))
+    {
+      if (c_encoding != NULL)
+	free (c_encoding);
+      SCM_SYSERROR;
+    }
+
+  return SCM_BOOL_F;
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
--- ../ugh-cvs/libguile/gettext.h	1970-01-01 01:00:00 +0100
+++ libguile/gettext.h	2004-09-07 09:27:39 +0200
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]


-- 
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond - The music typesetter
http://www.xs4all.nl/~jantien       | http://www.lilypond.org

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-09 16:25                           ` Jan Nieuwenhuizen
@ 2004-09-15 11:20                             ` Bruno Haible
  2004-09-22  0:42                             ` Marius Vollmer
  1 sibling, 0 replies; 28+ messages in thread
From: Bruno Haible @ 2004-09-15 11:20 UTC (permalink / raw)


Jan Nieuwenhuizen wrote a week ago:
> New and improved.  This version not only compiles, but has also been
> tested

Yes, I too consider it mature for inclusion into guile CVS.

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-09 16:25                           ` Jan Nieuwenhuizen
  2004-09-15 11:20                             ` Bruno Haible
@ 2004-09-22  0:42                             ` Marius Vollmer
  2004-09-22 14:55                               ` Bruno Haible
  1 sibling, 1 reply; 28+ messages in thread
From: Marius Vollmer @ 2004-09-22  0:42 UTC (permalink / raw)
  Cc: Bruno Haible, guile-devel

[-- Attachment #1: Type: text/plain, Size: 552 bytes --]

Jan Nieuwenhuizen <janneke@gnu.org> writes:

> New and improved.  This version not only compiles, but has also been
> tested; it should now work even with --disable-nls.  Thanks Bruno!

I changed it a bit, mostly by using scm_frame_begin and scm_frame_end
in i18n.c to manage the temporary strings.  Also, there is no need to
validate the arguments when using scm_to_local_string.  See the patch
below.

Do you intend scm_to_lc_category to be part of the public API?  If so,
it will have to be documented, of course.  I have made it internal for
now.


[-- Attachment #2: diff-i18n --]
[-- Type: text/plain, Size: 21021 bytes --]

Index: ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/ChangeLog,v
retrieving revision 1.447
diff -u -r1.447 ChangeLog
--- ChangeLog	21 Sep 2004 00:10:02 -0000	1.447
+++ ChangeLog	22 Sep 2004 00:38:51 -0000
@@ -1,3 +1,7 @@
+2004-09-22  Marius Vollmer  <mvo@zagadka.de>
+
+ 	* configure.in: Add AM_GNU_GETTEXT invocation.  From Bruno Haible.
+ 
 2004-09-21  Marius Vollmer  <mvo@zagadka.de>
 
 	* acinclude.m4 (ACX_PTHREAD): New.
Index: configure.in
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/configure.in,v
retrieving revision 1.254
diff -u -r1.254 configure.in
--- configure.in	21 Sep 2004 00:09:47 -0000	1.254
+++ configure.in	22 Sep 2004 00:38:55 -0000
@@ -637,6 +637,9 @@
             [mpz_import (0, 0, 0, 0, 0, 0, 0);] , ,
   [AC_MSG_ERROR([At least GNU MP 4.1 is required, see http://swox.com/gmp])])
 
+dnl i18n tests
+AM_GNU_GETTEXT([external], [need-ngettext])
+
 ### Some systems don't declare some functions.  On such systems, we
 ### need to at least provide our own K&R-style declarations.
 
Index: libguile/ChangeLog
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/ChangeLog,v
retrieving revision 1.2151
diff -u -r1.2151 ChangeLog
--- libguile/ChangeLog	21 Sep 2004 22:05:51 -0000	1.2151
+++ libguile/ChangeLog	22 Sep 2004 00:39:26 -0000
@@ -1,5 +1,35 @@
 2004-09-22  Marius Vollmer  <mvo@zagadka.de>
 
+	From Jan Nieuwenhuizen <janneke@gnu.org> and Bruno Haible
+	<bruno@clisp.org>:
+
+	* i18n.c: Handle --disable-nls (thanks Bruno).
+
+	* posix.c (scm_init_posix): Add LC_PAPER, LC_NAME, LC_ADDRESS,
+	LC_TELEPHONE, LC_MEASUREMENT, LC_IDENTIFICATION.
+
+	* i18n.c (scm_i_to_lc_category): New name and export.  Support all
+	LC categories.
+
+	* posix.c (s_scm_setlocale): Use it.
+
+	* i18n.h, i18n.c (scm_textdomain, scm_bindtextdomain,
+	scm_bind_textdomain_codeset): Make wrappers similar to C function
+	they wrap.
+
+	* i18n.h: New file.
+	* i18n.c: New file.
+	* gettext.h: New file, taken from GNU gettext.
+	* init.c: Include libguile/i18n.h.
+	(scm_init_guile_1): Add call to scm_init_i18n().
+	* Makefile.am (libguile_la_SOURCES): Add i18n.c.
+	(DOT_X_FILES): Add i18n.x.
+	(DOT_DOC_FILES): Add i18n.doc.
+	(libguile_la_LDFLAGS): Add @LTLIBINTL@.
+	(modinclude_HEADERS): Add i18n.h.
+
+2004-09-22  Marius Vollmer  <mvo@zagadka.de>
+
 	* eq.c (scm_equal_p): Allow smobs with different flags to be equal
 	by testing for smobs before insisting on equal SCM_CELL_TYPES.
 
Index: libguile/Makefile.am
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/Makefile.am,v
retrieving revision 1.192
diff -u -r1.192 Makefile.am
--- libguile/Makefile.am	8 Sep 2004 17:15:21 -0000	1.192
+++ libguile/Makefile.am	22 Sep 2004 00:39:27 -0000
@@ -97,7 +97,7 @@
     gc.c gc-mark.c gc-segment.c gc-malloc.c gc-card.c gc-freelist.c	    \
 	gc_os_dep.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c	    \
     gh_io.c gh_list.c gh_predicates.c goops.c gsubr.c guardians.c hash.c    \
-    hashtab.c hooks.c init.c inline.c ioext.c keywords.c		    \
+    hashtab.c hooks.c i18n.c init.c inline.c ioext.c keywords.c		    \
     lang.c list.c							    \
     load.c macros.c mallocs.c modules.c numbers.c objects.c objprop.c	    \
     options.c pairs.c ports.c print.c procprop.c procs.c properties.c	    \
@@ -113,7 +113,7 @@
     error.x eval.x evalext.x extensions.x feature.x fluids.x fports.x	 \
     futures.x								 \
     gc.x  gc-mark.x gc-segment.x gc-malloc.x gc-card.x goops.x		 \
-    gsubr.x guardians.x hash.x hashtab.x hooks.x init.x ioext.x		 \
+    gsubr.x guardians.x hash.x hashtab.x hooks.x i18n.x init.x ioext.x   \
     keywords.x lang.x list.x load.x macros.x mallocs.x modules.x	 \
     numbers.x objects.x objprop.x options.x pairs.x ports.x print.x	 \
     procprop.x procs.x properties.x random.x rdelim.x read.x root.x rw.x \
@@ -132,8 +132,8 @@
     extensions.doc feature.doc fluids.doc fports.doc futures.doc	    \
     gc.doc goops.doc							    \
     gsubr.doc gc-mark.doc gc-segment.doc gc-malloc.doc gc-card.doc	    \
-    guardians.doc hash.doc hashtab.doc hooks.doc init.doc ioext.doc	    \
-    keywords.doc lang.doc list.doc load.doc macros.doc			    \
+    guardians.doc hash.doc hashtab.doc hooks.doc i18n.doc init.doc	    \
+    ioext.doc keywords.doc lang.doc list.doc load.doc macros.doc	    \
     mallocs.doc modules.doc numbers.doc objects.doc objprop.doc		    \
     options.doc pairs.doc ports.doc print.doc procprop.doc		    \
     procs.doc properties.doc random.doc rdelim.doc read.doc root.doc rw.doc \
@@ -172,7 +172,7 @@
 
 libguile_la_DEPENDENCIES = @LIBLOBJS@
 libguile_la_LIBADD = @LIBLOBJS@ ../libguile-ltdl/libguile-ltdl.la $(THREAD_LIBS_LOCAL)
-libguile_la_LDFLAGS = -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
+libguile_la_LDFLAGS = @LTLIBINTL@ -version-info @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGUILE_INTERFACE_AGE@ -export-dynamic -no-undefined
 
 # These are headers visible as <guile/mumble.h>
 pkginclude_HEADERS = gh.h
@@ -187,7 +187,7 @@
     error.h eval.h							      \
     evalext.h extensions.h feature.h filesys.h fluids.h fports.h futures.h    \
     gc.h gdb_interface.h gdbint.h					      \
-    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h init.h		      \
+    goops.h gsubr.h guardians.h hash.h hashtab.h hooks.h i18n.h init.h        \
     inline.h ioext.h							      \
     iselect.h keywords.h lang.h list.h load.h macros.h mallocs.h modules.h    \
     net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h  \
Index: libguile/gettext.h
===================================================================
RCS file: libguile/gettext.h
diff -N libguile/gettext.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libguile/gettext.h	22 Sep 2004 00:39:28 -0000
@@ -0,0 +1,69 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+   Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library 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 _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option.  */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions.  */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+   chokes if dcgettext is defined as a macro.  So include it now, to make
+   later inclusions of <locale.h> a NOP.  We don't include <libintl.h>
+   as well because people using "gettext.h" will not include <libintl.h>,
+   and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+   is OK.  */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+   The casts to 'const char *' serve the purpose of producing warnings
+   for invalid uses of the value returned from these functions.
+   On pre-ANSI systems without 'const', the config.h file is supposed to
+   contain "#define const".  */
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+    ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+   extraction of messages, but does not call gettext().  The run-time
+   translation is done at a different place in the code.
+   The argument, String, should be a literal string.  Concatenated strings
+   and other string expressions won't work.
+   The macro's expansion is not parenthesized, so that it is suitable as
+   initializer for static 'char[]' or 'const char[]' variables.  */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
Index: libguile/i18n.c
===================================================================
RCS file: libguile/i18n.c
diff -N libguile/i18n.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libguile/i18n.c	22 Sep 2004 00:39:28 -0000
@@ -0,0 +1,327 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libguile/_scm.h"
+#include "libguile/feature.h"
+#include "libguile/i18n.h"
+#include "libguile/strings.h"
+#include "libguile/dynwind.h"
+
+#include "gettext.h"
+#include <locale.h>
+
+
+int
+scm_i_to_lc_category (SCM category, int allow_lc_all)
+{
+  int c_category = scm_to_int (category);
+  switch (c_category)
+    {
+#ifdef LC_CTYPE
+    case LC_CTYPE:
+#endif
+#ifdef LC_NUMERIC
+    case LC_NUMERIC:
+#endif
+#ifdef LC_COLLATE
+    case LC_COLLATE:
+#endif
+#ifdef LC_TIME
+    case LC_TIME:
+#endif
+#ifdef LC_MONETARY
+    case LC_MONETARY:
+#endif
+#ifdef LC_MESSAGES
+    case LC_MESSAGES:
+#endif
+#ifdef LC_PAPER
+    case LC_PAPER:
+#endif
+#ifdef LC_NAME
+    case LC_NAME:
+#endif
+#ifdef LC_ADDRESS
+    case LC_ADDRESS:
+#endif
+#ifdef LC_TELEPHONE
+    case LC_TELEPHONE:
+#endif
+#ifdef LC_MEASUREMENT
+    case LC_MEASUREMENT:
+#endif
+#ifdef LC_IDENTIFICATION
+    case LC_IDENTIFICATION:
+#endif
+      return c_category;
+#ifdef LC_ALL
+    case LC_ALL:
+      if (allow_lc_all)
+	return c_category;
+#endif  
+    }
+  scm_wrong_type_arg (0, 0, category);
+}
+
+SCM_DEFINE (scm_gettext, "gettext", 1, 2, 0,
+	    (SCM msgid, SCM domain, SCM category),
+	    "Return the translation of @var{msgid} in the message domain "
+	    "@var{domain}. @var{domain} is optional and defaults to the "
+	    "domain set through (textdomain).  @var{category} is optional "
+	    "and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_gettext
+{
+  char *c_msgid;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  c_msgid = scm_to_locale_string (msgid);
+  scm_frame_free (c_msgid);
+
+  if (SCM_UNBNDP (domain))
+    {
+      /* 1 argument case.  */
+      c_result = gettext (c_msgid);
+    }
+  else
+    {
+      char *c_domain;
+
+      c_domain = scm_to_locale_string (domain);
+      scm_frame_free (c_domain);
+
+      if (SCM_UNBNDP (category))
+	{
+	  /* 2 argument case.  */
+	  c_result = dgettext (c_domain, c_msgid);
+	}
+      else
+	{
+	  /* 3 argument case.  */
+	  int c_category;
+
+	  c_category = scm_i_to_lc_category (category, 0);
+	  c_result = dcgettext (c_domain, c_msgid, c_category);
+	}
+    }
+
+  if (c_result == c_msgid)
+    result = msgid;
+  else
+    result = scm_from_locale_string (c_result);
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_ngettext, "ngettext", 3, 2, 0,
+	    (SCM msgid, SCM msgid_plural, SCM n, SCM domain, SCM category),
+	    "Return the translation of @var{msgid}/@var{msgid_plural} in the "
+	    "message domain @var{domain}, with the plural form being chosen "
+	    "appropriately for the number @var{n}.  @var{domain} is optional "
+	    "and defaults to the domain set through (textdomain). "
+	    "@var{category} is optional and defaults to LC_MESSAGES.")
+#define FUNC_NAME s_scm_ngettext
+{
+  char *c_msgid;
+  char *c_msgid_plural;
+  unsigned long c_n;
+  const char *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  c_msgid = scm_to_locale_string (msgid);
+  scm_frame_free (c_msgid);
+
+  c_msgid_plural = scm_to_locale_string (msgid_plural);
+  scm_frame_free (c_msgid_plural);
+
+  c_n = scm_to_ulong (n);
+
+  if (SCM_UNBNDP (domain))
+    {
+      /* 3 argument case.  */
+      c_result = ngettext (c_msgid, c_msgid_plural, c_n);
+    }
+  else
+    {
+      char *c_domain;
+
+      c_domain = scm_to_locale_string (domain);
+      scm_frame_free (c_domain);
+
+      if (SCM_UNBNDP (category))
+	{
+	  /* 4 argument case.  */
+	  c_result = dngettext (c_domain, c_msgid, c_msgid_plural, c_n);
+	}
+      else
+	{
+	  /* 5 argument case.  */
+	  int c_category;
+
+	  c_category = scm_i_to_lc_category (category, 0);
+	  c_result = dcngettext (c_domain, c_msgid, c_msgid_plural, c_n,
+				 c_category);
+	}
+    }
+
+  if (c_result == c_msgid)
+    result = msgid;
+  else if (c_result == c_msgid_plural)
+    result = msgid_plural;
+  else
+    result = scm_from_locale_string (c_result);
+  
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_textdomain, "textdomain", 0, 1, 0,
+	    (SCM domainname),
+	    "If optional parameter @var{domainname} is supplied, "
+	    "set the textdomain.  "
+	    "Return the textdomain.")
+#define FUNC_NAME s_scm_textdomain
+{
+  char const *c_result;
+  char *c_domain;
+  SCM result = SCM_BOOL_F;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (domainname))
+    c_domain = NULL;
+  else
+    {
+      c_domain = scm_to_locale_string (domainname);
+      scm_frame_free (c_domain);
+    }
+
+  c_result = textdomain (c_domain);
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (domainname))
+    SCM_SYSERROR;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bindtextdomain, "bindtextdomain", 1, 1, 0,
+	    (SCM domainname, SCM directory),
+	    "If optional parameter @var{directory} is supplied, "
+	    "set message catalogs to directory @{directory}.  "
+	    "Return the directory bound to @var{domainname}.")
+#define FUNC_NAME s_scm_bindtextdomain
+{
+  char *c_domain;
+  char *c_directory;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (directory))
+    c_directory = NULL;
+  else
+    {
+      c_directory = scm_to_locale_string (directory);
+      scm_frame_free (c_directory);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  scm_frame_free (c_domain);
+
+  c_result = bindtextdomain (c_domain, c_directory);
+
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (directory))
+    SCM_SYSERROR;
+  else
+    result = SCM_BOOL_F;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_bind_textdomain_codeset, "bind-textdomain-codeset", 1, 1, 0,
+	    (SCM domainname, SCM encoding),
+	    "If optional parameter @var{encoding} is supplied, "
+	    "set encoding for message catalogs of @{domainname}.  "
+	    "Return the encoding of @var{domainname}.")
+#define FUNC_NAME s_scm_bind_textdomain_codeset
+{
+  char *c_domain;
+  char *c_encoding;
+  char const *c_result;
+  SCM result;
+
+  scm_frame_begin (0);
+
+  if (SCM_UNBNDP (encoding))
+    c_encoding = NULL;
+  else
+    {
+      c_encoding = scm_to_locale_string (encoding);
+      scm_frame_free (c_encoding);
+    }
+
+  c_domain = scm_to_locale_string (domainname);
+  scm_frame_free (c_domain);
+
+  c_result = bind_textdomain_codeset (c_domain, c_encoding);
+
+  if (c_result != NULL)
+    result = scm_from_locale_string (c_result);
+  else if (!SCM_UNBNDP (encoding))
+    SCM_SYSERROR;
+  else
+    result = SCM_BOOL_F;
+
+  scm_frame_end ();
+  return result;
+}
+#undef FUNC_NAME
+
+void 
+scm_init_i18n ()
+{
+  scm_add_feature ("i18n");
+#include "libguile/i18n.x"
+}
+
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
Index: libguile/i18n.h
===================================================================
RCS file: libguile/i18n.h
diff -N libguile/i18n.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libguile/i18n.h	22 Sep 2004 00:39:28 -0000
@@ -0,0 +1,41 @@
+/* classes: h_files */
+
+#ifndef SCM_I18N_H
+#define SCM_I18N_H
+
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * 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.1 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
+ */
+
+#include "libguile/__scm.h"
+
+SCM_API SCM scm_gettext (SCM msgid, SCM domainname, SCM category);
+SCM_API SCM scm_ngettext (SCM msgid, SCM msgid_plural, SCM n, SCM domainname, SCM category);
+SCM_API SCM scm_textdomain (SCM domainname);
+SCM_API SCM scm_bindtextdomain (SCM domainname, SCM directory);
+SCM_API SCM scm_bind_textdomain_codeset (SCM domainname, SCM encoding);
+
+SCM_API int scm_i_to_lc_category (SCM category, int allow_lc_all);
+
+SCM_API void scm_init_i18n (void);
+
+#endif  /* SCM_I18N_H */
+
+/*
+  Local Variables:
+  c-file-style: "gnu"
+  End:
+*/
Index: libguile/init.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/init.c,v
retrieving revision 1.159
diff -u -r1.159 init.c
--- libguile/init.c	24 Aug 2004 22:13:07 -0000	1.159
+++ libguile/init.c	22 Sep 2004 00:39:29 -0000
@@ -63,6 +63,7 @@
 #include "libguile/hash.h"
 #include "libguile/hashtab.h"
 #include "libguile/hooks.h"
+#include "libguile/i18n.h"
 #include "libguile/iselect.h"
 #include "libguile/ioext.h"
 #include "libguile/keywords.h"
@@ -477,6 +478,7 @@
   scm_init_properties ();
   scm_init_hooks ();            /* Requires smob_prehistory */
   scm_init_gc ();		/* Requires hooks, async */
+  scm_init_i18n ();
   scm_init_ioext ();
   scm_init_keywords ();
   scm_init_list ();
Index: libguile/posix.c
===================================================================
RCS file: /cvsroot/guile/guile/guile-core/libguile/posix.c,v
retrieving revision 1.147
diff -u -r1.147 posix.c
--- libguile/posix.c	7 Sep 2004 00:26:48 -0000	1.147
+++ libguile/posix.c	22 Sep 2004 00:39:34 -0000
@@ -39,6 +39,7 @@
 
 #include "libguile/validate.h"
 #include "libguile/posix.h"
+#include "libguile/i18n.h"
 \f
 
 #ifdef HAVE_STRING_H
@@ -1365,7 +1366,7 @@
       scm_frame_free (clocale);
     }
 
-  rv = setlocale (scm_to_int (category), clocale);
+  rv = setlocale (scm_i_to_lc_category (category, 1), clocale);
   if (rv == NULL)
     SCM_SYSERROR;
 
@@ -1929,6 +1930,24 @@
 #ifdef LC_ALL
   scm_c_define ("LC_ALL", scm_from_int (LC_ALL));
 #endif
+#ifdef LC_PAPER
+  scm_c_define ("LC_PAPER", scm_from_int (LC_PAPER));
+#endif
+#ifdef LC_NAME
+  scm_c_define ("LC_NAME", scm_from_int (LC_NAME));
+#endif
+#ifdef LC_ADDRESS
+  scm_c_define ("LC_ADDRESS", scm_from_int (LC_ADDRESS));
+#endif
+#ifdef LC_TELEPHONE
+  scm_c_define ("LC_TELEPHONE", scm_from_int (LC_TELEPHONE));
+#endif
+#ifdef LC_MEASUREMENT
+  scm_c_define ("LC_MEASUREMENT", scm_from_int (LC_MEASUREMENT));
+#endif
+#ifdef LC_IDENTIFICATION
+  scm_c_define ("LC_IDENTIFICATION", scm_from_int (LC_IDENTIFICATION));
+#endif
 #ifdef PIPE_BUF
   scm_c_define ("PIPE_BUF", scm_from_long (PIPE_BUF));
 #endif

[-- Attachment #3: Type: text/plain, Size: 73 bytes --]



-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405

[-- Attachment #4: Type: text/plain, Size: 143 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: i18n, gettext support
  2004-09-22  0:42                             ` Marius Vollmer
@ 2004-09-22 14:55                               ` Bruno Haible
  0 siblings, 0 replies; 28+ messages in thread
From: Bruno Haible @ 2004-09-22 14:55 UTC (permalink / raw)
  Cc: guile-devel

Marius Vollmer wrote:
> Do you intend scm_to_lc_category to be part of the public API?

No; its only uses are in the setlocale and gettext bindings.

Bruno



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2004-09-22 14:55 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-20 20:26 i18n, gettext support Bruno Haible
2004-08-23  0:58 ` Kevin Ryde
2004-09-01 16:25 ` Jan Nieuwenhuizen
2004-09-01 20:57   ` Bruno Haible
2004-09-02  9:38     ` Jan Nieuwenhuizen
2004-09-02 16:06       ` Bruno Haible
2004-09-02 16:21         ` Bruno Haible
2004-09-03  1:34           ` Kevin Ryde
2004-09-04 17:25             ` Bruno Haible
2004-09-07  0:13               ` Kevin Ryde
2004-09-07 12:38                 ` Bruno Haible
2004-09-08  1:10                   ` Kevin Ryde
2004-09-07  8:20             ` Jan Nieuwenhuizen
2004-09-07 14:16               ` Jan Nieuwenhuizen
2004-09-08  1:15                 ` Kevin Ryde
2004-09-08  8:58                   ` Jan Nieuwenhuizen
2004-09-08 10:39                   ` Bruno Haible
2004-09-08 14:37                     ` Jan Nieuwenhuizen
2004-09-08 16:37                       ` Bruno Haible
2004-09-08 21:53                     ` Jan Nieuwenhuizen
2004-09-08 22:45                       ` Kevin Ryde
2004-09-08 23:46                         ` Jan Nieuwenhuizen
2004-09-09 16:25                           ` Jan Nieuwenhuizen
2004-09-15 11:20                             ` Bruno Haible
2004-09-22  0:42                             ` Marius Vollmer
2004-09-22 14:55                               ` Bruno Haible
2004-09-02 17:32         ` Jan Nieuwenhuizen
2004-09-01 21:44   ` Kevin Ryde

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).