get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2227401/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2227401,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2227401/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/glibc/patch/54fc5096228e57b86e75f5e2fb8e322d5254d431.1776957778.git.vivien@planete-kraus.eu/",
    "project": {
        "id": 41,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/41/?format=api",
        "name": "GNU C Library",
        "link_name": "glibc",
        "list_id": "libc-alpha.sourceware.org",
        "list_email": "libc-alpha@sourceware.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<54fc5096228e57b86e75f5e2fb8e322d5254d431.1776957778.git.vivien@planete-kraus.eu>",
    "date": "2026-04-23T16:03:59",
    "name": "[v22,1/9] posix: allow getopt_long to match translated option names",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "187263c57782622fdb380b21ce8685176a1bbe48",
    "submitter": {
        "id": 90948,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/90948/?format=api",
        "name": "Vivien Kraus",
        "email": "vivien@planete-kraus.eu"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/glibc/patch/54fc5096228e57b86e75f5e2fb8e322d5254d431.1776957778.git.vivien@planete-kraus.eu/mbox/",
    "series": [
        {
            "id": 501215,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/501215/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/glibc/list/?series=501215",
            "date": "2026-04-23T16:03:58",
            "name": "Support translated long option names in getopt and argp",
            "version": 22,
            "mbox": "http://patchwork.ozlabs.org/series/501215/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2227401/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2227401/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "libc-alpha@sourceware.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=planete-kraus.eu header.i=@planete-kraus.eu\n header.a=rsa-sha1 header.s=albinoniA header.b=pDKq69mq;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n secure) header.d=planete-kraus.eu header.i=@planete-kraus.eu\n header.a=rsa-sha1 header.s=albinoniA header.b=pDKq69mq",
            "sourceware.org; dmarc=pass (p=reject dis=none)\n header.from=planete-kraus.eu",
            "sourceware.org;\n spf=pass smtp.mailfrom=planete-kraus.eu",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=2a00:5881:4008:2810::309"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1gvG1Cwhz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 24 Apr 2026 02:06:34 +1000 (AEST)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 53EBB4BBC0E9\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 16:06:32 +0000 (GMT)",
            "from planete-kraus.eu (planete-kraus.eu\n [IPv6:2a00:5881:4008:2810::309])\n by sourceware.org (Postfix) with ESMTPS id D2B1A4BBF6D4\n for <libc-alpha@sourceware.org>; Thu, 23 Apr 2026 16:05:05 +0000 (GMT)",
            "from planete-kraus.eu (localhost [127.0.0.1])\n by planete-kraus.eu (OpenSMTPD) with ESMTP id 92001c5a;\n Thu, 23 Apr 2026 16:05:04 +0000 (UTC)",
            "by planete-kraus.eu (OpenSMTPD) with ESMTPSA id f820a652\n (TLSv1.3:TLS_CHACHA20_POLY1305_SHA256:256:NO);\n Thu, 23 Apr 2026 16:05:02 +0000 (UTC)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 53EBB4BBC0E9",
            "OpenDKIM Filter v2.11.0 sourceware.org D2B1A4BBF6D4"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org D2B1A4BBF6D4",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org D2B1A4BBF6D4",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776960306; cv=none;\n b=dBhw6ivarQ8LE0a92dnxVGIjsOtnebJI4uBuwkikHXC4FLDO+eHYjKbJQaHrQ0Aou+tbvrxXKrcXimDbPHbJ9YbtsLl+DRV+sTD7s2CfYQfuiqy87n+E/KZSKTIrZHsmB2m/f2haCanAXnS/G+qkTbgeuW49+ioEi7qo734035Y=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776960306; c=relaxed/simple;\n bh=MlWvWj2kUbR0ZDmKsug4IAxbtTilrLBjVM5BNof6FWQ=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=G2T6/MYyhSjwa1Jmyro0GuXZMVKkhnH/XnQG0XfpWWNEiXXs9+DB5N5SPNbAko+zFJdb2jYtaKT4rbWhVNVaEGoHpcX0g6ErRG8cORIwgNDG5m+th1iccKapnrEqYo/PwXKf7iA03gW4v5VD+HP2D/iMF8cHuFcH9tQOi425bM0=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha1; c=relaxed; d=planete-kraus.eu; h=from\n :to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-type:content-transfer-encoding; s=\n albinoniA; bh=MoSHxuOGtwVVZp0kzYaX0fSV/pI=; b=pDKq69mq5PVGQ1wFNk\n bVrDVHndRbKFtirOWG1foW3Cjblq15trgPzebFfdqxYR3By2R6YTrhin1BnHiHpr\n W7rMMKFAQhZpuISHCTNKIhbrpPVq3822M4ktvnI/CDjNN2755VOIiTKFfHgtGV83\n yWHEMR7ub9h6qoxCTsXWUOuTDJ7yjA3Q/OK11l2tgO7amXyQLgiziQbBmF+GRmEl\n E/ELYr0w4ZayJk5BxEyFHV/oGP75InWbAmhHQr2J6V8j0dKKbD7VY60h540kigFJ\n +tKA5StH7H7IcZ47eZ77EN1fqg5hc+QZRE/rE609d1T/Gss+wYVdqT+w1YIQriqO\n L2EA==",
        "From": "Vivien Kraus <vivien@planete-kraus.eu>",
        "To": "adhemerval.zanella@linaro.org,\n\tlibc-alpha@sourceware.org",
        "Cc": "Vivien Kraus <vivien@planete-kraus.eu>",
        "Subject": "[PATCH v22 1/9] posix: allow getopt_long to match translated option\n names",
        "Date": "Thu, 23 Apr 2026 18:03:59 +0200",
        "Message-ID": "\n <54fc5096228e57b86e75f5e2fb8e322d5254d431.1776957778.git.vivien@planete-kraus.eu>",
        "X-Mailer": "git-send-email 2.52.0",
        "In-Reply-To": "<cover.1776957777.git.vivien@planete-kraus.eu>",
        "References": "<cover.1776957777.git.vivien@planete-kraus.eu>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "libc-alpha@sourceware.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Libc-alpha mailing list <libc-alpha.sourceware.org>",
        "List-Unsubscribe": "<https://sourceware.org/mailman/options/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe>",
        "List-Archive": "<https://sourceware.org/pipermail/libc-alpha/>",
        "List-Post": "<mailto:libc-alpha@sourceware.org>",
        "List-Help": "<mailto:libc-alpha-request@sourceware.org?subject=help>",
        "List-Subscribe": "<https://sourceware.org/mailman/listinfo/libc-alpha>,\n <mailto:libc-alpha-request@sourceware.org?subject=subscribe>",
        "Errors-To": "libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org"
    },
    "content": "It is possible to support translated long option names in a program\nwith no change to glibc by duplicating the option names in the struct\noptions array: one version untranslated, and one version translated.\nHowever, doing so is significant work for all packages.\n\nWith this change, getopt will try and match the untranslated options\nnames, then the translated option names if not found.  Abbreviations\nwill only match the untranslated names.\n\n_getopt_internal{_r} has a new argument: a translation function\npointer.  This way, we can pass NULL to avoid linking to gettext in\nthe posix version of getopt, or pass something that calls gettext\notherwise.\n\nThe test tstgetoptl is adapted from tstgetopt and modernized to use\nthe test driver.\n---\n NEWS                |   2 +\n manual/getopt.texi  |  25 ++++++--\n posix/Makefile      |  13 +++++\n posix/getopt.c      |  92 ++++++++++++++++++++++++-----\n posix/getopt1.c     |  11 ++--\n posix/getopt_int.h  |   9 ++-\n posix/tstgetoptl.c  | 139 ++++++++++++++++++++++++++++++++++++++++++++\n posix/tstgetoptl.po |  29 +++++++++\n 8 files changed, 293 insertions(+), 27 deletions(-)\n create mode 100644 posix/tstgetoptl.c\n create mode 100644 posix/tstgetoptl.po",
    "diff": "diff --git a/NEWS b/NEWS\nindex eac9322161..4e53a079e9 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -18,6 +18,8 @@ Major new features:\n \n * New locale added: hrx_BR (Hunsrik language spoken in Brazil).\n \n+* The getopt_long function now accepts translated long option names.\n+\n Deprecated and removed features, and other changes affecting compatibility:\n \n * Although malloc and related functions currently return pointers\ndiff --git a/manual/getopt.texi b/manual/getopt.texi\nindex 79a942307c..5ae22a1595 100644\n--- a/manual/getopt.texi\n+++ b/manual/getopt.texi\n@@ -202,6 +202,15 @@ declared in @file{getopt.h}, not @file{unistd.h}.  You should make every\n program accept long options if it uses any options, for this takes\n little extra work and helps beginners remember how to use the program.\n \n+Both long option names and their translations provided by the program\n+for the user's current locale are recognized.  This helps users of\n+your program who do not speak English understand the meaning of the\n+options, and it does not break the function of the program in scripts\n+if the untranslated option names are used.  If international\n+communication involves the invocation of your program, the program\n+users should be encouraged to use untranslated option names or publish\n+the locale used for this invocation.\n+\n @deftp {Data Type} {struct option}\n @standards{GNU, getopt.h}\n This structure describes a single long option name for the sake of\n@@ -213,7 +222,9 @@ The @code{struct option} structure has these fields:\n \n @table @code\n @item const char *name\n-This field is the name of the option.  It is a string.\n+This field is the name of the option.  It is a string.  In order for\n+@command{getopt_long} to accept either the long option name or its\n+translated form, you should mark this string for translation.\n \n @item int has_arg\n This field says whether the option takes an argument.  It is an integer,\n@@ -248,10 +259,14 @@ When @code{getopt_long} encounters a short option, it does the same\n thing that @code{getopt} would do: it returns the character code for the\n option, and stores the option's argument (if it has one) in @code{optarg}.\n \n-When @code{getopt_long} encounters a long option, it takes actions based\n-on the @code{flag} and @code{val} fields of the definition of that\n-option.  The option name may be abbreviated as long as the abbreviation is\n-unique.\n+When @code{getopt_long} encounters a long option or its translation in\n+the current textdomain, it takes actions based on the @code{flag} and\n+@code{val} fields of the definition of that option.  The English name\n+of the option name may be abbreviated as long as the abbreviation is\n+unique.  No abbreviation of the translated option name is recognized.\n+Since the untranslated option names have precedence over the\n+translated option names, it is not possible to hide or divert an\n+option with a translation.\n \n If @code{flag} is a null pointer, then @code{getopt_long} returns the\n contents of @code{val} to indicate which option it found.  You should\ndiff --git a/posix/Makefile b/posix/Makefile\nindex a5e5162c61..8755f42bdc 100644\n--- a/posix/Makefile\n+++ b/posix/Makefile\n@@ -332,6 +332,7 @@ tests := \\\n   tst-wordexp-nocmd \\\n   tst-wordexp-reuse \\\n   tstgetopt \\\n+  tstgetoptl \\\n   # tests\n \n # Test for the glob symbol version that was replaced in glibc 2.27.\n@@ -529,6 +530,7 @@ LOCALES := \\\n   da_DK.ISO-8859-1 \\\n   de_DE.ISO-8859-1 \\\n   de_DE.UTF-8 \\\n+  en_GB.UTF-8 \\\n   en_US.UTF-8 \\\n   es_US.ISO-8859-1 \\\n   es_US.UTF-8 \\\n@@ -802,3 +804,14 @@ tst-wordexp-reuse-ENV += MALLOC_TRACE=$(objpfx)tst-wordexp-reuse.mtrace \\\n $(objpfx)tst-wordexp-reuse-mem.out: $(objpfx)tst-wordexp-reuse.out\n \t$(common-objpfx)malloc/mtrace $(objpfx)tst-wordexp-reuse.mtrace > $@; \\\n \t$(evaluate-test)\n+\n+# tstgetoptl uses a translation catalog for translated option names.\n+tstgetoptl_mo = $(objpfx)domaindir/en_GB/LC_MESSAGES/tstgetoptl.mo\n+\n+$(tstgetoptl_mo): tstgetoptl.po\n+\t$(make-target-directory)\n+\tmsgfmt -o $@T $<\n+\tmv -f $@T $@\n+\n+$(objpfx)tstgetoptl.out: $(tstgetoptl_mo) $(gen-locales)\n+CFLAGS-tstgetoptl.c += -DOBJPFX=\\\"$(objpfx)\\\"\ndiff --git a/posix/getopt.c b/posix/getopt.c\nindex 3e10579670..cdc02d4da9 100644\n--- a/posix/getopt.c\n+++ b/posix/getopt.c\n@@ -182,6 +182,24 @@ exchange (char **argv, struct _getopt_data *d)\n   d->__last_nonopt = d->optind;\n }\n \n+/* Return true iff a translation for opt_name has been found and it\n+   matches the substring from argument, length argument_length.\n+*/\n+static bool\n+match_translated_option_name (char *(*translate) (const char *msgid),\n+\t\t\t      const char *argument, size_t argument_length,\n+\t\t\t      const char *opt_name)\n+{\n+  const char *translated = opt_name;\n+  if (translate != NULL)\n+    translated = translate (opt_name);\n+\n+  if (strncmp (translated, argument, argument_length) != 0)\n+    return false;\n+  /* We know that argument is a prefix of translated.  */\n+  return translated[argument_length] == '\\0';\n+}\n+\n /* Process the argument starting with d->__nextchar as a long option.\n    d->optind should *not* have been advanced over this argument.\n \n@@ -194,7 +212,8 @@ static int\n process_long_option (int argc, char **argv, const char *optstring,\n \t\t     const struct option *longopts, int *longind,\n \t\t     int long_only, struct _getopt_data *d,\n-\t\t     int print_errors, const char *prefix)\n+\t\t     int print_errors, const char *prefix,\n+\t\t     char *(*translate) (const char *msgid))\n {\n   char *nameend;\n   size_t namelen;\n@@ -202,6 +221,7 @@ process_long_option (int argc, char **argv, const char *optstring,\n   const struct option *pfound = NULL;\n   int n_options;\n   int option_index;\n+  const char *translated_option_name;\n \n   for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)\n     /* Do nothing.  */ ;\n@@ -221,7 +241,22 @@ process_long_option (int argc, char **argv, const char *optstring,\n \n   if (pfound == NULL)\n     {\n-      /* Didn't find an exact match, so look for abbreviations.  */\n+      /* Didn't find an exact match, try with translated option\n+\t names.  */\n+      for (p = longopts, option_index = 0; p->name; p++, option_index++)\n+\tif (match_translated_option_name (translate, d->__nextchar, namelen, p->name))\n+\t  {\n+\t    /* Exact match found with translation.  */\n+\t    pfound = p;\n+\t    break;\n+\t  }\n+    }\n+\n+  if (pfound == NULL)\n+    {\n+      /* Didn't find an exact match with translations, so look for\n+\t abbreviations, but only for the option name in the C\n+\t locale.  */\n       unsigned char *ambig_set = NULL;\n       int ambig_malloced = 0;\n       int ambig_fallback = 0;\n@@ -341,10 +376,20 @@ process_long_option (int argc, char **argv, const char *optstring,\n       else\n \t{\n \t  if (print_errors)\n-\t    fprintf (stderr,\n-\t\t     _(\"%s: option '%s%s' doesn't allow an argument\\n\"),\n-\t\t     argv[0], prefix, pfound->name);\n-\n+\t    {\n+\t      translated_option_name = translate (pfound->name);\n+\t      if (strcmp (translated_option_name, pfound->name) != 0)\n+\t\t/* Print both names of the option.  */\n+\t\tfprintf (stderr,\n+\t\t\t _(\"%s: option '%s%s' / '%s%s' doesn't allow an argument\\n\"),\n+\t\t\t argv[0], prefix, translated_option_name, prefix, pfound->name);\n+\t      else\n+\t\t/* Either the option name is not translated, or its\n+\t\t   translation is the same as the option name.  */\n+\t\tfprintf (stderr,\n+\t\t\t _(\"%s: option '%s%s' doesn't allow an argument\\n\"),\n+\t\t\t argv[0], prefix, pfound->name);\n+\t    }\n \t  d->optopt = pfound->val;\n \t  return '?';\n \t}\n@@ -356,9 +401,19 @@ process_long_option (int argc, char **argv, const char *optstring,\n       else\n \t{\n \t  if (print_errors)\n-\t    fprintf (stderr,\n-\t\t     _(\"%s: option '%s%s' requires an argument\\n\"),\n-\t\t     argv[0], prefix, pfound->name);\n+\t    {\n+\t      /* Same dichotomy as when the option does not allow an\n+\t\t argument.  */\n+\t      translated_option_name = translate (pfound->name);\n+\t      if (strcmp (translated_option_name, pfound->name) != 0)\n+\t\tfprintf (stderr,\n+\t\t\t _(\"%s: option '%s%s' / '%s%s' requires an argument\\n\"),\n+\t\t\t argv[0], prefix, translated_option_name, prefix, pfound->name);\n+\t      else\n+\t\tfprintf (stderr,\n+\t\t\t _(\"%s: option '%s%s' requires an argument\\n\"),\n+\t\t\t argv[0], prefix, pfound->name);\n+\t    }\n \n \t  d->optopt = pfound->val;\n \t  return optstring[0] == ':' ? ':' : '?';\n@@ -470,7 +525,8 @@ _getopt_initialize (_GL_UNUSED int argc,\n int\n _getopt_internal_r (int argc, char **argv, const char *optstring,\n \t\t    const struct option *longopts, int *longind,\n-\t\t    int long_only, struct _getopt_data *d, int posixly_correct)\n+\t\t    int long_only, struct _getopt_data *d, int posixly_correct,\n+\t\t    char *(*translate) (const char *msgid))\n {\n   int print_errors = d->opterr;\n \n@@ -573,7 +629,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,\n \t      d->__nextchar = argv[d->optind] + 2;\n \t      return process_long_option (argc, argv, optstring, longopts,\n \t\t\t\t\t  longind, long_only, d,\n-\t\t\t\t\t  print_errors, \"--\");\n+\t\t\t\t\t  print_errors, \"--\",\n+\t\t\t\t\t  translate);\n \t    }\n \n \t  /* If long_only and the ARGV-element has the form \"-f\",\n@@ -595,7 +652,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,\n \t      d->__nextchar = argv[d->optind] + 1;\n \t      code = process_long_option (argc, argv, optstring, longopts,\n \t\t\t\t\t  longind, long_only, d,\n-\t\t\t\t\t  print_errors, \"-\");\n+\t\t\t\t\t  print_errors, \"-\",\n+\t\t\t\t\t  translate);\n \t      if (code != -1)\n \t\treturn code;\n \t    }\n@@ -649,7 +707,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,\n \td->__nextchar = d->optarg;\n \td->optarg = NULL;\n \treturn process_long_option (argc, argv, optstring, longopts, longind,\n-\t\t\t\t    0 /* long_only */, d, print_errors, \"-W \");\n+\t\t\t\t    0 /* long_only */, d, print_errors, \"-W \",\n+\t\t\t\t    translate);\n       }\n     if (temp[1] == ':')\n       {\n@@ -702,7 +761,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,\n int\n _getopt_internal (int argc, char **argv, const char *optstring,\n \t\t  const struct option *longopts, int *longind, int long_only,\n-\t\t  int posixly_correct)\n+\t\t  int posixly_correct, char *(*translate) (const char *))\n {\n   int result;\n \n@@ -711,7 +770,7 @@ _getopt_internal (int argc, char **argv, const char *optstring,\n \n   result = _getopt_internal_r (argc, argv, optstring, longopts,\n \t\t\t       longind, long_only, &getopt_data,\n-\t\t\t       posixly_correct);\n+\t\t\t       posixly_correct, translate);\n \n   optind = getopt_data.optind;\n   optarg = getopt_data.optarg;\n@@ -729,7 +788,8 @@ _getopt_internal (int argc, char **argv, const char *optstring,\n   NAME (int argc, char *const *argv, const char *optstring)\t\\\n   {\t\t\t\t\t\t\t\t\\\n     return _getopt_internal (argc, (char **)argv, optstring,\t\\\n-\t\t\t     NULL, NULL, 0, POSIXLY_CORRECT);\t\\\n+\t\t\t     NULL, NULL, 0, POSIXLY_CORRECT,\t\\\n+\t\t\t     NULL);\t\t\t\t\\\n   }\n \n #ifdef _LIBC\ndiff --git a/posix/getopt1.c b/posix/getopt1.c\nindex e6fc867de0..6342e2d417 100644\n--- a/posix/getopt1.c\n+++ b/posix/getopt1.c\n@@ -19,6 +19,9 @@\n \f\n #ifndef _LIBC\n # include <config.h>\n+# include \"gettext.h\"\n+#else\n+# include <libintl.h>\n #endif\n \n #include \"getopt.h\"\n@@ -29,7 +32,7 @@ getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,\n \t     const struct option *long_options, int *opt_index)\n {\n   return _getopt_internal (argc, (char **) argv, options, long_options,\n-\t\t\t   opt_index, 0, 0);\n+\t\t\t   opt_index, 0, 0, gettext);\n }\n \n int\n@@ -38,7 +41,7 @@ _getopt_long_r (int argc, char **argv, const char *options,\n \t\tstruct _getopt_data *d)\n {\n   return _getopt_internal_r (argc, argv, options, long_options, opt_index,\n-\t\t\t     0, d, 0);\n+\t\t\t     0, d, 0, gettext);\n }\n \n /* Like getopt_long, but '-' as well as '--' can indicate a long option.\n@@ -52,7 +55,7 @@ getopt_long_only (int argc, char *__getopt_argv_const *argv,\n \t\t  const struct option *long_options, int *opt_index)\n {\n   return _getopt_internal (argc, (char **) argv, options, long_options,\n-\t\t\t   opt_index, 1, 0);\n+\t\t\t   opt_index, 1, 0, gettext);\n }\n \n int\n@@ -61,7 +64,7 @@ _getopt_long_only_r (int argc, char **argv, const char *options,\n \t\t     struct _getopt_data *d)\n {\n   return _getopt_internal_r (argc, argv, options, long_options, opt_index,\n-\t\t\t     1, d, 0);\n+\t\t\t     1, d, 0, gettext);\n }\n \n \f\ndiff --git a/posix/getopt_int.h b/posix/getopt_int.h\nindex 023d8a4fe6..579233b08c 100644\n--- a/posix/getopt_int.h\n+++ b/posix/getopt_int.h\n@@ -22,10 +22,14 @@\n \n #include <getopt.h>\n \n+/* The translate argument here is optional (can be NULL), it is used\n+   to avoid depending on the gettext functions in the posix getopt\n+   function.  */\n extern int _getopt_internal (int ___argc, char **___argv,\n \t\t\t     const char *__shortopts,\n \t\t\t     const struct option *__longopts, int *__longind,\n-\t\t\t     int __long_only, int __posixly_correct);\n+\t\t\t     int __long_only, int __posixly_correct,\n+\t\t\t     char *(*translate) (const char *msgid));\n \n \f\n /* Reentrant versions which can handle parsing multiple argument\n@@ -102,7 +106,8 @@ extern int _getopt_internal_r (int ___argc, char **___argv,\n \t\t\t       const char *__shortopts,\n \t\t\t       const struct option *__longopts, int *__longind,\n \t\t\t       int __long_only, struct _getopt_data *__data,\n-\t\t\t       int __posixly_correct);\n+\t\t\t       int __posixly_correct,\n+\t\t\t       char *(*translate) (const char *msgid));\n \n extern int _getopt_long_r (int ___argc, char **___argv,\n \t\t\t   const char *__shortopts,\ndiff --git a/posix/tstgetoptl.c b/posix/tstgetoptl.c\nnew file mode 100644\nindex 0000000000..afefcf46f5\n--- /dev/null\n+++ b/posix/tstgetoptl.c\n@@ -0,0 +1,139 @@\n+/* Check that getopt uses translated option names.  */\n+/* Copyright (C) 2026 Free Software Foundation, Inc.\n+   This file is part of the GNU C Library.\n+\n+   The GNU C Library is free software; you can redistribute it and/or\n+   modify it under the terms of the GNU Lesser General Public\n+   License as published by the Free Software Foundation; either\n+   version 2.1 of the License, or (at your option) any later version.\n+\n+   The GNU C Library is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n+   Lesser General Public License for more details.\n+\n+   You should have received a copy of the GNU Lesser General Public\n+   License along with the GNU C Library; if not, see\n+   <https://www.gnu.org/licenses/>.  */\n+\n+#include <getopt.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <libintl.h>\n+#include <locale.h>\n+#include <array_length.h>\n+#include <support/support.h>\n+#include <support/check.h>\n+\n+/* This tests that --colour is accepted as a translation of --color.\n+   This echoes tstgetopt.c, where --colour was an option name alias\n+   for --color, so it had to be listed twice.  */\n+\n+/* This uses the en_GB locale so that colour means color.  As a\n+   special case, we also check that non-translated options have\n+   precedence over translated options, by translating \"optional\" as\n+   \"required\".  We also check that getopt only matches translations\n+   for actual options, by having the user pass --flavour (which is a\n+   known translation of flavor) without the program recognizing a\n+   --flavor option.  */\n+\n+static void\n+prepare_localedir (void)\n+{\n+  unsetenv (\"LANGUAGE\");\n+  xsetlocale (LC_MESSAGES, \"en_GB.UTF-8\");\n+  TEST_VERIFY_EXIT (bindtextdomain (\"tstgetoptl\", OBJPFX \"domaindir\") != NULL);\n+  TEST_VERIFY_EXIT (textdomain (\"tstgetoptl\") != NULL);\n+  /* Check that the catalog is OK: */\n+  TEST_COMPARE_STRING (gettext (\"color\"), \"colour\");\n+  TEST_COMPARE_STRING (gettext (\"flavor\"), \"flavour\");\n+}\n+\n+static char **\n+prepare_argv (int *argc)\n+{\n+  static char *argv[] =\n+    {\n+      (char *) \"tstgetoptl\", (char *) \"--required\", (char *) \"foobar\",\n+      (char *) \"--optional=bazbug\", (char *) \"--col\", (char *) \"--color\",\n+      (char *) \"--colour\", (char *) \"--flavour\", NULL\n+    };\n+  *argc = array_length (argv) - 1;\n+  return argv;\n+}\n+\n+static void\n+do_my_test (void)\n+{\n+  int argc;\n+  char **argv = prepare_argv (&argc);\n+  static const struct option options[] =\n+    {\n+      {\"required\", required_argument, NULL, 'r'},\n+      {\"optional\", optional_argument, NULL, 'o'},\n+      {\"color\",\t   no_argument,\t      NULL, 'C'},\n+      /* Now colour is handled as a translation of color.  */\n+      /* Note that there’s no \"--flavor\" option, so the \"flavor\" ->\n+\t \"flavour\" translation is useless.  */\n+      {NULL, 0, NULL, 0 }\n+    };\n+\n+  /* This tests the same arguments as tstgetopt.c.  */\n+\n+  int Cflag = 0;\n+  int index;\n+  int c;\n+  bool found_flavor = false;\n+\n+  optind = 0;\n+  fputs (\"Reminder that --flavor is not an option of the program.\\n\", stderr);\n+  while ((c = getopt_long (argc, argv, \"\", options, NULL)) >= 0)\n+    switch (c)\n+      {\n+      case 'C':\n+\t++Cflag;\n+\tbreak;\n+      case '?':\n+\tTEST_VERIFY (!found_flavor);\n+\tfound_flavor = true;\n+\tbreak;\n+      default:\n+\t/* This should not happen.  */\n+\tsupport_record_failure_reset ();\n+\treturn;\n+\n+      case 'r':\n+\tprintf (\"--required %s\\n\", optarg);\n+\tTEST_COMPARE_STRING (optarg, \"foobar\");\n+\tbreak;\n+      case 'o':\n+\tprintf (\"--optional %s\\n\", optarg);\n+\tif (optarg != NULL)\n+\t  TEST_COMPARE_STRING (optarg, \"bazbug\");\n+\tbreak;\n+      }\n+\n+  TEST_VERIFY (found_flavor);\n+\n+  printf (\"Cflags = %d\\n\", Cflag);\n+\n+  TEST_COMPARE (Cflag, 3);\n+\n+  for (index = optind; index < argc; index++)\n+    printf (\"Non-option argument %s\\n\", argv[index]);\n+\n+  TEST_COMPARE (optind, argc);\n+}\n+\n+int\n+do_test (void)\n+{\n+  prepare_localedir ();\n+  do_my_test ();\n+  return 0;\n+}\n+\n+#define TEST_FUNCTION do_test\n+#include <support/test-driver.c>\ndiff --git a/posix/tstgetoptl.po b/posix/tstgetoptl.po\nnew file mode 100644\nindex 0000000000..7091884faf\n--- /dev/null\n+++ b/posix/tstgetoptl.po\n@@ -0,0 +1,29 @@\n+# English translations for tstgetoptl, a test case in glibc.\n+# Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER\n+# This file is distributed under the same license as the glibc package.\n+#\n+msgid \"\"\n+msgstr \"\"\n+\"Project-Id-Version: tstgetoptl 0.0.0\\n\"\n+\"Report-Msgid-Bugs-To: \\n\"\n+\"POT-Creation-Date: 2025-05-27 19:29+0200\\n\"\n+\"PO-Revision-Date: 2025-05-27 19:30+0200\\n\"\n+\"Language-Team: English (British) <(nothing)>\\n\"\n+\"Language: en_GB\\n\"\n+\"MIME-Version: 1.0\\n\"\n+\"Content-Type: text/plain; charset=ASCII\\n\"\n+\"Content-Transfer-Encoding: 8bit\\n\"\n+\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n+\n+#: xxx.c:yy\n+msgid \"color\"\n+msgstr \"colour\"\n+\n+#: xxx.c:yy\n+msgid \"flavor\"\n+msgstr \"flavour\"\n+\n+# This is to make sure the translator cannot redirect options.\n+#: xxx.c:yy\n+msgid \"optional\"\n+msgstr \"required\"\n",
    "prefixes": [
        "v22",
        "1/9"
    ]
}