"Kefu Chai" <[email protected]> writes:

> On Tue Feb 17, 2026 at 11:45 PM CST, Maximiliano Sandoval wrote:
>
> Hi Maximiliano,
>
> Thanks for the detailed testing and feedback! I've addressed all the
> points you raised.
>
>> Kefu Chai <[email protected]> writes:
>>
>> Thanks for the update. Comments below.
>>
>>> This commit adds message context (msgctxt) support to the JavaScript
>>> [..]
>>>  Makefile |  1 +
>>>  po2js.pl | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--------
>>>  2 files changed, 61 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/Makefile b/Makefile
>>> index 86bd723..3feaee7 100644
>>> --- a/Makefile
>>> +++ b/Makefile
>>> @@ -155,6 +155,7 @@ define potupdate
>>>        --package-version="$(shell cd $(2);git rev-parse HEAD)" \
>>>        --msgid-bugs-address="<[email protected]>" \
>>>        --copyright-holder="Copyright (C) Proxmox Server Solutions GmbH 
>>> <[email protected]> & the translation contributors." \
>>> +      --keyword=npgettext:1c,2,3 \
>>
>> You were right in your previous reply, however as I mentioned, gettext
>> by default has keys for gettext, ngettext, pgettext and npgettext. There
>> is no need to add this here.
>
> I investigated this further and found that while this is true for C/C++, it's
> not true for JavaScript. The --keyword flag is actually required.
>
> According to the GNU gettext manual [1], the default keywords are
> language-specific:
>
>   For C, C++, GCC-source:
>     gettext, dgettext:2, dcgettext:2, ngettext:1,2, dngettext:2,3,
>     dcngettext:2,3, gettext_noop, pgettext:1c,2, dpgettext:2c,3,
>     dcpgettext:2c,3, npgettext:1c,2,3, dnpgettext:2c,3,4, dcnpgettext:2c,3,4
>
>   For JavaScript, TypeScript, TSX:
>     _, gettext, dgettext:2, dcgettext:2, ngettext:1,2, dngettext:2,3,
>     pgettext:1c,2, dpgettext:2c,3
>
> Notice that npgettext is present in C/C++ defaults but ABSENT from JavaScript.
>
> The xgettext source code confirms this. In gettext-tools/src/x-c.c [2]:
>
>   static void init_keywords () {
>     if (default_keywords) {
>       x_c_keyword ("gettext");
>       x_c_keyword ("dgettext:2");
>       x_c_keyword ("dcgettext:2");
>       x_c_keyword ("ngettext:1,2");
>       x_c_keyword ("dngettext:2,3");
>       x_c_keyword ("dcngettext:2,3");
>       x_c_keyword ("gettext_noop");
>       x_c_keyword ("pgettext:1c,2");
>       x_c_keyword ("dpgettext:2c,3");
>       x_c_keyword ("dcpgettext:2c,3");
>       x_c_keyword ("npgettext:1c,2,3");      /* <- present for C */
>       x_c_keyword ("dnpgettext:2c,3,4");
>       x_c_keyword ("dcnpgettext:2c,3,4");
>       // ...
>     }
>   }
>
> But in gettext-tools/src/x-javascript.c [3]:
>
>   static void init_keywords () {
>     if (default_keywords) {
>       x_javascript_keyword ("gettext");
>       x_javascript_keyword ("dgettext:2");
>       x_javascript_keyword ("dcgettext:2");
>       x_javascript_keyword ("ngettext:1,2");
>       x_javascript_keyword ("dngettext:2,3");
>       x_javascript_keyword ("pgettext:1c,2");
>       x_javascript_keyword ("dpgettext:2c,3");
>       x_javascript_keyword ("_");
>       /* npgettext is NOT here */      /* <- absent for JavaScript */
>       default_keywords = false;
>     }
>   }
>
> The official release notes for gettext 0.18.3 (July 2013) [4] explain
> the reason of the difference:
>
>
>   "JavaScript:
>    xgettext now partially supports JavaScript. Since the current
>    JavaScript specification (ECMA-262) does not define the standard
>    set of formatting methods nor translation functions, the
>    implementation supports only a limited set of formatting methods
>    and translation functions commonly used in Gjs and other popular
>    JavaScript implementations and libraries."
>
> This was a deliberate design decision to include only commonly-used
> functions in the JavaScript defaults. The context+plural combination
> (npgettext) was apparently not common enough in 2013 to be included.
>
> We can confirm with testing:
>
>   # C: npgettext extracted by default
>   $ echo 'npgettext("ctx", "s", "p", n);' > test.c
>   $ xgettext test.c -o - | grep msgctxt
>   msgctxt "ctx"  # GOOD!
>
>   # JavaScript: npgettext NOT extracted without --keyword
>   $ echo 'npgettext("ctx", "s", "p", n);' > test.js
>   $ xgettext --language=JavaScript test.js -o - | grep msgctxt
>   (empty)  # MISSING!
>
>   # JavaScript WITH --keyword flag
>   $ xgettext --language=JavaScript --keyword=npgettext:1c,2,3 test.js -o - | 
> grep msgctxt
>   msgctxt "ctx"  # GOOD!
>
> References:
>
> [1] GNU gettext manual - xgettext Invocation (Language-specific default 
> keywords)
>     
> https://www.gnu.org/software/gettext/manual/html_node/xgettext-Invocation.html
>
> [2] gettext source: x-c.c (C language keyword definitions)
>     
> https://github.com/autotools-mirror/gettext/blob/master/gettext-tools/src/x-c.c
>
> [3] gettext source: x-javascript.c (JavaScript language keyword definitions)
>     
> https://github.com/autotools-mirror/gettext/blob/master/gettext-tools/src/x-javascript.c
>
> [4] gettext 0.18.3 Release Notes (July 2013 - JavaScript support added)
>     https://git.savannah.gnu.org/gitweb/?p=gettext.git;a=blob;f=NEWS
>     Or: https://github.com/autotools-mirror/gettext/blob/master/NEWS

Thanks for digging up all this! When you send a new version, please link
the GNU gettext manual in the commit message with a brief explanation of
why it is needed.

>>
>>>        --output="$(1)".pot
>>>  endef
>>>  
>>> diff --git a/po2js.pl b/po2js.pl
>>> index 316c0bd..4b7b044 100755
>>> [..]
>>>  
>>>  if ($outfile) {
>>
>>
>> I tested this with pve-manager.
>>
>> - Sprinkled a few uses of pgettext
>> - Extracted the strings with make do_update at proxmox-i18n
>> - Translated two strings with context
>> - Checked that the translated string were visible at the web UI and that
>>   each one had the correct translation given its context
>>
>> To make the above work I had to patch proxmox-biome to accept the
>> ngettext and pngettext keywords:
>>
>> modified   src/biome.json
>> @@ -128,7 +128,9 @@
>>              "Proxmox",
>>              "eslint",
>>              "ngettext",
>> -            "gettext"
>> +            "gettext",
>> +            "pgettext",
>> +            "npgettext"
>>          ]
>>      }
>>  }
>
> Updated proxmox-biome/src/biome.json to add pgettext and npgettext
> to the globals list. Will send a separate patch to the mailing list.
>
>>
>> Otherwise `make deb` would fail when building the .debs.
>>
>> I also had to modify the index.html.tpl to pve-manager to have default
>> implementations for these fns, otherwise the UI won't work if there is
>> no language selected (which is the default):
>
> Done. Added default implementations to all three locations:
>   - pve-manager/www/index.html.tpl
>   - proxmox-backup/www/index.hbs
>   - pmg-gui/pmg-index.html.tt
>
> Will update them separately, and bump up the submodules in the next
> revision of this patch once these patches land.
>
> FWIW, to replicate your testing approach, I performed the following
> verification:
>
> 1. Added pgettext/npgettext test translation to zh_CN.po, 
> 2. Generated JavaScript with po2js.pl:
>    ./po2js.pl -t pve -v "3.6.6" -o pve-lang-zh_CN-test.js zh_CN.po
> 3. Verified context-aware translations in generated JavaScript manually.
>
> Also, I built all .deb packages with:
>
>   make deb
>
>
>>
>> modified   www/index.html.tpl
>> @@ -27,6 +27,8 @@
>>      <script type='text/javascript'>
>>          function gettext(message) { return message; }
>>          function ngettext(singular, plural, count) { return count === 1 ? 
>> singular : plural; }
>> +        function pgettext(context, message) { return message; }
>> +        function pngettext(context, singular, plural, count) { return count 
>> === 1 ? singular : plural; }
>>      </script>
>>      [% END %]
>>      [%- IF debug %]
>>
>> There are similar files at pmg-gui and proxmox-backup-server that would
>> also need updating.

-- 
Maximiliano



Reply via email to