# Sorting swedish index with makeidx correctly

I have a problem getting makeidx sort the special characters of the swedish alphabet, å,ä and ö. They are supposed to be the last three positions, but they appear in the index before "A".

How can makeidx behaviour be changed to the correct sorting?

-
As far as I know MakeIndex knows only ASCII sorting and a special German one, and 8 bit encodings or Unicode are not supported. You have to use Xindy for different sorting rules, I'm afraid. – egreg Feb 19 '13 at 16:12
@egreg How unfortunate. I've tried to use Xindy but as far as I understand, pearl is required. This minimizes portability. Are there any other system that don't require external software? – Hugo Feb 19 '13 at 16:28
Sorry, no; MakeIndex is really old and Xindy is the way to go. – egreg Feb 19 '13 at 16:42
It's not an easy problem as sorting Swedish correctly requires either dedicated Swedish support in the tool or, as it increasingly common, real UTF-8 support. In fact this isn't quite enough either as the tool needs to support CLDR tailoring of the Unicode Collation algorithm as this is needed to sort Swedish correctly. biblatex+biber can do this for Swedish in bibliography sorting as it supports UTF-8 plus CLDR but for indexing, xindy, as far as I know, uses its own custom modules and doesn't support a real Unicode Collation algorithm. – PLK May 18 '13 at 15:17

The correct approach is probably to use a more modern alternative to makeindex, as was suggested in the comments.

However, it is possible to trick makeindex into thinking that those letters are in fact characters in the range 127–255, which it considers larger than any other. What the code below does is to turn \index{ångström} into \index{^^80ngstr^^82m@ångström}, where ^^80 and ^^82 (hexadecimal) denote the characters with character code 128 and 130. The part before @ will be used by makeindex for sorting purposes. The part after @ is used as the TeX code to display the entry.

Compile with pdflatex file.tex, makeindex file.idx, pdflatex file.tex.

\documentclass{article}
\usepackage{makeidx}
\makeindex
\usepackage{lipsum}
\usepackage[utf8]{inputenc}

%%%%% The letters z, å, ä and ö should be sorted in that order.  This is
%%%%% done by turning å, ä and ö into characters 128 to 130 (80 to 82 in

\usepackage{expl3}
\ExplSyntaxOn
\makeatletter
\tl_new:N \l_wrindex_tl
\cs_generate_variant:Nn \tl_replace_all:Nnn { Nx }
\cs_new_protected:Npn \wrindex:n #1
{
\tl_set:Nn \l_wrindex_tl {#1}
\tl_replace_all:Nxn \l_wrindex_tl { \token_to_str:N @ } { @ }
\tl_if_in:NnF \l_wrindex_tl { @ }
{ \tl_put_right:Nx \l_wrindex_tl { @ \exp_not:V \l_wrindex_tl } }
\exp_after:wN \wrindex_aux:w \l_wrindex_tl \q_stop
}
\cs_new_protected:Npn \wrindex_aux:w #1 @ #2 \q_stop
{
\tl_set:Nn \l_wrindex_tl {#1}
\tl_replace_all:Nnn \l_wrindex_tl { å } { ^^80 }
\tl_replace_all:Nnn \l_wrindex_tl { ä } { ^^81 }
\tl_replace_all:Nnn \l_wrindex_tl { ö } { ^^82 }
\wrindex_do:x { \tl_to_str:N \l_wrindex_tl @ \exp_not:n {#2} }
}
\cs_new_eq:NN \wrindex_do:n \@wrindex
\cs_generate_variant:Nn \wrindex_do:n { x }
\cs_set_eq:NN \@wrindex \wrindex:n
\makeatother
\ExplSyntaxOff

\begin{document}
\lipsum[1-2]\index{car}\index{za}
\lipsum[3-4]\index{cåb}\index{zå}
\lipsum[5-6]\index{car}\index{åa}
\lipsum[1-2]\index{cz}\index{ä}
\lipsum[3-4]\index{da}
\printindex
\end{document}


But really, use a xindy, or whatever people use nowadays (I don't usually deal in indexes, so other people's opinions are more useful).

-
This fails if you use "see": \index{blub|see{cz}} leads to the error !! Input index error (file = test-utf8.idx, line = 10): -- Extra @' at position 13 of first argument. in the ilg. – Ulrike Fischer Feb 7 '14 at 11:26
@UlrikeFischer The correct approach (besides switching to a more modern tool for indexes) would be to parse the argument of \index. Do you know of a full description of the syntax? – Bruno Le Floch Feb 7 '14 at 22:06

I enclose an example using Xindy. We can run it with shell escape on thanks to imakeidx package, or, we can run these three lines externally:

lualatex mal-xindy-swedish.tex
xindy -M texindy -L swedish -C utf8 -M mal-style mal-xindy-swedish.idx
lualatex mal-xindy-swedish.tex

%! lualatex mal-xindy-numbers.tex
%  with shell escape on
% or
%!lualatex mal-xindy-swedish.tex
%!xindy -M texindy -L swedish -C utf8 -M mal-style -o mal-xindy-swedish.ind mal-xindy-swedish.idx
%!lualatex mal-xindy-swedish.tex
\documentclass[a4paper]{article}
%\usepackage[utf8]{inputenc}% pdflatex, but it would need additional setup to get everything working
%\usepackage{xltxtra}% xelatex
\usepackage{luatextra}% lualatex
\usepackage[xindy]{imakeidx}
\indexsetup{firstpagestyle=empty}
\makeatletter\def\imki@progdefault{xindy}\makeatother
\makeindex[title=Index of Swedish words, options=-M texindy -L swedish -C utf8 -M mal-style, columns=2]
\usepackage{filecontents}
\begin{filecontents*}{mal-style.xdy}
(markup-locref :attr "default" :open "\hyperpage{" :close "}")
\end{filecontents*}

\begin{document}
My first paragraph!
\index{massabruk}
\index{lagerstyrare}
% Terms from http://tex.stackexchange.com/questions/98944/sorting-swedish-index-with-makeidx-correctly
\index{car}\index{za}
\index{cåb}\index{zå}
\index{car}\index{åa}
\index{cz}\index{ä}
\index{da}\index{ångström}
% From English->Swedish lite dictionary
\index{överge}\index{ändå}
\index{årlig}\index{åsikt}
\index{Ö}\index{Ändå}
\index{Årlig}\index{Åsikt}
\index{skändlig}\index{Skändlig}
\index{förstuga}\index{Förstuga}
\index{förrum}\index{Förrum}
\index{äga}\index{Äga}
\index{äganderätt}\index{Äganderätt}
\index{överanstränga}\index{Överanstränga}
\printindex
\end{document}
`

-