## Description: add some description
## Origin/Author: add some origin or author
## Bug: bug URL
diff -Nur -x '*.orig' -x '*~' grub2-1.98/gettext/gettext.c grub2-1.98.new/gettext/gettext.c
--- grub2-1.98/gettext/gettext.c	2010-03-07 07:51:37.000000000 +1100
+++ grub2-1.98.new/gettext/gettext.c	2010-04-09 16:47:49.143231405 +1000
@@ -41,6 +41,7 @@
 static int grub_gettext_max;
 
 static const char *(*grub_gettext_original) (const char *s);
+static const char *(*grub_ngettext_original) (const char *s1, const char *s2, unsigned long n);
 
 struct grub_gettext_msg
 {
@@ -48,6 +49,7 @@
   const char *name;
 
   const char *translated;
+  grub_uint32_t length;
 };
 
 struct grub_gettext_msg *grub_gettext_msg_list = NULL;
@@ -91,25 +93,25 @@
 }
 
 static const char *
-grub_gettext_gettranslation_from_position (int position)
+grub_gettext_gettranslation_from_position (int position, grub_uint32_t *length)
 {
   int offsettranslation;
   int internal_position;
-  grub_uint32_t length, offset;
+  grub_uint32_t offset;
   char *translation;
 
   offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION);
 
   internal_position = offsettranslation + position * 8;
 
-  grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position);
-  length = grub_cpu_to_le32 (length);
+  grub_gettext_pread (fd_mo, (char *) length, 4, internal_position);
+  *length = grub_cpu_to_le32 (*length);
 
   grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4);
   offset = grub_cpu_to_le32 (offset);
 
-  translation = grub_malloc (length + 1);
-  grub_gettext_getstring_from_offset (offset, length, translation);
+  translation = grub_malloc (*length + 1);
+  grub_gettext_getstring_from_offset (offset, *length, translation);
 
   return translation;
 }
@@ -138,7 +140,7 @@
 }
 
 static const char *
-grub_gettext_translate (const char *orig)
+grub_gettext_find_translation (const char *orig, grub_uint32_t *length)
 {
   char *current_string;
   const char *ret;
@@ -195,7 +197,7 @@
       current = (max + min) / 2;
     }
 
-  ret = found ? grub_gettext_gettranslation_from_position (current) : orig;
+  ret = found ? grub_gettext_gettranslation_from_position (current, length) : orig;
 
   if (found)
     {
@@ -207,6 +209,7 @@
 	  if (cur->name)
 	    {
 	      cur->translated = ret;
+          cur->length = *length;
 	      grub_list_push (GRUB_AS_LIST_P (&grub_gettext_msg_list),
 			      GRUB_AS_LIST (cur));
 	    }
@@ -219,6 +222,34 @@
   return ret;
 }
 
+static const char *
+grub_gettext_translate (const char *orig)
+{
+  grub_uint32_t length = 0;
+  return grub_gettext_find_translation (orig, &length);
+}
+
+static const char *
+grub_gettext_translate_n (const char *s1, const char *s2, unsigned long n)
+{
+  grub_uint32_t length = 0, l;
+  const char *ret;
+
+  ret = grub_gettext_find_translation (s1, &length);
+  if (ret == s1)
+    return n == 1 ? s1 : s2;
+
+  /* Find the nth string */
+  while (n > 1 && (l = grub_strlen (ret)) < length)
+    {
+      length -= l + 1;
+      ret += l + 1;
+      n--;
+    }
+
+  return ret;
+}
+
 /* This is similar to grub_gzfile_open. */
 static grub_file_t
 grub_mofile_open (const char *filename)
@@ -303,6 +334,8 @@
 
       grub_gettext_original = grub_gettext;
       grub_gettext = grub_gettext_translate;
+      grub_ngettext_original = grub_ngettext;
+      grub_ngettext = grub_gettext_translate_n;
     }
 }
 
@@ -345,6 +378,19 @@
   return 0;
 }
 
+static grub_err_t
+grub_cmd_translate_n (grub_command_t cmd __attribute__ ((unused)),
+		    int argc, char **args)
+{
+  if (argc != 3)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required");
+
+  const char *translation;
+  translation = grub_gettext_translate_n (args[0], args[1], grub_strtoul(args[2], NULL, 10));
+  grub_printf ("%s\n", translation);
+  return 0;
+}
+
 GRUB_MOD_INIT (gettext)
 {
   (void) mod;			/* To stop warning.  */
@@ -358,6 +404,9 @@
   grub_register_command_p1 ("gettext", grub_cmd_translate,
 			    N_("STRING"),
 			    N_("Translates the string with the current settings."));
+  grub_register_command_p1 ("ngettext", grub_cmd_translate_n,
+			    N_("STRING STRING INT"),
+			    N_("Translates the string with the current settings."));
 
   /* Reload .mo file information if lang changes.  */
   grub_register_variable_hook ("lang", NULL, grub_gettext_env_write_lang);
@@ -374,4 +423,5 @@
   grub_gettext_delete_list ();
 
   grub_gettext = grub_gettext_original;
+  grub_ngettext = grub_ngettext_original;
 }
diff -Nur -x '*.orig' -x '*~' grub2-1.98/include/grub/i18n.h grub2-1.98.new/include/grub/i18n.h
--- grub2-1.98/include/grub/i18n.h	2010-03-07 07:51:37.000000000 +1100
+++ grub2-1.98.new/include/grub/i18n.h	2010-04-09 16:46:35.695688143 +1000
@@ -23,6 +23,7 @@
 #include <grub/symbol.h>
 
 extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
+extern const char *(*EXPORT_VAR(grub_ngettext)) (const char *s, const char *s_plural, unsigned long int n);
 
 /* NLS can be disabled through the configure --disable-nls option.  */
 #if ENABLE_NLS
@@ -43,8 +44,10 @@
    contain "#define const".  */
 # ifdef GRUB_UTIL
 #  define gettext(Msgid) ((const char *) (Msgid))
+#  define ngettext(Msgid) ((const char *) (Msgid))
 # else
 #  define grub_gettext(str) ((const char *) (str))
+#  define grub_ngettext(str) ((const char *) (str))
 # endif /* GRUB_UTIL */
 
 #endif /* ENABLE_NLS */
diff -Nur -x '*.orig' -x '*~' grub2-1.98/kern/misc.c grub2-1.98.new/kern/misc.c
--- grub2-1.98/kern/misc.c	2010-03-07 07:51:37.000000000 +1100
+++ grub2-1.98.new/kern/misc.c	2010-04-09 16:46:35.695688143 +1000
@@ -43,6 +43,15 @@
 
 const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
 
+/* grub_ngettext_dummy is not translating anything.  */
+static const char *
+grub_ngettext_dummy (const char *s1, const char *s2, unsigned long n)
+{
+  return n == 1 ? s1 : s2;
+}
+
+const char* (*grub_ngettext) (const char *s1, const char *s2, unsigned long n) = grub_ngettext_dummy;
+
 void *
 grub_memmove (void *dest, const void *src, grub_size_t n)
 {
