All of lore.kernel.org
 help / color / mirror / Atom feed
* gettext patch (beta)
@ 2009-01-21 21:17 Carles Pina i Estany
  2009-01-21 21:38 ` Vesa Jääskeläinen
  2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
  0 siblings, 2 replies; 21+ messages in thread
From: Carles Pina i Estany @ 2009-01-21 21:17 UTC (permalink / raw)
  To: grub-devel

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


Hello,

I have been working with the gettext patch (and Robert gave me a hand,
thanks)

Take this version as a RFC and call for help (see at the bottom, it
includes beer invitation in Fosdem).

ChangeLog:
-------------------
YYYY-MM-DD  Carles Pina i Estany <carles@pina.cat>

        * Makefile.in: Add uptrans target to help to update .pot file
        * conf/common.rmk: Add grub-gettext_lib target, dependency and
          SOURCES, CFLAGS, LDFLAGS
        * kern/misc.c: Define grub_gettext symbol and add implement
          grub_gettext_dummy function
        * po/TODO: Temporary file with instructions of what Makefile.in
          will do
        * po/ca.po: Catalan translation stub
        * include/grub/misc.h: Define macro _(char *s). Declare
          grub_gettext_dummy and grub_gettext
        * gettext/gettext.c: New file with gettext implementation
        * normal/menu.c (print_message): add _( ) to some strings
        * util/grub.d/10_linux.in: include grub-gettext_lib file.
          For the Linux menuentry, call eval_gettext
        * util/grub.d/00_header.in: add locale_prefix and gettext 
          locale detection and setting up the access to the mo directory
        * util/grub-mkconfig_lib.in: add get_locale_lang
        * util/grub-gettext_lib.in: new file
-------------------

How to test and see something:
-Apply the patch

-In po/ execute msgfmt ca.po -o ca.mo

-Copy ca.mo to /usr/share/locale/ca/LC_MESSAGES/grub.mo

-Compile and install the patched Grub

-Maybe the new 00_header will detect your language and add the 
 configuration (this has not been tested)

-In Grub2 console you should:
set lang=ca
set locale_prefix=/usr/share/locale
insmod gettext
(ESC)

Then the lines under the menu box will appear in Catalan.

The gettext module has a hook to the lang variable, if you change lang to 
a new value, it will reload the file. Ops! And I didn't do any hook for
locale_prefix, I will do it but by the moment you can rmmod gettext
and insmod again

CALL FOR HELP:
I need to write the Makefile.in (see po/TODO :-( ). I'm not used or
familiar to write Makefiles :-( if someone wants to help it would 
speed up the process quite much. It needs only to merge the files with
the new .pot, compile (msgfmt), and install to the correct directory.

I exactly know what has to do, so if someone knows about
installation/Makefiles and doesn't know about gettext it's not a
problem, contact me. Else I will try to implement soon.

I would even invite to a couple of beers in Fosdem if someone does
this part :-)

TODO:
-the Makefile.in
-and more testing about 00_header with gettext detection.
-Add _("") for mainly all strings (I would do in a separate patch)
-I have seen that Grub2 is not printing correctly the accents,
could be a problem in gettext or in some other layer

-- 
Carles Pina i Estany		GPG id: 0x17756391
	http://pinux.info

[-- Attachment #2: gettext01.patch --]
[-- Type: text/x-diff, Size: 21744 bytes --]

Index: Makefile.in
===================================================================
--- Makefile.in	(revision 1952)
+++ Makefile.in	(working copy)
@@ -170,6 +170,16 @@
 endif
 endif
 
+#TODO: define on the header?    
+SHELLSDIR = $(srcdir)/util/grub.d
+uptrans:
+	#TODO: only one xgettext for everything
+	xgettext -k_ -LC -o - `find "$(srcdir)/" -name '*.c'` -o po/grub.pot
+
+	#TODO: in which variable we have all shell scripts?
+	xgettext -k_ -Lshell -o - $(SHELLSDIR)/00_header.in $(SHELLSDIR)/10_freebsd.in $(SHELLSDIR)/10_hurd.in $(SHELLSDIR)/10_linux.in $(SHELLSDIR)/10_windows.in $(SHELLSDIR)/30_os-prober.in $(SHELLSDIR)/40_custom.in -o po/grub.pot
+
+
 # Used for building modules externally
 pkglib_BUILDDIR += build_env.mk
 build_env.mk: Makefile
Index: conf/common.rmk
===================================================================
--- conf/common.rmk	(revision 1952)
+++ conf/common.rmk	(working copy)
@@ -142,6 +142,12 @@
 lib_DATA += 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 $@
@@ -329,7 +335,7 @@
 	cmp.mod cat.mod help.mod search.mod					\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
-	read.mod sleep.mod loadenv.mod crc.mod
+	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
 
 # For hello.mod.
 hello_mod_SOURCES = hello/hello.c
@@ -492,3 +498,10 @@
 bufio_mod_SOURCES = io/bufio.c
 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)
+
+
Index: conf/common.mk
===================================================================
--- conf/common.mk	(revision 1952)
+++ conf/common.mk	(working copy)
@@ -567,6 +567,12 @@
 lib_DATA += 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 $@
@@ -2366,7 +2372,7 @@
 	cmp.mod cat.mod help.mod search.mod					\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
-	read.mod sleep.mod loadenv.mod crc.mod
+	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
 
 # For hello.mod.
 hello_mod_SOURCES = hello/hello.c
@@ -4236,3 +4242,62 @@
 
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gettext.mod.
+gettext_mod_SOURCES = gettext/gettext.c
+CLEANFILES += gettext.mod mod-gettext.o mod-gettext.c pre-gettext.o gettext_mod-gettext_gettext.o und-gettext.lst
+ifneq ($(gettext_mod_EXPORTS),no)
+CLEANFILES += def-gettext.lst
+DEFSYMFILES += def-gettext.lst
+endif
+MOSTLYCLEANFILES += gettext_mod-gettext_gettext.d
+UNDSYMFILES += und-gettext.lst
+
+gettext.mod: pre-gettext.o mod-gettext.o $(TARGET_OBJ2ELF)
+	-rm -f $@
+	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gettext.o mod-gettext.o
+	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gettext.o: $(gettext_mod_DEPENDENCIES) gettext_mod-gettext_gettext.o
+	-rm -f $@
+	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gettext_mod-gettext_gettext.o
+
+mod-gettext.o: mod-gettext.c
+	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -c -o $@ $<
+
+mod-gettext.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+	sh $(srcdir)/genmodsrc.sh 'gettext' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gettext_mod_EXPORTS),no)
+def-gettext.lst: pre-gettext.o
+	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gettext/' > $@
+endif
+
+und-gettext.lst: pre-gettext.o
+	echo 'gettext' > $@
+	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gettext_mod-gettext_gettext.o: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES)
+	$(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -MD -c -o $@ $<
+-include gettext_mod-gettext_gettext.d
+
+CLEANFILES += cmd-gettext_mod-gettext_gettext.lst fs-gettext_mod-gettext_gettext.lst partmap-gettext_mod-gettext_gettext.lst
+COMMANDFILES += cmd-gettext_mod-gettext_gettext.lst
+FSFILES += fs-gettext_mod-gettext_gettext.lst
+PARTMAPFILES += partmap-gettext_mod-gettext_gettext.lst
+
+cmd-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) gencmdlist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh gettext > $@ || (rm -f $@; exit 1)
+
+fs-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genfslist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh gettext > $@ || (rm -f $@; exit 1)
+
+partmap-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genpartmaplist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh gettext > $@ || (rm -f $@; exit 1)
+
+
+gettext_mod_CFLAGS = $(COMMON_CFLAGS)
+gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+
Index: kern/misc.c
===================================================================
--- kern/misc.c	(revision 1952)
+++ kern/misc.c	(working copy)
@@ -24,6 +24,8 @@
 #include <grub/term.h>
 #include <grub/env.h>
 
+char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
+
 void *
 grub_memmove (void *dest, const void *src, grub_size_t n)
 {
@@ -1036,6 +1038,13 @@
   return p - dest;
 }
 
+/* grub_gettext_dummy is not translating anything.  */
+char *
+grub_gettext_dummy (const char *s)
+{
+  return s;
+}
+
 /* Abort GRUB. This function does not return.  */
 void
 grub_abort (void)
Index: po/ca.po
===================================================================
--- po/ca.po	(revision 0)
+++ po/ca.po	(revision 0)
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-01-21 21:14+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: normal/menu.c:90
+#, 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 seleccionar l'entrada.\n"
+
+#: normal/menu.c:93
+msgid ""
+"      Press enter to boot the selected OS, 'e' to edit the\n"
+"      commands before booting or 'c' for a command-line."
+msgstr ""
+"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"
+"      les comandes abans d'arrancar, 'c' per línia d'ordres."
+
+#: util/grub.d/10_linux.in:148
+#, sh-format
+msgid "${OS}, linux ${version} (single-user mode)"
+msgstr "${OS}, linux ${version} (mode mono-usuari)"
Index: po/TODO
===================================================================
--- po/TODO	(revision 0)
+++ po/TODO	(revision 0)
@@ -0,0 +1,5 @@
+Prepare a Makefile.in to:
+
+-Compile all .po to .mo (msgfmt $LANG.po -o $LANG.mo)
+-Copy to /usr/share/locale/$LANG/LC_MESSAGES/grub.mo (or /usr/local/share/locale/$LANG/LC_MESSAGES/..., so $prefix...)
+-Check that grub-gettext_lib.in is correct
Index: include/grub/misc.h
===================================================================
--- include/grub/misc.h	(revision 1952)
+++ include/grub/misc.h	(working copy)
@@ -31,6 +31,8 @@
 /* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
 #define grub_memcpy(d,s,n)	grub_memmove ((d), (s), (n))
 
+#define _(s)	grub_gettext(s)
+
 void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
 char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
 char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
@@ -84,6 +86,9 @@
 grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
 					  grub_uint32_t d, grub_uint32_t *r);
 
+char *EXPORT_FUNC(grub_gettext_dummy) (const char *s);
+extern 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
Index: gettext/gettext.c
===================================================================
--- gettext/gettext.c	(revision 0)
+++ gettext/gettext.c	(revision 0)
@@ -0,0 +1,299 @@
+/* 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 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
+
+static int
+grub_gettext_get_info (int offset)
+{
+  int buf;
+
+  grub_file_seek (fd_mo, offset);
+  grub_file_read (fd_mo, (char*) &buf, 4);
+  return buf;
+}
+
+static void
+grub_gettext_getstring_from_offset (int offset, int length, char *translation)
+{
+  grub_file_seek (fd_mo,offset);
+  grub_file_read (fd_mo,translation,length);
+  translation[length] = '\0';
+}
+
+static char*
+grub_gettext_gettranslation_number (int i)
+{
+  int offsettranslation;
+  int position;
+  int length, offset;
+  char *translation;
+
+  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
+
+  position=offsettranslation+i*8;
+
+  grub_file_seek (fd_mo, position);
+  grub_file_read (fd_mo, (char*) &length, 4);
+  
+  grub_file_seek (fd_mo, position + 4),
+  grub_file_read (fd_mo, (char*) &offset, 4);
+
+  translation = grub_malloc(length + 1);
+  grub_gettext_getstring_from_offset (offset, length, translation);
+
+  return translation;
+}
+
+static char*
+grub_gettext_getstring_num (int num)
+{
+  int position;
+  int length, offset;
+  char *original;
+
+  /* Get position for string i.  */
+  position = grub_gettext_offsetoriginal + (num * 8);
+
+  /* Get the length of the string i.  */
+  grub_file_seek (fd_mo, position);
+  grub_file_read (fd_mo, (char *) &length, 4);
+
+  /* Get the offset of the string i.  */
+  grub_file_seek (fd_mo, 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 char*
+grub_gettext_translate (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_num (current);
+      /* grub_printf("Current: %s\n",current_string);  */
+
+      /* Search by bissection.  */
+      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_number (current);
+        }
+    current = (max+min)/2;
+    }
+
+  ret = grub_malloc(grub_strlen(orig) + 1);
+  grub_strcpy(ret,orig);
+  return ret;
+}
+
+// XXX: Return a real grub_err_t or static void
+static grub_err_t
+grub_cmd_translate (struct grub_arg_list *state __attribute__ ((unused)),
+		int argc __attribute__ ((unused)),
+		char **args __attribute__ ((unused)))
+{
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
+
+  char *translation;
+
+  translation = grub_gettext_translate(args[0]);
+  grub_printf("%s\n",translation);
+  //grub_printf("grub__: %d\n",grub__);
+
+  return 0;
+}
+
+/* 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 != 0x950412de)
+    {
+      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_prefix;
+
+  locale_prefix = grub_env_get ("locale_prefix");
+  
+  fd_mo = 0;
+      
+  // mo_file e.g.: /usr/share/locale/ca/LC_MESSAGES/grub.mo
+
+  mo_file = grub_malloc (grub_strlen (locale_prefix) + sizeof ("/") + grub_strlen (lang) + sizeof ("/LC_MESSAGES/grub.mo"));
+      
+  if (! mo_file)
+    return;
+
+  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
+  /* XXX: lang is written by the user, need to sanitaze the input?  */
+
+  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;
+}
Index: normal/menu.c
===================================================================
--- normal/menu.c	(revision 1952)
+++ normal/menu.c	(working copy)
@@ -87,17 +87,16 @@
     }
   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 ("\
+      grub_printf (_("\
       Press enter to boot the selected OS, \'e\' to edit the\n\
-      commands before booting or \'c\' for a command-line.");
+      commands before booting or \'c\' for a command-line."));
       if (nested)
 	grub_printf ("\n\
       ESC to return previous menu.");
     }
-  
 }
 
 static grub_menu_entry_t
@@ -317,7 +316,7 @@
      They are required to clear the line.  */
   char *msg = "   The highlighted entry will be booted automatically in %ds.    ";
   char *msg_end = grub_strchr (msg, '%');
-  
+
   grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
   grub_printf (second_stage ? msg_end : msg, timeout);
   grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
Index: util/grub.d/10_linux.in
===================================================================
--- util/grub.d/10_linux.in	(revision 1952)
+++ util/grub.d/10_linux.in	(working copy)
@@ -20,6 +20,7 @@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 . ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/grub/grub-gettext_lib
 
 if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
   OS=GNU/Linux
@@ -139,7 +140,7 @@
 EOF
 
   cat << EOF
-menuentry "${OS}, linux ${version} (single-user mode)" {
+menuentry "$(eval_gettext '${OS}, linux ${version} (single-user mode)')" {
 EOF
   prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
   cat << EOF
Index: util/grub.d/00_header.in
===================================================================
--- util/grub.d/00_header.in	(revision 1952)
+++ util/grub.d/00_header.in	(working copy)
@@ -22,6 +22,7 @@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 grub_prefix=`echo /boot/grub | sed ${transform}`
+locale_prefix="/usr/share/locale" # TODO: dynamic with exec_prefix ?
 
 . ${libdir}/grub/grub-mkconfig_lib
 
@@ -112,3 +113,17 @@
 EOF
   ;;
 esac
+
+if test -e ${grub_prefix}/gettext.mod ; then
+  # Make the locales accesible
+  prepare_grub_to_access_device `${grub_probe} --target=device ${locale_prefix}`
+  lang=`get_locale_lang`
+  cat << EOF
+if `make_system_path_relative_to_its_root ${locale_prefix}` ; then
+  set locale_prefix=${locale_prefix}
+  set lang=${lang}
+  insmod gettext 
+EOF
+else
+  echo "gettext module is not available"
+fi
Index: util/grub-mkconfig_lib.in
===================================================================
--- util/grub-mkconfig_lib.in	(revision 1952)
+++ util/grub-mkconfig_lib.in	(working copy)
@@ -176,3 +176,14 @@
   fi
   return 0
 }
+
+get_locale_lang ()
+{
+  lang="`echo ${LANG} | cut -d _ -f 1`"
+  if [ "x${lang}" = "x" ] ; then
+    return 1
+  else
+    echo "${lang}"
+    return 0
+  fi
+}
Index: util/grub-gettext_lib.in
===================================================================
--- util/grub-gettext_lib.in	(revision 0)
+++ util/grub-gettext_lib.in	(revision 0)
@@ -0,0 +1,23 @@
+# Configuration of grub-gettext
+# 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+TEXTDOMAINDIR=@prefix@/share/locale
+TEXTDOMAIN=grub
+. gettext.sh

Property changes on: util/grub-gettext_lib.in
___________________________________________________________________
Added: svn:mergeinfo


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

* Re: gettext patch (beta)
  2009-01-21 21:17 gettext patch (beta) Carles Pina i Estany
@ 2009-01-21 21:38 ` Vesa Jääskeläinen
  2009-01-21 21:48   ` Carles Pina i Estany
  2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
  1 sibling, 1 reply; 21+ messages in thread
From: Vesa Jääskeläinen @ 2009-01-21 21:38 UTC (permalink / raw)
  To: The development of GRUB 2

Carles Pina i Estany wrote:
> -I have seen that Grub2 is not printing correctly the accents,
> could be a problem in gettext or in some other layer

Please provide example what is wrong and how it should look like.



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

* Re: gettext patch (beta)
  2009-01-21 21:38 ` Vesa Jääskeläinen
@ 2009-01-21 21:48   ` Carles Pina i Estany
  2009-01-21 22:08     ` Vesa Jääskeläinen
  0 siblings, 1 reply; 21+ messages in thread
From: Carles Pina i Estany @ 2009-01-21 21:48 UTC (permalink / raw)
  To: The development of GRUB 2


Hello,

On Jan/21/2009, Vesa Jääskeläinen wrote:
> Carles Pina i Estany wrote:
> > -I have seen that Grub2 is not printing correctly the accents,
> > could be a problem in gettext or in some other layer
> 
> Please provide example what is wrong and how it should look like.

po/ca.po contains:
"      les comandes abans d'arrancar, 'c' per línia d'ordres."

in Grub i get "l?ia" and not "línia".

I've changed a non-gettext text in Grub and I've written "línia" (in a
standard grub_printf, like "The highlighted entry..." and I have the
same result (so it's not specific about gettext).

-- 
Carles Pina i Estany		GPG id: 0x17756391
	http://pinux.info



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

* Re: gettext patch (beta)
  2009-01-21 21:48   ` Carles Pina i Estany
@ 2009-01-21 22:08     ` Vesa Jääskeläinen
  2009-01-21 22:21       ` Carles Pina i Estany
  2009-02-07 21:26       ` unicode font slowness (Re: gettext patch (beta)) Robert Millan
  0 siblings, 2 replies; 21+ messages in thread
From: Vesa Jääskeläinen @ 2009-01-21 22:08 UTC (permalink / raw)
  To: The development of GRUB 2

Carles Pina i Estany wrote:
> Hello,
> 
> On Jan/21/2009, Vesa Jääskeläinen wrote:
>> Carles Pina i Estany wrote:
>>> -I have seen that Grub2 is not printing correctly the accents,
>>> could be a problem in gettext or in some other layer
>> Please provide example what is wrong and how it should look like.
> 
> po/ca.po contains:
> "      les comandes abans d'arrancar, 'c' per línia d'ordres."
> 
> in Grub i get "l?ia" and not "línia".
> 
> I've changed a non-gettext text in Grub and I've written "línia" (in a
> standard grub_printf, like "The highlighted entry..." and I have the
> same result (so it's not specific about gettext).

Are you using gfxterm ? If yes, then your font is missing í. Try to load
unifont.bf2 or unicode.bf2. I think debian defaults to ascii.bf2 which
may not include that glyph.




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

* Re: gettext patch (beta)
  2009-01-21 22:08     ` Vesa Jääskeläinen
@ 2009-01-21 22:21       ` Carles Pina i Estany
  2009-01-24 10:59         ` Niels Böhm
  2009-02-07 21:26       ` unicode font slowness (Re: gettext patch (beta)) Robert Millan
  1 sibling, 1 reply; 21+ messages in thread
From: Carles Pina i Estany @ 2009-01-21 22:21 UTC (permalink / raw)
  To: The development of GRUB 2


Hi,

On Jan/22/2009, Vesa Jääskeläinen wrote:
> Carles Pina i Estany wrote:
> > Hello,
> > 
> > On Jan/21/2009, Vesa Jääskeläinen wrote:
> >> Carles Pina i Estany wrote:
> >>> -I have seen that Grub2 is not printing correctly the accents,
> >>> could be a problem in gettext or in some other layer
> >> Please provide example what is wrong and how it should look like.
> > 
> > po/ca.po contains:
> > "      les comandes abans d'arrancar, 'c' per línia d'ordres."
> > 
> > in Grub i get "l?ia" and not "línia".
> > 
> > I've changed a non-gettext text in Grub and I've written "línia" (in a
> > standard grub_printf, like "The highlighted entry..." and I have the
> > same result (so it's not specific about gettext).
> 
> Are you using gfxterm ? If yes, then your font is missing í. Try to load

using everything by default from Grub2 SVN

> unifont.bf2 or unicode.bf2. I think debian defaults to ascii.bf2 which
> may not include that glyph.

I'll try, any instructions?

But looks strange: I write "línia", if í is missing should appear
"l?nia", not "l?ia". Maybe expecting some UTF8 (multi-byte) special
character?

-- 
Carles Pina i Estany		GPG id: 0x17756391
	http://pinux.info



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

* Re: gettext patch (beta)
  2009-01-21 22:21       ` Carles Pina i Estany
@ 2009-01-24 10:59         ` Niels Böhm
  2009-02-07 21:30           ` Robert Millan
  0 siblings, 1 reply; 21+ messages in thread
From: Niels Böhm @ 2009-01-24 10:59 UTC (permalink / raw)
  To: The development of GRUB 2

On Wednesday 21 January 2009, Carles Pina i Estany wrote:
>
> But looks strange: I write "línia", if í is missing should appear
> "l?nia", not "l?ia". Maybe expecting some UTF8 (multi-byte) special
> character?

Looks to me like in this case the function expects UTF-8-encoded strings, but 
the translated string including "línia" is not UTF-8 (but something like 
ISO8859-1 instead).

So probably the message catalog has the wrong encoding.


Regards,
Niels Böhm



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

* Re: gettext patch (beta)
  2009-01-21 21:17 gettext patch (beta) Carles Pina i Estany
  2009-01-21 21:38 ` Vesa Jääskeläinen
@ 2009-01-24 14:26 ` Carles Pina i Estany
  2009-01-24 15:09   ` Carles Pina i Estany
                     ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: Carles Pina i Estany @ 2009-01-24 14:26 UTC (permalink / raw)
  To: grub-devel

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


New version (same ChangeLog), fixing some warning messages, mistake in
00_header, etc.

On Jan/21/2009, Carles Pina i Estany wrote:
> 
> Hello,
> 
> I have been working with the gettext patch (and Robert gave me a hand,
> thanks)
> 
> Take this version as a RFC and call for help (see at the bottom, it
> includes beer invitation in Fosdem).
> 
> ChangeLog:
> -------------------
> YYYY-MM-DD  Carles Pina i Estany <carles@pina.cat>
> 
>         * Makefile.in: Add uptrans target to help to update .pot file
>         * conf/common.rmk: Add grub-gettext_lib target, dependency and
>           SOURCES, CFLAGS, LDFLAGS
>         * kern/misc.c: Define grub_gettext symbol and add implement
>           grub_gettext_dummy function
>         * po/TODO: Temporary file with instructions of what Makefile.in
>           will do
>         * po/ca.po: Catalan translation stub
>         * include/grub/misc.h: Define macro _(char *s). Declare
>           grub_gettext_dummy and grub_gettext
>         * gettext/gettext.c: New file with gettext implementation
>         * normal/menu.c (print_message): add _( ) to some strings
>         * util/grub.d/10_linux.in: include grub-gettext_lib file.
>           For the Linux menuentry, call eval_gettext
>         * util/grub.d/00_header.in: add locale_prefix and gettext 
>           locale detection and setting up the access to the mo directory
>         * util/grub-mkconfig_lib.in: add get_locale_lang
>         * util/grub-gettext_lib.in: new file
> -------------------
> 
> How to test and see something:
> -Apply the patch
> 
> -In po/ execute msgfmt ca.po -o ca.mo
> 
> -Copy ca.mo to /usr/share/locale/ca/LC_MESSAGES/grub.mo
> 
> -Compile and install the patched Grub
> 
> -Maybe the new 00_header will detect your language and add the 
>  configuration (this has not been tested)
> 
> -In Grub2 console you should:
> set lang=ca
> set locale_prefix=/usr/share/locale
> insmod gettext
> (ESC)
> 
> Then the lines under the menu box will appear in Catalan.
> 
> The gettext module has a hook to the lang variable, if you change lang to 
> a new value, it will reload the file. Ops! And I didn't do any hook for
> locale_prefix, I will do it but by the moment you can rmmod gettext
> and insmod again
> 
> CALL FOR HELP:
> I need to write the Makefile.in (see po/TODO :-( ). I'm not used or
> familiar to write Makefiles :-( if someone wants to help it would 
> speed up the process quite much. It needs only to merge the files with
> the new .pot, compile (msgfmt), and install to the correct directory.
> 
> I exactly know what has to do, so if someone knows about
> installation/Makefiles and doesn't know about gettext it's not a
> problem, contact me. Else I will try to implement soon.
> 
> I would even invite to a couple of beers in Fosdem if someone does
> this part :-)
> 
> TODO:
> -the Makefile.in
> -and more testing about 00_header with gettext detection.
> -Add _("") for mainly all strings (I would do in a separate patch)
> -I have seen that Grub2 is not printing correctly the accents,
> could be a problem in gettext or in some other layer
> 
> -- 
> Carles Pina i Estany		GPG id: 0x17756391
> 	http://pinux.info

> Index: Makefile.in
> ===================================================================
> --- Makefile.in	(revision 1952)
> +++ Makefile.in	(working copy)
> @@ -170,6 +170,16 @@
>  endif
>  endif
>  
> +#TODO: define on the header?    
> +SHELLSDIR = $(srcdir)/util/grub.d
> +uptrans:
> +	#TODO: only one xgettext for everything
> +	xgettext -k_ -LC -o - `find "$(srcdir)/" -name '*.c'` -o po/grub.pot
> +
> +	#TODO: in which variable we have all shell scripts?
> +	xgettext -k_ -Lshell -o - $(SHELLSDIR)/00_header.in $(SHELLSDIR)/10_freebsd.in $(SHELLSDIR)/10_hurd.in $(SHELLSDIR)/10_linux.in $(SHELLSDIR)/10_windows.in $(SHELLSDIR)/30_os-prober.in $(SHELLSDIR)/40_custom.in -o po/grub.pot
> +
> +
>  # Used for building modules externally
>  pkglib_BUILDDIR += build_env.mk
>  build_env.mk: Makefile
> Index: conf/common.rmk
> ===================================================================
> --- conf/common.rmk	(revision 1952)
> +++ conf/common.rmk	(working copy)
> @@ -142,6 +142,12 @@
>  lib_DATA += 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 $@
> @@ -329,7 +335,7 @@
>  	cmp.mod cat.mod help.mod search.mod					\
>  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
>  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> -	read.mod sleep.mod loadenv.mod crc.mod
> +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
>  
>  # For hello.mod.
>  hello_mod_SOURCES = hello/hello.c
> @@ -492,3 +498,10 @@
>  bufio_mod_SOURCES = io/bufio.c
>  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)
> +
> +
> Index: conf/common.mk
> ===================================================================
> --- conf/common.mk	(revision 1952)
> +++ conf/common.mk	(working copy)
> @@ -567,6 +567,12 @@
>  lib_DATA += 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 $@
> @@ -2366,7 +2372,7 @@
>  	cmp.mod cat.mod help.mod search.mod					\
>  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
>  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> -	read.mod sleep.mod loadenv.mod crc.mod
> +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
>  
>  # For hello.mod.
>  hello_mod_SOURCES = hello/hello.c
> @@ -4236,3 +4242,62 @@
>  
>  bufio_mod_CFLAGS = $(COMMON_CFLAGS)
>  bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For gettext.mod.
> +gettext_mod_SOURCES = gettext/gettext.c
> +CLEANFILES += gettext.mod mod-gettext.o mod-gettext.c pre-gettext.o gettext_mod-gettext_gettext.o und-gettext.lst
> +ifneq ($(gettext_mod_EXPORTS),no)
> +CLEANFILES += def-gettext.lst
> +DEFSYMFILES += def-gettext.lst
> +endif
> +MOSTLYCLEANFILES += gettext_mod-gettext_gettext.d
> +UNDSYMFILES += und-gettext.lst
> +
> +gettext.mod: pre-gettext.o mod-gettext.o $(TARGET_OBJ2ELF)
> +	-rm -f $@
> +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gettext.o mod-gettext.o
> +	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
> +	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
> +
> +pre-gettext.o: $(gettext_mod_DEPENDENCIES) gettext_mod-gettext_gettext.o
> +	-rm -f $@
> +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gettext_mod-gettext_gettext.o
> +
> +mod-gettext.o: mod-gettext.c
> +	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -c -o $@ $<
> +
> +mod-gettext.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
> +	sh $(srcdir)/genmodsrc.sh 'gettext' $< > $@ || (rm -f $@; exit 1)
> +
> +ifneq ($(gettext_mod_EXPORTS),no)
> +def-gettext.lst: pre-gettext.o
> +	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gettext/' > $@
> +endif
> +
> +und-gettext.lst: pre-gettext.o
> +	echo 'gettext' > $@
> +	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
> +
> +gettext_mod-gettext_gettext.o: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES)
> +	$(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -MD -c -o $@ $<
> +-include gettext_mod-gettext_gettext.d
> +
> +CLEANFILES += cmd-gettext_mod-gettext_gettext.lst fs-gettext_mod-gettext_gettext.lst partmap-gettext_mod-gettext_gettext.lst
> +COMMANDFILES += cmd-gettext_mod-gettext_gettext.lst
> +FSFILES += fs-gettext_mod-gettext_gettext.lst
> +PARTMAPFILES += partmap-gettext_mod-gettext_gettext.lst
> +
> +cmd-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) gencmdlist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +fs-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genfslist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +partmap-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genpartmaplist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +
> +gettext_mod_CFLAGS = $(COMMON_CFLAGS)
> +gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +
> Index: kern/misc.c
> ===================================================================
> --- kern/misc.c	(revision 1952)
> +++ kern/misc.c	(working copy)
> @@ -24,6 +24,8 @@
>  #include <grub/term.h>
>  #include <grub/env.h>
>  
> +char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
> +
>  void *
>  grub_memmove (void *dest, const void *src, grub_size_t n)
>  {
> @@ -1036,6 +1038,13 @@
>    return p - dest;
>  }
>  
> +/* grub_gettext_dummy is not translating anything.  */
> +char *
> +grub_gettext_dummy (const char *s)
> +{
> +  return s;
> +}
> +
>  /* Abort GRUB. This function does not return.  */
>  void
>  grub_abort (void)
> Index: po/ca.po
> ===================================================================
> --- po/ca.po	(revision 0)
> +++ po/ca.po	(revision 0)
> @@ -0,0 +1,39 @@
> +# SOME DESCRIPTIVE TITLE.
> +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
> +# This file is distributed under the same license as the PACKAGE package.
> +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
> +#
> +#, fuzzy
> +msgid ""
> +msgstr ""
> +"Project-Id-Version: PACKAGE VERSION\n"
> +"Report-Msgid-Bugs-To: \n"
> +"POT-Creation-Date: 2009-01-21 21:14+0100\n"
> +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
> +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
> +"Language-Team: LANGUAGE <LL@li.org>\n"
> +"MIME-Version: 1.0\n"
> +"Content-Type: text/plain; charset=CHARSET\n"
> +"Content-Transfer-Encoding: 8bit\n"
> +
> +#: normal/menu.c:90
> +#, 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 seleccionar l'entrada.\n"
> +
> +#: normal/menu.c:93
> +msgid ""
> +"      Press enter to boot the selected OS, 'e' to edit the\n"
> +"      commands before booting or 'c' for a command-line."
> +msgstr ""
> +"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"
> +"      les comandes abans d'arrancar, 'c' per línia d'ordres."
> +
> +#: util/grub.d/10_linux.in:148
> +#, sh-format
> +msgid "${OS}, linux ${version} (single-user mode)"
> +msgstr "${OS}, linux ${version} (mode mono-usuari)"
> Index: po/TODO
> ===================================================================
> --- po/TODO	(revision 0)
> +++ po/TODO	(revision 0)
> @@ -0,0 +1,5 @@
> +Prepare a Makefile.in to:
> +
> +-Compile all .po to .mo (msgfmt $LANG.po -o $LANG.mo)
> +-Copy to /usr/share/locale/$LANG/LC_MESSAGES/grub.mo (or /usr/local/share/locale/$LANG/LC_MESSAGES/..., so $prefix...)
> +-Check that grub-gettext_lib.in is correct
> Index: include/grub/misc.h
> ===================================================================
> --- include/grub/misc.h	(revision 1952)
> +++ include/grub/misc.h	(working copy)
> @@ -31,6 +31,8 @@
>  /* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
>  #define grub_memcpy(d,s,n)	grub_memmove ((d), (s), (n))
>  
> +#define _(s)	grub_gettext(s)
> +
>  void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
>  char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
>  char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
> @@ -84,6 +86,9 @@
>  grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
>  					  grub_uint32_t d, grub_uint32_t *r);
>  
> +char *EXPORT_FUNC(grub_gettext_dummy) (const char *s);
> +extern 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
> Index: gettext/gettext.c
> ===================================================================
> --- gettext/gettext.c	(revision 0)
> +++ gettext/gettext.c	(revision 0)
> @@ -0,0 +1,299 @@
> +/* 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 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
> +
> +static int
> +grub_gettext_get_info (int offset)
> +{
> +  int buf;
> +
> +  grub_file_seek (fd_mo, offset);
> +  grub_file_read (fd_mo, (char*) &buf, 4);
> +  return buf;
> +}
> +
> +static void
> +grub_gettext_getstring_from_offset (int offset, int length, char *translation)
> +{
> +  grub_file_seek (fd_mo,offset);
> +  grub_file_read (fd_mo,translation,length);
> +  translation[length] = '\0';
> +}
> +
> +static char*
> +grub_gettext_gettranslation_number (int i)
> +{
> +  int offsettranslation;
> +  int position;
> +  int length, offset;
> +  char *translation;
> +
> +  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
> +
> +  position=offsettranslation+i*8;
> +
> +  grub_file_seek (fd_mo, position);
> +  grub_file_read (fd_mo, (char*) &length, 4);
> +  
> +  grub_file_seek (fd_mo, position + 4),
> +  grub_file_read (fd_mo, (char*) &offset, 4);
> +
> +  translation = grub_malloc(length + 1);
> +  grub_gettext_getstring_from_offset (offset, length, translation);
> +
> +  return translation;
> +}
> +
> +static char*
> +grub_gettext_getstring_num (int num)
> +{
> +  int position;
> +  int length, offset;
> +  char *original;
> +
> +  /* Get position for string i.  */
> +  position = grub_gettext_offsetoriginal + (num * 8);
> +
> +  /* Get the length of the string i.  */
> +  grub_file_seek (fd_mo, position);
> +  grub_file_read (fd_mo, (char *) &length, 4);
> +
> +  /* Get the offset of the string i.  */
> +  grub_file_seek (fd_mo, 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 char*
> +grub_gettext_translate (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_num (current);
> +      /* grub_printf("Current: %s\n",current_string);  */
> +
> +      /* Search by bissection.  */
> +      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_number (current);
> +        }
> +    current = (max+min)/2;
> +    }
> +
> +  ret = grub_malloc(grub_strlen(orig) + 1);
> +  grub_strcpy(ret,orig);
> +  return ret;
> +}
> +
> +// XXX: Return a real grub_err_t or static void
> +static grub_err_t
> +grub_cmd_translate (struct grub_arg_list *state __attribute__ ((unused)),
> +		int argc __attribute__ ((unused)),
> +		char **args __attribute__ ((unused)))
> +{
> +  if (argc != 1)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
> +
> +  char *translation;
> +
> +  translation = grub_gettext_translate(args[0]);
> +  grub_printf("%s\n",translation);
> +  //grub_printf("grub__: %d\n",grub__);
> +
> +  return 0;
> +}
> +
> +/* 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 != 0x950412de)
> +    {
> +      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_prefix;
> +
> +  locale_prefix = grub_env_get ("locale_prefix");
> +  
> +  fd_mo = 0;
> +      
> +  // mo_file e.g.: /usr/share/locale/ca/LC_MESSAGES/grub.mo
> +
> +  mo_file = grub_malloc (grub_strlen (locale_prefix) + sizeof ("/") + grub_strlen (lang) + sizeof ("/LC_MESSAGES/grub.mo"));
> +      
> +  if (! mo_file)
> +    return;
> +
> +  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
> +  /* XXX: lang is written by the user, need to sanitaze the input?  */
> +
> +  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;
> +}
> Index: normal/menu.c
> ===================================================================
> --- normal/menu.c	(revision 1952)
> +++ normal/menu.c	(working copy)
> @@ -87,17 +87,16 @@
>      }
>    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 ("\
> +      grub_printf (_("\
>        Press enter to boot the selected OS, \'e\' to edit the\n\
> -      commands before booting or \'c\' for a command-line.");
> +      commands before booting or \'c\' for a command-line."));
>        if (nested)
>  	grub_printf ("\n\
>        ESC to return previous menu.");
>      }
> -  
>  }
>  
>  static grub_menu_entry_t
> @@ -317,7 +316,7 @@
>       They are required to clear the line.  */
>    char *msg = "   The highlighted entry will be booted automatically in %ds.    ";
>    char *msg_end = grub_strchr (msg, '%');
> -  
> +
>    grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
>    grub_printf (second_stage ? msg_end : msg, timeout);
>    grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
> Index: util/grub.d/10_linux.in
> ===================================================================
> --- util/grub.d/10_linux.in	(revision 1952)
> +++ util/grub.d/10_linux.in	(working copy)
> @@ -20,6 +20,7 @@
>  exec_prefix=@exec_prefix@
>  libdir=@libdir@
>  . ${libdir}/grub/grub-mkconfig_lib
> +. ${libdir}/grub/grub-gettext_lib
>  
>  if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
>    OS=GNU/Linux
> @@ -139,7 +140,7 @@
>  EOF
>  
>    cat << EOF
> -menuentry "${OS}, linux ${version} (single-user mode)" {
> +menuentry "$(eval_gettext '${OS}, linux ${version} (single-user mode)')" {
>  EOF
>    prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
>    cat << EOF
> Index: util/grub.d/00_header.in
> ===================================================================
> --- util/grub.d/00_header.in	(revision 1952)
> +++ util/grub.d/00_header.in	(working copy)
> @@ -22,6 +22,7 @@
>  exec_prefix=@exec_prefix@
>  libdir=@libdir@
>  grub_prefix=`echo /boot/grub | sed ${transform}`
> +locale_prefix="/usr/share/locale" # TODO: dynamic with exec_prefix ?
>  
>  . ${libdir}/grub/grub-mkconfig_lib
>  
> @@ -112,3 +113,17 @@
>  EOF
>    ;;
>  esac
> +
> +if test -e ${grub_prefix}/gettext.mod ; then
> +  # Make the locales accesible
> +  prepare_grub_to_access_device `${grub_probe} --target=device ${locale_prefix}`
> +  lang=`get_locale_lang`
> +  cat << EOF
> +if `make_system_path_relative_to_its_root ${locale_prefix}` ; then
> +  set locale_prefix=${locale_prefix}
> +  set lang=${lang}
> +  insmod gettext 
> +EOF
> +else
> +  echo "gettext module is not available"
> +fi
> Index: util/grub-mkconfig_lib.in
> ===================================================================
> --- util/grub-mkconfig_lib.in	(revision 1952)
> +++ util/grub-mkconfig_lib.in	(working copy)
> @@ -176,3 +176,14 @@
>    fi
>    return 0
>  }
> +
> +get_locale_lang ()
> +{
> +  lang="`echo ${LANG} | cut -d _ -f 1`"
> +  if [ "x${lang}" = "x" ] ; then
> +    return 1
> +  else
> +    echo "${lang}"
> +    return 0
> +  fi
> +}
> Index: util/grub-gettext_lib.in
> ===================================================================
> --- util/grub-gettext_lib.in	(revision 0)
> +++ util/grub-gettext_lib.in	(revision 0)
> @@ -0,0 +1,23 @@
> +# Configuration of grub-gettext
> +# 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/>.
> +
> +prefix=@prefix@
> +exec_prefix=@exec_prefix@
> +libdir=@libdir@
> +
> +TEXTDOMAINDIR=@prefix@/share/locale
> +TEXTDOMAIN=grub
> +. gettext.sh
> 
> Property changes on: util/grub-gettext_lib.in
> ___________________________________________________________________
> Added: svn:mergeinfo
> 

> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel

-- 
Carles Pina i Estany		GPG id: 0x17756391
	http://pinux.info

[-- Attachment #2: gettext02.patch --]
[-- Type: text/x-diff, Size: 21253 bytes --]

Index: Makefile.in
===================================================================
--- Makefile.in	(revision 1954)
+++ Makefile.in	(working copy)
@@ -112,6 +112,7 @@
 PKGDATA = $(pkgdata_DATA) $(pkgdata_SRCDIR)
 PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES)
 SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS) $(grub-mkconfig_SCRIPTS)
+GRUBD = $(srcdir)/util/grub.d
 
 CLEANFILES =
 MOSTLYCLEANFILES = 
@@ -170,6 +171,11 @@
 endif
 endif
 
+uptrans:
+	xgettext -k_ -LC -o - `find "$(srcdir)/" -name '*.c'` -o po/grub.pot
+	xgettext -k_ -Lshell -o - $(GRUBD)/* -j -o po/grub.pot
+
+
 # Used for building modules externally
 pkglib_BUILDDIR += build_env.mk
 build_env.mk: Makefile
Index: conf/common.rmk
===================================================================
--- conf/common.rmk	(revision 1954)
+++ conf/common.rmk	(working copy)
@@ -142,6 +142,12 @@
 lib_DATA += 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 $@
@@ -329,7 +335,7 @@
 	cmp.mod cat.mod help.mod search.mod					\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
-	read.mod sleep.mod loadenv.mod crc.mod
+	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
 
 # For hello.mod.
 hello_mod_SOURCES = hello/hello.c
@@ -492,3 +498,10 @@
 bufio_mod_SOURCES = io/bufio.c
 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)
+
+
Index: conf/common.mk
===================================================================
--- conf/common.mk	(revision 1954)
+++ conf/common.mk	(working copy)
@@ -567,6 +567,12 @@
 lib_DATA += 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 $@
@@ -2366,7 +2372,7 @@
 	cmp.mod cat.mod help.mod search.mod					\
 	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
 	terminfo.mod test.mod blocklist.mod hexdump.mod		\
-	read.mod sleep.mod loadenv.mod crc.mod
+	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
 
 # For hello.mod.
 hello_mod_SOURCES = hello/hello.c
@@ -4236,3 +4242,62 @@
 
 bufio_mod_CFLAGS = $(COMMON_CFLAGS)
 bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For gettext.mod.
+gettext_mod_SOURCES = gettext/gettext.c
+CLEANFILES += gettext.mod mod-gettext.o mod-gettext.c pre-gettext.o gettext_mod-gettext_gettext.o und-gettext.lst
+ifneq ($(gettext_mod_EXPORTS),no)
+CLEANFILES += def-gettext.lst
+DEFSYMFILES += def-gettext.lst
+endif
+MOSTLYCLEANFILES += gettext_mod-gettext_gettext.d
+UNDSYMFILES += und-gettext.lst
+
+gettext.mod: pre-gettext.o mod-gettext.o $(TARGET_OBJ2ELF)
+	-rm -f $@
+	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gettext.o mod-gettext.o
+	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
+	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
+
+pre-gettext.o: $(gettext_mod_DEPENDENCIES) gettext_mod-gettext_gettext.o
+	-rm -f $@
+	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gettext_mod-gettext_gettext.o
+
+mod-gettext.o: mod-gettext.c
+	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -c -o $@ $<
+
+mod-gettext.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
+	sh $(srcdir)/genmodsrc.sh 'gettext' $< > $@ || (rm -f $@; exit 1)
+
+ifneq ($(gettext_mod_EXPORTS),no)
+def-gettext.lst: pre-gettext.o
+	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gettext/' > $@
+endif
+
+und-gettext.lst: pre-gettext.o
+	echo 'gettext' > $@
+	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
+
+gettext_mod-gettext_gettext.o: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES)
+	$(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -MD -c -o $@ $<
+-include gettext_mod-gettext_gettext.d
+
+CLEANFILES += cmd-gettext_mod-gettext_gettext.lst fs-gettext_mod-gettext_gettext.lst partmap-gettext_mod-gettext_gettext.lst
+COMMANDFILES += cmd-gettext_mod-gettext_gettext.lst
+FSFILES += fs-gettext_mod-gettext_gettext.lst
+PARTMAPFILES += partmap-gettext_mod-gettext_gettext.lst
+
+cmd-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) gencmdlist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh gettext > $@ || (rm -f $@; exit 1)
+
+fs-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genfslist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh gettext > $@ || (rm -f $@; exit 1)
+
+partmap-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genpartmaplist.sh
+	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh gettext > $@ || (rm -f $@; exit 1)
+
+
+gettext_mod_CFLAGS = $(COMMON_CFLAGS)
+gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+
Index: kern/misc.c
===================================================================
--- kern/misc.c	(revision 1954)
+++ kern/misc.c	(working copy)
@@ -24,6 +24,8 @@
 #include <grub/term.h>
 #include <grub/env.h>
 
+const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
+
 void *
 grub_memmove (void *dest, const void *src, grub_size_t n)
 {
@@ -1044,6 +1046,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)
Index: po/ca.po
===================================================================
--- po/ca.po	(revision 0)
+++ po/ca.po	(revision 0)
@@ -0,0 +1,39 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-01-21 21:14+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: normal/menu.c:90
+#, 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 seleccionar l'entrada.\n"
+
+#: normal/menu.c:93
+msgid ""
+"      Press enter to boot the selected OS, 'e' to edit the\n"
+"      commands before booting or 'c' for a command-line."
+msgstr ""
+"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"
+"      les comandes abans d'arrancar, 'c' per línia d'ordres."
+
+#: util/grub.d/10_linux.in:148
+#, sh-format
+msgid "${OS}, linux ${version} (single-user mode)"
+msgstr "${OS}, linux ${version} (mode mono-usuari)"
Index: po/TODO
===================================================================
--- po/TODO	(revision 0)
+++ po/TODO	(revision 0)
@@ -0,0 +1,5 @@
+Prepare a Makefile.in to:
+
+-Compile all .po to .mo (msgfmt $LANG.po -o $LANG.mo)
+-Copy to /usr/share/locale/$LANG/LC_MESSAGES/grub.mo (or /usr/local/share/locale/$LANG/LC_MESSAGES/..., so $prefix...)
+-Check that grub-gettext_lib.in is correct
Index: include/grub/misc.h
===================================================================
--- include/grub/misc.h	(revision 1954)
+++ include/grub/misc.h	(working copy)
@@ -31,6 +31,8 @@
 /* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
 #define grub_memcpy(d,s,n)	grub_memmove ((d), (s), (n))
 
+#define _(s)	grub_gettext(s)
+
 void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
 char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
 char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
@@ -84,6 +86,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
Index: gettext/gettext.c
===================================================================
--- gettext/gettext.c	(revision 0)
+++ gettext/gettext.c	(revision 0)
@@ -0,0 +1,300 @@
+/* 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
+
+static int
+grub_gettext_get_info (int offset)
+{
+  int buf;
+
+  grub_file_seek (fd_mo, offset);
+  grub_file_read (fd_mo, (char*) &buf, 4);
+  return buf;
+}
+
+static void
+grub_gettext_getstring_from_offset (int offset, int length, char *translation)
+{
+  grub_file_seek (fd_mo,offset);
+  grub_file_read (fd_mo,translation,length);
+  translation[length] = '\0';
+}
+
+static char*
+grub_gettext_gettranslation_number (int i)
+{
+  int offsettranslation;
+  int position;
+  int length, offset;
+  char *translation;
+
+  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
+
+  position=offsettranslation+i*8;
+
+  grub_file_seek (fd_mo, position);
+  grub_file_read (fd_mo, (char*) &length, 4);
+  
+  grub_file_seek (fd_mo, position + 4),
+  grub_file_read (fd_mo, (char*) &offset, 4);
+
+  translation = grub_malloc(length + 1);
+  grub_gettext_getstring_from_offset (offset, length, translation);
+
+  return translation;
+}
+
+static char*
+grub_gettext_getstring_num (int num)
+{
+  int position;
+  int length, offset;
+  char *original;
+
+  /* Get position for string i.  */
+  position = grub_gettext_offsetoriginal + (num * 8);
+
+  /* Get the length of the string i.  */
+  grub_file_seek (fd_mo, position);
+  grub_file_read (fd_mo, (char *) &length, 4);
+
+  /* Get the offset of the string i.  */
+  grub_file_seek (fd_mo, 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_num (current);
+      /* grub_printf("Current: %s\n",current_string);  */
+
+      /* Search by bissection.  */
+      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_number (current);
+        }
+    current = (max+min)/2;
+    }
+
+  ret = grub_malloc(grub_strlen(orig) + 1);
+  grub_strcpy(ret,orig);
+  return ret;
+}
+
+// XXX: Return a real grub_err_t or static void
+/*static grub_err_t
+grub_cmd_translate (struct grub_arg_list *state __attribute__ ((unused)),
+		int argc __attribute__ ((unused)),
+		char **args __attribute__ ((unused)))
+{
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
+
+  char *translation;
+
+  translation = grub_gettext_translate(args[0]);
+  grub_printf("%s\n",translation);
+  //grub_printf("grub__: %d\n",grub__);
+
+  return 0;
+}
+*/
+
+/* 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 != 0x950412de)
+    {
+      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_prefix;
+
+  locale_prefix = grub_env_get ("locale_prefix");
+  
+  fd_mo = 0;
+      
+  // mo_file e.g.: /usr/share/locale/ca/LC_MESSAGES/grub.mo
+
+  mo_file = grub_malloc (grub_strlen (locale_prefix) + sizeof ("/") + grub_strlen (lang) + sizeof ("/LC_MESSAGES/grub.mo"));
+      
+  if (! mo_file)
+    return;
+
+  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
+  /* XXX: lang is written by the user, need to sanitaze the input?  */
+
+  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;
+}
Index: normal/menu.c
===================================================================
--- normal/menu.c	(revision 1954)
+++ normal/menu.c	(working copy)
@@ -87,12 +87,12 @@
     }
   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 ("\
+      grub_printf (_("\
       Press enter to boot the selected OS, \'e\' to edit the\n\
-      commands before booting or \'c\' for a command-line.");
+      commands before booting or \'c\' for a command-line."));
       if (nested)
 	grub_printf ("\n\
       ESC to return previous menu.");
Index: util/grub.d/10_linux.in
===================================================================
--- util/grub.d/10_linux.in	(revision 1954)
+++ util/grub.d/10_linux.in	(working copy)
@@ -20,6 +20,7 @@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 . ${libdir}/grub/grub-mkconfig_lib
+. ${libdir}/grub/grub-gettext_lib
 
 if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
   OS=GNU/Linux
@@ -139,7 +140,7 @@
 EOF
 
   cat << EOF
-menuentry "${OS}, linux ${version} (single-user mode)" {
+menuentry "$(eval_gettext '${OS}, linux ${version} (single-user mode)')" {
 EOF
   prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
   cat << EOF
Index: util/grub.d/00_header.in
===================================================================
--- util/grub.d/00_header.in	(revision 1954)
+++ util/grub.d/00_header.in	(working copy)
@@ -22,6 +22,7 @@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 grub_prefix=`echo /boot/grub | sed ${transform}`
+locale_prefix="/usr/share/locale" # TODO: dynamic with exec_prefix ?
 
 . ${libdir}/grub/grub-mkconfig_lib
 
@@ -112,3 +113,18 @@
 EOF
   ;;
 esac
+
+if test -e ${grub_prefix}/gettext.mod ; then
+  # Make the locales accesible
+  prepare_grub_to_access_device `${grub_probe} --target=device ${locale_prefix}`
+  lang=`get_locale_lang`
+  cat << EOF
+if `make_system_path_relative_to_its_root ${locale_prefix}` ; then
+  set locale_prefix=${locale_prefix}
+  set lang=${lang}
+  insmod gettext 
+fi
+EOF
+else
+  echo "gettext module is not available"
+fi
Index: util/grub-mkconfig_lib.in
===================================================================
--- util/grub-mkconfig_lib.in	(revision 1954)
+++ util/grub-mkconfig_lib.in	(working copy)
@@ -176,3 +176,14 @@
   fi
   return 0
 }
+
+get_locale_lang ()
+{
+  lang="`echo ${LANG} | cut -d _ -f 1`"
+  if [ "x${lang}" = "x" ] ; then
+    return 1
+  else
+    echo "${lang}"
+    return 0
+  fi
+}
Index: util/grub-gettext_lib.in
===================================================================
--- util/grub-gettext_lib.in	(revision 0)
+++ util/grub-gettext_lib.in	(revision 0)
@@ -0,0 +1,23 @@
+# Configuration of grub-gettext
+# 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/>.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+TEXTDOMAINDIR=@prefix@/share/locale
+TEXTDOMAIN=grub
+. gettext.sh

Property changes on: util/grub-gettext_lib.in
___________________________________________________________________
Added: svn:mergeinfo


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

* Re: gettext patch (beta)
  2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
@ 2009-01-24 15:09   ` Carles Pina i Estany
  2009-02-09 14:39   ` Robert Millan
  2009-04-10 22:47   ` gettext patch (beta) phcoder
  2 siblings, 0 replies; 21+ messages in thread
From: Carles Pina i Estany @ 2009-01-24 15:09 UTC (permalink / raw)
  To: grub-devel


Sorry, a new mistake has been removed

If someone wants to test:
a) msgfmt po/ca.po -o /usr/share/locale/ca/LC_MESSAGES/grub.mo
b) edit /boot/grub/grub.cfg and change lang=C by lang=ca

Thanks,

On Jan/24/2009, Carles Pina i Estany wrote:
> 
> New version (same ChangeLog), fixing some warning messages, mistake in
> 00_header, etc.
> 
> On Jan/21/2009, Carles Pina i Estany wrote:
> > 
> > Hello,
> > 
> > I have been working with the gettext patch (and Robert gave me a hand,
> > thanks)
> > 
> > Take this version as a RFC and call for help (see at the bottom, it
> > includes beer invitation in Fosdem).
> > 
> > ChangeLog:
> > -------------------
> > YYYY-MM-DD  Carles Pina i Estany <carles@pina.cat>
> > 
> >         * Makefile.in: Add uptrans target to help to update .pot file
> >         * conf/common.rmk: Add grub-gettext_lib target, dependency and
> >           SOURCES, CFLAGS, LDFLAGS
> >         * kern/misc.c: Define grub_gettext symbol and add implement
> >           grub_gettext_dummy function
> >         * po/TODO: Temporary file with instructions of what Makefile.in
> >           will do
> >         * po/ca.po: Catalan translation stub
> >         * include/grub/misc.h: Define macro _(char *s). Declare
> >           grub_gettext_dummy and grub_gettext
> >         * gettext/gettext.c: New file with gettext implementation
> >         * normal/menu.c (print_message): add _( ) to some strings
> >         * util/grub.d/10_linux.in: include grub-gettext_lib file.
> >           For the Linux menuentry, call eval_gettext
> >         * util/grub.d/00_header.in: add locale_prefix and gettext 
> >           locale detection and setting up the access to the mo directory
> >         * util/grub-mkconfig_lib.in: add get_locale_lang
> >         * util/grub-gettext_lib.in: new file
> > -------------------
> > 
> > How to test and see something:
> > -Apply the patch
> > 
> > -In po/ execute msgfmt ca.po -o ca.mo
> > 
> > -Copy ca.mo to /usr/share/locale/ca/LC_MESSAGES/grub.mo
> > 
> > -Compile and install the patched Grub
> > 
> > -Maybe the new 00_header will detect your language and add the 
> >  configuration (this has not been tested)
> > 
> > -In Grub2 console you should:
> > set lang=ca
> > set locale_prefix=/usr/share/locale
> > insmod gettext
> > (ESC)
> > 
> > Then the lines under the menu box will appear in Catalan.
> > 
> > The gettext module has a hook to the lang variable, if you change lang to 
> > a new value, it will reload the file. Ops! And I didn't do any hook for
> > locale_prefix, I will do it but by the moment you can rmmod gettext
> > and insmod again
> > 
> > CALL FOR HELP:
> > I need to write the Makefile.in (see po/TODO :-( ). I'm not used or
> > familiar to write Makefiles :-( if someone wants to help it would 
> > speed up the process quite much. It needs only to merge the files with
> > the new .pot, compile (msgfmt), and install to the correct directory.
> > 
> > I exactly know what has to do, so if someone knows about
> > installation/Makefiles and doesn't know about gettext it's not a
> > problem, contact me. Else I will try to implement soon.
> > 
> > I would even invite to a couple of beers in Fosdem if someone does
> > this part :-)
> > 
> > TODO:
> > -the Makefile.in
> > -and more testing about 00_header with gettext detection.
> > -Add _("") for mainly all strings (I would do in a separate patch)
> > -I have seen that Grub2 is not printing correctly the accents,
> > could be a problem in gettext or in some other layer
> > 
> > -- 
> > Carles Pina i Estany		GPG id: 0x17756391
> > 	http://pinux.info
> 
> > Index: Makefile.in
> > ===================================================================
> > --- Makefile.in	(revision 1952)
> > +++ Makefile.in	(working copy)
> > @@ -170,6 +170,16 @@
> >  endif
> >  endif
> >  
> > +#TODO: define on the header?    
> > +SHELLSDIR = $(srcdir)/util/grub.d
> > +uptrans:
> > +	#TODO: only one xgettext for everything
> > +	xgettext -k_ -LC -o - `find "$(srcdir)/" -name '*.c'` -o po/grub.pot
> > +
> > +	#TODO: in which variable we have all shell scripts?
> > +	xgettext -k_ -Lshell -o - $(SHELLSDIR)/00_header.in $(SHELLSDIR)/10_freebsd.in $(SHELLSDIR)/10_hurd.in $(SHELLSDIR)/10_linux.in $(SHELLSDIR)/10_windows.in $(SHELLSDIR)/30_os-prober.in $(SHELLSDIR)/40_custom.in -o po/grub.pot
> > +
> > +
> >  # Used for building modules externally
> >  pkglib_BUILDDIR += build_env.mk
> >  build_env.mk: Makefile
> > Index: conf/common.rmk
> > ===================================================================
> > --- conf/common.rmk	(revision 1952)
> > +++ conf/common.rmk	(working copy)
> > @@ -142,6 +142,12 @@
> >  lib_DATA += 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 $@
> > @@ -329,7 +335,7 @@
> >  	cmp.mod cat.mod help.mod search.mod					\
> >  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
> >  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> > -	read.mod sleep.mod loadenv.mod crc.mod
> > +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
> >  
> >  # For hello.mod.
> >  hello_mod_SOURCES = hello/hello.c
> > @@ -492,3 +498,10 @@
> >  bufio_mod_SOURCES = io/bufio.c
> >  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)
> > +
> > +
> > Index: conf/common.mk
> > ===================================================================
> > --- conf/common.mk	(revision 1952)
> > +++ conf/common.mk	(working copy)
> > @@ -567,6 +567,12 @@
> >  lib_DATA += 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 $@
> > @@ -2366,7 +2372,7 @@
> >  	cmp.mod cat.mod help.mod search.mod					\
> >  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
> >  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> > -	read.mod sleep.mod loadenv.mod crc.mod
> > +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
> >  
> >  # For hello.mod.
> >  hello_mod_SOURCES = hello/hello.c
> > @@ -4236,3 +4242,62 @@
> >  
> >  bufio_mod_CFLAGS = $(COMMON_CFLAGS)
> >  bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
> > +
> > +# For gettext.mod.
> > +gettext_mod_SOURCES = gettext/gettext.c
> > +CLEANFILES += gettext.mod mod-gettext.o mod-gettext.c pre-gettext.o gettext_mod-gettext_gettext.o und-gettext.lst
> > +ifneq ($(gettext_mod_EXPORTS),no)
> > +CLEANFILES += def-gettext.lst
> > +DEFSYMFILES += def-gettext.lst
> > +endif
> > +MOSTLYCLEANFILES += gettext_mod-gettext_gettext.d
> > +UNDSYMFILES += und-gettext.lst
> > +
> > +gettext.mod: pre-gettext.o mod-gettext.o $(TARGET_OBJ2ELF)
> > +	-rm -f $@
> > +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gettext.o mod-gettext.o
> > +	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
> > +	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
> > +
> > +pre-gettext.o: $(gettext_mod_DEPENDENCIES) gettext_mod-gettext_gettext.o
> > +	-rm -f $@
> > +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gettext_mod-gettext_gettext.o
> > +
> > +mod-gettext.o: mod-gettext.c
> > +	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -c -o $@ $<
> > +
> > +mod-gettext.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
> > +	sh $(srcdir)/genmodsrc.sh 'gettext' $< > $@ || (rm -f $@; exit 1)
> > +
> > +ifneq ($(gettext_mod_EXPORTS),no)
> > +def-gettext.lst: pre-gettext.o
> > +	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gettext/' > $@
> > +endif
> > +
> > +und-gettext.lst: pre-gettext.o
> > +	echo 'gettext' > $@
> > +	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
> > +
> > +gettext_mod-gettext_gettext.o: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES)
> > +	$(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -MD -c -o $@ $<
> > +-include gettext_mod-gettext_gettext.d
> > +
> > +CLEANFILES += cmd-gettext_mod-gettext_gettext.lst fs-gettext_mod-gettext_gettext.lst partmap-gettext_mod-gettext_gettext.lst
> > +COMMANDFILES += cmd-gettext_mod-gettext_gettext.lst
> > +FSFILES += fs-gettext_mod-gettext_gettext.lst
> > +PARTMAPFILES += partmap-gettext_mod-gettext_gettext.lst
> > +
> > +cmd-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) gencmdlist.sh
> > +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh gettext > $@ || (rm -f $@; exit 1)
> > +
> > +fs-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genfslist.sh
> > +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh gettext > $@ || (rm -f $@; exit 1)
> > +
> > +partmap-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genpartmaplist.sh
> > +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh gettext > $@ || (rm -f $@; exit 1)
> > +
> > +
> > +gettext_mod_CFLAGS = $(COMMON_CFLAGS)
> > +gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
> > +
> > +
> > Index: kern/misc.c
> > ===================================================================
> > --- kern/misc.c	(revision 1952)
> > +++ kern/misc.c	(working copy)
> > @@ -24,6 +24,8 @@
> >  #include <grub/term.h>
> >  #include <grub/env.h>
> >  
> > +char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
> > +
> >  void *
> >  grub_memmove (void *dest, const void *src, grub_size_t n)
> >  {
> > @@ -1036,6 +1038,13 @@
> >    return p - dest;
> >  }
> >  
> > +/* grub_gettext_dummy is not translating anything.  */
> > +char *
> > +grub_gettext_dummy (const char *s)
> > +{
> > +  return s;
> > +}
> > +
> >  /* Abort GRUB. This function does not return.  */
> >  void
> >  grub_abort (void)
> > Index: po/ca.po
> > ===================================================================
> > --- po/ca.po	(revision 0)
> > +++ po/ca.po	(revision 0)
> > @@ -0,0 +1,39 @@
> > +# SOME DESCRIPTIVE TITLE.
> > +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
> > +# This file is distributed under the same license as the PACKAGE package.
> > +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
> > +#
> > +#, fuzzy
> > +msgid ""
> > +msgstr ""
> > +"Project-Id-Version: PACKAGE VERSION\n"
> > +"Report-Msgid-Bugs-To: \n"
> > +"POT-Creation-Date: 2009-01-21 21:14+0100\n"
> > +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
> > +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
> > +"Language-Team: LANGUAGE <LL@li.org>\n"
> > +"MIME-Version: 1.0\n"
> > +"Content-Type: text/plain; charset=CHARSET\n"
> > +"Content-Transfer-Encoding: 8bit\n"
> > +
> > +#: normal/menu.c:90
> > +#, 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 seleccionar l'entrada.\n"
> > +
> > +#: normal/menu.c:93
> > +msgid ""
> > +"      Press enter to boot the selected OS, 'e' to edit the\n"
> > +"      commands before booting or 'c' for a command-line."
> > +msgstr ""
> > +"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"
> > +"      les comandes abans d'arrancar, 'c' per línia d'ordres."
> > +
> > +#: util/grub.d/10_linux.in:148
> > +#, sh-format
> > +msgid "${OS}, linux ${version} (single-user mode)"
> > +msgstr "${OS}, linux ${version} (mode mono-usuari)"
> > Index: po/TODO
> > ===================================================================
> > --- po/TODO	(revision 0)
> > +++ po/TODO	(revision 0)
> > @@ -0,0 +1,5 @@
> > +Prepare a Makefile.in to:
> > +
> > +-Compile all .po to .mo (msgfmt $LANG.po -o $LANG.mo)
> > +-Copy to /usr/share/locale/$LANG/LC_MESSAGES/grub.mo (or /usr/local/share/locale/$LANG/LC_MESSAGES/..., so $prefix...)
> > +-Check that grub-gettext_lib.in is correct
> > Index: include/grub/misc.h
> > ===================================================================
> > --- include/grub/misc.h	(revision 1952)
> > +++ include/grub/misc.h	(working copy)
> > @@ -31,6 +31,8 @@
> >  /* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
> >  #define grub_memcpy(d,s,n)	grub_memmove ((d), (s), (n))
> >  
> > +#define _(s)	grub_gettext(s)
> > +
> >  void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
> >  char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
> >  char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
> > @@ -84,6 +86,9 @@
> >  grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
> >  					  grub_uint32_t d, grub_uint32_t *r);
> >  
> > +char *EXPORT_FUNC(grub_gettext_dummy) (const char *s);
> > +extern 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
> > Index: gettext/gettext.c
> > ===================================================================
> > --- gettext/gettext.c	(revision 0)
> > +++ gettext/gettext.c	(revision 0)
> > @@ -0,0 +1,299 @@
> > +/* 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 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
> > +
> > +static int
> > +grub_gettext_get_info (int offset)
> > +{
> > +  int buf;
> > +
> > +  grub_file_seek (fd_mo, offset);
> > +  grub_file_read (fd_mo, (char*) &buf, 4);
> > +  return buf;
> > +}
> > +
> > +static void
> > +grub_gettext_getstring_from_offset (int offset, int length, char *translation)
> > +{
> > +  grub_file_seek (fd_mo,offset);
> > +  grub_file_read (fd_mo,translation,length);
> > +  translation[length] = '\0';
> > +}
> > +
> > +static char*
> > +grub_gettext_gettranslation_number (int i)
> > +{
> > +  int offsettranslation;
> > +  int position;
> > +  int length, offset;
> > +  char *translation;
> > +
> > +  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
> > +
> > +  position=offsettranslation+i*8;
> > +
> > +  grub_file_seek (fd_mo, position);
> > +  grub_file_read (fd_mo, (char*) &length, 4);
> > +  
> > +  grub_file_seek (fd_mo, position + 4),
> > +  grub_file_read (fd_mo, (char*) &offset, 4);
> > +
> > +  translation = grub_malloc(length + 1);
> > +  grub_gettext_getstring_from_offset (offset, length, translation);
> > +
> > +  return translation;
> > +}
> > +
> > +static char*
> > +grub_gettext_getstring_num (int num)
> > +{
> > +  int position;
> > +  int length, offset;
> > +  char *original;
> > +
> > +  /* Get position for string i.  */
> > +  position = grub_gettext_offsetoriginal + (num * 8);
> > +
> > +  /* Get the length of the string i.  */
> > +  grub_file_seek (fd_mo, position);
> > +  grub_file_read (fd_mo, (char *) &length, 4);
> > +
> > +  /* Get the offset of the string i.  */
> > +  grub_file_seek (fd_mo, 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 char*
> > +grub_gettext_translate (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_num (current);
> > +      /* grub_printf("Current: %s\n",current_string);  */
> > +
> > +      /* Search by bissection.  */
> > +      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_number (current);
> > +        }
> > +    current = (max+min)/2;
> > +    }
> > +
> > +  ret = grub_malloc(grub_strlen(orig) + 1);
> > +  grub_strcpy(ret,orig);
> > +  return ret;
> > +}
> > +
> > +// XXX: Return a real grub_err_t or static void
> > +static grub_err_t
> > +grub_cmd_translate (struct grub_arg_list *state __attribute__ ((unused)),
> > +		int argc __attribute__ ((unused)),
> > +		char **args __attribute__ ((unused)))
> > +{
> > +  if (argc != 1)
> > +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
> > +
> > +  char *translation;
> > +
> > +  translation = grub_gettext_translate(args[0]);
> > +  grub_printf("%s\n",translation);
> > +  //grub_printf("grub__: %d\n",grub__);
> > +
> > +  return 0;
> > +}
> > +
> > +/* 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 != 0x950412de)
> > +    {
> > +      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_prefix;
> > +
> > +  locale_prefix = grub_env_get ("locale_prefix");
> > +  
> > +  fd_mo = 0;
> > +      
> > +  // mo_file e.g.: /usr/share/locale/ca/LC_MESSAGES/grub.mo
> > +
> > +  mo_file = grub_malloc (grub_strlen (locale_prefix) + sizeof ("/") + grub_strlen (lang) + sizeof ("/LC_MESSAGES/grub.mo"));
> > +      
> > +  if (! mo_file)
> > +    return;
> > +
> > +  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
> > +  /* XXX: lang is written by the user, need to sanitaze the input?  */
> > +
> > +  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;
> > +}
> > Index: normal/menu.c
> > ===================================================================
> > --- normal/menu.c	(revision 1952)
> > +++ normal/menu.c	(working copy)
> > @@ -87,17 +87,16 @@
> >      }
> >    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 ("\
> > +      grub_printf (_("\
> >        Press enter to boot the selected OS, \'e\' to edit the\n\
> > -      commands before booting or \'c\' for a command-line.");
> > +      commands before booting or \'c\' for a command-line."));
> >        if (nested)
> >  	grub_printf ("\n\
> >        ESC to return previous menu.");
> >      }
> > -  
> >  }
> >  
> >  static grub_menu_entry_t
> > @@ -317,7 +316,7 @@
> >       They are required to clear the line.  */
> >    char *msg = "   The highlighted entry will be booted automatically in %ds.    ";
> >    char *msg_end = grub_strchr (msg, '%');
> > -  
> > +
> >    grub_gotoxy (second_stage ? (msg_end - msg) : 0, GRUB_TERM_HEIGHT - 3);
> >    grub_printf (second_stage ? msg_end : msg, timeout);
> >    grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
> > Index: util/grub.d/10_linux.in
> > ===================================================================
> > --- util/grub.d/10_linux.in	(revision 1952)
> > +++ util/grub.d/10_linux.in	(working copy)
> > @@ -20,6 +20,7 @@
> >  exec_prefix=@exec_prefix@
> >  libdir=@libdir@
> >  . ${libdir}/grub/grub-mkconfig_lib
> > +. ${libdir}/grub/grub-gettext_lib
> >  
> >  if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
> >    OS=GNU/Linux
> > @@ -139,7 +140,7 @@
> >  EOF
> >  
> >    cat << EOF
> > -menuentry "${OS}, linux ${version} (single-user mode)" {
> > +menuentry "$(eval_gettext '${OS}, linux ${version} (single-user mode)')" {
> >  EOF
> >    prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
> >    cat << EOF
> > Index: util/grub.d/00_header.in
> > ===================================================================
> > --- util/grub.d/00_header.in	(revision 1952)
> > +++ util/grub.d/00_header.in	(working copy)
> > @@ -22,6 +22,7 @@
> >  exec_prefix=@exec_prefix@
> >  libdir=@libdir@
> >  grub_prefix=`echo /boot/grub | sed ${transform}`
> > +locale_prefix="/usr/share/locale" # TODO: dynamic with exec_prefix ?
> >  
> >  . ${libdir}/grub/grub-mkconfig_lib
> >  
> > @@ -112,3 +113,17 @@
> >  EOF
> >    ;;
> >  esac
> > +
> > +if test -e ${grub_prefix}/gettext.mod ; then
> > +  # Make the locales accesible
> > +  prepare_grub_to_access_device `${grub_probe} --target=device ${locale_prefix}`
> > +  lang=`get_locale_lang`
> > +  cat << EOF
> > +if `make_system_path_relative_to_its_root ${locale_prefix}` ; then
> > +  set locale_prefix=${locale_prefix}
> > +  set lang=${lang}
> > +  insmod gettext 
> > +EOF
> > +else
> > +  echo "gettext module is not available"
> > +fi
> > Index: util/grub-mkconfig_lib.in
> > ===================================================================
> > --- util/grub-mkconfig_lib.in	(revision 1952)
> > +++ util/grub-mkconfig_lib.in	(working copy)
> > @@ -176,3 +176,14 @@
> >    fi
> >    return 0
> >  }
> > +
> > +get_locale_lang ()
> > +{
> > +  lang="`echo ${LANG} | cut -d _ -f 1`"
> > +  if [ "x${lang}" = "x" ] ; then
> > +    return 1
> > +  else
> > +    echo "${lang}"
> > +    return 0
> > +  fi
> > +}
> > Index: util/grub-gettext_lib.in
> > ===================================================================
> > --- util/grub-gettext_lib.in	(revision 0)
> > +++ util/grub-gettext_lib.in	(revision 0)
> > @@ -0,0 +1,23 @@
> > +# Configuration of grub-gettext
> > +# 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/>.
> > +
> > +prefix=@prefix@
> > +exec_prefix=@exec_prefix@
> > +libdir=@libdir@
> > +
> > +TEXTDOMAINDIR=@prefix@/share/locale
> > +TEXTDOMAIN=grub
> > +. gettext.sh
> > 
> > Property changes on: util/grub-gettext_lib.in
> > ___________________________________________________________________
> > Added: svn:mergeinfo
> > 
> 
> > _______________________________________________
> > Grub-devel mailing list
> > Grub-devel@gnu.org
> > http://lists.gnu.org/mailman/listinfo/grub-devel
> 
> -- 
> Carles Pina i Estany		GPG id: 0x17756391
> 	http://pinux.info

> Index: Makefile.in
> ===================================================================
> --- Makefile.in	(revision 1954)
> +++ Makefile.in	(working copy)
> @@ -112,6 +112,7 @@
>  PKGDATA = $(pkgdata_DATA) $(pkgdata_SRCDIR)
>  PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES)
>  SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS) $(grub-mkconfig_SCRIPTS)
> +GRUBD = $(srcdir)/util/grub.d
>  
>  CLEANFILES =
>  MOSTLYCLEANFILES = 
> @@ -170,6 +171,11 @@
>  endif
>  endif
>  
> +uptrans:
> +	xgettext -k_ -LC -o - `find "$(srcdir)/" -name '*.c'` -o po/grub.pot
> +	xgettext -k_ -Lshell -o - $(GRUBD)/* -j -o po/grub.pot
> +
> +
>  # Used for building modules externally
>  pkglib_BUILDDIR += build_env.mk
>  build_env.mk: Makefile
> Index: conf/common.rmk
> ===================================================================
> --- conf/common.rmk	(revision 1954)
> +++ conf/common.rmk	(working copy)
> @@ -142,6 +142,12 @@
>  lib_DATA += 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 $@
> @@ -329,7 +335,7 @@
>  	cmp.mod cat.mod help.mod search.mod					\
>  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
>  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> -	read.mod sleep.mod loadenv.mod crc.mod
> +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
>  
>  # For hello.mod.
>  hello_mod_SOURCES = hello/hello.c
> @@ -492,3 +498,10 @@
>  bufio_mod_SOURCES = io/bufio.c
>  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)
> +
> +
> Index: conf/common.mk
> ===================================================================
> --- conf/common.mk	(revision 1954)
> +++ conf/common.mk	(working copy)
> @@ -567,6 +567,12 @@
>  lib_DATA += 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 $@
> @@ -2366,7 +2372,7 @@
>  	cmp.mod cat.mod help.mod search.mod					\
>  	loopback.mod fs_uuid.mod configfile.mod echo.mod	\
>  	terminfo.mod test.mod blocklist.mod hexdump.mod		\
> -	read.mod sleep.mod loadenv.mod crc.mod
> +	read.mod sleep.mod loadenv.mod crc.mod gettext.mod
>  
>  # For hello.mod.
>  hello_mod_SOURCES = hello/hello.c
> @@ -4236,3 +4242,62 @@
>  
>  bufio_mod_CFLAGS = $(COMMON_CFLAGS)
>  bufio_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For gettext.mod.
> +gettext_mod_SOURCES = gettext/gettext.c
> +CLEANFILES += gettext.mod mod-gettext.o mod-gettext.c pre-gettext.o gettext_mod-gettext_gettext.o und-gettext.lst
> +ifneq ($(gettext_mod_EXPORTS),no)
> +CLEANFILES += def-gettext.lst
> +DEFSYMFILES += def-gettext.lst
> +endif
> +MOSTLYCLEANFILES += gettext_mod-gettext_gettext.d
> +UNDSYMFILES += und-gettext.lst
> +
> +gettext.mod: pre-gettext.o mod-gettext.o $(TARGET_OBJ2ELF)
> +	-rm -f $@
> +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) $(MODULE_LDFLAGS) -Wl,-r,-d -o $@ pre-gettext.o mod-gettext.o
> +	if test ! -z $(TARGET_OBJ2ELF); then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
> +	$(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $@
> +
> +pre-gettext.o: $(gettext_mod_DEPENDENCIES) gettext_mod-gettext_gettext.o
> +	-rm -f $@
> +	$(TARGET_CC) $(gettext_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ gettext_mod-gettext_gettext.o
> +
> +mod-gettext.o: mod-gettext.c
> +	$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -c -o $@ $<
> +
> +mod-gettext.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
> +	sh $(srcdir)/genmodsrc.sh 'gettext' $< > $@ || (rm -f $@; exit 1)
> +
> +ifneq ($(gettext_mod_EXPORTS),no)
> +def-gettext.lst: pre-gettext.o
> +	$(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 gettext/' > $@
> +endif
> +
> +und-gettext.lst: pre-gettext.o
> +	echo 'gettext' > $@
> +	$(NM) -u -P -p $< | cut -f1 -d' ' >> $@
> +
> +gettext_mod-gettext_gettext.o: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES)
> +	$(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -MD -c -o $@ $<
> +-include gettext_mod-gettext_gettext.d
> +
> +CLEANFILES += cmd-gettext_mod-gettext_gettext.lst fs-gettext_mod-gettext_gettext.lst partmap-gettext_mod-gettext_gettext.lst
> +COMMANDFILES += cmd-gettext_mod-gettext_gettext.lst
> +FSFILES += fs-gettext_mod-gettext_gettext.lst
> +PARTMAPFILES += partmap-gettext_mod-gettext_gettext.lst
> +
> +cmd-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) gencmdlist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/gencmdlist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +fs-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genfslist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genfslist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +partmap-gettext_mod-gettext_gettext.lst: gettext/gettext.c $(gettext/gettext.c_DEPENDENCIES) genpartmaplist.sh
> +	set -e; 	  $(TARGET_CC) -Igettext -I$(srcdir)/gettext $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(gettext_mod_CFLAGS) -E $< 	  | sh $(srcdir)/genpartmaplist.sh gettext > $@ || (rm -f $@; exit 1)
> +
> +
> +gettext_mod_CFLAGS = $(COMMON_CFLAGS)
> +gettext_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +
> Index: kern/misc.c
> ===================================================================
> --- kern/misc.c	(revision 1954)
> +++ kern/misc.c	(working copy)
> @@ -24,6 +24,8 @@
>  #include <grub/term.h>
>  #include <grub/env.h>
>  
> +const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
> +
>  void *
>  grub_memmove (void *dest, const void *src, grub_size_t n)
>  {
> @@ -1044,6 +1046,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)
> Index: po/ca.po
> ===================================================================
> --- po/ca.po	(revision 0)
> +++ po/ca.po	(revision 0)
> @@ -0,0 +1,39 @@
> +# SOME DESCRIPTIVE TITLE.
> +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
> +# This file is distributed under the same license as the PACKAGE package.
> +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
> +#
> +#, fuzzy
> +msgid ""
> +msgstr ""
> +"Project-Id-Version: PACKAGE VERSION\n"
> +"Report-Msgid-Bugs-To: \n"
> +"POT-Creation-Date: 2009-01-21 21:14+0100\n"
> +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
> +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
> +"Language-Team: LANGUAGE <LL@li.org>\n"
> +"MIME-Version: 1.0\n"
> +"Content-Type: text/plain; charset=CHARSET\n"
> +"Content-Transfer-Encoding: 8bit\n"
> +
> +#: normal/menu.c:90
> +#, 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 seleccionar l'entrada.\n"
> +
> +#: normal/menu.c:93
> +msgid ""
> +"      Press enter to boot the selected OS, 'e' to edit the\n"
> +"      commands before booting or 'c' for a command-line."
> +msgstr ""
> +"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"
> +"      les comandes abans d'arrancar, 'c' per línia d'ordres."
> +
> +#: util/grub.d/10_linux.in:148
> +#, sh-format
> +msgid "${OS}, linux ${version} (single-user mode)"
> +msgstr "${OS}, linux ${version} (mode mono-usuari)"
> Index: po/TODO
> ===================================================================
> --- po/TODO	(revision 0)
> +++ po/TODO	(revision 0)
> @@ -0,0 +1,5 @@
> +Prepare a Makefile.in to:
> +
> +-Compile all .po to .mo (msgfmt $LANG.po -o $LANG.mo)
> +-Copy to /usr/share/locale/$LANG/LC_MESSAGES/grub.mo (or /usr/local/share/locale/$LANG/LC_MESSAGES/..., so $prefix...)
> +-Check that grub-gettext_lib.in is correct
> Index: include/grub/misc.h
> ===================================================================
> --- include/grub/misc.h	(revision 1954)
> +++ include/grub/misc.h	(working copy)
> @@ -31,6 +31,8 @@
>  /* XXX: If grub_memmove is too slow, we must implement grub_memcpy.  */
>  #define grub_memcpy(d,s,n)	grub_memmove ((d), (s), (n))
>  
> +#define _(s)	grub_gettext(s)
> +
>  void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
>  char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
>  char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
> @@ -84,6 +86,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
> Index: gettext/gettext.c
> ===================================================================
> --- gettext/gettext.c	(revision 0)
> +++ gettext/gettext.c	(revision 0)
> @@ -0,0 +1,300 @@
> +/* 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
> +
> +static int
> +grub_gettext_get_info (int offset)
> +{
> +  int buf;
> +
> +  grub_file_seek (fd_mo, offset);
> +  grub_file_read (fd_mo, (char*) &buf, 4);
> +  return buf;
> +}
> +
> +static void
> +grub_gettext_getstring_from_offset (int offset, int length, char *translation)
> +{
> +  grub_file_seek (fd_mo,offset);
> +  grub_file_read (fd_mo,translation,length);
> +  translation[length] = '\0';
> +}
> +
> +static char*
> +grub_gettext_gettranslation_number (int i)
> +{
> +  int offsettranslation;
> +  int position;
> +  int length, offset;
> +  char *translation;
> +
> +  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
> +
> +  position=offsettranslation+i*8;
> +
> +  grub_file_seek (fd_mo, position);
> +  grub_file_read (fd_mo, (char*) &length, 4);
> +  
> +  grub_file_seek (fd_mo, position + 4),
> +  grub_file_read (fd_mo, (char*) &offset, 4);
> +
> +  translation = grub_malloc(length + 1);
> +  grub_gettext_getstring_from_offset (offset, length, translation);
> +
> +  return translation;
> +}
> +
> +static char*
> +grub_gettext_getstring_num (int num)
> +{
> +  int position;
> +  int length, offset;
> +  char *original;
> +
> +  /* Get position for string i.  */
> +  position = grub_gettext_offsetoriginal + (num * 8);
> +
> +  /* Get the length of the string i.  */
> +  grub_file_seek (fd_mo, position);
> +  grub_file_read (fd_mo, (char *) &length, 4);
> +
> +  /* Get the offset of the string i.  */
> +  grub_file_seek (fd_mo, 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_num (current);
> +      /* grub_printf("Current: %s\n",current_string);  */
> +
> +      /* Search by bissection.  */
> +      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_number (current);
> +        }
> +    current = (max+min)/2;
> +    }
> +
> +  ret = grub_malloc(grub_strlen(orig) + 1);
> +  grub_strcpy(ret,orig);
> +  return ret;
> +}
> +
> +// XXX: Return a real grub_err_t or static void
> +/*static grub_err_t
> +grub_cmd_translate (struct grub_arg_list *state __attribute__ ((unused)),
> +		int argc __attribute__ ((unused)),
> +		char **args __attribute__ ((unused)))
> +{
> +  if (argc != 1)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
> +
> +  char *translation;
> +
> +  translation = grub_gettext_translate(args[0]);
> +  grub_printf("%s\n",translation);
> +  //grub_printf("grub__: %d\n",grub__);
> +
> +  return 0;
> +}
> +*/
> +
> +/* 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 != 0x950412de)
> +    {
> +      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_prefix;
> +
> +  locale_prefix = grub_env_get ("locale_prefix");
> +  
> +  fd_mo = 0;
> +      
> +  // mo_file e.g.: /usr/share/locale/ca/LC_MESSAGES/grub.mo
> +
> +  mo_file = grub_malloc (grub_strlen (locale_prefix) + sizeof ("/") + grub_strlen (lang) + sizeof ("/LC_MESSAGES/grub.mo"));
> +      
> +  if (! mo_file)
> +    return;
> +
> +  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
> +  /* XXX: lang is written by the user, need to sanitaze the input?  */
> +
> +  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;
> +}
> Index: normal/menu.c
> ===================================================================
> --- normal/menu.c	(revision 1954)
> +++ normal/menu.c	(working copy)
> @@ -87,12 +87,12 @@
>      }
>    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 ("\
> +      grub_printf (_("\
>        Press enter to boot the selected OS, \'e\' to edit the\n\
> -      commands before booting or \'c\' for a command-line.");
> +      commands before booting or \'c\' for a command-line."));
>        if (nested)
>  	grub_printf ("\n\
>        ESC to return previous menu.");
> Index: util/grub.d/10_linux.in
> ===================================================================
> --- util/grub.d/10_linux.in	(revision 1954)
> +++ util/grub.d/10_linux.in	(working copy)
> @@ -20,6 +20,7 @@
>  exec_prefix=@exec_prefix@
>  libdir=@libdir@
>  . ${libdir}/grub/grub-mkconfig_lib
> +. ${libdir}/grub/grub-gettext_lib
>  
>  if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
>    OS=GNU/Linux
> @@ -139,7 +140,7 @@
>  EOF
>  
>    cat << EOF
> -menuentry "${OS}, linux ${version} (single-user mode)" {
> +menuentry "$(eval_gettext '${OS}, linux ${version} (single-user mode)')" {
>  EOF
>    prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
>    cat << EOF
> Index: util/grub.d/00_header.in
> ===================================================================
> --- util/grub.d/00_header.in	(revision 1954)
> +++ util/grub.d/00_header.in	(working copy)
> @@ -22,6 +22,7 @@
>  exec_prefix=@exec_prefix@
>  libdir=@libdir@
>  grub_prefix=`echo /boot/grub | sed ${transform}`
> +locale_prefix="/usr/share/locale" # TODO: dynamic with exec_prefix ?
>  
>  . ${libdir}/grub/grub-mkconfig_lib
>  
> @@ -112,3 +113,18 @@
>  EOF
>    ;;
>  esac
> +
> +if test -e ${grub_prefix}/gettext.mod ; then
> +  # Make the locales accesible
> +  prepare_grub_to_access_device `${grub_probe} --target=device ${locale_prefix}`
> +  lang=`get_locale_lang`
> +  cat << EOF
> +if `make_system_path_relative_to_its_root ${locale_prefix}` ; then
> +  set locale_prefix=${locale_prefix}
> +  set lang=${lang}
> +  insmod gettext 
> +fi
> +EOF
> +else
> +  echo "gettext module is not available"
> +fi
> Index: util/grub-mkconfig_lib.in
> ===================================================================
> --- util/grub-mkconfig_lib.in	(revision 1954)
> +++ util/grub-mkconfig_lib.in	(working copy)
> @@ -176,3 +176,14 @@
>    fi
>    return 0
>  }
> +
> +get_locale_lang ()
> +{
> +  lang="`echo ${LANG} | cut -d _ -f 1`"
> +  if [ "x${lang}" = "x" ] ; then
> +    return 1
> +  else
> +    echo "${lang}"
> +    return 0
> +  fi
> +}
> Index: util/grub-gettext_lib.in
> ===================================================================
> --- util/grub-gettext_lib.in	(revision 0)
> +++ util/grub-gettext_lib.in	(revision 0)
> @@ -0,0 +1,23 @@
> +# Configuration of grub-gettext
> +# 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/>.
> +
> +prefix=@prefix@
> +exec_prefix=@exec_prefix@
> +libdir=@libdir@
> +
> +TEXTDOMAINDIR=@prefix@/share/locale
> +TEXTDOMAIN=grub
> +. gettext.sh
> 
> Property changes on: util/grub-gettext_lib.in
> ___________________________________________________________________
> Added: svn:mergeinfo
> 

> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel

-- 
Carles Pina i Estany		GPG id: 0x17756391
	http://pinux.info



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

* unicode font slowness (Re: gettext patch (beta))
  2009-01-21 22:08     ` Vesa Jääskeläinen
  2009-01-21 22:21       ` Carles Pina i Estany
@ 2009-02-07 21:26       ` Robert Millan
  2009-02-08  8:47         ` Colin D Bennett
  1 sibling, 1 reply; 21+ messages in thread
From: Robert Millan @ 2009-02-07 21:26 UTC (permalink / raw)
  To: The development of GRUB 2

On Thu, Jan 22, 2009 at 12:08:28AM +0200, Vesa Jääskeläinen wrote:
> 
> Are you using gfxterm ? If yes, then your font is missing í. Try to load
> unifont.bf2 or unicode.bf2. I think debian defaults to ascii.bf2 which
> may not include that glyph.

Actually, it's us who default to ascii:

2008-07-23  Robert Millan  <rmh@aybabtu.com>

	[...]

        * util/update-grub_lib.in (font_path): Prefer ascii.pff over complete
        fonts, because the latter are too slow.

before this change, using the complete fonts was incredibly slow in things
like QEMU or VirtualBox.

Perhaps there's some way in which this can be optimized, so we can go back to
using the complete set by default?

Or maybe we should provide a font file for each language (without duplicates,
of course).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: gettext patch (beta)
  2009-01-24 10:59         ` Niels Böhm
@ 2009-02-07 21:30           ` Robert Millan
  0 siblings, 0 replies; 21+ messages in thread
From: Robert Millan @ 2009-02-07 21:30 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: Carles Pina i Estany

On Sat, Jan 24, 2009 at 11:59:43AM +0100, Niels Böhm wrote:
> On Wednesday 21 January 2009, Carles Pina i Estany wrote:
> >
> > But looks strange: I write "línia", if í is missing should appear
> > "l?nia", not "l?ia". Maybe expecting some UTF8 (multi-byte) special
> > character?
> 
> Looks to me like in this case the function expects UTF-8-encoded strings, but 
> the translated string including "línia" is not UTF-8 (but something like 
> ISO8859-1 instead).
> 
> So probably the message catalog has the wrong encoding.

Definitely:

+"Content-Type: text/plain; charset=CHARSET\n"

it should say "utf-8" instead of "CHARSET"

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: unicode font slowness (Re: gettext patch (beta))
  2009-02-07 21:26       ` unicode font slowness (Re: gettext patch (beta)) Robert Millan
@ 2009-02-08  8:47         ` Colin D Bennett
  0 siblings, 0 replies; 21+ messages in thread
From: Colin D Bennett @ 2009-02-08  8:47 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: rmh

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

On Sat, 7 Feb 2009 22:26:36 +0100
Robert Millan <rmh@aybabtu.com> wrote:

> On Thu, Jan 22, 2009 at 12:08:28AM +0200, Vesa Jääskeläinen wrote:
> > 
> > Are you using gfxterm ? If yes, then your font is missing í. Try to load
> > unifont.bf2 or unicode.bf2. I think debian defaults to ascii.bf2 which
> > may not include that glyph.
> 
> Actually, it's us who default to ascii:
> 
> 2008-07-23  Robert Millan  <rmh@aybabtu.com>
> 
> 	[...]
> 
>         * util/update-grub_lib.in (font_path): Prefer ascii.pff over complete
>         fonts, because the latter are too slow.
> 
> before this change, using the complete fonts was incredibly slow in things
> like QEMU or VirtualBox.
> 
> Perhaps there's some way in which this can be optimized, so we can go back to
> using the complete set by default?

I'm optimizing the font rendering now for fonts with many characters.
It was using a linear search (gasp!!) for finding the glyph each time
it is requested.  I just never got around to using the proper data
structure, but I will have this done soon.

I made a text rendering benchmark and added it to 'videotest bench' so
I can objectively measure the improvement achieved.  The improvement
could be significant.  I'll report more later.

Regards,
Colin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: gettext patch (beta)
  2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
  2009-01-24 15:09   ` Carles Pina i Estany
@ 2009-02-09 14:39   ` Robert Millan
  2009-02-10  1:58     ` BandiPat
  2009-04-10 22:47   ` gettext patch (beta) phcoder
  2 siblings, 1 reply; 21+ messages in thread
From: Robert Millan @ 2009-02-09 14:39 UTC (permalink / raw)
  To: The development of GRUB 2


Hi Carles

On Sat, Jan 24, 2009 at 03:26:04PM +0100, Carles Pina i Estany wrote:
> Index: Makefile.in
> ===================================================================
> --- Makefile.in	(revision 1954)
> +++ Makefile.in	(working copy)
> @@ -112,6 +112,7 @@
>  PKGDATA = $(pkgdata_DATA) $(pkgdata_SRCDIR)
>  PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES)
>  SCRIPTS = $(bin_SCRIPTS) $(sbin_SCRIPTS) $(grub-mkconfig_SCRIPTS)
> +GRUBD = $(srcdir)/util/grub.d

If you're adding GRUBD, perhaps you can use it in other places that currently
hardcode "util/grub.d".

> +"Content-Type: text/plain; charset=CHARSET\n"

That should be charset=utf-8

> +"      Presioneu retorn per arrancar el SO seleccionat, 'e' editar\n"

"l'SO" ;-)

> +"      les comandes abans d'arrancar, 'c' per línia d'ordres."

The 'í' should be in utf-8 (it displays in utf-8 here because
your mailer set Content-Type to iso-8859-1).

> +#: util/grub.d/10_linux.in:148
> +#, sh-format
> +msgid "${OS}, linux ${version} (single-user mode)"
> +msgstr "${OS}, linux ${version} (mode mono-usuari)"

I wonder if we should replace the original string "single-user mode" with
something else.  Novice users find it confusing, since they may assume
"single-user mode" is the normal mode for them (a single user) to use
the computer.

> +          grub_free(current_string);
> +          min=current;
> [...]
> +    current = (max+min)/2;

Remember to add spaces in such places.

> +  if (magic != 0x950412de)

This should be a macro.  Also, it probably needs endian conversion (use the
macros in types.h).

> +  /* Testing:
> +  grub_register_command ("_", grub_cmd_translate, GRUB_COMMAND_FLAG_BOTH,
> +			 "_", "internalization support trans", 0);
> +  */

We could register the "gettext" command and leave it there by default.

> +else
> +  echo "gettext module is not available"
> +fi

This should have ">&2", or it might end up as part of grub.cfg.  Also it
could be more descriptive (like, letting user know text output will be in
English).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: gettext patch (beta)
  2009-02-09 14:39   ` Robert Millan
@ 2009-02-10  1:58     ` BandiPat
  2009-02-21 13:02       ` "single-user mode" string (Re: gettext patch (beta)) Robert Millan
  0 siblings, 1 reply; 21+ messages in thread
From: BandiPat @ 2009-02-10  1:58 UTC (permalink / raw)
  To: The development of GRUB 2

Robert Millan wrote:

>> +#: util/grub.d/10_linux.in:148
>> +#, sh-format
>> +msgid "${OS}, linux ${version} (single-user mode)"
>> +msgstr "${OS}, linux ${version} (mode mono-usuari)"
> 
> I wonder if we should replace the original string "single-user mode" with
> something else.  Novice users find it confusing, since they may assume
> "single-user mode" is the normal mode for them (a single user) to use
> the computer.
===========
Thanks for mentioning this Robert, as I could see it being somewhat 
confusing to new users of Grub2 without some research.  I've written a 
piece in the Zenwalk WIKI to explain the use and reason it's added in a 
basic grub.cfg.  It may indeed be a good idea though to change it to 
something more descriptive of what function it performs and that is to 
only boot to runlevel 1 of the system.  I think that's right, isn't it?

Regards,
Pat

-- 
        ---Zenwalk v6.0--Linux 2.6.28---
         Registered Linux User #225206
"Ever tried Zen computing?"  http://www.zenwalk.org





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

* "single-user mode" string (Re: gettext patch (beta))
  2009-02-10  1:58     ` BandiPat
@ 2009-02-21 13:02       ` Robert Millan
  2009-02-21 16:07         ` BandiPat
  0 siblings, 1 reply; 21+ messages in thread
From: Robert Millan @ 2009-02-21 13:02 UTC (permalink / raw)
  To: The development of GRUB 2

On Mon, Feb 09, 2009 at 08:58:10PM -0500, BandiPat wrote:
> Robert Millan wrote:
>
>>> +#: util/grub.d/10_linux.in:148
>>> +#, sh-format
>>> +msgid "${OS}, linux ${version} (single-user mode)"
>>> +msgstr "${OS}, linux ${version} (mode mono-usuari)"
>>
>> I wonder if we should replace the original string "single-user mode" with
>> something else.  Novice users find it confusing, since they may assume
>> "single-user mode" is the normal mode for them (a single user) to use
>> the computer.
> ===========
> Thanks for mentioning this Robert, as I could see it being somewhat  
> confusing to new users of Grub2 without some research.  I've written a  
> piece in the Zenwalk WIKI to explain the use and reason it's added in a  
> basic grub.cfg.  It may indeed be a good idea though to change it to  
> something more descriptive of what function it performs and that is to  
> only boot to runlevel 1 of the system.  I think that's right, isn't it?

I'd keep it a bit less technical.  Something like "rescue mode" or
"recovery mode".

Suggestions?

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: "single-user mode" string (Re: gettext patch (beta))
  2009-02-21 13:02       ` "single-user mode" string (Re: gettext patch (beta)) Robert Millan
@ 2009-02-21 16:07         ` BandiPat
  2009-02-21 19:49           ` Robert Millan
  0 siblings, 1 reply; 21+ messages in thread
From: BandiPat @ 2009-02-21 16:07 UTC (permalink / raw)
  To: The development of GRUB 2

Robert Millan wrote:

> I'd keep it a bit less technical.  Something like "rescue mode" or
> "recovery mode".
> 
> Suggestions?
> 
------------------

I think either of those may work better.  Either better describes the 
level the machine boots to, yet will be less confusing to the user as to 
why it's in the list.

--
Pat



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

* Re: "single-user mode" string (Re: gettext patch (beta))
  2009-02-21 16:07         ` BandiPat
@ 2009-02-21 19:49           ` Robert Millan
       [not found]             ` <20090221201015.GA4618@piper.oerlikon.madduck.net>
  2009-02-22  0:40             ` BandiPat
  0 siblings, 2 replies; 21+ messages in thread
From: Robert Millan @ 2009-02-21 19:49 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: martin f krafft

On Sat, Feb 21, 2009 at 11:07:22AM -0500, BandiPat wrote:
> Robert Millan wrote:
>
>> I'd keep it a bit less technical.  Something like "rescue mode" or
>> "recovery mode".
>>
>> Suggestions?
>>
> ------------------
>
> I think either of those may work better.  Either better describes the  
> level the machine boots to, yet will be less confusing to the user as to  
> why it's in the list.

Uhm the current "single-user mode" string is inspired by the one in debian's
original update-grub script, which used to be "recovery mode" but was changed
in 2006:

  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=370110

I guess it'd be polite to ask Martin about it before switching to
"recovery mode" or "rescue mode".

Martin, our problem is that "single-user mode" is very confusing for those
not experienced with Un*x.  They tend to think this is the normal mode of
operation since they are (usually) a "single user".

Any comments?

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: "single-user mode" string (Re: gettext patch (beta))
       [not found]             ` <20090221201015.GA4618@piper.oerlikon.madduck.net>
@ 2009-02-21 21:08               ` Robert Millan
  0 siblings, 0 replies; 21+ messages in thread
From: Robert Millan @ 2009-02-21 21:08 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Feb 21, 2009 at 09:10:15PM +0100, martin f krafft wrote:
> also sprach Robert Millan <rmh@aybabtu.com> [2009.02.21.2049 +0100]:
> > Martin, our problem is that "single-user mode" is very confusing for those
> > not experienced with Un*x.  They tend to think this is the normal mode of
> > operation since they are (usually) a "single user".
> > 
> > Any comments?
> 
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=370110
> 
> It was purely aesthetic for me. I would not oppose a change back for
> the purpose of increasing clarity for others. I suppose
> a configuration option might be possible, but even that could be
> considered overkill by the person who has to implement it, and
> I wouldn't blame him/her. :)
> 
> Thanks for asking. No opposition from me.

Okay thanks for the quick reply.  If nobody has a better idea, I'll just set
it to "recovery mode".

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: "single-user mode" string (Re: gettext patch (beta))
  2009-02-21 19:49           ` Robert Millan
       [not found]             ` <20090221201015.GA4618@piper.oerlikon.madduck.net>
@ 2009-02-22  0:40             ` BandiPat
  2009-02-27 21:37               ` Robert Millan
  1 sibling, 1 reply; 21+ messages in thread
From: BandiPat @ 2009-02-22  0:40 UTC (permalink / raw)
  To: The development of GRUB 2

Robert Millan wrote:
> On Sat, Feb 21, 2009 at 11:07:22AM -0500, BandiPat wrote:
>> Robert Millan wrote:
>>
>>> I'd keep it a bit less technical.  Something like "rescue mode" or
>>> "recovery mode".
>>>
>>> Suggestions?
>>>
>> ------------------
>>
>> I think either of those may work better.  Either better describes the  
>> level the machine boots to, yet will be less confusing to the user as to  
>> why it's in the list.
> 
> Uhm the current "single-user mode" string is inspired by the one in debian's
> original update-grub script, which used to be "recovery mode" but was changed
> in 2006:
> 
>   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=370110
> 
> I guess it'd be polite to ask Martin about it before switching to
> "recovery mode" or "rescue mode".
> 
> Martin, our problem is that "single-user mode" is very confusing for those
> not experienced with Un*x.  They tend to think this is the normal mode of
> operation since they are (usually) a "single user".
> 
> Any comments?
> 
===========
Why not then make it a combination of both?  Maybe 
recovery--single-user-mode or single-user-mode/rescue?  Just some little 
something to help clarify it to a new user or user that didn't play with 
Unix.  :-)

It wouldn't extend the selection in either the loader list or the 
grub.cfg that much.

--
Pat



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

* Re: "single-user mode" string (Re: gettext patch (beta))
  2009-02-22  0:40             ` BandiPat
@ 2009-02-27 21:37               ` Robert Millan
  0 siblings, 0 replies; 21+ messages in thread
From: Robert Millan @ 2009-02-27 21:37 UTC (permalink / raw)
  To: The development of GRUB 2

On Sat, Feb 21, 2009 at 07:40:35PM -0500, BandiPat wrote:
>>
>> Martin, our problem is that "single-user mode" is very confusing for those
>> not experienced with Un*x.  They tend to think this is the normal mode of
>> operation since they are (usually) a "single user".
>>
>> Any comments?

Martin said it he was ok with it (his reply didn't make it to the list).

I just changed it to "recovery mode".

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."



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

* Re: gettext patch (beta)
  2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
  2009-01-24 15:09   ` Carles Pina i Estany
  2009-02-09 14:39   ` Robert Millan
@ 2009-04-10 22:47   ` phcoder
  2009-04-14  8:54     ` Carles Pina i Estany
  2 siblings, 1 reply; 21+ messages in thread
From: phcoder @ 2009-04-10 22:47 UTC (permalink / raw)
  To: The development of GRUB 2; +Cc: carles

Hello, thanks for your work. It's a nice stuff, however it has some 
minor problems
Carles Pina i Estany wrote:
>> -Copy ca.mo to /usr/share/locale/ca/LC_MESSAGES/grub.mo
Languages files should go to a subdir of $PREFIX. E.g. to 
$PREFIX/langs/$LANG.mo
linux directories may be inaccessible
>> CALL FOR HELP:
>> I need to write the Makefile.in (see po/TODO :-( ). I'm not used or
>> familiar to write Makefiles :-( if someone wants to help it would 
>> speed up the process quite much. It needs only to merge the files with
>> the new .pot, compile (msgfmt), and install to the correct directory.
Use common.rmk, don't write directly to Makefile.
>>
>> I exactly know what has to do, so if someone knows about
>> installation/Makefiles and doesn't know about gettext it's not a
>> problem, contact me. Else I will try to implement soon.
I can help you, I'm not a makefile expert but can be useful
>>
>> I would even invite to a couple of beers in Fosdem if someone does
>> this part :-)
>>
>> TODO:
>> -the Makefile.in
>> -and more testing about 00_header with gettext detection.
>> -Add _("") for mainly all strings (I would do in a separate patch)
>> -I have seen that Grub2 is not printing correctly the accents,
>> could be a problem in gettext or in some other layer
Did you load unifont as your font? Are you in gfxterm mode? Plain pc 
console can't output unicode characters because it uses fixed-width 
8-bit font. Perhaps loading the characters most useful for current 
languages to the upper 128 characters would be an option. OR we can just 
tell everyone to use gfxterm
>> Index: conf/common.mk
>> ===================================================================
>> --- conf/common.mk	(revision 1952)
>> +++ conf/common.mk	(working copy)
Don't include auto-generated files in your patch
>> Index: gettext/gettext.c
>> ===================================================================
>> --- gettext/gettext.c	(revision 0)
>> +++ gettext/gettext.c	(revision 0)
>> +static int
>> +grub_gettext_get_info (int offset)
>> +{
>> +  int buf;
Use grub_uint32_t here. Also be aware of endianness. It should be
static grub_uint32_t
grub_gettext_get_info (int offset)
{
   grub_uint32_t buf;

   grub_file_seek (fd_mo, offset);
   grub_file_read (fd_mo, (char*) &buf, sizeof (buf));
   buf = grub_cpu_to_le32 (buf);
   return buf;
}
Same applies multiple times in different places.
grub_gettext_translation_number is a bit a misnomer because this name 
would suggest transforming translation into number
>> +  offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
>> +
>> +  position=offsettranslation+i*8;
Please respect GCS. This should be position = offsettranslation + i * 8;
>> +  ret = grub_malloc(grub_strlen(orig) + 1);
>> +  grub_strcpy(ret,orig);
>> +  return ret;
This would fail if the string isn't present at all in .mo
>> +  if (magic != 0x950412de)
A define instead of hardcoded number is suggested
>> +  locale_prefix = grub_env_get ("locale_prefix");
You need to treat the case when no locale_prefix is defined. I suggest 
to put a default $prefix/locale
>> +  grub_sprintf (mo_file, "%s/%s/LC_MESSAGES/grub.mo", locale_prefix, lang);
>> +  /* XXX: lang is written by the user, need to sanitaze the input?  */
I suggest
grub_sprintf (mo_file, "%s/%s.mo", locale_prefix, lang);
because .mo need to reside together with grub so all LC_MESSAGE is just 
unnecessary


-- 

Regards
Vladimir 'phcoder' Serbinenko



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

* Re: gettext patch (beta)
  2009-04-10 22:47   ` gettext patch (beta) phcoder
@ 2009-04-14  8:54     ` Carles Pina i Estany
  0 siblings, 0 replies; 21+ messages in thread
From: Carles Pina i Estany @ 2009-04-14  8:54 UTC (permalink / raw)
  To: phcoder; +Cc: The development of GRUB 2


Hello,

On Apr/11/2009, phcoder wrote:
> Hello, thanks for your work. It's a nice stuff, however it has some  
> minor problems

During last months I have been extremely busy :-( and I think that I
will be during some more weeks, that's the reason that I have not been
following up :-(

I will catch up it as soon as possible (merge with the current SVN and
do your changes).

Thanks for pointing some mistakes.

-- 
Carles Pina i Estany
	http://pinux.info



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

end of thread, other threads:[~2009-04-14  9:18 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-21 21:17 gettext patch (beta) Carles Pina i Estany
2009-01-21 21:38 ` Vesa Jääskeläinen
2009-01-21 21:48   ` Carles Pina i Estany
2009-01-21 22:08     ` Vesa Jääskeläinen
2009-01-21 22:21       ` Carles Pina i Estany
2009-01-24 10:59         ` Niels Böhm
2009-02-07 21:30           ` Robert Millan
2009-02-07 21:26       ` unicode font slowness (Re: gettext patch (beta)) Robert Millan
2009-02-08  8:47         ` Colin D Bennett
2009-01-24 14:26 ` gettext patch (beta) Carles Pina i Estany
2009-01-24 15:09   ` Carles Pina i Estany
2009-02-09 14:39   ` Robert Millan
2009-02-10  1:58     ` BandiPat
2009-02-21 13:02       ` "single-user mode" string (Re: gettext patch (beta)) Robert Millan
2009-02-21 16:07         ` BandiPat
2009-02-21 19:49           ` Robert Millan
     [not found]             ` <20090221201015.GA4618@piper.oerlikon.madduck.net>
2009-02-21 21:08               ` Robert Millan
2009-02-22  0:40             ` BandiPat
2009-02-27 21:37               ` Robert Millan
2009-04-10 22:47   ` gettext patch (beta) phcoder
2009-04-14  8:54     ` Carles Pina i Estany

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.