Re: texi2dvi not passing locale to texindex
Gavin Smith <[email protected]> Mon, 20 Apr 2026 21:07:18 +0100
| Newsgroups | gmane.comp.tex.texinfo.bugs |
|---|---|
| Message-ID | <aeaHdlPeqLqXIXw9@orangestar> |
On Sun, Apr 19, 2026 at 09:27:13PM +0100, Gavin Smith wrote:
> * Here's my current preferred solution, which should work with any awk (gawk
> or mawk) regardless of the locale setting, as well as with XeTeX and
> LuaTeX (which Werner Lemberg reported problems with in 2022):
>
> In texinfo.tex, output multibyte UTF-8 sequences with braces around
> them in the sort key.
>
> This works because texindex preserves braced units.
[...]
> Possibly texinfo.tex could be further modified to uppercase é to Ã
> (or E if more appropriate). This should be possible in theory as
> we provide explicit definitions for all the Unicode characters we
> support
>
> (We've got no control over the collation order though - this is a
> fundamental limitation, but a minor one, in my opinion.)
>
>
> I've made a start on working on this last idea. Here's my current
> patch to texinfo.tex. I will need to do more work on this before
> committing anything.
At the end of this mail is an updated version of my patch.
This now outputs "é" as "e" in the index sort key, as shown:
$ cat test.texi
\input texinfo
@cindex à gré, césure
@cindex écrire des lettres
@cindex bbbb
Index:
@printindex cp
@bye
$ pdftex test.texi
[...]
$ cat test.cp
@entry{{à } gre, cesure}{1}{à gré, césure}
@entry{ecrire des lettres}{1}{écrire des lettres}
@entry{bbbb}{1}{bbbb}
$ LC_ALL=C texindex test.cp
$ cat test.cps
@initial {{Ã }}
@entry{à gré, césure}{1}
@initial {B}
@entry{bbbb}{1}
@initial {E}
@entry{écrire des lettres}{1}
Note how here é becomes e in the sort key, while à is output surrounded
by braces, which is the default for multibyte UTF-8 characters with this
patch.
The definition of the strings used in the sort key for é and à is in
the lines:
\DefineSortKey{00C9}{E} % E acute
\DefineSortKey{00E9}{e} % e acute
The first argument is the hexadecimal Unicode codepoint, the second
is the string to use.
Perhaps we could put these and similar lines in txi-fr.tex along
with the rest of the patch in texinfo.tex.
I've attached a couple of screenshots showing the current results
with latex2e-fr.texi (I had to comment out a line with @image in
the version I've been sent as I didn't have the image file referenced).
This appears to me to be an improvement, as the version of latex2e-fr.pdf
on the website (at http://latexref.xyz/) has all the entries beginning
with accented characters at the start of the index, before "A".
What would be much harder would be to make a letter sort as its
own independent letter between A and Z, with its own heading in the
index: for example, à between N and O. We could make à sort between
N and O by outputting its sort string as NZZZ, but texindex would take
an entry with a sort key beginning with NZZZ as part of the "N"
section. (I'm not sure what languages this would be an issue for.)
Also multi-level collation (as in the Unicode Collation Algorithm)
is right out.
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
index d429e32031..dcf7855768 100644
--- a/doc/texinfo.tex
+++ b/doc/texinfo.tex
@@ -5437,6 +5437,7 @@ $$%
\extractindexcommands\segment
\ifx\indexsortkey\empty{%
\indexnonalnumdisappear
+ \inindexsortkeytrue
\xdef\trimmed{\segment}%
\xdef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}%
\xdef\indexsortkey{\trimmed}%
@@ -10711,6 +10712,23 @@ directory should work if nowhere else does.}
\newif\ifutfviiidefinedwarning
\utfviiidefinedwarningtrue
+% Macros to output multibyte UTF-8 sequences surrounded by braces.
+% Check if there is a special definition to be used in the index
+% sort key for a character.
+\gdef\UTFviiiSortkeyTwo#1#2{%
+ \expandafter\ifx\csname sort:#1#2\endcsname\relax
+ {\string #1\string #2}%
+ \else
+ \csname sort:#1#2\endcsname
+ \fi
+}
+\gdef\UTFviiiSortkeyThree#1#2#3{{\string #1\string #2\string #3}}
+\gdef\UTFviiiSortkeyFour#1#2#3#4{{\string #1\string #2\string #3\string #4}}
+
+% We use this with the \ifindexsortkey condition to expand and discard
+% an \else block in the containing conditional.
+\def\swapnestedfi#1\fi{\fi\expandafter#1\expandafter}
+
% Give non-ASCII bytes the active definitions for processing UTF-8 sequences
\begingroup
\catcode`\~13
@@ -10729,8 +10747,8 @@ directory should work if nowhere else does.}
\expandafter\UTFviiiLoop
\fi}
%
- % For bytes other than the first in a UTF-8 sequence. Not expected to
- % be expanded except when writing to auxiliary files.
+ % UTF-8 continuation bytes (10XX XXXX) or unused (hex C1, C2).
+ % Not expected to be expanded except when writing to auxiliary files.
\countUTFx = "80
\countUTFy = "C2
\def\UTFviiiTmp{%
@@ -10742,7 +10760,9 @@ directory should work if nowhere else does.}
\countUTFy = "E0
\def\UTFviiiTmp{%
\gdef~{%
- \ifpassthroughchars $%
+ \ifpassthroughchars
+ \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyTwo\fi
+ $%
\else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}%
\UTFviiiLoop
@@ -10750,7 +10770,9 @@ directory should work if nowhere else does.}
\countUTFy = "F0
\def\UTFviiiTmp{%
\gdef~{%
- \ifpassthroughchars $%
+ \ifpassthroughchars
+ \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyThree\fi
+ $%
\else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}%
\UTFviiiLoop
@@ -10758,7 +10780,9 @@ directory should work if nowhere else does.}
\countUTFy = "F4
\def\UTFviiiTmp{%
\gdef~{%
- \ifpassthroughchars $%
+ \ifpassthroughchars
+ \ifinindexsortkey\swapnestedfi\UTFviiiSortkeyFour\fi
+ $%
\else\expandafter\UTFviiiFourOctets\expandafter$\fi
}}%
\UTFviiiLoop
@@ -10852,7 +10876,7 @@ directory should work if nowhere else does.}
\parseXMLCharref
%
% Completely expand \UTFviiiTmp, which looks like:
- % 1. \UTFviiTwoOctetsName B1 B2
+ % 1. \UTFviiiTwoOctetsName B1 B2
% 2. \csname u8:B1 \string B2 \endcsname
% 3. \u8: B1 B2 (a single control sequence token)
\xdef\UTFviiiTmp{\UTFviiiTmp}%
@@ -10929,6 +10953,39 @@ directory should work if nowhere else does.}
\uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
\endgroup
+% Used in \DefineSortKey as temporary definitions of \UTFviiiTwoOctetsName etc.
+\def\UTFviiiSortTwoOctetsName#1#2{%
+ \csname sort:#1\string #2\endcsname}%
+\def\UTFviiiSortThreeOctetsName#1#2#3{%
+ \csname sort:#1\string #2\string #3\endcsname}%
+\def\UTFviiiSortFourOctetsName#1#2#3#4{%
+ \csname sort:#1\string #2\string #3\string #4\endcsname}%
+
+% To be used in translation files to provide strings to be output
+% in the index sort key where a character occurs.
+\def\DefineSortKey#1#2{%
+ \countUTFz = "#1\relax
+ \parseXMLCharref
+ \expandafter\let\csname sort:#1\endcsname\tmp
+
+ \bgroup
+ \let\UTFviiiTwoOctetsName\UTFviiiSortTwoOctetsName
+ \let\UTFviiiThreeOctetsName\UTFviiiSortThreeOctetsName
+ \let\UTFviiiFourOctetsName\UTFviiiSortFourOctetsName
+ %
+ % Completely expand \UTFviiiTmp, which looks like:
+ % 1. \UTFviiiTwoOctetsName B1 B2
+ % 2. \csname sort:B1 \string B2 \endcsname
+ % 3. \sort: B1 B2 (a single control sequence token)
+ \xdef\UTFviiiTmp{\UTFviiiTmp}%
+ \egroup
+ \expandafter\def\UTFviiiTmp{#2}%
+}
+
+\DefineSortKey{00C9}{E} % E acute
+\DefineSortKey{00E9}{e} % e acute
+
+
% For native Unicode handling (XeTeX and LuaTeX),
% provide a definition macro that sets a catcode to `other' non-globally
%
@@ -11757,6 +11814,9 @@ directory should work if nowhere else does.}
\newif\ifpassthroughchars
\passthroughcharsfalse
+\newif\ifinindexsortkey
+\inindexsortkeyfalse
+
% For native Unicode handling (XeTeX and LuaTeX),
% provide a definition macro to replace/pass-through a Unicode character
%
@@ -11768,7 +11828,11 @@ directory should work if nowhere else does.}
\uccode`\~="##2\relax
\uppercase{\gdef~}{%
\ifpassthroughchars
- ##1%
+ \ifinindexsortkey
+ {##1}%
+ \else
+ ##1%
+ \fi
\else
##3%
\fi
index-e.png
(image/png, 208.3 KB) - not displayed
index-a.png
(image/png, 115.2 KB) - not displayed