From: Carles Pina i Estany <carles@pina.cat>
To: grub-devel@gnu.org
Subject: Re: gettext patch (beta)
Date: Sat, 24 Jan 2009 16:09:33 +0100 [thread overview]
Message-ID: <20090124150933.GA28775@pina.cat> (raw)
In-Reply-To: <20090124142604.GB27695@pina.cat>
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
next prev parent reply other threads:[~2009-01-24 15:09 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090124150933.GA28775@pina.cat \
--to=carles@pina.cat \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.