]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
New facility for logging untranslated messages to a file.
authorBruno Haible <bruno@clisp.org>
Tue, 18 Feb 2003 13:12:57 +0000 (13:12 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:10:10 +0000 (12:10 +0200)
NEWS
PACKAGING
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/Makefile.in
gettext-runtime/intl/dcigettext.c
gettext-runtime/intl/intl-compat.c
gettext-runtime/intl/log.c [new file with mode: 0644]
gettext-runtime/m4/ChangeLog
gettext-runtime/m4/gettext.m4
gettext-tools/doc/ChangeLog
gettext-tools/doc/gettext.texi

diff --git a/NEWS b/NEWS
index fb52234ab32e671b41da3eef23ed0dd7a922783b..7aedbe929efff7b7fb0b36c3514a5b9b74c8f98c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,9 @@ Version 0.11.6 - October 2002
   New documentation section:
   - Writing your own programs that process PO files.
 
+* New documentation section:
+  - Prioritizing messages: How to determine which messages to translate first.
+
 * xgettext now supports msgid strings in other encodings than ASCII.
   xgettext has a new option --from-code that specifies the encoding of the
   source files. The resulting POT files are UTF-8 encoded.
index 44d80ec91c4c987645c34309bd39d5bf60d0d21d..b74fc8e31abbbb155ca01a7e9d1aaa93026288b9 100644 (file)
--- a/PACKAGING
+++ b/PACKAGING
@@ -94,6 +94,7 @@ following file list.
       $prefix/lib/libgettextlib*
       $prefix/lib/libgettextsrc*
       $prefix/lib/libgettextpo*
+      $prefix/lib/preloadable_libintl.so  (only installed on glibc systems)
       $prefix/lib/gettext/*
       $prefix/share/locale/*/LC_MESSAGES/gettext-tools.mo
       $prefix/share/gettext/config.rpath
index 9b00b138602e495e37068aa685d2500f2674c8ee..d5983750f90adcf439a20a07a381de6f840df9a4 100644 (file)
@@ -1,3 +1,15 @@
+2003-02-16  Bruno Haible  <bruno@clisp.org>
+
+       * log.c: New file.
+       * dcigettext.c (DCIGETTEXT) [!_LIBC]: Before returning the
+       untranslated string, call _nl_log_untranslated.
+       * intl-compat.c: Comments.
+       * Makefile.in (SOURCES): Add log.c.
+       (OBJECTS): Add intl-compat.$lo unconditionally. Add log.$lo.
+       (log.lo): New rule.
+       (install-exec): Stop using @INTLOBJS@. Install preloadable_libintl.so.
+       (installdirs, uninstall): Update accordingly.
+
 2003-02-16  Bruno Haible  <bruno@clisp.org>
 
        * Makefile.in (.sin.sed): Remove rule.
index 1472b7ab7fd46bce5daafc84414258b6fd4b22f6..030a258d7b513258013831b41dd4467a1df2b047 100644 (file)
@@ -87,10 +87,11 @@ SOURCES = \
   plural-exp.c \
   localcharset.c \
   localename.c \
+  log.c \
   osdep.c \
   os2compat.c \
   intl-compat.c
-OBJECTS = @INTLOBJS@ \
+OBJECTS = \
   bindtextdom.$lo \
   dcgettext.$lo \
   dgettext.$lo \
@@ -109,8 +110,9 @@ OBJECTS = @INTLOBJS@ \
   plural-exp.$lo \
   localcharset.$lo \
   localename.$lo \
-  osdep.$lo
-GETTOBJS = intl-compat.$lo
+  log.$lo \
+  osdep.$lo \
+  intl-compat.$lo
 DISTFILES.common = Makefile.in \
 config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES)
 DISTFILES.generated = plural.c
@@ -193,6 +195,8 @@ localcharset.lo: $(srcdir)/localcharset.c
        $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localcharset.c
 localename.lo: $(srcdir)/localename.c
        $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c
+log.lo: $(srcdir)/log.c
+       $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c
 osdep.lo: $(srcdir)/osdep.c
        $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c
 intl-compat.lo: $(srcdir)/intl-compat.c
@@ -227,7 +231,7 @@ check: all
 install: install-exec install-data
 install-exec: all
        if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
          $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
          $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \
          $(LIBTOOL) --mode=install \
@@ -235,6 +239,18 @@ install-exec: all
        else \
          : ; \
        fi
+       if test "$(PACKAGE)" = "gettext-tools" \
+          && test '@USE_INCLUDED_LIBINTL@' = no; then \
+         $(mkinstalldirs) $(DESTDIR)$(libdir); \
+         $(LIBTOOL) --mode=install \
+           $(INSTALL_DATA) libgnuintl.$la $(DESTDIR)$(libdir)/libgnuintl.$la; \
+         rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+         $(INSTALL_DATA) $(DESTDIR)$(libdir)/libgnuintl.so $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+         $(LIBTOOL) --mode=uninstall \
+           rm -f $(DESTDIR)$(libdir)/libgnuintl.$la; \
+       else \
+         : ; \
+       fi
        if test '@USE_INCLUDED_LIBINTL@' = yes; then \
          test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
          temp=$(DESTDIR)$(libdir)/t-charset.alias; \
@@ -293,11 +309,17 @@ install-strip: install
 
 installdirs:
        if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
          $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
        else \
          : ; \
        fi
+       if test "$(PACKAGE)" = "gettext-tools" \
+          && test '@USE_INCLUDED_LIBINTL@' = no; then \
+         $(mkinstalldirs) $(DESTDIR)$(libdir); \
+       else \
+         : ; \
+       fi
        if test '@USE_INCLUDED_LIBINTL@' = yes; then \
          test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \
          $(mkinstalldirs) $(DESTDIR)$(localedir); \
@@ -315,13 +337,19 @@ installcheck:
 
 uninstall:
        if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
-          && test '@INTLOBJS@' = '$(GETTOBJS)'; then \
+          && test '@USE_INCLUDED_LIBINTL@' = yes; then \
          rm -f $(DESTDIR)$(includedir)/libintl.h; \
          $(LIBTOOL) --mode=uninstall \
            rm -f $(DESTDIR)$(libdir)/libintl.$la; \
        else \
          : ; \
        fi
+       if test "$(PACKAGE)" = "gettext-tools" \
+          && test '@USE_INCLUDED_LIBINTL@' = no; then \
+         rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+       else \
+         : ; \
+       fi
        if test '@USE_INCLUDED_LIBINTL@' = yes; then \
          if test -f $(DESTDIR)$(libdir)/charset.alias; then \
            temp=$(DESTDIR)$(libdir)/t-charset.alias; \
index 55aaa060f1c2030d95e541d2ac6ad63af763299c..593adb09fa867cc67e1b4c00a99512a93d77ce9d 100644 (file)
@@ -550,17 +550,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
        }
 
       if (ret == NULL)
-       {
-         /* We cannot get the current working directory.  Don't signal an
-            error but simply return the default string.  */
-         FREE_BLOCKS (block_list);
-         __libc_rwlock_unlock (_nl_state_lock);
-         __set_errno (saved_errno);
-         return (plural == 0
-                 ? (char *) msgid1
-                 /* Use the Germanic plural rule.  */
-                 : n == 1 ? (char *) msgid1 : (char *) msgid2);
-       }
+       /* We cannot get the current working directory.  Don't signal an
+          error but simply return the default string.  */
+       goto return_untranslated;
 
       stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
     }
@@ -617,16 +609,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
         domain.  Return the MSGID.  */
       if (strcmp (single_locale, "C") == 0
          || strcmp (single_locale, "POSIX") == 0)
-       {
-         FREE_BLOCKS (block_list);
-         __libc_rwlock_unlock (_nl_state_lock);
-         __set_errno (saved_errno);
-         return (plural == 0
-                 ? (char *) msgid1
-                 /* Use the Germanic plural rule.  */
-                 : n == 1 ? (char *) msgid1 : (char *) msgid2);
-       }
-
+       break;
 
       /* Find structure describing the message catalog matching the
         DOMAINNAME and CATEGORY.  */
@@ -707,7 +690,30 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
            }
        }
     }
-  /* NOTREACHED */
+
+ return_untranslated:
+  /* Return the untranslated MSGID.  */
+  FREE_BLOCKS (block_list);
+  __libc_rwlock_unlock (_nl_state_lock);
+#ifndef _LIBC
+  if (!ENABLE_SECURE)
+    {
+      extern void _nl_log_untranslated PARAMS ((const char *logfilename,
+                                               const char *domainname,
+                                               const char *msgid1,
+                                               const char *msgid2,
+                                               int plural));
+      const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
+
+      if (logfilename != NULL && logfilename[0] != '\0')
+       _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
+    }
+#endif
+  __set_errno (saved_errno);
+  return (plural == 0
+         ? (char *) msgid1
+         /* Use the Germanic plural rule.  */
+         : n == 1 ? (char *) msgid1 : (char *) msgid2);
 }
 
 
index da890159f8029c9e5020bf7346c81144377eebb4..129c60e5b449052fa4bb653ad16a00383795b507 100644 (file)
@@ -1,6 +1,6 @@
 /* intl-compat.c - Stub functions to call gettext functions from GNU gettext
    Library.
-   Copyright (C) 1995, 2000-2002 Software Foundation, Inc.
+   Copyright (C) 1995, 2000-2003 Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published
    defined in the included GNU libintl library (with "libintl_" prefix).
    It is compiled into libintl in order to make the AM_GNU_GETTEXT test
    of gettext <= 0.11.2 work with the libintl library >= 0.11.3 which
-   has the redirections primarily in the <libintl.h> include file.  */
+   has the redirections primarily in the <libintl.h> include file.
+   It is also compiled into libgnuintl so that libgnuintl.so can be used
+   as LD_PRELOADable library on glibc systems, to provide the extra
+   features that the functions in the libc don't have (namely, logging).  */
 
 
 #undef gettext
diff --git a/gettext-runtime/intl/log.c b/gettext-runtime/intl/log.c
new file mode 100644 (file)
index 0000000..9c84791
--- /dev/null
@@ -0,0 +1,104 @@
+/* Log file output.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Print an ASCII string with quotes and escape sequences where needed.  */
+static void
+print_escaped (stream, str)
+     FILE *stream;
+     const char *str;
+{
+  putc ('"', stream);
+  for (; *str != '\0'; str++)
+    if (*str == '\n')
+      {
+       fputs ("\\n\"", stream);
+       if (str[1] == '\0')
+         return;
+       fputs ("\n\"", stream);
+      }
+    else
+      {
+       if (*str == '"' || *str == '\\')
+         putc ('\\', stream);
+       putc (*str, stream);
+      }
+  putc ('"', stream);
+}
+
+/* Add to the log file an entry denoting a failed translation.  */
+void
+_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural)
+     const char *logfilename;
+     const char *domainname;
+     const char *msgid1;
+     const char *msgid2;
+     int plural;
+{
+  static char *last_logfilename = NULL;
+  static FILE *last_logfile = NULL;
+  FILE *logfile;
+
+  /* Can we reuse the last opened logfile?  */
+  if (last_logfilename == NULL || strcmp (logfilename, last_logfilename) != 0)
+    {
+      /* Close the last used logfile.  */
+      if (last_logfilename != NULL)
+       {
+         if (last_logfile != NULL)
+           {
+             fclose (last_logfile);
+             last_logfile = NULL;
+           }
+         free (last_logfilename);
+         last_logfilename = NULL;
+       }
+      /* Open the logfile.  */
+      last_logfilename = (char *) malloc (strlen (logfilename) + 1);
+      if (last_logfilename == NULL)
+       return;
+      strcpy (last_logfilename, logfilename);
+      last_logfile = fopen (logfilename, "a");
+      if (last_logfile == NULL)
+       return;
+    }
+  logfile = last_logfile;
+
+  fprintf (logfile, "domain ");
+  print_escaped (logfile, domainname);
+  fprintf (logfile, "\nmsgid ");
+  print_escaped (logfile, msgid1);
+  if (plural)
+    {
+      fprintf (logfile, "\nmsgid_plural ");
+      print_escaped (logfile, msgid2);
+      fprintf (logfile, "\nmsgstr[0] \"\"\n");
+    }
+  else
+    fprintf (logfile, "\nmsgstr \"\"\n");
+  putc ('\n', logfile);
+}
index 42f38f0965b68e932d5312cfac3312aae007f845..cf4b062848d672046866d068fa9fe5639e512cb3 100644 (file)
@@ -1,3 +1,8 @@
+2003-02-16  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.m4 (AM_GNU_GETTEXT): Move INTLOBJS to backward compatibility
+       section.
+
 2003-02-12  Bruno Haible  <bruno@clisp.org>
 
        Restructure gettext package.
index 2348d625356199db75c4ef68fe8476557ed7cb9c..1ac36a85ce4cd68f99f71482bb17a3dc020f5bf1 100644 (file)
@@ -17,7 +17,7 @@ dnl They are *not* in the public domain.
 
 dnl Authors:
 dnl   Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
-dnl   Bruno Haible <haible@clisp.cons.org>, 2000-2002.
+dnl   Bruno Haible <haible@clisp.cons.org>, 2000-2003.
 
 dnl Macro to add for using GNU gettext.
 
@@ -236,7 +236,6 @@ return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("",
 
       if test "$nls_cv_use_gnu_gettext" = "yes"; then
         dnl Mark actions used to generate GNU NLS library.
-        INTLOBJS="\$(GETTOBJS)"
         BUILD_INCLUDED_LIBINTL=yes
         USE_INCLUDED_LIBINTL=yes
         LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV"
@@ -308,7 +307,6 @@ return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("",
     AC_SUBST(BUILD_INCLUDED_LIBINTL)
     AC_SUBST(USE_INCLUDED_LIBINTL)
     AC_SUBST(CATOBJEXT)
-    AC_SUBST(INTLOBJS)
 
     dnl For backward compatibility. Some configure.ins may be using this.
     nls_cv_header_intl=
@@ -326,6 +324,12 @@ return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("",
     GENCAT=gencat
     AC_SUBST(GENCAT)
 
+    dnl For backward compatibility. Some Makefiles may be using this.
+    if test "$USE_INCLUDED_LIBINTL" = yes; then
+      INTLOBJS="\$(GETTOBJS)"
+    fi
+    AC_SUBST(INTLOBJS)
+
     dnl Enable libtool support if the surrounding package wishes it.
     INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
     AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
index 5b125640e2934542f8ab9a9702b58c03d50896bd..4517026ecb03c4192819205fbedd3731481a8fe7 100644 (file)
@@ -1,3 +1,7 @@
+2003-02-16  Bruno Haible  <bruno@clisp.org>
+
+       * gettext.texi (Prioritizing messages): New section.
+
 2003-02-16  Bruno Haible  <bruno@clisp.org>
 
        * gettext.texi (po/LINGUAS): Document en@quot and en@boldquot.
index f1aa312a555a5428ee8936954cb219eefa0b2c8d..29d06fc1388ccefe1099d636c223218d8c397c96 100644 (file)
@@ -115,7 +115,7 @@ by the Foundation.
 @node Top, Introduction, (dir), (dir)
 @top GNU @code{gettext} utilities
 
-This manual document the GNU gettext tools and the GNU libintl library,
+This manual documents the GNU gettext tools and the GNU libintl library,
 version @value{VERSION}.
 
 @menu
@@ -264,6 +264,7 @@ The Translator's View
 * Discussions::                 Discussions
 * Organization::                Organization
 * Information Flow::            Information Flow
+* Prioritizing messages::       How to find which messages to translate first
 
 Organization
 
@@ -5369,6 +5370,7 @@ Solaris is not the only system having @code{gettext}.
 * Discussions::                 Discussions
 * Organization::                Organization
 * Information Flow::            Information Flow
+* Prioritizing messages::       How to find which messages to translate first
 @end menu
 
 @node Trans Intro 0, Trans Intro 1, Translators, Translators
@@ -5524,10 +5526,11 @@ the GNU Library General Public License, when they do not want to make
 their program free, or want other kinds of freedom.  The simplest
 answer is ``normally not''.
 
-The GNU @code{gettext} library, i.e. the contents of @code{libintl},
-is covered by the GNU Library General Public License.  The rest of
-the GNU @code{gettext} package is covered by the GNU General Public
-License.
+The @code{gettext-runtime} part of GNU @code{gettext}, i.e. the
+contents of @code{libintl}, is covered by the GNU Library General Public
+License.  The @code{gettext-tools} part of GNU @code{gettext}, i.e. the
+rest of the GNU @code{gettext} package, is covered by the GNU General
+Public License.
 
 The mere marking of localizable strings in a package, or conditional
 inclusion of a few lines for initialization, is not really including
@@ -5740,7 +5743,7 @@ run, each team should run its own list, from within their country.
 There also should be some central list to which all teams could
 subscribe as they see fit, as long as each team is represented in it.
 
-@node Information Flow,  , Organization, Translators
+@node Information Flow, Prioritizing messages, Organization, Translators
 @section Information Flow
 
 There will surely be some discussion about this messages after the
@@ -5778,6 +5781,116 @@ I sent a proposal for a fast and flexible format, but it is not
 receiving acceptance yet by the GNU deciders.  I'll tell you when I
 have more information about this.
 
+@node Prioritizing messages,  , Information Flow, Translators
+@section Prioritizing messages: How to determine which messages to translate first
+
+A translator sometimes has only a limited amount of time per week to
+spend on a package, and some packages have quite large message catalogs
+(over 1000 messages).  Therefore she wishes to translate the messages
+first that are the most visible to the user, or that occur most frequently.
+This section describes how to determine these "most urgent" messages.
+It also applies to determine the "next most urgent" messages after the
+message catalog has already been partially translated.
+
+In a first step, she uses the programs like a user would do.  While she
+does this, the GNU @code{gettext} library logs into a file the not yet
+translated messages for which a translation was requested from the program.
+
+In a second step, she uses the PO mode to translate precisely this set
+of messages.
+
+@vindex GETTEXT_LOG_UNTRANSLATED@r{, environment variable}
+Here a more details.  The GNU @code{libintl} library (but not the
+corresponding functions in GNU @code{libc}) supports an environment variable
+@code{GETTEXT_LOG_UNTRANSLATED}.  The GNU @code{libintl} library will
+log into this file the messages for which @code{gettext()} and related
+functions couldn't find the translation.  If the file doesn't exist, it
+will be created as needed.  On systems with GNU @code{libc} a shared library
+@samp{preloadable_libintl.so} is provided that can be used with the ELF
+@samp{LD_PRELOAD} mechanism.
+
+So, in the first step, the translator uses these commands on systems with
+GNU @code{libc}:
+
+@smallexample
+$ LD_PRELOAD=/usr/local/lib/preloadable_libintl.so
+$ export LD_PRELOAD
+$ GETTEXT_LOG_UNTRANSLATED=$HOME/gettextlogused
+$ export GETTEXT_LOG_UNTRANSLATED
+@end smallexample
+
+@noindent
+and these commands on other systems:
+
+@smallexample
+$ GETTEXT_LOG_UNTRANSLATED=$HOME/gettextlogused
+$ export GETTEXT_LOG_UNTRANSLATED
+@end smallexample
+
+Then she uses and peruses the programs.  (It is a good and recommended
+practice to use the programs for which you provide translations: it
+gives you the needed context.)  When done, she removes the environment
+variables:
+
+@smallexample
+$ unset LD_PRELOAD
+$ unset GETTEXT_LOG_UNTRANSLATED
+@end smallexample
+
+The second step starts with removing duplicates:
+
+@smallexample
+$ msguniq $HOME/gettextlogused > missing.po
+@end smallexample
+
+The result is a PO file, but needs some preprocessing before the Emacs PO
+mode can be used with it.  First, it is a multi-domain PO file, containing
+messages from many translation domains.  Second, it lacks all translator
+comments and source references.  Here is how to get a list of the affected
+translation domains:
+
+@smallexample
+$ sed -n -e 's,^domain "\(.*\)"$,\1,p' < missing.po | sort | uniq
+@end smallexample
+
+Then the translator can handle the domains one by one.  For simplicity,
+let's use environment variables to denote the language, domain and source
+package.
+
+@smallexample
+$ lang=nl             # your language
+$ domain=coreutils    # the name of the domain to be handled
+$ package=/usr/src/gnu/coreutils-4.5.4   # the package where it comes from
+@end smallexample
+
+She takes the latest copy of @file{$lang.po} from the Translation Project,
+or from the package (in most cases, @file{$package/po/$lang.po}), or
+creates a fresh one if she's the first translator (see @ref{Creating}).
+She then uses the following commands to mark the not urgent messages as
+"obsolete".  (This doesn't mean that these messages - translated and
+untranslated ones - will go away.  It simply means that Emacs PO mode
+will ignore them in the following editing session.)
+
+@smallexample
+$ msggrep --domain=$domain missing.po | grep -v '^domain' \
+  > $domain-missing.po
+$ msgattrib --set-obsolete --ignore-file $domain-missing.po $domain.$lang.po \
+  > $domain.$lang-urgent.po
+@end smallexample
+
+The she translates @file{$domain.$lang-urgent.po} by use of Emacs PO mode.
+(FIXME: I don't know whether @code{KBabel} and @code{gtranslator} also
+preserve obsolete messages, as they should.)
+Finally she restores the not urgent messages (with their earlier
+translations, for those which were already translated) through this command:
+
+@smallexample
+$ msgmerge --no-fuzzy-matching $domain.$lang-urgent.po $package/po/$domain.pot \
+  > $domain.$lang.po
+@end smallexample
+
+Then she can submit @file{$domain.$lang.po} and proceed to the next domain.
+
 @node Maintainers, Programming Languages, Translators, Top
 @chapter The Maintainer's View
 @cindex package maintainer's view of @code{gettext}