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 #include +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 , 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 \n" +"Language-Team: LANGUAGE \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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + .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 @@ address@hidden@ address@hidden@ . ${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 @@ address@hidden@ address@hidden@ 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 . + address@hidden@ address@hidden@ address@hidden@ + address@hidden@/share/locale +TEXTDOMAIN=grub +. gettext.sh Property changes on: util/grub-gettext_lib.in ___________________________________________________________________ Added: svn:mergeinfo