Mattias Engdegård wrote in thread "Translation of Subversion":
What really needs to be done to make life for translators somewhat
bearable is to split the long strings into individual paragraphs;
this is standard practice.

The attached patch "split-long-strings-1.patch" (unfinished; see included log message) puts code in place to achieve this for 'svn' help, and demonstrates by splitting the 'svn log' and 'svn merge' strings.

One issue occurs to me. If we make this change, splitting all the long strings into paragraphs, won't that cause one enormous headache to the translators because they will then have a bunch of paragraph-length strings that the translation tools think are untranslated individually, even though translations of them existed as substrings of a previous long string?

How could we ease that transition? It looks like it could be quite easy to write a script that updates the .po files, if we choose our new breaks to be at a deterministic points (e.g. every empty line), and if the current translations keep the same structure (1:1 paragraphs) as the English version. Would that work with most translators' work flows?

- Julian
Split long strings into paragraphs to ease translation.

Some of the tools our translators use do not handle very long (multi-
paragraph) strings well, just showing the whole string has changed. The
recommended solution is to break long strings at paragraph boundaries.

This patch revises svn_opt_subcommand_desc2_t into svn_opt_subcommand_desc3_t
supporting an array of strings instead of a single string for the main help
text, and revises all the supporting functions accordingly.

### This patch demonstrates the principle by adding breaks in only the 'log'
### and 'merge' help strings.

### We might want to deprecate the previous set of functions.

### Doc strings for the new functions aren't all there.

* subversion/include/svn_opt.h,
  subversion/libsvn_subr/opt.c
  (SVN_OPT_MAX_PARAGRAPHS,
   svn_opt_subcommand_desc3_t,
   svn_opt_get_canonical_subcommand3,
   svn_opt_get_option_from_code3,
   svn_opt_subcommand_takes_option4,
   svn_opt_print_generic_help3,
   svn_opt_subcommand_help4,
   svn_opt_print_help5): New.

* subversion/svn/cl.h
  (svn_cl__cmd_table): Update.

* subversion/svn/help-cmd.c
  (svn_cl__help): Update.

* subversion/svn/svn.c
  (svn_cl__cmd_table): Update to the new format.
--This line, and those below, will be ignored--

Index: subversion/include/svn_opt.h
===================================================================
--- subversion/include/svn_opt.h	(revision 1825927)
+++ subversion/include/svn_opt.h	(working copy)
@@ -71,2 +71,5 @@
 
+/** The maximum number of paragraphs of help text a subcommand can have. */
+#define SVN_OPT_MAX_PARAGRAPHS 50
+
 /** Options that have no short option char should use an identifying
@@ -79,2 +82,33 @@
  *
+ * @since New in 1.11.
+ */
+typedef struct svn_opt_subcommand_desc3_t
+{
+  /** The full name of this command. */
+  const char *name;
+
+  /** The function this command invokes. */
+  svn_opt_subcommand_t *cmd_func;
+
+  /** A list of alias names for this command (e.g., 'up' for 'update'). */
+  const char *aliases[SVN_OPT_MAX_ALIASES];
+
+  /** A multi-paragraph string describing this command, for usage messages. */
+  const char *help3[SVN_OPT_MAX_PARAGRAPHS];
+
+  /** A list of options accepted by this command.  Each value in the
+   * array is a unique enum (the 2nd field in apr_getopt_option_t)
+   */
+  int valid_options[SVN_OPT_MAX_OPTIONS];
+
+  /** A list of option help descriptions, keyed by the option unique enum
+   * (the 2nd field in apr_getopt_option_t), which override the generic
+   * descriptions given in an apr_getopt_option_t on a per-subcommand basis.
+   */
+  struct { int optch; const char *desc; } desc_overrides[SVN_OPT_MAX_OPTIONS];
+} svn_opt_subcommand_desc3_t;
+
+
+/** One element of a subcommand dispatch table.
+ *
  * @since New in 1.4.
@@ -141,2 +175,13 @@
  *
+ * @since New in 1.11.
+ */
+const svn_opt_subcommand_desc3_t *
+svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table,
+                                  const char *cmd_name);
+
+
+/**
+ * Return the entry in @a table whose name matches @a cmd_name, or @c NULL if
+ * none.  @a cmd_name may be an alias.
+ *
  * @since New in 1.4.
@@ -175,2 +220,7 @@
 const apr_getopt_option_t *
+svn_opt_get_option_from_code3(int code,
+                              const apr_getopt_option_t *option_table,
+                              const svn_opt_subcommand_desc3_t *command,
+                              apr_pool_t *pool);
+const apr_getopt_option_t *
 svn_opt_get_option_from_code2(int code,
@@ -203,2 +253,6 @@
 svn_boolean_t
+svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command,
+                                 int option_code,
+                                 const int *global_options);
+svn_boolean_t
 svn_opt_subcommand_takes_option3(const svn_opt_subcommand_desc2_t *command,
@@ -249,2 +303,9 @@
 void
+svn_opt_print_generic_help3(const char *header,
+                            const svn_opt_subcommand_desc3_t *cmd_table,
+                            const apr_getopt_option_t *opt_table,
+                            const char *footer,
+                            apr_pool_t *pool,
+                            FILE *stream);
+void
 svn_opt_print_generic_help2(const char *header,
@@ -302,2 +363,8 @@
 void
+svn_opt_subcommand_help4(const char *subcommand,
+                         const svn_opt_subcommand_desc3_t *table,
+                         const apr_getopt_option_t *options_table,
+                         const int *global_options,
+                         apr_pool_t *pool);
+void
 svn_opt_subcommand_help3(const char *subcommand,
@@ -706,2 +773,15 @@
 svn_error_t *
+svn_opt_print_help5(apr_getopt_t *os,
+                    const char *pgm_name,
+                    svn_boolean_t print_version,
+                    svn_boolean_t quiet,
+                    svn_boolean_t verbose,
+                    const char *version_footer,
+                    const char *header,
+                    const svn_opt_subcommand_desc3_t *cmd_table,
+                    const apr_getopt_option_t *option_table,
+                    const int *global_options,
+                    const char *footer,
+                    apr_pool_t *pool);
+svn_error_t *
 svn_opt_print_help4(apr_getopt_t *os,
Index: subversion/libsvn_subr/opt.c
===================================================================
--- subversion/libsvn_subr/opt.c	(revision 1825927)
+++ subversion/libsvn_subr/opt.c	(working copy)
@@ -57,2 +57,26 @@
 
+const svn_opt_subcommand_desc3_t *
+svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table,
+                                  const char *cmd_name)
+{
+  int i = 0;
+
+  if (cmd_name == NULL)
+    return NULL;
+
+  while (table[i].name) {
+    int j;
+    if (strcmp(cmd_name, table[i].name) == 0)
+      return table + i;
+    for (j = 0; (j < SVN_OPT_MAX_ALIASES) && table[i].aliases[j]; j++)
+      if (strcmp(cmd_name, table[i].aliases[j]) == 0)
+        return table + i;
+
+    i++;
+  }
+
+  /* If we get here, there was no matching subcommand name or alias. */
+  return NULL;
+}
+
 const svn_opt_subcommand_desc2_t *
@@ -82,2 +106,34 @@
 const apr_getopt_option_t *
+svn_opt_get_option_from_code3(int code,
+                              const apr_getopt_option_t *option_table,
+                              const svn_opt_subcommand_desc3_t *command,
+                              apr_pool_t *pool)
+{
+  apr_size_t i;
+
+  for (i = 0; option_table[i].optch; i++)
+    if (option_table[i].optch == code)
+      {
+        if (command)
+          {
+            int j;
+
+            for (j = 0; ((j < SVN_OPT_MAX_OPTIONS) &&
+                         command->desc_overrides[j].optch); j++)
+              if (command->desc_overrides[j].optch == code)
+                {
+                  apr_getopt_option_t *tmpopt =
+                      apr_palloc(pool, sizeof(*tmpopt));
+                  *tmpopt = option_table[i];
+                  tmpopt->description = command->desc_overrides[j].desc;
+                  return tmpopt;
+                }
+          }
+        return &(option_table[i]);
+      }
+
+  return NULL;
+}
+
+const apr_getopt_option_t *
 svn_opt_get_option_from_code2(int code,
@@ -128,2 +184,30 @@
 
+/* Like svn_opt_get_option_from_code3(), but also, if CODE appears a second
+ * time in OPTION_TABLE with a different name, then set *LONG_ALIAS to that
+ * second name, else set it to NULL. */
+static const apr_getopt_option_t *
+get_option_from_code3(const char **long_alias,
+                      int code,
+                      const apr_getopt_option_t *option_table,
+                      const svn_opt_subcommand_desc3_t *command,
+                      apr_pool_t *pool)
+{
+  const apr_getopt_option_t *i;
+  const apr_getopt_option_t *opt
+    = svn_opt_get_option_from_code3(code, option_table, command, pool);
+
+  /* Find a long alias in the table, if there is one. */
+  *long_alias = NULL;
+  for (i = option_table; i->optch; i++)
+    {
+      if (i->optch == code && i->name != opt->name)
+        {
+          *long_alias = i->name;
+          break;
+        }
+    }
+
+  return opt;
+}
+
 /* Like svn_opt_get_option_from_code2(), but also, if CODE appears a second
@@ -207,2 +291,21 @@
 svn_boolean_t
+svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command,
+                                 int option_code,
+                                 const int *global_options)
+{
+  apr_size_t i;
+
+  for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++)
+    if (command->valid_options[i] == option_code)
+      return TRUE;
+
+  if (global_options)
+    for (i = 0; global_options[i]; i++)
+      if (global_options[i] == option_code)
+        return TRUE;
+
+  return FALSE;
+}
+
+svn_boolean_t
 svn_opt_subcommand_takes_option3(const svn_opt_subcommand_desc2_t *command,
@@ -253,2 +356,110 @@
 static svn_error_t *
+print_command_info3(const svn_opt_subcommand_desc3_t *cmd,
+                    const apr_getopt_option_t *options_table,
+                    const int *global_options,
+                    svn_boolean_t help,
+                    apr_pool_t *pool,
+                    FILE *stream)
+{
+  svn_boolean_t first_time;
+  apr_size_t i;
+
+  /* Print the canonical command name. */
+  SVN_ERR(svn_cmdline_fputs(cmd->name, stream, pool));
+
+  /* Print the list of aliases. */
+  first_time = TRUE;
+  for (i = 0; i < SVN_OPT_MAX_ALIASES; i++)
+    {
+      if (cmd->aliases[i] == NULL)
+        break;
+
+      if (first_time) {
+        SVN_ERR(svn_cmdline_fputs(" (", stream, pool));
+        first_time = FALSE;
+      }
+      else
+        SVN_ERR(svn_cmdline_fputs(", ", stream, pool));
+
+      SVN_ERR(svn_cmdline_fputs(cmd->aliases[i], stream, pool));
+    }
+
+  if (! first_time)
+    SVN_ERR(svn_cmdline_fputs(")", stream, pool));
+
+  if (help)
+    {
+      const apr_getopt_option_t *option;
+      const char *long_alias;
+      svn_boolean_t have_options = FALSE;
+
+      SVN_ERR(svn_cmdline_fprintf(stream, pool, ": "));
+
+      for (i = 0; cmd->help3[i] && i < SVN_OPT_MAX_PARAGRAPHS; i++)
+        {
+          SVN_ERR(svn_cmdline_fprintf(stream, pool, "%s", _(cmd->help3[i])));
+        }
+
+      /* Loop over all valid option codes attached to the subcommand */
+      for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++)
+        {
+          if (cmd->valid_options[i])
+            {
+              if (!have_options)
+                {
+                  SVN_ERR(svn_cmdline_fputs(_("\nValid options:\n"),
+                                            stream, pool));
+                  have_options = TRUE;
+                }
+
+              /* convert each option code into an option */
+              option = get_option_from_code3(&long_alias, cmd->valid_options[i],
+                                             options_table, cmd, pool);
+
+              /* print the option's docstring */
+              if (option && option->description)
+                {
+                  const char *optstr;
+                  format_option(&optstr, option, long_alias, TRUE, pool);
+                  SVN_ERR(svn_cmdline_fprintf(stream, pool, "  %s\n",
+                                              optstr));
+                }
+            }
+        }
+      /* And global options too */
+      if (global_options && *global_options)
+        {
+          SVN_ERR(svn_cmdline_fputs(_("\nGlobal options:\n"),
+                                    stream, pool));
+          have_options = TRUE;
+
+          for (i = 0; global_options[i]; i++)
+            {
+
+              /* convert each option code into an option */
+              option = get_option_from_code3(&long_alias, global_options[i],
+                                             options_table, cmd, pool);
+
+              /* print the option's docstring */
+              if (option && option->description)
+                {
+                  const char *optstr;
+                  format_option(&optstr, option, long_alias, TRUE, pool);
+                  SVN_ERR(svn_cmdline_fprintf(stream, pool, "  %s\n",
+                                              optstr));
+                }
+            }
+        }
+
+      if (have_options)
+        SVN_ERR(svn_cmdline_fprintf(stream, pool, "\n"));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+/* Print the canonical command name for CMD, and all its aliases, to
+   STREAM.  If HELP is set, print CMD's help string too, in which case
+   obtain option usage from OPTIONS_TABLE. */
+static svn_error_t *
 print_command_info2(const svn_opt_subcommand_desc2_t *cmd,
@@ -352,2 +563,34 @@
 
+/* The body for svn_opt_print_generic_help3() function with standard error
+ * handling semantic. Handling of errors implemented at caller side. */
+static svn_error_t *
+print_generic_help_body3(const char *header,
+                         const svn_opt_subcommand_desc3_t *cmd_table,
+                         const apr_getopt_option_t *opt_table,
+                         const char *footer,
+                         apr_pool_t *pool, FILE *stream)
+{
+  int i = 0;
+
+  if (header)
+    SVN_ERR(svn_cmdline_fputs(header, stream, pool));
+
+  while (cmd_table[i].name)
+    {
+      SVN_ERR(svn_cmdline_fputs("   ", stream, pool));
+      SVN_ERR(print_command_info3(cmd_table + i, opt_table,
+                                  NULL, FALSE,
+                                  pool, stream));
+      SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
+      i++;
+    }
+
+  SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
+
+  if (footer)
+    SVN_ERR(svn_cmdline_fputs(footer, stream, pool));
+
+  return SVN_NO_ERROR;
+}
+
 /* The body for svn_opt_print_generic_help2() function with standard error
@@ -385,2 +628,26 @@
 void
+svn_opt_print_generic_help3(const char *header,
+                            const svn_opt_subcommand_desc3_t *cmd_table,
+                            const apr_getopt_option_t *opt_table,
+                            const char *footer,
+                            apr_pool_t *pool, FILE *stream)
+{
+  svn_error_t *err;
+
+  err = print_generic_help_body3(header, cmd_table, opt_table, footer, pool,
+                                 stream);
+
+  /* Issue #3014:
+   * Don't print anything on broken pipes. The pipe was likely
+   * closed by the process at the other end. We expect that
+   * process to perform error reporting as necessary.
+   *
+   * ### This assumes that there is only one error in a chain for
+   * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
+  if (err && err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
+    svn_handle_error2(err, stderr, FALSE, "svn: ");
+  svn_error_clear(err);
+}
+
+void
 svn_opt_print_generic_help2(const char *header,
@@ -410,2 +677,28 @@
 void
+svn_opt_subcommand_help4(const char *subcommand,
+                         const svn_opt_subcommand_desc3_t *table,
+                         const apr_getopt_option_t *options_table,
+                         const int *global_options,
+                         apr_pool_t *pool)
+{
+  const svn_opt_subcommand_desc3_t *cmd =
+    svn_opt_get_canonical_subcommand3(table, subcommand);
+  svn_error_t *err;
+
+  if (cmd)
+    err = print_command_info3(cmd, options_table, global_options,
+                              TRUE, pool, stdout);
+  else
+    err = svn_cmdline_fprintf(stderr, pool,
+                              _("\"%s\": unknown command.\n\n"), subcommand);
+
+  if (err) {
+    /* Issue #3014: Don't print anything on broken pipes. */
+    if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
+      svn_handle_error2(err, stderr, FALSE, "svn: ");
+    svn_error_clear(err);
+  }
+}
+
+void
 svn_opt_subcommand_help3(const char *subcommand,
@@ -1192,2 +1485,52 @@
 
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_opt_print_help5(apr_getopt_t *os,
+                    const char *pgm_name,
+                    svn_boolean_t print_version,
+                    svn_boolean_t quiet,
+                    svn_boolean_t verbose,
+                    const char *version_footer,
+                    const char *header,
+                    const svn_opt_subcommand_desc3_t *cmd_table,
+                    const apr_getopt_option_t *option_table,
+                    const int *global_options,
+                    const char *footer,
+                    apr_pool_t *pool)
+{
+  apr_array_header_t *targets = NULL;
+
+  if (os)
+    SVN_ERR(svn_opt_parse_all_args(&targets, os, pool));
+
+  if (os && targets->nelts)  /* help on subcommand(s) requested */
+    {
+      int i;
+
+      for (i = 0; i < targets->nelts; i++)
+        {
+          svn_opt_subcommand_help4(APR_ARRAY_IDX(targets, i, const char *),
+                                   cmd_table, option_table,
+                                   global_options, pool);
+        }
+    }
+  else if (print_version)   /* just --version */
+    {
+      SVN_ERR(svn_opt__print_version_info(pgm_name, version_footer,
+                                          svn_version_extended(verbose, pool),
+                                          quiet, verbose, pool));
+    }
+  else if (os && !targets->nelts)            /* `-h', `--help', or `help' */
+    svn_opt_print_generic_help3(header,
+                                cmd_table,
+                                option_table,
+                                footer,
+                                pool,
+                                stdout);
+  else                                       /* unknown option or cmd */
+    SVN_ERR(svn_cmdline_fprintf(stderr, pool,
+                                _("Type '%s help' for usage.\n"), pgm_name));
+
   return SVN_NO_ERROR;
Index: subversion/svn/cl.h
===================================================================
--- subversion/svn/cl.h	(revision 1825927)
+++ subversion/svn/cl.h	(working copy)
@@ -322,3 +322,3 @@
 /* See definition in svn.c for documentation. */
-extern const svn_opt_subcommand_desc2_t svn_cl__cmd_table[];
+extern const svn_opt_subcommand_desc3_t svn_cl__cmd_table[];
 
Index: subversion/svn/help-cmd.c
===================================================================
--- subversion/svn/help-cmd.c	(revision 1825927)
+++ subversion/svn/help-cmd.c	(working copy)
@@ -181,3 +181,3 @@
 
-  return svn_opt_print_help4(os,
+  return svn_opt_print_help5(os,
                              "svn",   /* ### erm, derive somehow? */
Index: subversion/svn/svn.c
===================================================================
--- subversion/svn/svn.c	(revision 1825927)
+++ subversion/svn/svn.c	(working copy)
@@ -522,8 +522,9 @@
 
-const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] =
+const svn_opt_subcommand_desc3_t svn_cl__cmd_table[] =
 {
-  { "add", svn_cl__add, {0}, N_
-    ("Put files and directories under version control, scheduling\n"
+  { "add", svn_cl__add, {0}, {N_(
+     "Put files and directories under version control, scheduling\n"
      "them for addition to repository.  They will be added in next commit.\n"
      "usage: add PATH...\n"),
+    },
     {opt_targets, 'N', opt_depth, 'q', opt_force, opt_no_ignore, opt_autoprops,
@@ -532,4 +533,4 @@
 
-  { "auth", svn_cl__auth, {0}, N_
-   ("Manage cached authentication credentials.\n"
+  { "auth", svn_cl__auth, {0}, {N_(
+    "Manage cached authentication credentials.\n"
     "usage: 1. svn auth [PATTERN ...]\n"
@@ -553,2 +554,3 @@
     "  expand them.\n"),
+    },
     { opt_remove, opt_show_passwords },
@@ -558,4 +560,4 @@
 
-  { "blame", svn_cl__blame, {"praise", "annotate", "ann"}, N_
-    ("Show when each line of a file was last (or\n"
+  { "blame", svn_cl__blame, {"praise", "annotate", "ann"}, {N_(
+     "Show when each line of a file was last (or\n"
      "next) changed.\n"
@@ -580,6 +582,7 @@
      "  Write the annotated result to standard output.\n"),
+    },
     {'r', 'v', 'g', opt_incremental, opt_xml, 'x', opt_force} },
 
-  { "cat", svn_cl__cat, {0}, N_
-    ("Output the content of specified files or URLs.\n"
+  { "cat", svn_cl__cat, {0}, {N_(
+     "Output the content of specified files or URLs.\n"
      "usage: cat TARGET[@REV]...\n"
@@ -588,12 +591,14 @@
      "  looked up.\n"),
+    },
     {'r', opt_ignore_keywords} },
 
-  { "changelist", svn_cl__changelist, {"cl"}, N_
-    ("Associate (or dissociate) changelist CLNAME with the named files.\n"
+  { "changelist", svn_cl__changelist, {"cl"}, {N_(
+     "Associate (or dissociate) changelist CLNAME with the named files.\n"
      "usage: 1. changelist CLNAME PATH...\n"
      "       2. changelist --remove PATH...\n"),
+    },
     { 'q', 'R', opt_depth, opt_remove, opt_targets, opt_changelist} },
 
-  { "checkout", svn_cl__checkout, {"co"}, N_
-    ("Check out a working copy from a repository.\n"
+  { "checkout", svn_cl__checkout, {"co"}, {N_(
+     "Check out a working copy from a repository.\n"
      "usage: checkout URL[@REV]... [PATH]\n"
@@ -621,6 +626,7 @@
      "  reporting the action taken.\n"),
+    },
     {'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals} },
 
-  { "cleanup", svn_cl__cleanup, {0}, N_
-    ("Either recover from an interrupted operation that left the working copy locked,\n"
+  { "cleanup", svn_cl__cleanup, {0}, {N_(
+     "Either recover from an interrupted operation that left the working copy locked,\n"
      "or remove unwanted files.\n"
@@ -650,2 +656,3 @@
      "    referenced by any file in the working copy.\n"),
+    },
     { opt_remove_unversioned, opt_remove_ignored, opt_vacuum_pristines,
@@ -654,4 +661,4 @@
       
-  { "commit", svn_cl__commit, {"ci"},
-    N_("Send changes from your working copy to the repository.\n"
+  { "commit", svn_cl__commit, {"ci"}, {N_(
+       "Send changes from your working copy to the repository.\n"
        "usage: commit [PATH...]\n"
@@ -667,2 +674,3 @@
        "  fixed revision.\n"),
+    },
     {'q', 'N', opt_depth, opt_targets, opt_no_unlock, SVN_CL__LOG_MSG_OPTIONS,
@@ -670,4 +678,4 @@
 
-  { "copy", svn_cl__copy, {"cp"}, N_
-    ("Copy files and directories in a working copy or repository.\n"
+  { "copy", svn_cl__copy, {"cp"}, {N_(
+     "Copy files and directories in a working copy or repository.\n"
      "usage: copy SRC[@REV]... DST\n"
@@ -688,2 +696,3 @@
      "  to the destination.\n"),
+    },
     {'r', 'q', opt_ignore_externals, opt_parents, SVN_CL__LOG_MSG_OPTIONS,
@@ -691,4 +700,4 @@
 
-  { "delete", svn_cl__delete, {"del", "remove", "rm"}, N_
-    ("Remove files and directories from version control.\n"
+  { "delete", svn_cl__delete, {"del", "remove", "rm"}, {N_(
+     "Remove files and directories from version control.\n"
      "usage: 1. delete PATH...\n"
@@ -705,6 +714,7 @@
      "    via an immediate commit.\n"),
+    },
     {opt_force, 'q', opt_targets, SVN_CL__LOG_MSG_OPTIONS, opt_keep_local} },
 
-  { "diff", svn_cl__diff, {"di"}, N_
-    ("Display local changes or differences between two revisions or paths.\n"
+  { "diff", svn_cl__diff, {"di"}, {N_(
+     "Display local changes or differences between two revisions or paths.\n"
      "usage: 1. diff\n"
@@ -743,2 +753,3 @@
      "  6. Shorthand for 'svn diff --old=OLD-PATH[@OLDREV] --new=NEW-URL[@NEWREV]'\n"),
+    },
     {'r', 'c', opt_old_cmd, opt_new_cmd, 'N', opt_depth, opt_diff_cmd,
@@ -748,4 +759,4 @@
      opt_force, opt_xml, opt_use_git_diff_format, opt_patch_compatible} },
-  { "export", svn_cl__export, {0}, N_
-    ("Create an unversioned copy of a tree.\n"
+  { "export", svn_cl__export, {0}, {N_(
+     "Create an unversioned copy of a tree.\n"
      "usage: 1. export [-r REV] URL[@PEGREV] [PATH]\n"
@@ -767,2 +778,3 @@
      "  looked up.\n"),
+    },
     {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, opt_ignore_externals,
@@ -770,5 +782,6 @@
 
-  { "help", svn_cl__help, {"?", "h"}, N_
-    ("Describe the usage of this program or its subcommands.\n"
+  { "help", svn_cl__help, {"?", "h"}, {N_(
+     "Describe the usage of this program or its subcommands.\n"
      "usage: help [SUBCOMMAND...]\n"),
+    },
     {0} },
@@ -776,4 +789,4 @@
 
-  { "import", svn_cl__import, {0}, N_
-    ("Commit an unversioned file or tree into the repository.\n"
+  { "import", svn_cl__import, {0}, {N_(
+     "Commit an unversioned file or tree into the repository.\n"
      "usage: import [PATH] URL\n"
@@ -787,2 +800,3 @@
      "  if --force is specified.\n"),
+    },
     {'q', 'N', opt_depth, opt_autoprops, opt_force, opt_no_autoprops,
@@ -790,4 +804,4 @@
 
-  { "info", svn_cl__info, {0}, N_
-    ("Display information about a local or remote item.\n"
+  { "info", svn_cl__info, {0}, {N_(
+     "Display information about a local or remote item.\n"
      "usage: info [TARGET[@REV]...]\n"
@@ -801,2 +815,3 @@
      "  about TARGET.\n"),
+    },
     {'r', 'R', opt_depth, opt_targets, opt_incremental, opt_xml,
@@ -807,4 +822,4 @@
 #if defined(WIN32)
-    N_
-    ("List directory entries in the repository.\n"
+    {N_(
+     "List directory entries in the repository.\n"
      "usage: list [TARGET[@REV]...]\n"
@@ -831,5 +846,6 @@
      "    Date and time of the last commit\n"),
+    },
 #else
-    N_
-    ("List directory entries in the repository.\n"
+    {N_(
+     "List directory entries in the repository.\n"
      "usage: list [TARGET[@REV]...]\n"
@@ -855,2 +871,3 @@
      "    Date and time of the last commit\n"),
+    },
 #endif
@@ -859,4 +876,4 @@
 
-  { "lock", svn_cl__lock, {0}, N_
-    ("Lock working copy paths or URLs in the repository, so that\n"
+  { "lock", svn_cl__lock, {0}, {N_(
+     "Lock working copy paths or URLs in the repository, so that\n"
      "no other user can commit changes to them.\n"
@@ -865,2 +882,3 @@
      "  Use --force to steal a lock from another user or working copy.\n"),
+    },
     { opt_targets, 'm', 'F', opt_force_log, opt_encoding, opt_force, 'q' },
@@ -871,7 +889,7 @@
 
-  { "log", svn_cl__log, {0}, N_
-    ("Show the log messages for a set of revision(s) and/or path(s).\n"
+  { "log", svn_cl__log, {0}, {N_(
+     "Show the log messages for a set of revision(s) and/or path(s).\n"), N_(
      "usage: 1. log [PATH][@REV]\n"
      "       2. log URL[@REV] [PATH...]\n"
-     "\n"
+     "\n"), N_(
      "  1. Print the log messages for the URL corresponding to PATH\n"
@@ -881,3 +899,3 @@
      "     since the URL might not exist in the HEAD revision.\n"
-     "\n"
+     "\n"), N_(
      "  2. Print the log messages for the PATHs (default: '.') under URL.\n"
@@ -887,3 +905,3 @@
      "     HEAD:1.\n"
-     "\n"
+     "\n"), N_(
      "  Multiple '-c' or '-r' options may be specified (but not a\n"
@@ -891,3 +909,3 @@
      "  reverse ranges is allowed.\n"
-     "\n"
+     "\n"), N_(
      "  With -v, also print all affected paths with each log message.\n"
@@ -903,6 +921,6 @@
      "  as copied from the old path at a prior revision.\n"
-     "\n"
+     "\n"), N_(
      "  With -q, don't print the log message body itself (note that this is\n"
      "  compatible with -v).\n"
-     "\n"
+     "\n"), N_(
      "  Each log message is printed just once, even if more than one of the\n"
@@ -911,6 +929,6 @@
      "  behavior, which can be useful for determining branchpoints.\n"
-     "\n"
+     "\n"), N_(
      "  The --depth option is only valid in combination with the --diff option\n"
      "  and limits the scope of the displayed diff to the specified depth.\n"
-     "\n"
+     "\n"), N_(
      "  If the --search option is used, log messages are displayed only if the\n"
@@ -931,3 +949,3 @@
      "  to a particular number of matching log messages.\n"
-     "\n"
+     "\n"), N_(
      "  Examples:\n"
@@ -962,2 +980,3 @@
      "       A /trunk/bar.c (from /trunk/foo.c:21)\n"),
+    },
     {'r', 'c', 'q', 'v', 'g', opt_targets, opt_stop_on_copy, opt_incremental,
@@ -971,7 +990,7 @@
 
-  { "merge", svn_cl__merge, {0}, N_
-    ( /* For this large section, let's keep it unindented for easier
+  { "merge", svn_cl__merge, {0}, {N_(
+      /* For this large section, let's keep it unindented for easier
        * viewing/editing. It has been vim-treated with a textwidth=75 and 'gw'
        * (with quotes and newlines removed). */
-"Merge changes into a working copy.\n"
+"Merge changes into a working copy.\n"), N_(
 "usage: 1. merge SOURCE[@REV] [TARGET_WCPATH]\n"
@@ -982,8 +1001,8 @@
 "          (the '2-URL' merge)\n"
-"\n"
+"\n"), N_(
 "  1. This form, with one source path and no revision range, is called\n"
 "     a 'complete' merge:\n"
-"\n"
+"\n"), N_(
 "       svn merge SOURCE[@REV] [TARGET_WCPATH]\n"
-"\n"
+"\n"), N_(
 "     The complete merge is used for the 'sync' and 'reintegrate' merges\n"
@@ -993,3 +1012,3 @@
 "     is used to know which changes have already been merged.\n"
-"\n"
+"\n"), N_(
 "     SOURCE specifies the branch from where the changes will be pulled, and\n"
@@ -1000,3 +1019,3 @@
 "     TARGET_WCPATH; this is discouraged, to avoid subtree mergeinfo.)\n"
-"\n"
+"\n"), N_(
 "     SOURCE is usually a URL. The optional '@REV' specifies both the peg\n"
@@ -1007,6 +1026,6 @@
 "     revision last updated to).\n"
-"\n"
+"\n"), N_(
 "     TARGET_WCPATH is a working copy path; if omitted, '.' is generally\n"
 "     assumed. There are some special cases:\n"
-"\n"
+"\n"), N_(
 "       - If SOURCE is a URL:\n"
@@ -1302,2 +1321,3 @@
 "  repositories.\n"),
+    },
     {'r', 'c', 'N', opt_depth, 'q', opt_force, opt_dry_run, opt_merge_cmd,
@@ -1308,4 +1328,4 @@
 
-  { "mergeinfo", svn_cl__mergeinfo, {0}, N_
-    ("Display merge-related information.\n"
+  { "mergeinfo", svn_cl__mergeinfo, {0}, {N_(
+     "Display merge-related information.\n"
      "usage: 1. mergeinfo SOURCE[@REV] [TARGET[@REV]]\n"
@@ -1337,2 +1357,3 @@
      "  The depth can be 'empty' or 'infinity'; the default is 'empty'.\n"),
+    },
     {'r', 'R', 'q', 'v', opt_depth, opt_show_revs, opt_mergeinfo_log,
@@ -1340,4 +1361,4 @@
 
-  { "mkdir", svn_cl__mkdir, {0}, N_
-    ("Create a new directory under version control.\n"
+  { "mkdir", svn_cl__mkdir, {0}, {N_(
+     "Create a new directory under version control.\n"
      "usage: 1. mkdir PATH...\n"
@@ -1355,6 +1376,7 @@
      "  unless the --parents option is given.\n"),
+    },
     {'q', opt_parents, SVN_CL__LOG_MSG_OPTIONS} },
 
-  { "move", svn_cl__move, {"mv", "rename", "ren"}, N_
-    ("Move (rename) an item in a working copy or repository.\n"
+  { "move", svn_cl__move, {"mv", "rename", "ren"}, {N_(
+     "Move (rename) an item in a working copy or repository.\n"
      "usage: move SRC... DST\n"
@@ -1375,2 +1397,3 @@
      "  The --allow-mixed-revisions option is provided for backward compatibility.\n"),
+    },
     {'q', opt_force, opt_parents, opt_allow_mixed_revisions,
@@ -1379,4 +1402,4 @@
 
-  { "patch", svn_cl__patch, {0}, N_
-    ("Apply a patch to a working copy.\n"
+  { "patch", svn_cl__patch, {0}, {N_(
+     "Apply a patch to a working copy.\n"
      "usage: patch PATCHFILE [WCPATH]\n"
@@ -1424,2 +1447,3 @@
      ),
+    },
     {'q', opt_dry_run, opt_strip, opt_reverse_diff,
@@ -1427,4 +1451,4 @@
 
-  { "propdel", svn_cl__propdel, {"pdel", "pd"}, N_
-    ("Remove a property from files, dirs, or revisions.\n"
+  { "propdel", svn_cl__propdel, {"pdel", "pd"}, {N_(
+     "Remove a property from files, dirs, or revisions.\n"
      "usage: 1. propdel PROPNAME [PATH...]\n"
@@ -1437,6 +1461,7 @@
      "  See 'svn help propset' for descriptions of the svn:* special properties.\n"),
+    },
     {'q', 'R', opt_depth, 'r', opt_revprop, opt_changelist} },
 
-  { "propedit", svn_cl__propedit, {"pedit", "pe"}, N_
-    ("Edit a property with an external editor.\n"
+  { "propedit", svn_cl__propedit, {"pedit", "pe"}, {N_(
+     "Edit a property with an external editor.\n"
      "usage: 1. propedit PROPNAME TARGET...\n"
@@ -1449,6 +1474,7 @@
      "  See 'svn help propset' for descriptions of the svn:* special properties.\n"),
+    },
     {'r', opt_revprop, SVN_CL__LOG_MSG_OPTIONS, opt_force} },
 
-  { "propget", svn_cl__propget, {"pget", "pg"}, N_
-    ("Print the value of a property on files, dirs, or revisions.\n"
+  { "propget", svn_cl__propget, {"pget", "pg"}, {N_(
+     "Print the value of a property on files, dirs, or revisions.\n"
      "usage: 1. propget PROPNAME [TARGET[@REV]...]\n"
@@ -1472,2 +1498,3 @@
      "  See 'svn help propset' for descriptions of the svn:* special properties.\n"),
+    },
     {'v', 'R', opt_depth, 'r', opt_revprop, opt_strict, opt_no_newline, opt_xml,
@@ -1477,4 +1504,4 @@
 
-  { "proplist", svn_cl__proplist, {"plist", "pl"}, N_
-    ("List all properties on files, dirs, or revisions.\n"
+  { "proplist", svn_cl__proplist, {"plist", "pl"}, {N_(
+     "List all properties on files, dirs, or revisions.\n"
      "usage: 1. proplist [TARGET[@REV]...]\n"
@@ -1491,2 +1518,3 @@
      "  See 'svn help propset' for descriptions of the svn:* special properties.\n"),
+    },
     {'v', 'R', opt_depth, 'r', 'q', opt_revprop, opt_xml, opt_changelist,
@@ -1496,4 +1524,4 @@
 
-  { "propset", svn_cl__propset, {"pset", "ps"}, N_
-    ("Set the value of a property on files, dirs, or revisions.\n"
+  { "propset", svn_cl__propset, {"pset", "ps"}, {N_(
+     "Set the value of a property on files, dirs, or revisions.\n"
      "usage: 1. propset PROPNAME PROPVAL PATH...\n"
@@ -1582,2 +1610,3 @@
      "      Lines starting with a '#' character are ignored.\n"),
+    },
     {'F', opt_encoding, 'q', 'r', opt_targets, 'R', opt_depth, opt_revprop,
@@ -1586,4 +1615,4 @@
 
-  { "relocate", svn_cl__relocate, {0}, N_
-    ("Relocate the working copy to point to a different repository root URL.\n"
+  { "relocate", svn_cl__relocate, {0}, {N_(
+     "Relocate the working copy to point to a different repository root URL.\n"
      "usage: 1. relocate FROM-PREFIX TO-PREFIX [PATH...]\n"
@@ -1607,6 +1636,7 @@
      "                 svn://svn.example.com/repo/project\n"),
+    },
     {opt_ignore_externals} },
 
-  { "resolve", svn_cl__resolve, {0}, N_
-    ("Resolve conflicts on working copy files or directories.\n"
+  { "resolve", svn_cl__resolve, {0}, {N_(
+     "Resolve conflicts on working copy files or directories.\n"
      "usage: resolve [PATH...]\n"
@@ -1660,2 +1690,3 @@
      "  copied, deleted, or moved.\n"),
+    },
     {opt_targets, 'R', opt_depth, 'q', opt_accept},
@@ -1667,4 +1698,4 @@
 
-  { "resolved", svn_cl__resolved, {0}, N_
-    ("Remove 'conflicted' state on working copy files or directories.\n"
+  { "resolved", svn_cl__resolved, {0}, {N_(
+     "Remove 'conflicted' state on working copy files or directories.\n"
      "usage: resolved PATH...\n"
@@ -1675,6 +1706,7 @@
      "  deprecated in favor of running 'svn resolve --accept working'.\n"),
+    },
     {opt_targets, 'R', opt_depth, 'q'} },
 
-  { "revert", svn_cl__revert, {0}, N_
-    ("Restore pristine working copy state (undo local changes).\n"
+  { "revert", svn_cl__revert, {0}, {N_(
+     "Restore pristine working copy state (undo local changes).\n"
      "usage: revert PATH...\n"
@@ -1687,6 +1719,7 @@
      "  the output of 'svn help merge' for 'undo'.\n"),
+    },
     {opt_targets, 'R', opt_depth, 'q', opt_changelist} },
 
-  { "shelf-diff", svn_cl__shelf_diff, {0}, N_
-    ("Show shelved changes as a diff.\n"
+  { "shelf-diff", svn_cl__shelf_diff, {0}, {N_(
+     "Show shelved changes as a diff.\n"
      "usage: shelf-diff NAME [VERSION]\n"
@@ -1698,6 +1731,7 @@
     ),
+    },
   },
 
-  { "shelf-drop", svn_cl__shelf_drop, {0}, N_
-    ("Delete a shelf.\n"
+  { "shelf-drop", svn_cl__shelf_drop, {0}, {N_(
+     "Delete a shelf.\n"
      "usage: shelf-drop NAME\n"
@@ -1709,6 +1743,7 @@
     ),
+    },
   },
 
-  { "shelf-list", svn_cl__shelf_list, {"shelves"}, N_
-    ("List shelves.\n"
+  { "shelf-list", svn_cl__shelf_list, {"shelves"}, {N_(
+     "List shelves.\n"
      "usage: shelf-list\n"
@@ -1722,2 +1757,3 @@
     ),
+    },
     {'q', 'v'}
@@ -1725,4 +1761,4 @@
 
-  { "shelf-list-by-paths", svn_cl__shelf_list_by_paths, {0}, N_
-    ("List which shelf affects each path.\n"
+  { "shelf-list-by-paths", svn_cl__shelf_list_by_paths, {0}, {N_(
+     "List which shelf affects each path.\n"
      "usage: shelf-list-by-paths [PATH...]\n"
@@ -1734,6 +1770,7 @@
     ),
+    },
   },
 
-  { "shelf-log", svn_cl__shelf_log, {0}, N_
-    ("Show the versions of a shelf.\n"
+  { "shelf-log", svn_cl__shelf_log, {0}, {N_(
+     "Show the versions of a shelf.\n"
      "usage: shelf-log NAME\n"
@@ -1745,2 +1782,3 @@
     ),
+    },
     {'q', 'v'}
@@ -1748,4 +1786,4 @@
 
-  { "shelf-save", svn_cl__shelf_save, {0}, N_
-    ("Copy local changes onto a new version of a shelf.\n"
+  { "shelf-save", svn_cl__shelf_save, {0}, {N_(
+     "Copy local changes onto a new version of a shelf.\n"
      "usage: shelf-save NAME [PATH...]\n"
@@ -1760,2 +1798,3 @@
     ),
+    },
     {'q', opt_dry_run,
@@ -1766,4 +1805,4 @@
 
-  { "shelve", svn_cl__shelf_shelve, {0}, N_
-    ("Move local changes onto a shelf.\n"
+  { "shelve", svn_cl__shelf_shelve, {0}, {N_(
+     "Move local changes onto a shelf.\n"
      "usage: shelve [--keep-local] NAME [PATH...]\n"
@@ -1788,2 +1827,3 @@
     ),
+    },
     {'q', opt_dry_run, opt_keep_local,
@@ -1793,4 +1833,4 @@
 
-  { "unshelve", svn_cl__shelf_unshelve, {0}, N_
-    ("Copy shelved changes back into the WC.\n"
+  { "unshelve", svn_cl__shelf_unshelve, {0}, {N_(
+     "Copy shelved changes back into the WC.\n"
      "usage: unshelve [--drop] [NAME [VERSION]]\n"
@@ -1810,6 +1850,7 @@
     ),
+    },
     {opt_drop, 'q', opt_dry_run} },
 
-  { "status", svn_cl__status, {"stat", "st"}, N_
-    ("Print the status of working copy files and directories.\n"
+  { "status", svn_cl__status, {"stat", "st"}, {N_(
+     "Print the status of working copy files and directories.\n"
      "usage: status [PATH...]\n"
@@ -1904,2 +1945,3 @@
      "    D       wc/qax.c\n"),
+    },
     { 'u', 'v', 'N', opt_depth, 'r', 'q', opt_no_ignore, opt_incremental,
@@ -1908,4 +1950,4 @@
 
-  { "switch", svn_cl__switch, {"sw"}, N_
-    ("Update the working copy to a different URL within the same repository.\n"
+  { "switch", svn_cl__switch, {"sw"}, {N_(
+     "Update the working copy to a different URL within the same repository.\n"
      "usage: 1. switch URL[@PEGREV] [PATH]\n"
@@ -1948,2 +1990,3 @@
      "                          svn://svn.example.com/repo/project\n"),
+    },
     { 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd,
@@ -1958,4 +2001,4 @@
 
-  { "unlock", svn_cl__unlock, {0}, N_
-    ("Unlock working copy paths or URLs.\n"
+  { "unlock", svn_cl__unlock, {0}, {N_(
+     "Unlock working copy paths or URLs.\n"
      "usage: unlock TARGET...\n"
@@ -1963,2 +2006,3 @@
      "  Use --force to break a lock held by another user or working copy.\n"),
+    },
     { opt_targets, opt_force, 'q' },
@@ -1966,4 +2010,4 @@
 
-  { "update", svn_cl__update, {"up"},  N_
-    ("Bring changes from the repository into the working copy.\n"
+  { "update", svn_cl__update, {"up"},  {N_(
+     "Bring changes from the repository into the working copy.\n"
      "usage: update [PATH...]\n"
@@ -2012,2 +2056,3 @@
      "  targets of this operation.\n"),
+    },
     {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_force,
@@ -2018,4 +2063,4 @@
 
-  { "upgrade", svn_cl__upgrade, {0}, N_
-    ("Upgrade the metadata storage format for a working copy.\n"
+  { "upgrade", svn_cl__upgrade, {0}, {N_(
+     "Upgrade the metadata storage format for a working copy.\n"
      "usage: upgrade [WCPATH...]\n"
@@ -2023,5 +2068,6 @@
      "  Local modifications are preserved.\n"),
+    },
     { 'q' } },
 
-  { NULL, NULL, {0}, NULL, {0} }
+  { NULL, NULL, {0}, {NULL}, {0} }
 };
@@ -2108,3 +2154,3 @@
   int i;
-  const svn_opt_subcommand_desc2_t *subcommand = NULL;
+  const svn_opt_subcommand_desc3_t *subcommand = NULL;
   const char *dash_F_arg = NULL;
@@ -2737,3 +2783,3 @@
   if (opt_state.help)
-    subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table, "help");
+    subcommand = svn_opt_get_canonical_subcommand3(svn_cl__cmd_table, "help");
 
@@ -2748,4 +2794,4 @@
               /* Use the "help" subcommand to handle the "--version" option. */
-              static const svn_opt_subcommand_desc2_t pseudo_cmd =
-                { "--version", svn_cl__help, {0}, "",
+              static const svn_opt_subcommand_desc3_t pseudo_cmd =
+              { "--version", svn_cl__help, {0}, {""},
                   {opt_version,    /* must accept its own option */
@@ -2774,3 +2820,3 @@
                                           pool));
-          subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table,
+          subcommand = svn_opt_get_canonical_subcommand3(svn_cl__cmd_table,
                                                          first_arg);
@@ -2812,3 +2858,3 @@
 
-      if (! svn_opt_subcommand_takes_option3(subcommand, opt_id,
+      if (! svn_opt_subcommand_takes_option4(subcommand, opt_id,
                                              svn_cl__global_options))
@@ -2817,3 +2863,3 @@
           const apr_getopt_option_t *badopt =
-            svn_opt_get_option_from_code2(opt_id, svn_cl__options,
+            svn_opt_get_option_from_code3(opt_id, svn_cl__options,
                                           subcommand, pool);

Reply via email to