Hello,

On Nov/21/2009, Robert Millan wrote:
> On Sat, Nov 21, 2009 at 09:27:12PM +0000, Carles Pina i Estany wrote:
> > 
> > Hello,
> > 
> > My gettext branch:
> > bzr.savannah.gnu.org/srv/bzr/grub/people/cpina/gettext/
> > 
> > Is currently synchronized with Robert's changes and working.
> 
> Great.  Could you please attach it as a patch?  This makes it easier
> to review.

find attached

> > (mmm... locale_dir could be hard coded)
> 
> Better let the user specify it.  $prefix points to the module load dir
> and may not always be what user expects (this happens e.g. with
> grub-mkrescue).

yes, I realised of this case ($prefix in grub-mkrescue). Actually before
I was using $prefix/locale and I've changed it.

> > Once merged I will gettize more string
> > in the loader and other utilities.
> 
> Gettext support for utilities can be done already;  you're welcome to add it
> to more of the stuff in util/, see:
> http://lists.gnu.org/archive/html/grub-devel/2009-11/msg00273.html

I will do soon, I just want to finish ASAP the other part and feel
relieved :-)

> For strings in GRUB itself, we need to be more selective.  There are a
> few strings which we obviously want to translate, and some for which
> it isn't so clear.  We can talk about this after the merge.

When it's merged I will gettize the common sense ones (menu ones) and we
will think about the other ones.

-- 
Carles Pina i Estany
        http://pinux.info
=== modified file 'conf/common.rmk'
--- conf/common.rmk	2009-11-18 23:05:59 +0000
+++ conf/common.rmk	2009-11-19 21:12:02 +0000
@@ -163,6 +163,12 @@
 lib_SCRIPTS += update-grub_lib
 CLEANFILES += update-grub_lib
 
+grub-gettext_lib: util/grub-gettext_lib.in config.status
+	./config.status --file=$@:$<
+	chmod +x $@
+lib_DATA += grub-gettext_lib
+CLEANFILES += grub-gettext_lib
+
 %: util/grub.d/%.in config.status
 	./config.status --file=$@:$<
 	chmod +x $@
@@ -179,7 +185,7 @@
 pkglib_MODULES += fshelp.mod fat.mod ufs1.mod ufs2.mod ext2.mod ntfs.mod \
 	ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod	\
 	affs.mod sfs.mod hfsplus.mod reiserfs.mod cpio.mod tar.mod	\
-	udf.mod	afs.mod afs_be.mod befs.mod befs_be.mod
+	udf.mod	afs.mod afs_be.mod befs.mod befs_be.mod gettext.mod
 
 # For fshelp.mod.
 fshelp_mod_SOURCES = fs/fshelp.c
@@ -610,6 +616,11 @@
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
 
+# For gettext.mod.
+gettext_mod_SOURCES = gettext/gettext.c
+gettext_mod_CFLAGS = $(COMMON_CFLAGS)
+gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # Misc.
 pkglib_MODULES += xnu_uuid.mod
 

=== added directory 'gettext'
=== added file 'gettext/gettext.c'
--- gettext/gettext.c	1970-01-01 00:00:00 +0000
+++ gettext/gettext.c	2009-11-21 21:06:44 +0000
@@ -0,0 +1,286 @@
+/* gettext.c - gettext module */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/kernel.h>
+
+/* 
+   .mo file information from: 
+   http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html .
+*/
+
+
+static grub_file_t grub_mofile_open (const char *name);
+static grub_file_t fd_mo;
+
+static int grub_gettext_offsetoriginal;
+static int grub_gettext_max;
+
+static const char* (*grub_gettext_original) (const char *s);
+
+#define GETTEXT_MAGIC_NUMBER 0
+#define GETTEXT_FILE_FORMAT 4
+#define GETTEXT_NUMBER_OF_STRINGS 8
+#define GETTEXT_OFFSET_ORIGINAL 12
+#define GETTEXT_OFFSET_TRANSLATION 16
+
+#define MO_MAGIC_NUMBER 0x950412de
+
+static grub_uint32_t
+grub_gettext_get_info (int offset)
+{
+  grub_uint32_t value;
+
+  grub_file_seek (fd_mo, offset);
+  grub_file_read (fd_mo, (char*) &value, 4);
+  value = grub_cpu_to_le32 (value);
+  return value;
+}
+
+static void
+grub_gettext_getstring_from_offset (grub_uint32_t offset, grub_uint32_t length, char *translation)
+{
+  grub_file_seek (fd_mo, offset);
+  grub_file_read (fd_mo, translation, length);
+  translation[length] = '\0';
+}
+
+static char*
+grub_gettext_gettranslation_from_position (int position)
+{
+  int offsettranslation;
+  int internal_position;
+  grub_uint32_t length, offset;
+  char *translation;
+
+  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
+
+  internal_position = offsettranslation + position * 8;
+
+  grub_file_seek (fd_mo, internal_position);
+  grub_file_read (fd_mo, (char*) &length, 4);
+  length = grub_cpu_to_le32 (length);
+  
+  grub_file_seek (fd_mo, internal_position + 4),
+  grub_file_read (fd_mo, (char*) &offset, 4);
+  offset = grub_cpu_to_le32 (offset);
+
+  translation = grub_malloc(length + 1);
+  grub_gettext_getstring_from_offset (offset, length, translation);
+
+  return translation;
+}
+
+static char*
+grub_gettext_getstring_from_position (int position)
+{
+  int internal_position;
+  int length, offset;
+  char *original;
+
+  /* Get position for string i.  */
+  internal_position = grub_gettext_offsetoriginal + (position * 8);
+
+  /* Get the length of the string i.  */
+  grub_file_seek (fd_mo, internal_position);
+  grub_file_read (fd_mo, (char *) &length, 4);
+
+  /* Get the offset of the string i.  */
+  grub_file_seek (fd_mo, internal_position + 4);
+  grub_file_read (fd_mo, (char *) &offset, 4);
+
+  /* Get the string i.  */
+  original = grub_malloc (length + 1);
+  grub_gettext_getstring_from_offset (offset, length, original);
+
+  return original;
+}
+
+static const char*
+grub_gettext_translate (const char *orig)
+{
+  char *current_string;
+  char *ret;
+
+  int min,max,current;
+
+  if (fd_mo == 0)
+    return orig;
+
+  min = 0;
+  max = grub_gettext_max;
+
+  current = (max + min) / 2;
+
+  while (current != min && current != max)
+    {
+      current_string = grub_gettext_getstring_from_position (current);
+
+      /* Search by bisection.  */
+      if (grub_strcmp (current_string, orig) < 0)
+        {
+          grub_free(current_string);
+          min=current;
+        }
+      else if (grub_strcmp (current_string, orig) > 0)
+        {
+          grub_free(current_string);
+          max=current;
+        }
+      else if (grub_strcmp (current_string, orig) == 0)
+        {
+          grub_free(current_string);
+          return grub_gettext_gettranslation_from_position (current);
+        }
+    current = (max+min)/2;
+    }
+
+  ret = grub_malloc(grub_strlen(orig) + 1);
+  grub_strcpy(ret,orig);
+  return ret;
+}
+
+/* This is similar to grub_gzfile_open. */
+static grub_file_t
+grub_mofile_open (const char *filename)
+{
+  int unsigned magic;
+  int version;
+
+  /* Using fd_mo and not another variable because
+     it's needed for grub_gettext_get_info.  */
+
+  fd_mo = grub_file_open (filename);
+  if (! fd_mo)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Cannot read %s",filename);
+      return 0;
+    }
+
+  magic = grub_gettext_get_info (GETTEXT_MAGIC_NUMBER);
+
+  if (magic != MO_MAGIC_NUMBER)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo file: %s", filename);
+      grub_file_close (fd_mo);
+      fd_mo = 0;
+      return 0;
+    }
+  
+  version = grub_gettext_get_info (GETTEXT_FILE_FORMAT);
+
+  if (version != 0)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo version in file: %s", filename);
+      fd_mo = 0;
+      return 0;
+    }
+  
+  /*
+  Do we want .mo.gz files? Then, the code:
+  file = grub_gzio_open (io, 0); // 0: transparent
+  if (! file)
+    {
+      grub_printf("Problems opening the file\n");
+      grub_file_close (io);
+      return 0;
+    }
+  */
+
+  return fd_mo;
+}
+
+static void
+grub_gettext_init_ext (const char *lang)
+{
+  char *mo_file;
+  char *locale_dir;
+
+  locale_dir = grub_env_get ("locale_dir");
+  
+  fd_mo = 0;
+      
+  // mo_file e.g.: /boot/grub/locale/ca.mo
+
+  mo_file = grub_malloc (grub_strlen (locale_dir) + sizeof ("/") + grub_strlen (lang) + sizeof(".mo"));
+ 
+  // Warning: if changing some paths in the below line, change the grub_malloc
+  // contents below
+ 
+  grub_sprintf (mo_file, "%s/%s.mo", locale_dir, lang);
+
+  grub_dprintf("gettext", "Will try to open file: %s " ,mo_file);
+
+  fd_mo = grub_mofile_open(mo_file);
+  grub_free (mo_file);
+
+  if (fd_mo)
+    {
+      grub_gettext_offsetoriginal = grub_gettext_get_info(GETTEXT_OFFSET_ORIGINAL);
+      grub_gettext_max = grub_gettext_get_info(GETTEXT_NUMBER_OF_STRINGS);
+
+      grub_gettext_original = grub_gettext;
+      grub_gettext = grub_gettext_translate;
+    }
+}
+
+static char*
+grub_gettext_env_write_lang (struct grub_env_var *var __attribute__ ((unused)),
+			     const char *val)
+{
+  grub_gettext_init_ext (val);
+
+  return grub_strdup (val);
+}
+
+GRUB_MOD_INIT(gettext)
+{
+  (void)mod;			/* To stop warning.  */
+ 
+  const char *lang;
+
+  lang = grub_env_get ("lang"); 
+
+  grub_gettext_init_ext (lang);
+
+  /* Testing:
+  grub_register_command ("_", grub_cmd_translate, GRUB_COMMAND_FLAG_BOTH,
+			 "_", "internalization support trans", 0);
+  */
+
+  /* Reload .mo file information if lang changes.  */
+  grub_register_variable_hook ("lang", NULL, grub_gettext_env_write_lang);
+
+  /* Preserve hooks after context changes.  */
+  grub_env_export ("lang");
+}
+
+GRUB_MOD_FINI(gettext)
+{
+  if (fd_mo != 0)
+    grub_file_close(fd_mo);
+
+  grub_gettext = grub_gettext_original;
+}

=== added file 'include/grub/i18n_grub.h'
--- include/grub/i18n_grub.h	1970-01-01 00:00:00 +0000
+++ include/grub/i18n_grub.h	2009-11-19 21:32:05 +0000
@@ -0,0 +1,24 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef	GRUB_I18N_GRUB_H
+#define	GRUB_I18N_GRUB_H	1
+
+# define _(str) grub_gettext(str)
+
+#endif /* GRUB_I18N_GRUB_H */

=== modified file 'include/grub/misc.h'
--- include/grub/misc.h	2009-10-28 22:55:27 +0000
+++ include/grub/misc.h	2009-11-19 21:29:16 +0000
@@ -1,7 +1,7 @@
 /* misc.h - prototypes for misc functions */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2008  Free Software Foundation, Inc.
+ *  Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2008,2009  Free Software Foundation, Inc.
  *
  *  GRUB is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -191,6 +191,9 @@
 grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
 					  grub_uint32_t d, grub_uint32_t *r);
 
+const char *EXPORT_FUNC(grub_gettext_dummy) (const char *s);
+extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);// = grub_gettext_dummy;
+
 #ifdef NEED_ENABLE_EXECUTE_STACK
 void EXPORT_FUNC(__enable_execute_stack) (void *addr);
 #endif

=== modified file 'kern/misc.c'
--- kern/misc.c	2009-11-01 23:03:09 +0000
+++ kern/misc.c	2009-11-13 20:32:00 +0000
@@ -30,6 +30,8 @@
   return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
 }
 
+const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
+
 void *
 grub_memmove (void *dest, const void *src, grub_size_t n)
 {
@@ -984,6 +986,13 @@
   return p - dest;
 }
 
+/* grub_gettext_dummy is not translating anything.  */
+const char *
+grub_gettext_dummy (const char *s)
+{
+  return s;
+}
+
 /* Abort GRUB. This function does not return.  */
 void
 grub_abort (void)

=== modified file 'normal/menu_text.c'
--- normal/menu_text.c	2009-05-02 19:49:34 +0000
+++ normal/menu_text.c	2009-11-19 21:32:39 +0000
@@ -25,6 +25,7 @@
 #include <grub/time.h>
 #include <grub/env.h>
 #include <grub/menu_viewer.h>
+#include <grub/i18n_grub.h>
 
 /* Time to delay after displaying an error message about a default/fallback
    entry failing to boot.  */
@@ -93,8 +94,8 @@
     }
   else
     {
-      grub_printf ("\n\
-      Use the %C and %C keys to select which entry is highlighted.\n",
+      grub_printf (_("\n\
+      Use the %C and %C keys to select which entry is highlighted.\n"),
 		   (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN);
       grub_printf ("\
       Press enter to boot the selected OS, \'e\' to edit the\n\

=== modified file 'po/POTFILES'
--- po/POTFILES	2009-11-18 23:20:22 +0000
+++ po/POTFILES	2009-11-19 21:37:10 +0000
@@ -10,3 +10,5 @@
 util/mkisofs/rock.c
 util/mkisofs/tree.c
 util/mkisofs/write.c
+
+normal/menu_text.c

=== modified file 'po/ca.po'
--- po/ca.po	2009-11-18 23:20:22 +0000
+++ po/ca.po	2009-11-19 21:38:55 +0000
@@ -6,7 +6,7 @@
 msgstr ""
 "Project-Id-Version: GNU GRUB\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-11-19 00:16+0100\n"
+"POT-Creation-Date: 2009-11-19 21:37+0000\n"
 "PO-Revision-Date: 2009-11-17 12:26+0100\n"
 "Last-Translator: Robert Millan <rmh.g...@aybabtu.com>\n"
 "Language-Team: None <no-team-...@li.org>\n"
@@ -882,6 +882,15 @@
 msgid "Path table size(bytes): %d\n"
 msgstr ""
 
+#: normal/menu_text.c:97
+#, c-format
+msgid ""
+"\n"
+"      Use the %C and %C keys to select which entry is highlighted.\n"
+msgstr ""
+"\n"
+"      Utilitzeu les tecles %C i %C per a seleccionar l'entrada.\n"
+
 #: util/grub.d/10_kfreebsd.in:40
 msgid "%s, with kFreeBSD %s"
 msgstr ""

=== modified file 'util/grub.d/00_header.in'
--- util/grub.d/00_header.in	2009-08-25 19:42:56 +0000
+++ util/grub.d/00_header.in	2009-11-21 21:06:21 +0000
@@ -22,6 +22,8 @@
 exec_pref...@exec_prefix@
 libd...@libdir@
 grub_prefix=`echo /boot/grub | sed ${transform}`
+locale_dir=`echo /boot/grub/locale | sed ${transform}`
+grub_lang=`echo $LANG | cut -d _ -f 1`
 
 . ${libdir}/grub/grub-mkconfig_lib
 
@@ -100,6 +102,13 @@
   ;;
 esac
 
+# Gettext variables and module
+cat << EOF
+set locale_dir=${locale_dir}
+set lang=${grub_lang}
+insmod gettext 
+EOF
+
 if [ "x${GRUB_HIDDEN_TIMEOUT}" != "x" ] ; then
   if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then 
     verbose=

YYYY-MM-DD  Carles Pina i Estany <car...@pina.cat>

        * conf/common.rmk: Add grub-gettext_lib target, dependency and
          SOURCES, CFLAGS, LDFLAGS
        * gettext/gettext.c: New file with gettext implementation
        * include/grub/i18n_grub.h: New file with grub_gettext macros
        * include/grub/misc.h: Define macro _(char *s). Declare
          grub_gettext_dummy and grub_gettext
        * kern/misc.c: Define grub_gettext symbol implementation of the
          grub_gettext_dummy function
        * normal/menu_text.c: Gettextize one message in print_message
        * po/POTFILES: Adds normal/menu_text.c
        * po/ca.po: Adds the new string
        * util/grub.d/00_header.in: defines gettext variables and loads
          the module
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to