From c682a2af4035b8fc25ef591f11edb7e57bd51179 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Thu, 14 Oct 2021 03:01:09 +0000
Subject: CTAN sync 202110140301

---
 macros/latex/required/babel/base/babel.dtx | 11076 +++++++++++++--------------
 1 file changed, 5508 insertions(+), 5568 deletions(-)

(limited to 'macros/latex/required/babel/base/babel.dtx')

diff --git a/macros/latex/required/babel/base/babel.dtx b/macros/latex/required/babel/base/babel.dtx
index 28b1a76683..6fe5db94f2 100644
--- a/macros/latex/required/babel/base/babel.dtx
+++ b/macros/latex/required/babel/base/babel.dtx
@@ -32,7 +32,7 @@
 %
 % \iffalse
 %<*filedriver>
-\ProvidesFile{babel.dtx}[2021/07/22 v3.63 The Babel package]
+\ProvidesFile{babel.dtx}[2021/10/13 v3.64 The Babel package]
 \documentclass{ltxdoc}
 \GetFileInfo{babel.dtx}
 \usepackage{fontspec}
@@ -788,9 +788,11 @@ group.
   |\text...| is heavily overloaded in \LaTeX{} and conflicts with
   existing macros may arise (|\textlatin|, |\textbar|, |\textit|,
   |\textcolor| and many others). The same applies to environments,
-  because |arabic| conflicts with |\arabic|. Except if there is a
-  reason for this ‘syntactical sugar’, the best option is to stick to
-  the default selectors or to define your own alternatives. 
+  because |arabic| conflicts with |\arabic|. Furthermore, and because of
+  this overloading, detecting the language of a chunk of text by
+  external tools can become unfeasible. Except if there is a reason for
+  this ‘syntactical sugar’, the best option is to stick to the default
+  selectors or to define your own alternatives.
 \end{warning}
 
 \begin{example}
@@ -2278,7 +2280,7 @@ to select fonts in addition to the three basic families.
   \textit{Package fontspec Warning: 'Language 'LANG' not available for
   font 'FONT' with script 'SCRIPT' 'Default' language used instead'}.
 
-  \textbf{This is \textit{not} and error.} This warning is shown by
+  \textbf{This is \textit{not} an error.} This warning is shown by
   \textsf{fontspec}, not by \babel. It can be irrelevant for English,
   but not for many other languages, including Urdu and Turkish. This is
   a useful and harmless warning, and if everything is fine with your
@@ -2290,7 +2292,7 @@ to select fonts in addition to the three basic families.
   standard families} \textit{Package babel Info: The following fonts
   are not babel standard families}.
 
-  \textbf{This is \textit{not} and error.} \babel{} assumes that if you
+  \textbf{This is \textit{not} an error.} \babel{} assumes that if you
   are using |\babelfont| for a family, very likely you want to define
   the rest of them. If you don't, you can find some inconsistencies
   between families. This checking is done at the beginning of the
@@ -4859,7 +4861,7 @@ corresponding place. A selective list follows:
 \item Active chars where not reset at the end of language options, and
   that lead to incompatibilities between languages.
 
-\item |\textormath| raised and error with a conditional.
+\item |\textormath| raised an error with a conditional.
 
 \item |\aliasshorthand| didn't work (or only in a few and very specific
   cases).
@@ -5024,8 +5026,8 @@ help from Bernd Raichle, for which I am grateful.
 % \section{Tools}
 %
 %    \begin{macrocode}
-%<<version=3.63>>
-%<<date=2021/07/22>>
+%<<version=3.64>>
+%<<date=2021/10/13>>
 %    \end{macrocode}
 %
 % \textbf{Do not use the following macros in \texttt{ldf} files. They
@@ -5111,9 +5113,13 @@ help from Bernd Raichle, for which I am grateful.
 \def\bbl@exp#1{%
   \begingroup
     \let\\\noexpand
-    \def\<##1>{\expandafter\noexpand\csname##1\endcsname}%
+    \let\<\bbl@exp@en
+    \let\[\bbl@exp@ue
     \edef\bbl@exp@aux{\endgroup#1}%
   \bbl@exp@aux}
+\def\bbl@exp@en#1>{\expandafter\noexpand\csname#1\endcsname}%
+\def\bbl@exp@ue#1]{%
+  \unexpanded\expandafter\expandafter\expandafter{\csname#1\endcsname}}%
 %    \end{macrocode}
 % \end{macro}
 %
@@ -5146,7 +5152,7 @@ help from Bernd Raichle, for which I am grateful.
 % \begin{macro}{\bbl@ifunset}
 %   To check if a macro is defined, we create a new macro, which does
 %   the same as |\@ifundefined|. However, in an $\epsilon$-tex engine,
-%   it is based on |\ifcsname|, which is more efficient, and do not
+%   it is based on |\ifcsname|, which is more efficient, and does not
 %   waste memory.
 %
 %    \begin{macrocode}
@@ -5157,7 +5163,7 @@ help from Bernd Raichle, for which I am grateful.
     \else
       \expandafter\@secondoftwo
     \fi}
-  \bbl@ifunset{ifcsname}%
+  \bbl@ifunset{ifcsname}% TODO. A better test?
     {}%
     {\gdef\bbl@ifunset#1{%
        \ifcsname#1\endcsname
@@ -5358,7 +5364,8 @@ help from Bernd Raichle, for which I am grateful.
 %
 % The following adds some code to |\extras...| both before and after,
 % while avoiding doing it twice. It's somewhat convoluted, to deal with
-% |#|'s.
+% |#|'s. Used to deal with alph, Alph and frenchspacing when there are
+% already changes (with |\babel@save|). 
 %
 %    \begin{macrocode}  
 \def\bbl@extras@wrap#1#2#3{% 1:in-test, 2:before, 3:after
@@ -5446,21 +5453,16 @@ help from Bernd Raichle, for which I am grateful.
 %
 % \subsection{The Package File (\LaTeX, \texttt{babel.sty})}
 %
-% This file also takes care of a number of compatibility issues with
-% other packages an defines a few aditional package options. Apart from
-% all the language options below we also have a few options that
-% influence the behavior of language definition files.
-%
-% Many of the following options don't do anything themselves, they are
-% just defined in order to make it possible for babel and language
-% definition files to check if one of them was specified by the user.
-%
-% The first two options are for debugging.
-%
 %    \begin{macrocode}
 %<*package>
 \NeedsTeXFormat{LaTeX2e}[2005/12/01]
 \ProvidesPackage{babel}[<@date@> <@version@> The Babel package]
+%    \end{macrocode}
+% 
+% Start with some “private” debugging tool, and then define macros for
+% errors.
+%
+%    \begin{macrocode}
 \@ifpackagewith{babel}{debug}
   {\providecommand\bbl@trace[1]{\message{^^J[ #1 ]}}%
    \let\bbl@debug\@firstofone
@@ -5475,64 +5477,43 @@ help from Bernd Raichle, for which I am grateful.
      \directlua{ Babel = Babel or {}
        Babel.debug = false }%
    \fi}
+\def\bbl@error#1#2{%
+  \begingroup
+    \def\\{\MessageBreak}%
+    \PackageError{babel}{#1}{#2}%
+  \endgroup}
+\def\bbl@warning#1{%
+  \begingroup
+    \def\\{\MessageBreak}%
+    \PackageWarning{babel}{#1}%
+  \endgroup}
+\def\bbl@infowarn#1{%
+  \begingroup
+    \def\\{\MessageBreak}%
+    \GenericWarning
+      {(babel) \@spaces\@spaces\@spaces}%
+      {Package babel Info: #1}%
+  \endgroup}
+\def\bbl@info#1{%
+  \begingroup
+    \def\\{\MessageBreak}%
+    \PackageInfo{babel}{#1}%
+  \endgroup}
+%    \end{macrocode}
+%
+% This file also takes care of a number of compatibility issues with
+% other packages an defines a few aditional package options. Apart from
+% all the language options below we also have a few options that
+% influence the behavior of language definition files.
+%
+% Many of the following options don’t do anything themselves, they are
+% just defined in order to make it possible for babel and language
+% definition files to check if one of them was specified by the user.
+%
+% But first, include here the \textit{Basic macros} defined above.
+%
+%    \begin{macrocode}
 <@Basic macros@>
-  % Temporarily repeat here the code for errors. TODO.
-  \def\bbl@error#1#2{%
-    \begingroup
-      \def\\{\MessageBreak}%
-      \PackageError{babel}{#1}{#2}%
-    \endgroup}
-  \def\bbl@warning#1{%
-    \begingroup
-      \def\\{\MessageBreak}%
-      \PackageWarning{babel}{#1}%
-    \endgroup}
-  \def\bbl@infowarn#1{%
-    \begingroup
-      \def\\{\MessageBreak}%
-      \GenericWarning
-        {(babel) \@spaces\@spaces\@spaces}%
-        {Package babel Info: #1}%
-    \endgroup}
-  \def\bbl@info#1{%
-    \begingroup
-      \def\\{\MessageBreak}%
-      \PackageInfo{babel}{#1}%
-    \endgroup}
-\def\bbl@nocaption{\protect\bbl@nocaption@i}
-% TODO - Wrong for \today !!! Must be a separate macro.
-\def\bbl@nocaption@i#1#2{% 1: text to be printed 2: caption macro \langXname
-  \global\@namedef{#2}{\textbf{?#1?}}%
-  \@nameuse{#2}%
-  \edef\bbl@tempa{#1}%
-  \bbl@sreplace\bbl@tempa{name}{}%
-  \bbl@warning{%
-    \@backslashchar#1 not set for '\languagename'. Please,\\%
-    define it after the language has been loaded\\%
-    (typically in the preamble) with\\% 
-    \string\setlocalecaption{\languagename}{\bbl@tempa}{..}\\%
-    Reported}}
-\def\bbl@tentative{\protect\bbl@tentative@i}
-\def\bbl@tentative@i#1{%
-  \bbl@warning{%
-    Some functions for '#1' are tentative.\\%
-    They might not work as expected and their behavior\\%
-    may change in the future.\\%
-    Reported}}
-\def\@nolanerr#1{%
-  \bbl@error
-    {You haven't defined the language '#1' yet.\\%
-     Perhaps you misspelled it or your installation\\%
-     is not complete}%
-    {Your command will be ignored, type <return> to proceed}}
-\def\@nopatterns#1{%
-  \bbl@warning
-    {No hyphenation patterns were preloaded for\\%
-     the language '#1' into the format.\\%
-     Please, configure your TeX system to add them and\\%
-     rebuild the format. Now I will use the patterns\\%
-     preloaded for \bbl@nulllanguage\space instead}}
-    % End of errors
 \@ifpackagewith{babel}{silent}
   {\let\bbl@info\@gobble
    \let\bbl@infowarn\@gobble
@@ -5601,7 +5582,7 @@ help from Bernd Raichle, for which I am grateful.
   \global\let\@ifl@ter@@\@ifl@ter
   \def\@ifl@ter#1#2#3#4#5{\global\let\@ifl@ter\@ifl@ter@@}%
   \endinput}{}%
-% \end{macrocode}
+%    \end{macrocode}
 %
 % \subsection{\texttt{key=value} options and other general option}
 %
@@ -5714,8 +5695,12 @@ help from Bernd Raichle, for which I am grateful.
   \bbl@xin@{\string=}{\CurrentOption}%
   \ifin@
     \expandafter\bbl@tempa\CurrentOption\bbl@tempa
-  \else
-    \bbl@add@list\bbl@language@opts{\CurrentOption}%
+  \else  
+    \bbl@xin@{,\CurrentOption,}{,\bbl@language@opts,}%
+    \ifin@
+      \bbl@exp{\\\bbl@replace\\\bbl@language@opts{,\CurrentOption,}{}}%
+    \fi
+    \edef\bbl@language@opts{\bbl@language@opts,\CurrentOption,}
   \fi}
 %    \end{macrocode}
 %
@@ -5726,8 +5711,16 @@ help from Bernd Raichle, for which I am grateful.
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ifx\bbl@opt@provide\@nnil\else % Tests. Ignore.
+\ifx\bbl@opt@provide\@nnil
+  \let\bbl@opt@provide\@empty  % %%% MOVE above
+\else 
   \chardef\bbl@iniflag\@ne
+  \bbl@exp{\\\bbl@forkv{\@nameuse{@raw@opt@babel.sty}}}{%
+    \in@{,provide,}{,#1,}%
+    \ifin@
+      \def\bbl@opt@provide{#2}%
+      \bbl@replace\bbl@opt@provide{;}{,}%
+    \fi}
 \fi
 % 
 %    \end{macrocode}
@@ -5813,10 +5806,13 @@ help from Bernd Raichle, for which I am grateful.
 \ifx\bbl@opt@safe\@undefined
   \def\bbl@opt@safe{BR}
 \fi
+%    \end{macrocode}
+%
+% Make sure the language set with `main` is the last one. 
+%
+%    \begin{macrocode}
 \ifx\bbl@opt@main\@nnil\else
-  \edef\bbl@language@opts{%
-    \ifx\bbl@language@opts\@empty\else\bbl@language@opts,\fi
-      \bbl@opt@main}
+  \edef\bbl@language@opts{\bbl@language@opts,\bbl@opt@main,}
 \fi
 %    \end{macrocode}
 %
@@ -5837,6463 +5833,6355 @@ help from Bernd Raichle, for which I am grateful.
       \expandafter\@secondoftwo
     \fi}
 \fi
+%</package>
+%<*core>
 %    \end{macrocode}
 %
-% \textbf{Common definitions.} \textit{In progress.} Still based on
-% |babel.def|, but the code should be moved here.
-%
-%    \begin{macrocode}
-\input babel.def
-%    \end{macrocode}
-%
-% \subsection{Cross referencing macros}
-%
-% The \LaTeX\ book states:
-% \begin{quote}
-%   The \emph{key} argument is any sequence of letters, digits, and
-%   punctuation symbols; upper- and lowercase letters are regarded as
-%   different.
-% \end{quote}
-% When the above quote should still be true when a document is
-% typeset in a language that has active characters, special care
-% has to be taken of the category codes of these characters when
-% they appear in an argument of the cross referencing macros.
-%
-% When a cross referencing command processes its argument, all
-% tokens in this argument should be character tokens with category
-% `letter' or `other'.
+% \subsection{Interlude for Plain}
 %
-% The following package options control which macros are to be
-% redefined.
+% Because of the way \pkg{docstrip} works, we need to insert some code
+% for Plain here. However, the tools provided by the \babel{}
+% installer for literate programming makes this section a short
+% interlude, because the actual code is below, tagged as
+% \textit{Emulate LaTeX}.
 %
 %    \begin{macrocode}
-%<<*More package options>>
-\DeclareOption{safe=none}{\let\bbl@opt@safe\@empty}
-\DeclareOption{safe=bib}{\def\bbl@opt@safe{B}}
-\DeclareOption{safe=ref}{\def\bbl@opt@safe{R}}
-%<</More package options>>
+\ifx\ldf@quit\@undefined\else
+\endinput\fi % Same line!
+<@Make sure ProvidesFile is defined@>
+\ProvidesFile{babel.def}[<@date@> <@version@> Babel common definitions]
+\ifx\AtBeginDocument\@undefined  % TODO. change test.
+  <@Emulate LaTeX@>
+\fi
 %    \end{macrocode}
 %
-% \begin{macro}{\@newl@bel}
-%
-% First we open a new group to keep the changed setting of
-% |\protect| local and then we set the |@safe@actives| switch to
-% true to make sure that any shorthand that appears in any of the
-% arguments immediately expands to its non-active self.
+% That is all for the moment. Now follows some common stuff, for both
+% Plain and \LaTeX{}. After it, we will resume the \LaTeX-only stuff.
 %
 %    \begin{macrocode}
-\bbl@trace{Cross referencing macros}
-\ifx\bbl@opt@safe\@empty\else
-  \def\@newl@bel#1#2#3{%
-   {\@safe@activestrue
-    \bbl@ifunset{#1@#2}%
-       \relax
-       {\gdef\@multiplelabels{%
-          \@latex@warning@no@line{There were multiply-defined labels}}%
-        \@latex@warning@no@line{Label `#2' multiply defined}}%
-    \global\@namedef{#1@#2}{#3}}}
+%</core>
+%<*package|core>
 %    \end{macrocode}
 %
-%  \end{macro}
+% \section{Multiple languages}
 %
-%  \begin{macro}{\@testdef}
+% This is not a separate file (\texttt{switch.def}) anymore.
 %
-% An internal \LaTeX\ macro used to test if the labels that have
-% been written on the |.aux| file have changed.  It is called by
-% the |\enddocument| macro.
+% Plain \TeX\ version~3.0 provides the primitive |\language| that
+% is used to store the current language. When used with a pre-3.0
+% version this function has to be implemented by allocating a
+% counter.
 %
 %    \begin{macrocode}
-  \CheckCommand*\@testdef[3]{%
-    \def\reserved@a{#3}%
-    \expandafter\ifx\csname#1@#2\endcsname\reserved@a
-    \else
-      \@tempswatrue
-    \fi}
+\def\bbl@version{<@version@>}
+\def\bbl@date{<@date@>}
+<@Define core switching macros@>
 %    \end{macrocode}
 %
-% Now that we made sure that |\@testdef| still has the same definition
-% we can rewrite it. First we make the shorthands `safe'. Then we use
-% |\bbl@tempa| as an `alias' for the macro that contains the label
-% which is being checked. Then we define |\bbl@tempb| just as
-% |\@newl@bel| does it. When the label is defined we replace the
-% definition of |\bbl@tempa| by its meaning. If the label didn't
-% change, |\bbl@tempa| and |\bbl@tempb| should be identical macros.
+% \begin{macro}{\adddialect}
+% The macro |\adddialect| can be used to add the name of a dialect
+% or variant language, for which an already defined hyphenation
+% table can be used.
 %
 %    \begin{macrocode}
-  \def\@testdef#1#2#3{%  TODO. With @samestring?
-    \@safe@activestrue
-    \expandafter\let\expandafter\bbl@tempa\csname #1@#2\endcsname
-    \def\bbl@tempb{#3}%
-    \@safe@activesfalse
-    \ifx\bbl@tempa\relax
-    \else
-      \edef\bbl@tempa{\expandafter\strip@prefix\meaning\bbl@tempa}%
-    \fi
-    \edef\bbl@tempb{\expandafter\strip@prefix\meaning\bbl@tempb}%
-    \ifx\bbl@tempa\bbl@tempb
-    \else
-      \@tempswatrue
-    \fi}
-\fi
+\def\adddialect#1#2{%
+  \global\chardef#1#2\relax
+  \bbl@usehooks{adddialect}{{#1}{#2}}%
+  \begingroup
+    \count@#1\relax
+    \def\bbl@elt##1##2##3##4{%
+      \ifnum\count@=##2\relax
+        \edef\bbl@tempa{\expandafter\@gobbletwo\string#1}%
+        \bbl@info{Hyphen rules for '\expandafter\@gobble\bbl@tempa'
+                  set to \expandafter\string\csname l@##1\endcsname\\%
+                  (\string\language\the\count@). Reported}%
+        \def\bbl@elt####1####2####3####4{}%
+      \fi}%
+    \bbl@cs{languages}%
+  \endgroup}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \begin{macro}{\ref}
-% \begin{macro}{\pageref}
+%    |\bbl@iflanguage| executes code only if the language |l@|
+%    exists. Otherwise raises an error.
 %
-% The same holds for the macro |\ref| that references a label and
-% |\pageref| to reference a page. We make them robust as well (if
-% they weren't already) to prevent problems if they should become
-% expanded at the wrong moment.
+%    The argument of |\bbl@fixname| has to be a macro name, as it may get
+%    ``fixed'' if casing (lc/uc) is wrong. It's an attempt to fix a
+%    long-standing bug when |\foreignlanguage| and the like appear in
+%    a |\MakeXXXcase|. However, a lowercase form is not imposed to
+%    improve backward compatibility (perhaps you defined a language
+%    named |MYLANG|, but unfortunately mixed case names cannot be
+%    trapped). Note |l@| is encapsulated, so that its case does not
+%    change.
 %
 %    \begin{macrocode}
-\bbl@xin@{R}\bbl@opt@safe
-\ifin@
-  \bbl@redefinerobust\ref#1{%
-    \@safe@activestrue\org@ref{#1}\@safe@activesfalse}
-  \bbl@redefinerobust\pageref#1{%
-    \@safe@activestrue\org@pageref{#1}\@safe@activesfalse}
-\else
-  \let\org@ref\ref
-  \let\org@pageref\pageref
-\fi
+\def\bbl@fixname#1{%
+  \begingroup
+    \def\bbl@tempe{l@}%
+    \edef\bbl@tempd{\noexpand\@ifundefined{\noexpand\bbl@tempe#1}}%
+    \bbl@tempd
+      {\lowercase\expandafter{\bbl@tempd}%
+         {\uppercase\expandafter{\bbl@tempd}%
+           \@empty
+           {\edef\bbl@tempd{\def\noexpand#1{#1}}%
+            \uppercase\expandafter{\bbl@tempd}}}%
+         {\edef\bbl@tempd{\def\noexpand#1{#1}}%
+          \lowercase\expandafter{\bbl@tempd}}}%
+      \@empty
+    \edef\bbl@tempd{\endgroup\def\noexpand#1{#1}}%
+  \bbl@tempd
+  \bbl@exp{\\\bbl@usehooks{languagename}{{\languagename}{#1}}}}
+\def\bbl@iflanguage#1{%
+  \@ifundefined{l@#1}{\@nolanerr{#1}\@gobble}\@firstofone}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-% \begin{macro}{\@citex}
-%
-% The macro used to cite from a bibliography, |\cite|, uses an
-% internal macro, |\@citex|.
-% It is this internal macro that picks up the argument(s),
-% so we redefine this internal macro and leave |\cite| alone. The
-% first argument is used for typesetting, so the shorthands need
-% only be deactivated in the second argument.
+% After a name has been ‘fixed’, the selectors will try to load the
+% language. If even the fixed name is not defined, will load it on the
+% fly, either based on its name, or if activated, its BCP47 code.
 %
-%    \begin{macrocode}
-\bbl@xin@{B}\bbl@opt@safe
-\ifin@
-  \bbl@redefine\@citex[#1]#2{%
-    \@safe@activestrue\edef\@tempa{#2}\@safe@activesfalse
-    \org@@citex[#1]{\@tempa}}
+% We first need a couple of macros for a simple BCP 47 look up. It also
+% makes sure, with |\bbl@bcpcase|, casing is the correct one, so that
+% sr-latn-ba becomes fr-Latn-BA. Note |#4| may contain some
+% |\@empty|'s, but they are eventually removed. |\bbl@bcplookup| either
+% returns the found |ini| or it is |\relax|.
+% 
+%    \begin{macrocode}
+\def\bbl@bcpcase#1#2#3#4\@@#5{%
+  \ifx\@empty#3%
+    \uppercase{\def#5{#1#2}}%
+  \else
+    \uppercase{\def#5{#1}}%
+    \lowercase{\edef#5{#5#2#3#4}}%
+  \fi}
+\def\bbl@bcplookup#1-#2-#3-#4\@@{%
+  \let\bbl@bcp\relax
+  \lowercase{\def\bbl@tempa{#1}}%
+  \ifx\@empty#2%
+    \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
+  \else\ifx\@empty#3%
+    \bbl@bcpcase#2\@empty\@empty\@@\bbl@tempb
+    \IfFileExists{babel-\bbl@tempa-\bbl@tempb.ini}%
+      {\edef\bbl@bcp{\bbl@tempa-\bbl@tempb}}%
+      {}%
+    \ifx\bbl@bcp\relax   
+      \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
+    \fi
+  \else
+    \bbl@bcpcase#2\@empty\@empty\@@\bbl@tempb
+    \bbl@bcpcase#3\@empty\@empty\@@\bbl@tempc
+    \IfFileExists{babel-\bbl@tempa-\bbl@tempb-\bbl@tempc.ini}%
+      {\edef\bbl@bcp{\bbl@tempa-\bbl@tempb-\bbl@tempc}}%
+      {}%
+    \ifx\bbl@bcp\relax   
+      \IfFileExists{babel-\bbl@tempa-\bbl@tempc.ini}%
+        {\edef\bbl@bcp{\bbl@tempa-\bbl@tempc}}%
+        {}%
+    \fi
+    \ifx\bbl@bcp\relax   
+      \IfFileExists{babel-\bbl@tempa-\bbl@tempc.ini}%
+        {\edef\bbl@bcp{\bbl@tempa-\bbl@tempc}}%
+        {}%
+    \fi
+    \ifx\bbl@bcp\relax   
+      \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
+    \fi
+  \fi\fi}
+\let\bbl@initoload\relax
+\def\bbl@provide@locale{%
+  \ifx\babelprovide\@undefined
+    \bbl@error{For a language to be defined on the fly 'base'\\%
+               is not enough, and the whole package must be\\%
+               loaded. Either delete the 'base' option or\\%
+               request the languages explicitly}%
+              {See the manual for further details.}%
+  \fi
+% TODO. Option to search if loaded, with \LocaleForEach
+  \let\bbl@auxname\languagename % Still necessary. TODO
+  \bbl@ifunset{bbl@bcp@map@\languagename}{}% Move uplevel??
+    {\edef\languagename{\@nameuse{bbl@bcp@map@\languagename}}}% 
+  \ifbbl@bcpallowed
+    \expandafter\ifx\csname date\languagename\endcsname\relax
+      \expandafter
+      \bbl@bcplookup\languagename-\@empty-\@empty-\@empty\@@
+      \ifx\bbl@bcp\relax\else  % Returned by \bbl@bcplookup
+        \edef\languagename{\bbl@bcp@prefix\bbl@bcp}%
+        \edef\localename{\bbl@bcp@prefix\bbl@bcp}%
+        \expandafter\ifx\csname date\languagename\endcsname\relax
+          \let\bbl@initoload\bbl@bcp
+          \bbl@exp{\\\babelprovide[\bbl@autoload@bcpoptions]{\languagename}}%
+          \let\bbl@initoload\relax
+        \fi
+        \bbl@csarg\xdef{bcp@map@\bbl@bcp}{\localename}%
+      \fi
+    \fi
+  \fi
+  \expandafter\ifx\csname date\languagename\endcsname\relax
+    \IfFileExists{babel-\languagename.tex}%
+      {\bbl@exp{\\\babelprovide[\bbl@autoload@options]{\languagename}}}%
+      {}%
+  \fi}
 %    \end{macrocode}
 %
-% Unfortunately, the packages \pkg{natbib} and \pkg{cite} need a
-% different definition of |\@citex|...
-% To begin with, \pkg{natbib} has a definition for |\@citex| with
-% \emph{three} arguments... We only know that a package is loaded
-% when |\begin{document}| is executed, so we need to postpone the
-% different redefinition.
+%  \begin{macro}{\iflanguage}
+% Users might want to test (in a private package for instance)
+% which language is currently active. For this we provide a test
+% macro, |\iflanguage|, that has three arguments.  It checks
+% whether the first argument is a known language. If so, it
+% compares the first argument with the value of |\language|. Then,
+% depending on the result of the comparison, it executes either the
+% second or the third argument.
 %
 %    \begin{macrocode}
-  \AtBeginDocument{%
-    \@ifpackageloaded{natbib}{%
+\def\iflanguage#1{%
+  \bbl@iflanguage{#1}{%
+    \ifnum\csname l@#1\endcsname=\language
+      \expandafter\@firstoftwo
+    \else
+      \expandafter\@secondoftwo
+    \fi}}
 %    \end{macrocode}
 %
-% Notice that we use |\def| here instead of |\bbl@redefine| because
-% |\org@@citex| is already defined and we don't want to overwrite
-% that definition (it would result in parameter stack overflow
-% because of a circular definition).
+%  \end{macro}
 %
-% (Recent versions of \pkg{natbib} change dynamically |\@citex|, so PR4087
-% doesn't seem fixable in a simple way. Just load \pkg{natbib} before.)
+% \subsection{Selecting the language}
 %
-%    \begin{macrocode}
-    \def\@citex[#1][#2]#3{%
-      \@safe@activestrue\edef\@tempa{#3}\@safe@activesfalse
-      \org@@citex[#1][#2]{\@tempa}}%
-    }{}}
-%    \end{macrocode}
+%  \begin{macro}{\selectlanguage}
 %
-% The package \pkg{cite} has a definition of |\@citex| where the
-% shorthands need to be turned off in both arguments.
+% The macro |\selectlanguage| checks whether the language is
+% already defined before it performs its actual task, which is to
+% update |\language| and activate language-specific definitions.
 %
 %    \begin{macrocode}
-  \AtBeginDocument{%
-    \@ifpackageloaded{cite}{%
-      \def\@citex[#1]#2{%
-        \@safe@activestrue\org@@citex[#1]{#2}\@safe@activesfalse}%
-      }{}}
+\let\bbl@select@type\z@
+\edef\selectlanguage{%
+  \noexpand\protect
+  \expandafter\noexpand\csname selectlanguage \endcsname}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% \begin{macro}{\nocite}
-%
-% The macro |\nocite| which is used to instruct BiB\TeX\ to
-% extract uncited references from the database.
+% Because the command |\selectlanguage| could be used in a moving
+% argument it expands to \verb*=\protect\selectlanguage =.
+% Therefore, we have to make sure that a macro |\protect| exists.
+% If it doesn't it is |\let| to |\relax|.
 %
 %    \begin{macrocode}
-  \bbl@redefine\nocite#1{%
-    \@safe@activestrue\org@nocite{#1}\@safe@activesfalse}
+\ifx\@undefined\protect\let\protect\relax\fi
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% \begin{macro}{\bibcite}
-%
-% The macro that is used in the |.aux| file to
-% define citation labels. When packages such as \pkg{natbib} or
-% \pkg{cite} are not loaded its second argument is used to typeset the
-% citation label. In that case, this second argument can contain
-% active characters but is used in an environment where
-% |\@safe@activestrue| is in effect. This switch needs to be reset
-% inside the |\hbox| which contains the citation label. In order to
-% determine during \file{.aux} file processing which definition of
-% |\bibcite| is needed we define |\bibcite| in such a way that it
-% redefines itself with the proper definition. We call
-% |\bbl@cite@choice| to select the proper definition for |\bibcite|.
-% This new definition is then activated.
+% The following definition is preserved for backwards compatibility
+% (eg, \textsf{arabi}, \textsf{koma}). It is related to a trick for
+% 2.09, now discarded.
 %
 %    \begin{macrocode}
-  \bbl@redefine\bibcite{%
-    \bbl@cite@choice
-    \bibcite}
+\let\xstring\string
 %    \end{macrocode}
 %
-%  \end{macro}
+% \end{macro}
 %
-% \begin{macro}{\bbl@bibcite}
+%    Since version 3.5 \babel\ writes entries to the auxiliary files in
+%    order to typeset table of contents etc. in the correct language
+%    environment.
 %
-% The macro |\bbl@bibcite| holds the definition of |\bibcite|
-% needed when neither \pkg{natbib} nor \pkg{cite} is loaded.
+% \begin{macro}{\bbl@pop@language}
+%
+% \emph{But} when the language change happens \emph{inside} a group
+% the end of the group doesn't write anything to the auxiliary
+% files. Therefore we need \TeX's |aftergroup| mechanism to help
+% us. The command |\aftergroup| stores the token immediately
+% following it to be executed when the current group is closed. So
+% we define a temporary control sequence |\bbl@pop@language| to be
+% executed at the end of the group. It calls |\bbl@set@language|
+% with the name of the current language as its argument.
+%
+% \begin{macro}{\bbl@language@stack}
+% The previous solution works for one level of nesting groups, but
+% as soon as more levels are used it is no longer adequate. For
+% that case we need to keep track of the nested languages using a
+% stack mechanism. This stack is called |\bbl@language@stack| and
+% initially empty.
 %
 %    \begin{macrocode}
-  \def\bbl@bibcite#1#2{%
-    \org@bibcite{#1}{\@safe@activesfalse#2}}
+\def\bbl@language@stack{}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% \begin{macro}{\bbl@cite@choice}
+% When using a stack we need a mechanism to push an element on the
+% stack and to retrieve the information afterwards.
 %
-% The macro |\bbl@cite@choice| determines which definition of
-% |\bibcite| is needed. First we give |\bibcite| its default
-% definition.
+% \begin{macro}{\bbl@push@language}
+% \begin{macro}{\bbl@pop@language}
+% The stack is simply a list of languagenames, separated with a `+'
+% sign; the push function can be simple:
 %
 %    \begin{macrocode}
-  \def\bbl@cite@choice{%
-    \global\let\bibcite\bbl@bibcite
-    \@ifpackageloaded{natbib}{\global\let\bibcite\org@bibcite}{}%
-    \@ifpackageloaded{cite}{\global\let\bibcite\org@bibcite}{}%
-    \global\let\bbl@cite@choice\relax}
+\def\bbl@push@language{%
+  \ifx\languagename\@undefined\else
+    \ifx\currentgrouplevel\@undefined
+      \xdef\bbl@language@stack{\languagename+\bbl@language@stack}%
+    \else
+      \ifnum\currentgrouplevel=\z@
+        \xdef\bbl@language@stack{\languagename+}%
+      \else
+        \xdef\bbl@language@stack{\languagename+\bbl@language@stack}%
+      \fi    
+    \fi
+  \fi}
 %    \end{macrocode}
 %
-% When a document is run for the first time, no \file{.aux} file is
-% available, and |\bibcite| will not yet be properly defined. In
-% this case, this has to happen before the document starts.
+% Retrieving information from the stack is a little bit less simple, as
+% we need to remove the element from the stack while storing it in the
+% macro |\languagename|. For this we first define a helper function.
+%  \begin{macro}{\bbl@pop@lang}
+%    This macro stores its first element (which is delimited by the
+%    `+'-sign) in |\languagename| and stores the rest of the string
+%    in |\bbl@language@stack|.
 %
 %    \begin{macrocode}
-  \AtBeginDocument{\bbl@cite@choice}
+\def\bbl@pop@lang#1+#2\@@{%
+  \edef\languagename{#1}%
+  \xdef\bbl@language@stack{#2}}
 %    \end{macrocode}
 %
 %  \end{macro}
-%
-% \begin{macro}{\@bibitem}
-%
-% One of the two internal \LaTeX\ macros called by |\bibitem|
-% that write the citation label on the |.aux| file.
+% The reason for the somewhat weird arrangement of arguments to the
+% helper function is the fact it is called in the following way.
+% This means that before |\bbl@pop@lang| is executed \TeX\ first
+% \emph{expands} the stack, stored in |\bbl@language@stack|. The
+% result of that is that the argument string of |\bbl@pop@lang|
+% contains one or more language names, each followed by a `+'-sign
+% (zero language names won't occur as this macro will only be
+% called after something has been pushed on the stack).
 %
 %    \begin{macrocode}
-  \bbl@redefine\@bibitem#1{%
-    \@safe@activestrue\org@@bibitem{#1}\@safe@activesfalse}
-\else
-  \let\org@nocite\nocite
-  \let\org@@citex\@citex
-  \let\org@bibcite\bibcite
-  \let\org@@bibitem\@bibitem
-\fi
+\let\bbl@ifrestoring\@secondoftwo
+\def\bbl@pop@language{%
+  \expandafter\bbl@pop@lang\bbl@language@stack\@@
+  \let\bbl@ifrestoring\@firstoftwo
+  \expandafter\bbl@set@language\expandafter{\languagename}%
+  \let\bbl@ifrestoring\@secondoftwo}
 %    \end{macrocode}
 %
+% Once the name of the previous language is retrieved from the stack,
+% it is fed to |\bbl@set@language| to do the actual work of
+% switching everything that needs switching.
+%  \end{macro}
+%  \end{macro}
 %  \end{macro}
 %
-% \subsection{Marks}
-%
-% \begin{macro}{\markright}
-% Because the output routine is asynchronous, we must pass the
-% current language attribute to the head lines. To achieve this we
-% need to adapt the definition of |\markright| and |\markboth|
-% somewhat. However, headlines and footlines can contain text
-% outside marks; for that we must take some actions in the output
-% routine if the 'headfoot' options is used. 
-%
-% We need to make some redefinitions to the output routine
-% to avoid an endless loop and to correctly handle the page number
-% in bidi documents.
+% An alternative way to identify languages (in the \babel{} sense)
+% with a numerical value is introduced in 3.30. This is one of the
+% first steps for a new interface based on the concept of locale,
+% which explains the name of |\localeid|. This means |\l@...| will be
+% reserved for hyphenation patterns (so that two locales can share the
+% same rules).
 %
 %    \begin{macrocode}
-\bbl@trace{Marks}
-\IfBabelLayout{sectioning}
-  {\ifx\bbl@opt@headfoot\@nnil
-     \g@addto@macro\@resetactivechars{%
-       \set@typeset@protect
-       \expandafter\select@language@x\expandafter{\bbl@main@language}%
-       \let\protect\noexpand
-       \ifcase\bbl@bidimode\else % Only with bidi. See also above
-         \edef\thepage{%
-           \noexpand\babelsublr{\unexpanded\expandafter{\thepage}}}%
-       \fi}%
-   \fi}
-  {\ifbbl@single\else
-     \bbl@ifunset{markright }\bbl@redefine\bbl@redefinerobust
-     \markright#1{%
-       \bbl@ifblank{#1}%
-         {\org@markright{}}%
-         {\toks@{#1}%
-          \bbl@exp{%
-            \\\org@markright{\\\protect\\\foreignlanguage{\languagename}%
-              {\\\protect\\\bbl@restore@actives\the\toks@}}}}}%
+\chardef\localeid\z@
+\def\bbl@id@last{0}    % No real need for a new counter
+\def\bbl@id@assign{%
+  \bbl@ifunset{bbl@id@@\languagename}%
+    {\count@\bbl@id@last\relax
+     \advance\count@\@ne
+     \bbl@csarg\chardef{id@@\languagename}\count@
+     \edef\bbl@id@last{\the\count@}%
+     \ifcase\bbl@engine\or
+       \directlua{
+         Babel = Babel or {}
+         Babel.locale_props = Babel.locale_props or {}
+         Babel.locale_props[\bbl@id@last] = {}
+         Babel.locale_props[\bbl@id@last].name = '\languagename'
+        }%
+      \fi}%
+    {}%
+    \chardef\localeid\bbl@cl{id@}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\markboth}
-%  \begin{macro}{\@mkboth}
-%    The definition of |\markboth| is equivalent to that of
-%    |\markright|, except that we need two token registers. The
-%    documentclasses \cls{report} and \cls{book} define and set the
-%    headings for the page. While doing so they also store a copy of
-%    |\markboth| in |\@mkboth|. Therefore we need to check whether
-%    |\@mkboth| has already been set. If so we neeed to do that again
-%    with the new definition of |\markboth|. (As of Oct 2019, \LaTeX{}
-%    stores the definition in an intermediate macro, so it's not
-%    necessary anymore, but it's preserved for older versions.)
+% The unprotected part of |\selectlanguage|.
 %
 %    \begin{macrocode}
-     \ifx\@mkboth\markboth
-       \def\bbl@tempc{\let\@mkboth\markboth}
-     \else
-       \def\bbl@tempc{}
-     \fi
-     \bbl@ifunset{markboth }\bbl@redefine\bbl@redefinerobust
-     \markboth#1#2{%
-       \protected@edef\bbl@tempb##1{%
-         \protect\foreignlanguage
-         {\languagename}{\protect\bbl@restore@actives##1}}%
-       \bbl@ifblank{#1}%
-         {\toks@{}}%
-         {\toks@\expandafter{\bbl@tempb{#1}}}%
-       \bbl@ifblank{#2}%
-         {\@temptokena{}}%
-         {\@temptokena\expandafter{\bbl@tempb{#2}}}%
-       \bbl@exp{\\\org@markboth{\the\toks@}{\the\@temptokena}}}
-       \bbl@tempc
-     \fi}  % end ifbbl@single, end \IfBabelLayout
+\expandafter\def\csname selectlanguage \endcsname#1{%
+  \ifnum\bbl@hymapsel=\@cclv\let\bbl@hymapsel\tw@\fi
+  \bbl@push@language
+  \aftergroup\bbl@pop@language
+  \bbl@set@language{#1}}
 %    \end{macrocode}
 %
 %  \end{macro}
-%  \end{macro}
 %
-% \subsection{Preventing clashes with other packages}
+%  \begin{macro}{\bbl@set@language}
 %
-% \subsubsection{\pkg{ifthen}}
+% The macro |\bbl@set@language| takes care of switching the language
+% environment \emph{and} of writing entries on the auxiliary files.
+% For historial reasons, language names can be either |language| of
+% |\language|. To catch either form a trick is used, but
+% unfortunately as a side effect the catcodes of letters in
+% |\languagename| are messed up. This is a bug, but preserved for
+% backwards compatibility. The list of auxiliary files can be
+% extended by redefining |\BabelContentsFiles|, but make sure they
+% are loaded inside a group (as |aux|, |toc|, |lof|, and |lot| do)
+% or the last language of the document will remain active
+% afterwards.
 %
-% \begin{macro}{\ifthenelse}
+% We also write a command to change the current language in the
+% auxiliary files.
 %
-% Sometimes a document writer wants to create a special effect
-% depending on the page a certain fragment of text appears on. This
-% can be achieved by the following piece of code:
-%\begin{verbatim}
-%    \ifthenelse{\isodd{\pageref{some:label}}}
-%               {code for odd pages}
-%               {code for even pages}
-%\end{verbatim}
-% In order for this to work the argument of |\isodd| needs to be
-% fully expandable. With the above redefinition of |\pageref| it is
-% not in the case of this example. To overcome that, we add some
-% code to the definition of |\ifthenelse| to make things work.
+% |\bbl@savelastskip| is used to deal with skips before the write
+% whatsit (as suggested by U Fischer). Adapted from \textsf{hyperref},
+% but it might fail, so I'll consider it a temporary hack, while I
+% study other options (the ideal, but very likely unfeasible except
+% perhaps in \luatex, is to avoid the |\write| altogether when not
+% needed).
 %
-% We want to revert the definition of |\pageref| and |\ref| to
-% their original definition for the first argument of |\ifthenelse|,
-% so we first need to store their current meanings.
+%    \begin{macrocode}
+\def\BabelContentsFiles{toc,lof,lot}
+\def\bbl@set@language#1{% from selectlanguage, pop@
+  % The old buggy way. Preserved for compatibility.
+  \edef\languagename{%
+    \ifnum\escapechar=\expandafter`\string#1\@empty
+    \else\string#1\@empty\fi}%
+  \ifcat\relax\noexpand#1%
+    \expandafter\ifx\csname date\languagename\endcsname\relax
+      \edef\languagename{#1}%
+      \let\localename\languagename
+    \else
+      \bbl@info{Using '\string\language' instead of 'language' is\\%
+                deprecated. If what you want is to use a\\%
+                macro containing the actual locale, make\\%
+                sure it does not not match any language.\\%
+                Reported}%
+      \ifx\scantokens\@undefined
+         \def\localename{??}%
+      \else
+        \scantokens\expandafter{\expandafter
+          \def\expandafter\localename\expandafter{\languagename}}%
+      \fi
+    \fi
+  \else
+    \def\localename{#1}% This one has the correct catcodes
+  \fi
+  \select@language{\languagename}%
+  % write to auxs
+  \expandafter\ifx\csname date\languagename\endcsname\relax\else
+    \if@filesw
+      \ifx\babel@aux\@gobbletwo\else % Set if single in the first, redundant
+        \bbl@savelastskip
+        \protected@write\@auxout{}{\string\babel@aux{\bbl@auxname}{}}%
+        \bbl@restorelastskip
+      \fi
+      \bbl@usehooks{write}{}%
+    \fi
+  \fi}
 %
-% Then we can set the |\@safe@actives| switch and call the original
-% |\ifthenelse|. In order to be able to use shorthands in the
-% second and third arguments of |\ifthenelse| the resetting of the
-% switch \emph{and} the definition of |\pageref| happens inside
-% those arguments. 
+\let\bbl@restorelastskip\relax
+\let\bbl@savelastskip\relax
 %
-%    \begin{macrocode}
-\bbl@trace{Preventing clashes with other packages}
-\bbl@xin@{R}\bbl@opt@safe
-\ifin@
-  \AtBeginDocument{%
-    \@ifpackageloaded{ifthen}{%
-      \bbl@redefine@long\ifthenelse#1#2#3{%
-        \let\bbl@temp@pref\pageref
-        \let\pageref\org@pageref
-        \let\bbl@temp@ref\ref
-        \let\ref\org@ref
-        \@safe@activestrue
-        \org@ifthenelse{#1}%
-          {\let\pageref\bbl@temp@pref
-           \let\ref\bbl@temp@ref
-           \@safe@activesfalse
-           #2}%
-          {\let\pageref\bbl@temp@pref
-           \let\ref\bbl@temp@ref
-           \@safe@activesfalse
-           #3}%
-        }%
-      }{}%
-    }
+\newif\ifbbl@bcpallowed
+\bbl@bcpallowedfalse
+\def\select@language#1{% from set@, babel@aux
+  % set hymap
+  \ifnum\bbl@hymapsel=\@cclv\chardef\bbl@hymapsel4\relax\fi
+  % set name
+  \edef\languagename{#1}%
+  \bbl@fixname\languagename
+  % TODO. name@map must be here?
+  \bbl@provide@locale
+  \bbl@iflanguage\languagename{%
+     \expandafter\ifx\csname date\languagename\endcsname\relax
+      \bbl@error
+        {Unknown language '\languagename'. Either you have\\%
+         misspelled its name, it has not been installed,\\%
+         or you requested it in a previous run. Fix its name,\\%
+         install it or just rerun the file, respectively. In\\%
+         some cases, you may need to remove the aux file}%
+        {You may proceed, but expect wrong results}%
+    \else
+      % set type
+      \let\bbl@select@type\z@
+      \expandafter\bbl@switch\expandafter{\languagename}%
+    \fi}}
+\def\babel@aux#1#2{%
+  \select@language{#1}%
+  \bbl@foreach\BabelContentsFiles{% \relax -> don't assume vertical mode
+    \@writefile{##1}{\babel@toc{#1}{#2}\relax}}}% TODO - plain?
+\def\babel@toc#1#2{%
+  \select@language{#1}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \subsubsection{\pkg{varioref}}
-%
-% \begin{macro}{\@@vpageref}
-% \begin{macro}{\vrefpagenum}
-% \begin{macro}{\Ref}
+% First, check if the user asks for a known language. If so,
+% update the value of |\language| and call |\originalTeX|
+% to bring \TeX\ in a certain pre-defined state.
 %
-% When the package varioref is in use we need to modify its
-% internal command |\@@vpageref| in order to prevent problems when
-% an active character ends up in the argument of |\vref|. The same
-% needs to happen for |\vrefpagenum|.
+% The name of the language is stored in the control sequence
+% |\languagename|.
 %
-%    \begin{macrocode}
-  \AtBeginDocument{%
-    \@ifpackageloaded{varioref}{%
-      \bbl@redefine\@@vpageref#1[#2]#3{%
-        \@safe@activestrue
-        \org@@@vpageref{#1}[#2]{#3}%
-        \@safe@activesfalse}%
-      \bbl@redefine\vrefpagenum#1#2{%
-        \@safe@activestrue
-        \org@vrefpagenum{#1}{#2}%
-        \@safe@activesfalse}%
-%    \end{macrocode}
+% Then we have to \emph{re}define |\originalTeX| to compensate for
+% the things that have been activated.  To save memory space for
+% the macro definition of |\originalTeX|, we construct the control
+% sequence name for the |\noextras|\langvar\ command at definition
+% time by expanding the |\csname| primitive.
 %
-% The package \pkg{varioref} defines |\Ref| to be a robust command
-% wich uppercases the first character of the reference text. In
-% order to be able to do that it needs to access the expandable form
-% of |\ref|. So we employ a little trick here. We redefine the
-% (internal) command \verb*|\Ref | to call |\org@ref| instead of
-% |\ref|. The disadvantage of this solution is that whenever the
-% definition of |\Ref| changes, this definition needs to be updated
-% as well.
+% Now activate the language-specific definitions. This is done by
+% constructing the names of three macros by concatenating three
+% words with the argument of |\selectlanguage|, and calling these
+% macros. \nb{What if \cs{hyphenation} was used in |extras|? Patch
+% temporarily |\set@hyphenmins| and hyphenation. It can be done in
+% hooks if necessary.}
+%
+% The switching of the values of |\lefthyphenmin| and
+% |\righthyphenmin| is somewhat different. First we save their
+% current values, then we check if |\|\langvar|hyphenmins| is
+% defined. If it is not, we set default values (2 and 3), otherwise
+% the values in |\|\langvar|hyphenmins| will be used.
 %
 %    \begin{macrocode}
-      \expandafter\def\csname Ref \endcsname#1{%
-        \protected@edef\@tempa{\org@ref{#1}}\expandafter\MakeUppercase\@tempa}
-      }{}%
-    }
-\fi
+\newif\ifbbl@usedategroup
+\def\bbl@switch#1{%  from select@, foreign@
+  % make sure there is info for the language if so requested
+  \bbl@ensureinfo{#1}%
+  % restore
+  \originalTeX
+  \expandafter\def\expandafter\originalTeX\expandafter{%
+    \csname noextras#1\endcsname
+    \let\originalTeX\@empty
+    \babel@beginsave}%
+  \bbl@usehooks{afterreset}{}%
+  \languageshorthands{none}%
+  % set the locale id
+  \bbl@id@assign
+  % switch captions, date
+  % No text is supposed to be added here, so we remove any
+  % spurious spaces.  
+  \bbl@bsphack
+    \ifcase\bbl@select@type
+      \csname captions#1\endcsname\relax
+      \csname date#1\endcsname\relax
+    \else
+      \bbl@xin@{,captions,}{,\bbl@select@opts,}%
+      \ifin@
+        \csname captions#1\endcsname\relax
+      \fi
+      \bbl@xin@{,date,}{,\bbl@select@opts,}%
+      \ifin@  % if \foreign... within \<lang>date
+        \csname date#1\endcsname\relax
+      \fi
+    \fi
+  \bbl@esphack
+  % switch extras
+  \bbl@usehooks{beforeextras}{}%
+  \csname extras#1\endcsname\relax
+  \bbl@usehooks{afterextras}{}%
+  %  > babel-ensure
+  %  > babel-sh-<short>
+  %  > babel-bidi
+  %  > babel-fontspec
+  % hyphenation - case mapping
+  \ifcase\bbl@opt@hyphenmap\or
+    \def\BabelLower##1##2{\lccode##1=##2\relax}%
+    \ifnum\bbl@hymapsel>4\else
+      \csname\languagename @bbl@hyphenmap\endcsname
+    \fi
+    \chardef\bbl@opt@hyphenmap\z@
+  \else
+    \ifnum\bbl@hymapsel>\bbl@opt@hyphenmap\else
+      \csname\languagename @bbl@hyphenmap\endcsname
+    \fi
+  \fi
+  \let\bbl@hymapsel\@cclv
+  % hyphenation - select rules
+  \ifnum\csname l@\languagename\endcsname=\l@unhyphenated
+    \edef\bbl@tempa{u}%
+  \else
+    \edef\bbl@tempa{\bbl@cl{lnbrk}}%
+  \fi
+  % linebreaking - handle u, e, k (v in the future)
+  \bbl@xin@{/u}{/\bbl@tempa}%
+  \ifin@\else\bbl@xin@{/e}{/\bbl@tempa}\fi % elongated forms 
+  \ifin@\else\bbl@xin@{/k}{/\bbl@tempa}\fi % only kashida
+  \ifin@\else\bbl@xin@{/v}{/\bbl@tempa}\fi % variable font
+  \ifin@
+    % unhyphenated/kashida/elongated = allow stretching
+    \language\l@unhyphenated
+    \babel@savevariable\emergencystretch
+    \emergencystretch\maxdimen
+    \babel@savevariable\hbadness
+    \hbadness\@M
+  \else
+    % other = select patterns
+    \bbl@patterns{#1}%
+  \fi
+  % hyphenation - mins
+  \babel@savevariable\lefthyphenmin
+  \babel@savevariable\righthyphenmin
+  \expandafter\ifx\csname #1hyphenmins\endcsname\relax
+    \set@hyphenmins\tw@\thr@@\relax
+  \else
+    \expandafter\expandafter\expandafter\set@hyphenmins
+      \csname #1hyphenmins\endcsname\relax
+  \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%  \end{macro}
+% \begin{environment}{otherlanguage}
+% The \Lenv{otherlanguage} environment can be used as an
+% alternative to using the |\selectlanguage| declarative
+% command. When you are typesetting a document which mixes
+% left-to-right and right-to-left typesetting you have to use this
+% environment in order to let things work as you expect them to.
 %
-% \subsubsection{\pkg{hhline}}
+% The |\ignorespaces| command is necessary to hide the environment
+% when it is entered in horizontal mode.
 %
-% \begin{macro}{\hhline}
+%    \begin{macrocode}
+\long\def\otherlanguage#1{%
+  \ifnum\bbl@hymapsel=\@cclv\let\bbl@hymapsel\thr@@\fi
+  \csname selectlanguage \endcsname{#1}%
+  \ignorespaces}
+%    \end{macrocode}
 %
-% Delaying the activation of the shorthand characters has introduced
-% a problem with the \pkg{hhline} package. The reason is that it
-% uses the `:' character which is made active by the french support
-% in \babel. Therefore we need to \emph{reload} the package when
-% the `:' is an active character. Note that this happens
-% \emph{after} the category code of the @-sign has been changed to
-% other, so we need to temporarily change it to letter again.
+% The |\endotherlanguage| part of the environment tries to hide
+% itself when it is called in horizontal mode.
 %
 %    \begin{macrocode}
-\AtEndOfPackage{%
-  \AtBeginDocument{%
-    \@ifpackageloaded{hhline}%
-      {\expandafter\ifx\csname normal@char\string:\endcsname\relax
-       \else
-         \makeatletter
-         \def\@currname{hhline}\input{hhline.sty}\makeatother
-       \fi}%
-      {}}}
+\long\def\endotherlanguage{%
+  \global\@ignoretrue\ignorespaces}
 %    \end{macrocode}
 %
-%  \end{macro}
+%  \end{environment}
 %
-% \subsubsection{\pkg{hyperref}}
+% \begin{environment}{otherlanguage*}
+% The \Lenv{otherlanguage} environment is meant to be used when a
+% large part of text from a different language needs to be typeset,
+% but without changing the translation of words such as `figure'.
+% This environment makes use of |\foreign@language|.
 %
-% \begin{macro}{\pdfstringdefDisableCommands}
+%    \begin{macrocode}
+\expandafter\def\csname otherlanguage*\endcsname{%
+  \@ifnextchar[\bbl@otherlanguage@s{\bbl@otherlanguage@s[]}}
+\def\bbl@otherlanguage@s[#1]#2{%
+  \ifnum\bbl@hymapsel=\@cclv\chardef\bbl@hymapsel4\relax\fi
+  \def\bbl@select@opts{#1}%
+  \foreign@language{#2}}
+%    \end{macrocode}
 %
-% A number of interworking problems between \pkg{babel} and
-% \pkg{hyperref} are tackled by \pkg{hyperref} itself. The
-% following code was introduced to prevent some annoying warnings
-% but it broke bookmarks. This was quickly fixed in \pkg{hyperref},
-% which essentially made it no-op. However, it will not removed for
-% the moment because \pkg{hyperref} is expecting it. TODO. Still
-% true? Commented out in 2020/07/27.
+% At the end of the environment we need to switch off the extra
+% definitions. The grouping mechanism of the environment will take
+% care of resetting the correct hyphenation rules and ``extras''.
 %
 %    \begin{macrocode}
-% \AtBeginDocument{%
-%   \ifx\pdfstringdefDisableCommands\@undefined\else
-%     \pdfstringdefDisableCommands{\languageshorthands{system}}%
-%   \fi}
+\expandafter\let\csname endotherlanguage*\endcsname\relax
 %    \end{macrocode}
 %
-%  \end{macro}
+%  \end{environment}
 %
-% \subsubsection{\pkg{fancyhdr}}
+% \begin{macro}{\foreignlanguage}
 %
-% \begin{macro}{\FOREIGNLANGUAGE}
+% The |\foreignlanguage| command is another substitute for the
+% |\selectlanguage| command. This command takes two arguments, the
+% first argument is the name of the language to use for typesetting
+% the text specified in the second argument.
 %
-% The package \pkg{fancyhdr} treats the running head and fout lines
-% somewhat differently as the standard classes. A symptom of this is
-% that the command |\foreignlanguage| which \babel\ adds to the
-% marks can end up inside the argument of |\MakeUppercase|. To
-% prevent unexpected results we need to define |\FOREIGNLANGUAGE|
-% here.
+% Unlike |\selectlanguage| this command doesn't switch
+% \emph{everything}, it only switches the hyphenation rules and the
+% extra definitions for the language specified. It does this within
+% a group and assumes the |\extras|\langvar\ command doesn't make
+% any |\global| changes. The coding is very similar to part of
+% |\selectlanguage|.
 %
-%    \begin{macrocode}
-\DeclareRobustCommand{\FOREIGNLANGUAGE}[1]{%
-  \lowercase{\foreignlanguage{#1}}}
-%    \end{macrocode}
+% |\bbl@beforeforeign| is a trick to fix a bug in bidi
+% texts. |\foreignlanguage| is supposed to be a `text' command, and
+% therefore it must emit a |\leavevmode|, but it does not, and
+% therefore the indent is placed on the opposite margin. For
+% backward compatibility, however, it is done only if a
+% right-to-left script is requested; otherwise, it is no-op.
 %
-%  \end{macro}
+% (3.11) |\foreignlanguage*| is a temporary, experimental macro for
+% a few lines with a different script direction, while preserving
+% the paragraph format (thank the braces around |\par|, things like
+% |\hangindent| are not reset). Do not use it in production,
+% because its semantics and its syntax may change (and very likely
+% will, or even it could be removed altogether). Currently it
+% enters in vmode and then selects the language (which in turn sets the
+% paragraph direction).
 %
-% \begin{macro}{\substitutefontfamily}
+% (3.11) Also experimental are the hook |foreign| and |foreign*|.
+% With them you can redefine |\BabelText| which by default does
+% nothing. Its behavior is not well defined yet. So, use it in
+% horizontal mode only if you do not want surprises.
 %
-% This command is deprecated. Use the tools provides by \LaTeX.
-% The command |\substitutefontfamily| creates an
-% \file{.fd} file on the fly. The first argument is an encoding
-% mnemonic, the second and third arguments are font family names.
+% In other words, at the beginning of a paragraph |\foreignlanguage|
+% enters into hmode with the surrounding lang, and with
+% |\foreignlanguage*| with the new lang.
 %
 %    \begin{macrocode}
-\def\substitutefontfamily#1#2#3{%
-  \lowercase{\immediate\openout15=#1#2.fd\relax}%
-  \immediate\write15{%
-    \string\ProvidesFile{#1#2.fd}%
-    [\the\year/\two@digits{\the\month}/\two@digits{\the\day}
-     \space generated font description file]^^J
-    \string\DeclareFontFamily{#1}{#2}{}^^J
-    \string\DeclareFontShape{#1}{#2}{m}{n}{<->ssub * #3/m/n}{}^^J
-    \string\DeclareFontShape{#1}{#2}{m}{it}{<->ssub * #3/m/it}{}^^J
-    \string\DeclareFontShape{#1}{#2}{m}{sl}{<->ssub * #3/m/sl}{}^^J
-    \string\DeclareFontShape{#1}{#2}{m}{sc}{<->ssub * #3/m/sc}{}^^J
-    \string\DeclareFontShape{#1}{#2}{b}{n}{<->ssub * #3/bx/n}{}^^J
-    \string\DeclareFontShape{#1}{#2}{b}{it}{<->ssub * #3/bx/it}{}^^J
-    \string\DeclareFontShape{#1}{#2}{b}{sl}{<->ssub * #3/bx/sl}{}^^J
-    \string\DeclareFontShape{#1}{#2}{b}{sc}{<->ssub * #3/bx/sc}{}^^J
-    }%
-  \closeout15
-  }
-\@onlypreamble\substitutefontfamily
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-% \subsection{Encoding and fonts}
+\providecommand\bbl@beforeforeign{}
+\edef\foreignlanguage{%
+  \noexpand\protect
+  \expandafter\noexpand\csname foreignlanguage \endcsname}
+\expandafter\def\csname foreignlanguage \endcsname{%
+  \@ifstar\bbl@foreign@s\bbl@foreign@x}
+\providecommand\bbl@foreign@x[3][]{%
+  \begingroup
+    \def\bbl@select@opts{#1}%
+    \let\BabelText\@firstofone
+    \bbl@beforeforeign
+    \foreign@language{#2}%
+    \bbl@usehooks{foreign}{}%
+    \BabelText{#3}% Now in horizontal mode!
+  \endgroup}
+\def\bbl@foreign@s#1#2{% TODO - \shapemode, \@setpar, ?\@@par
+  \begingroup
+    {\par}%
+    \let\bbl@select@opts\@empty
+    \let\BabelText\@firstofone
+    \foreign@language{#1}%
+    \bbl@usehooks{foreign*}{}%
+    \bbl@dirparastext
+    \BabelText{#2}% Still in vertical mode!
+    {\par}%
+  \endgroup}
+%    \end{macrocode}
 %
-%  Because documents may use non-ASCII font encodings, we make sure
-%  that the logos of \TeX\ and \LaTeX\ always come out in the right
-%  encoding. There is a list of non-ASCII encodings. Requested
-%  encodings are currently stored in |\@fontenc@load@list|. If a
-%  non-ASCII has been loaded, we define versions of |\TeX| and |\LaTeX|
-%  for them using |\ensureascii|. The default ASCII encoding is set,
-%  too (in reverse order): the ``main'' encoding (when the document
-%  begins), the last loaded, or |OT1|.
+%  \end{macro}
 %
-%  \begin{macro}{\ensureascii}
+%  \begin{macro}{\foreign@language}
+%
+% This macro does the work for |\foreignlanguage| and the
+% \Lenv{otherlanguage*} environment. First we need to store the name
+% of the language and check that it is a known language. Then it
+% just calls |bbl@switch|.
 %
 %    \begin{macrocode}
-\bbl@trace{Encoding and fonts}
-\newcommand\BabelNonASCII{LGR,X2,OT2,OT3,OT6,LHE,LWN,LMA,LMC,LMS,LMU}
-\newcommand\BabelNonText{TS1,T3,TS3}
-\let\org@TeX\TeX
-\let\org@LaTeX\LaTeX
-\let\ensureascii\@firstofone
-\AtBeginDocument{%
-  \def\@elt#1{,#1,}%
-  \edef\bbl@tempa{\expandafter\@gobbletwo\@fontenc@load@list}%
-  \let\@elt\relax
-  \let\bbl@tempb\@empty
-  \def\bbl@tempc{OT1}%
-  \bbl@foreach\BabelNonASCII{% LGR loaded in a non-standard way
-    \bbl@ifunset{T@#1}{}{\def\bbl@tempb{#1}}}%
-  \bbl@foreach\bbl@tempa{%
-    \bbl@xin@{#1}{\BabelNonASCII}%
-    \ifin@
-      \def\bbl@tempb{#1}% Store last non-ascii
-    \else\bbl@xin@{#1}{\BabelNonText}% Pass
-      \ifin@\else
-        \def\bbl@tempc{#1}% Store last ascii
-      \fi
-    \fi}%
-  \ifx\bbl@tempb\@empty\else
-    \bbl@xin@{,\cf@encoding,}{,\BabelNonASCII,\BabelNonText,}%
-    \ifin@\else
-      \edef\bbl@tempc{\cf@encoding}% The default if ascii wins
+\def\foreign@language#1{%
+  % set name
+  \edef\languagename{#1}%
+  \ifbbl@usedategroup
+    \bbl@add\bbl@select@opts{,date,}%
+    \bbl@usedategroupfalse
+  \fi
+  \bbl@fixname\languagename
+  % TODO. name@map here?
+  \bbl@provide@locale
+  \bbl@iflanguage\languagename{%
+    \expandafter\ifx\csname date\languagename\endcsname\relax
+      \bbl@warning   % TODO - why a warning, not an error?
+        {Unknown language '#1'. Either you have\\%
+         misspelled its name, it has not been installed,\\%
+         or you requested it in a previous run. Fix its name,\\%
+         install it or just rerun the file, respectively. In\\%
+         some cases, you may need to remove the aux file.\\%
+         I'll proceed, but expect wrong results.\\%
+         Reported}%
     \fi
-    \edef\ensureascii#1{%
-      {\noexpand\fontencoding{\bbl@tempc}\noexpand\selectfont#1}}%
-    \DeclareTextCommandDefault{\TeX}{\ensureascii{\org@TeX}}%
-    \DeclareTextCommandDefault{\LaTeX}{\ensureascii{\org@LaTeX}}%
-  \fi}
+    % set type
+    \let\bbl@select@type\@ne
+    \expandafter\bbl@switch\expandafter{\languagename}}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  Now comes the old deprecated stuff (with a little change in 3.9l,
-%  for \textsf{fontspec}).  The first thing we need to do is to
-%  determine, at |\begin{document}|, which latin fontencoding to use.
-%
-%  \begin{macro}{\latinencoding}
-%    When text is being typeset in an encoding other than `latin'
-%    (\texttt{OT1} or \texttt{T1}), it would be nice to still have
-%    Roman numerals come out in the Latin encoding.
-%    So we first assume that the current encoding at the end
-%    of processing the package is the Latin encoding.
+% \begin{macro}{\bbl@patterns}
 %
-%    \begin{macrocode}
-\AtEndOfPackage{\edef\latinencoding{\cf@encoding}}
-%    \end{macrocode}
+% This macro selects the hyphenation patterns by changing the
+% \cs{language} register.  If special hyphenation patterns
+% are available specifically for the current font encoding,
+% use them instead of the default.
 %
-%    But this might be overruled with a later loading of the package
-%    \pkg{fontenc}. Therefore we check at the execution of
-%    |\begin{document}| whether it was loaded with the \Lopt{T1}
-%    option. The normal way to do this (using |\@ifpackageloaded|) is
-%    disabled for this package. Now we have to revert to parsing the
-%    internal macro |\@filelist| which contains all the filenames
-%    loaded.
+% It also sets hyphenation exceptions, but only once, because they
+% are global (here language |\lccode|'s has been set, too).
+% |\bbl@hyphenation@| is set to relax until the very first
+% |\babelhyphenation|, so do nothing with this value. If the
+% exceptions for a language (by its number, not its name, so that
+% |:ENC| is taken into account) has been set, then use
+% |\hyphenation| with both global and language exceptions and empty
+% the latter to mark they must not be set again.
 %
 %    \begin{macrocode}
-\AtBeginDocument{%
-  \@ifpackageloaded{fontspec}%
-    {\xdef\latinencoding{%
-       \ifx\UTFencname\@undefined
-         EU\ifcase\bbl@engine\or2\or1\fi
-       \else
-         \UTFencname
-       \fi}}%
-    {\gdef\latinencoding{OT1}%
-     \ifx\cf@encoding\bbl@t@one
-       \xdef\latinencoding{\bbl@t@one}%
-     \else
-       \def\@elt#1{,#1,}%
-       \edef\bbl@tempa{\expandafter\@gobbletwo\@fontenc@load@list}%
-       \let\@elt\relax
-       \bbl@xin@{,T1,}\bbl@tempa
-       \ifin@
-         \xdef\latinencoding{\bbl@t@one}%
-       \fi
-     \fi}}
+\let\bbl@hyphlist\@empty
+\let\bbl@hyphenation@\relax
+\let\bbl@pttnlist\@empty
+\let\bbl@patterns@\relax
+\let\bbl@hymapsel=\@cclv
+\def\bbl@patterns#1{%
+  \language=\expandafter\ifx\csname l@#1:\f@encoding\endcsname\relax
+      \csname l@#1\endcsname
+      \edef\bbl@tempa{#1}%
+    \else
+      \csname l@#1:\f@encoding\endcsname
+      \edef\bbl@tempa{#1:\f@encoding}%
+    \fi
+  \@expandtwoargs\bbl@usehooks{patterns}{{#1}{\bbl@tempa}}%
+  %  > luatex
+  \@ifundefined{bbl@hyphenation@}{}{% Can be \relax!
+    \begingroup
+      \bbl@xin@{,\number\language,}{,\bbl@hyphlist}%
+      \ifin@\else
+        \@expandtwoargs\bbl@usehooks{hyphenation}{{#1}{\bbl@tempa}}%
+        \hyphenation{%
+          \bbl@hyphenation@
+          \@ifundefined{bbl@hyphenation@#1}%
+            \@empty
+            {\space\csname bbl@hyphenation@#1\endcsname}}%
+        \xdef\bbl@hyphlist{\bbl@hyphlist\number\language,}%
+      \fi
+    \endgroup}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\latintext}
-%    Then we can define the command |\latintext| which is a
-%    declarative switch to a latin font-encoding. Usage of this macro
-%    is deprecated.
+% \begin{environment}{hyphenrules}
+%
+% The environment \Lenv{hyphenrules} can be used to select
+% \emph{just} the hyphenation rules. This environment does
+% \emph{not} change |\languagename| and when the hyphenation rules
+% specified were not loaded it has no effect. Note however,
+% |\lccode|'s and font encodings are not set at all, so in most
+% cases you should use |otherlanguage*|.
 %
 %    \begin{macrocode}
-\DeclareRobustCommand{\latintext}{%
-  \fontencoding{\latinencoding}\selectfont
-  \def\encodingdefault{\latinencoding}}
+\def\hyphenrules#1{%
+  \edef\bbl@tempf{#1}%
+  \bbl@fixname\bbl@tempf
+  \bbl@iflanguage\bbl@tempf{%
+    \expandafter\bbl@patterns\expandafter{\bbl@tempf}%
+    \ifx\languageshorthands\@undefined\else
+      \languageshorthands{none}%
+    \fi
+    \expandafter\ifx\csname\bbl@tempf hyphenmins\endcsname\relax
+      \set@hyphenmins\tw@\thr@@\relax
+    \else
+      \expandafter\expandafter\expandafter\set@hyphenmins
+      \csname\bbl@tempf hyphenmins\endcsname\relax
+    \fi}}
+\let\endhyphenrules\@empty
 %    \end{macrocode}
 %
-%  \end{macro}
+%  \end{environment}
 %
-%  \begin{macro}{\textlatin}
-%    This command takes an argument which is then typeset using the
-%    requested font encoding. In order to avoid many encoding switches
-%    it operates in a local scope.
+% \begin{macro}{\providehyphenmins}
+% The macro |\providehyphenmins| should be used in the language
+% definition files to provide a \emph{default} setting for the
+% hyphenation parameters |\lefthyphenmin| and |\righthyphenmin|. If
+% the macro |\|\langvar|hyphenmins| is already defined this command
+% has no effect.
 %
 %    \begin{macrocode}
-\ifx\@undefined\DeclareTextFontCommand
-  \DeclareRobustCommand{\textlatin}[1]{\leavevmode{\latintext #1}}
-\else
-  \DeclareTextFontCommand{\textlatin}{\latintext}
-\fi
+\def\providehyphenmins#1#2{%
+  \expandafter\ifx\csname #1hyphenmins\endcsname\relax
+    \@namedef{#1hyphenmins}{#2}%
+  \fi}
 %    \end{macrocode}
 %
-% For several functions, we need to execute some code with
-% |\selectfont|. With \LaTeX\ 2021-06-01, there is a hook for this
-% purpose, but in older versions the \LaTeX{} command is patched (the
-% latter solution will be eventually removed).
+%  \end{macro}
+%
+%  \begin{macro}{\set@hyphenmins}
+%    This macro sets the values of |\lefthyphenmin| and
+%    |\righthyphenmin|. It expects two values as its argument.
 %
 %    \begin{macrocode}
-\bbl@ifformatlater{2021-06-01}%
-  {\def\bbl@patchfont#1{\AddToHook{selectfont}{#1}}}
-  {\def\bbl@patchfont#1{%
-     \expandafter\bbl@add\csname selectfont \endcsname{#1}%
-     \expandafter\bbl@toglobal\csname selectfont \endcsname}}
+\def\set@hyphenmins#1#2{%
+  \lefthyphenmin#1\relax
+  \righthyphenmin#2\relax}
 %    \end{macrocode}
 %
 % \end{macro}
 %
-% \subsection{Basic bidi support}
+% \begin{macro}{\ProvidesLanguage}
+% The identification code for each file is something that was
+% introduced in \LaTeXe. When the command |\ProvidesFile| does not
+% exist, a dummy definition is provided temporarily. For use in the
+% language definition file the command |\ProvidesLanguage| is
+% defined by \babel.
 %
-% \textbf{Work in progress.} This code is currently placed here for
-% practical reasons. It will be moved to the correct place soon, I
-% hope.
-%
-% It is loosely based on |rlbabel.def|, but most of it has been
-% developed from scratch. This \babel{} module (by Johannes Braams and
-% Boris Lavva) has served the purpose of typesetting R documents for
-% two decades, and despite its flaws I think it is still a good starting
-% point (some parts have been copied here almost verbatim), partly
-% thanks to its simplicity. I've also looked at \textsc{arabi} (by
-% Youssef Jabri), which is compatible with \babel{}.
-%
-% There are two ways of modifying macros to make them “bidi”, namely,
-% by patching the internal low-level macros (which is what I have done
-% with lists, columns, counters, tocs, much like |rlbabel| did), and
-% by introducing a “middle layer” just below the user interface
-% (sectioning, footnotes).
-%
-% \begin{itemize}
-% \item pdftex provides a minimal support for bidi text, and it
-%   must be done by hand. Vertical typesetting is not possible.
-% \item \xetex{} is somewhat better, thanks to its font engine
-%   (even if not always reliable) and a few additional tools. However,
-%   very little is done at the paragraph level. Another challenging
-%   problem is text direction does not honour \TeX{} grouping.
-% \item \luatex{} can provide the most complete solution, as we can
-%   manipulate almost freely the node list, the generated lines,
-%   and so on, but bidi text does not work out of the box and some
-%   development is necessary. It also provides tools to properly
-%   set left-to-right and right-to-left page layouts. As Lua\TeX-ja
-%   shows, vertical typesetting is possible, too.
-% \end{itemize}
+% Depending on the format, ie, on if the former is defined, we use
+% a similar definition or not.
 %
 %    \begin{macrocode}
-\bbl@trace{Loading basic (internal) bidi support}
-\ifodd\bbl@engine
-\else % TODO. Move to txtbabel
-  \ifnum\bbl@bidimode>100 \ifnum\bbl@bidimode<200
-    \bbl@error
-      {The bidi method 'basic' is available only in\\%
-       luatex. I'll continue with 'bidi=default', so\\%
-       expect wrong results}%
-      {See the manual for further details.}%
-    \let\bbl@beforeforeign\leavevmode
-    \AtEndOfPackage{%
-      \EnableBabelHook{babel-bidi}%
-      \bbl@xebidipar}
-  \fi\fi
-  \def\bbl@loadxebidi#1{%
-    \ifx\RTLfootnotetext\@undefined
-      \AtEndOfPackage{%
-        \EnableBabelHook{babel-bidi}%
-        \ifx\fontspec\@undefined
-          \bbl@loadfontspec % bidi needs fontspec
-        \fi
-        \usepackage#1{bidi}}%
-    \fi}
-  \ifnum\bbl@bidimode>200
-    \ifcase\expandafter\@gobbletwo\the\bbl@bidimode\or
-      \bbl@tentative{bidi=bidi}
-      \bbl@loadxebidi{}
-    \or
-      \bbl@loadxebidi{[rldocument]}
-    \or
-      \bbl@loadxebidi{}
-    \fi
-  \fi
-\fi
-% TODO? Separate:
-\ifnum\bbl@bidimode=\@ne
-  \let\bbl@beforeforeign\leavevmode
-  \ifodd\bbl@engine
-    \newattribute\bbl@attr@dir
-    \directlua{ Babel.attr_dir = luatexbase.registernumber'bbl@attr@dir' }
-    \bbl@exp{\output{\bodydir\pagedir\the\output}}
-  \fi
-  \AtEndOfPackage{%
-    \EnableBabelHook{babel-bidi}%
-    \ifodd\bbl@engine\else
-      \bbl@xebidipar
-    \fi}
+\ifx\ProvidesFile\@undefined
+  \def\ProvidesLanguage#1[#2 #3 #4]{%
+    \wlog{Language: #1 #4 #3 <#2>}%
+    }
+\else
+  \def\ProvidesLanguage#1{%
+    \begingroup
+      \catcode`\ 10 %
+      \@makeother\/%
+      \@ifnextchar[%]
+        {\@provideslanguage{#1}}{\@provideslanguage{#1}[]}}
+  \def\@provideslanguage#1[#2]{%
+    \wlog{Language: #1 #2}%
+    \expandafter\xdef\csname ver@#1.ldf\endcsname{#2}%
+    \endgroup}
 \fi
 %    \end{macrocode}
 %
-% Now come the macros used to set the direction when a language is
-% switched. First the (mostly) common macros.
-%
-%    \begin{macrocode}
-\bbl@trace{Macros to switch the text direction}
-\def\bbl@alscripts{,Arabic,Syriac,Thaana,}
-\def\bbl@rscripts{% TODO. Base on codes ??
-  ,Imperial Aramaic,Avestan,Cypriot,Hatran,Hebrew,%
-  Old Hungarian,Old Hungarian,Lydian,Mandaean,Manichaean,%
-  Manichaean,Meroitic Cursive,Meroitic,Old North Arabian,%
-  Nabataean,N'Ko,Orkhon,Palmyrene,Inscriptional Pahlavi,%
-  Psalter Pahlavi,Phoenician,Inscriptional Parthian,Samaritan,%
-  Old South Arabian,}%
-\def\bbl@provide@dirs#1{%
-  \bbl@xin@{\csname bbl@sname@#1\endcsname}{\bbl@alscripts\bbl@rscripts}%
-  \ifin@
-    \global\bbl@csarg\chardef{wdir@#1}\@ne
-    \bbl@xin@{\csname bbl@sname@#1\endcsname}{\bbl@alscripts}%
-    \ifin@
-      \global\bbl@csarg\chardef{wdir@#1}\tw@  % useless in xetex
-    \fi
-  \else
-    \global\bbl@csarg\chardef{wdir@#1}\z@
-  \fi
-  \ifodd\bbl@engine
-    \bbl@csarg\ifcase{wdir@#1}%
-      \directlua{ Babel.locale_props[\the\localeid].textdir = 'l' }%
-    \or
-      \directlua{ Babel.locale_props[\the\localeid].textdir = 'r' }%
-    \or
-      \directlua{ Babel.locale_props[\the\localeid].textdir = 'al' }%
-    \fi
-  \fi}
-\def\bbl@switchdir{%
-  \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
-  \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
-  \bbl@exp{\\\bbl@setdirs\bbl@cl{wdir}}}
-\def\bbl@setdirs#1{% TODO - math
-  \ifcase\bbl@select@type % TODO - strictly, not the right test
-    \bbl@bodydir{#1}%
-    \bbl@pardir{#1}%
-  \fi
-  \bbl@textdir{#1}}
-% TODO. Only if \bbl@bidimode > 0?:
-\AddBabelHook{babel-bidi}{afterextras}{\bbl@switchdir}
-\DisableBabelHook{babel-bidi}
-%    \end{macrocode}
+%  \end{macro}
 %
-% Now the engine-dependent macros. TODO. Must be moved to the engine
-% files.
+%  \begin{macro}{\originalTeX}
+%    The macro|\originalTeX| should be known to \TeX\ at this moment.
+%    As it has to be expandable we |\let| it to |\@empty| instead of
+%    |\relax|.
 %
-%    \begin{macrocode} 
-\ifodd\bbl@engine  % luatex=1
-\else % pdftex=0, xetex=2
-  \newcount\bbl@dirlevel
-  \chardef\bbl@thetextdir\z@
-  \chardef\bbl@thepardir\z@
-  \def\bbl@textdir#1{%
-    \ifcase#1\relax
-       \chardef\bbl@thetextdir\z@
-       \bbl@textdir@i\beginL\endL
-     \else
-       \chardef\bbl@thetextdir\@ne
-       \bbl@textdir@i\beginR\endR
-    \fi}
-  \def\bbl@textdir@i#1#2{%
-    \ifhmode
-      \ifnum\currentgrouplevel>\z@
-        \ifnum\currentgrouplevel=\bbl@dirlevel
-          \bbl@error{Multiple bidi settings inside a group}%
-            {I'll insert a new group, but expect wrong results.}%
-          \bgroup\aftergroup#2\aftergroup\egroup
-        \else
-          \ifcase\currentgrouptype\or % 0 bottom
-            \aftergroup#2% 1 simple {}
-          \or
-            \bgroup\aftergroup#2\aftergroup\egroup % 2 hbox
-          \or
-            \bgroup\aftergroup#2\aftergroup\egroup % 3 adj hbox
-          \or\or\or % vbox vtop align
-          \or
-            \bgroup\aftergroup#2\aftergroup\egroup % 7 noalign
-          \or\or\or\or\or\or % output math disc insert vcent mathchoice
-          \or
-            \aftergroup#2% 14 \begingroup
-          \else
-            \bgroup\aftergroup#2\aftergroup\egroup % 15 adj
-          \fi
-        \fi
-        \bbl@dirlevel\currentgrouplevel
-      \fi
-      #1%
-    \fi}
-  \def\bbl@pardir#1{\chardef\bbl@thepardir#1\relax}
-  \let\bbl@bodydir\@gobble
-  \let\bbl@pagedir\@gobble
-  \def\bbl@dirparastext{\chardef\bbl@thepardir\bbl@thetextdir}
+%    \begin{macrocode}
+\ifx\originalTeX\@undefined\let\originalTeX\@empty\fi
 %    \end{macrocode}
 %
-% The following command is executed only if there is a right-to-left
-% script (once). It activates the |\everypar| hack for \xetex, to
-% properly handle the par direction. Note text and par dirs are
-% decoupled to some extent (although not completely).
+%    Because this part of the code can be included in a format, we
+%    make sure that the macro which initializes the save mechanism,
+%    |\babel@beginsave|, is not considered to be undefined.
 %
 %    \begin{macrocode}
-  \def\bbl@xebidipar{%
-    \let\bbl@xebidipar\relax
-    \TeXXeTstate\@ne
-    \def\bbl@xeeverypar{%
-      \ifcase\bbl@thepardir
-        \ifcase\bbl@thetextdir\else\beginR\fi
-      \else
-        {\setbox\z@\lastbox\beginR\box\z@}%
-      \fi}%
-    \let\bbl@severypar\everypar
-    \newtoks\everypar
-    \everypar=\bbl@severypar
-    \bbl@severypar{\bbl@xeeverypar\the\everypar}}
-  \ifnum\bbl@bidimode>200
-    \let\bbl@textdir@i\@gobbletwo
-    \let\bbl@xebidipar\@empty
-    \AddBabelHook{bidi}{foreign}{%
-      \def\bbl@tempa{\def\BabelText####1}%
-      \ifcase\bbl@thetextdir
-        \expandafter\bbl@tempa\expandafter{\BabelText{\LR{##1}}}%
-      \else
-        \expandafter\bbl@tempa\expandafter{\BabelText{\RL{##1}}}%
-      \fi}
-    \def\bbl@pardir#1{\ifcase#1\relax\setLR\else\setRL\fi}
-  \fi
-\fi
+\ifx\babel@beginsave\@undefined\let\babel@beginsave\relax\fi
 %    \end{macrocode}
 %
-% A tool for weak L (mainly digits). We also disable warnings with
-% \textsf{hyperref}.
+%  \end{macro}
+%
+% A few macro names are reserved for future releases of \babel, which
+% will use the concept of `locale':
 %
 %    \begin{macrocode}
-\DeclareRobustCommand\babelsublr[1]{\leavevmode{\bbl@textdir\z@#1}}
-\AtBeginDocument{%
-  \ifx\pdfstringdefDisableCommands\@undefined\else
-    \ifx\pdfstringdefDisableCommands\relax\else
-      \pdfstringdefDisableCommands{\let\babelsublr\@firstofone}%
-    \fi
-  \fi}
+\providecommand\setlocale{%
+  \bbl@error
+    {Not yet available}%
+    {Find an armchair, sit down and wait}}
+\let\uselocale\setlocale
+\let\locale\setlocale
+\let\selectlocale\setlocale
+\let\localename\setlocale
+\let\textlocale\setlocale
+\let\textlanguage\setlocale
+\let\languagetext\setlocale
 %    \end{macrocode}
 %
-% \subsection{Local Language Configuration}
-%
-% \begin{macro}{\loadlocalcfg}
-%
-% At some sites it may be necessary to add site-specific actions to
-% a language definition file. This can be done by creating a file
-% with the same name as the language definition file, but with the
-% extension \file{.cfg}. For instance the file \file{norsk.cfg}
-% will be loaded when the language definition file \file{norsk.ldf}
-% is loaded. 
-%
-% For plain-based formats we don't want to override the definition
-% of |\loadlocalcfg| from \file{plain.def}.
+% \subsection{Errors}
 %
-%    \begin{macrocode}
-\bbl@trace{Local Language Configuration}
-\ifx\loadlocalcfg\@undefined
-  \@ifpackagewith{babel}{noconfigs}%
-    {\let\loadlocalcfg\@gobble}%
-    {\def\loadlocalcfg#1{%
-      \InputIfFileExists{#1.cfg}%
-        {\typeout{*************************************^^J%
-                       * Local config file #1.cfg used^^J%
-                       *}}%
-        \@empty}}
-\fi
-%    \end{macrocode}%
-%    \end{macro}
+% \begin{macro}{\@nolanerr}
+% \begin{macro}{\@nopatterns}
 %
-% \subsection{Language options}
+% The \babel\ package will signal an error when a documents tries
+% to select a language that hasn't been defined earlier. When a
+% user selects a language for which no hyphenation patterns were
+% loaded into the format he will be given a warning about that
+% fact. We revert to the patterns for |\language|=0 in that case.
+% In most formats that will be (US)english, but it might also be
+% empty.
 %
-% Languages are loaded when processing the corresponding option
-% \textit{except} if a |main| language has been set. In such a
-% case, it is not loaded until all options has been processed.
-% The following macro inputs the ldf file and does some additional
-% checks (|\input| works, too, but possible errors are not catched).
+% \begin{macro}{\@noopterr}
+% When the package was loaded without options not everything will
+% work as expected. An error message is issued in that case.
 %
-%    \begin{macrocode}
-\bbl@trace{Language options}
-\let\bbl@afterlang\relax
-\let\BabelModifiers\relax
-\let\bbl@loaded\@empty
-\def\bbl@load@language#1{%
-  \InputIfFileExists{#1.ldf}%
-    {\edef\bbl@loaded{\CurrentOption
-       \ifx\bbl@loaded\@empty\else,\bbl@loaded\fi}%
-     \expandafter\let\expandafter\bbl@afterlang
-        \csname\CurrentOption.ldf-h@@k\endcsname
-     \expandafter\let\expandafter\BabelModifiers
-        \csname bbl@mod@\CurrentOption\endcsname}%
-    {\bbl@error{%
-       Unknown option '\CurrentOption'. Either you misspelled it\\%
-       or the language definition file \CurrentOption.ldf was not found}{%
-       Valid options are, among others: shorthands=, KeepShorthandsActive,\\%
-       activeacute, activegrave, noconfigs, safe=, main=, math=\\%
-       headfoot=, strings=, config=, hyphenmap=, or a language name.}}}
-%    \end{macrocode}
+% When the format knows about |\PackageError| it must be \LaTeXe,
+% so we can safely use its error handling interface. Otherwise
+% we'll have to `keep it simple'.
 %
-% Now, we set a few language options whose names are different from
-% |ldf| files. These declarations are preserved for backwards
-% compatibility, but they must be eventually removed. Use proxy files
-% instead.
+% Infos are not written to the console, but on the other hand many
+% people think warnings are errors, so a further message type is
+% defined: an important info which is sent to the console.
 %
 %    \begin{macrocode}
-\def\bbl@try@load@lang#1#2#3{%
-  \IfFileExists{\CurrentOption.ldf}%
-    {\bbl@load@language{\CurrentOption}}%
-    {#1\bbl@load@language{#2}#3}}
-\DeclareOption{hebrew}{%
-  \input{rlbabel.def}%
-  \bbl@load@language{hebrew}}
-\DeclareOption{hungarian}{\bbl@try@load@lang{}{magyar}{}}
-\DeclareOption{lowersorbian}{\bbl@try@load@lang{}{lsorbian}{}}
-\DeclareOption{nynorsk}{\bbl@try@load@lang{}{norsk}{}}
-\DeclareOption{polutonikogreek}{%
-  \bbl@try@load@lang{}{greek}{\languageattribute{greek}{polutoniko}}}
-\DeclareOption{russian}{\bbl@try@load@lang{}{russianb}{}}
-\DeclareOption{ukrainian}{\bbl@try@load@lang{}{ukraineb}{}}
-\DeclareOption{uppersorbian}{\bbl@try@load@lang{}{usorbian}{}}
+\edef\bbl@nulllanguage{\string\language=0}
+\def\bbl@nocaption{\protect\bbl@nocaption@i}
+\def\bbl@nocaption@i#1#2{% 1: text to be printed 2: caption macro \langXname
+  \global\@namedef{#2}{\textbf{?#1?}}%
+  \@nameuse{#2}%
+  \edef\bbl@tempa{#1}%
+  \bbl@sreplace\bbl@tempa{name}{}%
+  \bbl@warning{% TODO.
+    \@backslashchar#1 not set for '\languagename'. Please,\\%
+    define it after the language has been loaded\\%
+    (typically in the preamble) with:\\% 
+    \string\setlocalecaption{\languagename}{\bbl@tempa}{..}\\%
+    Reported}}
+\def\bbl@tentative{\protect\bbl@tentative@i}
+\def\bbl@tentative@i#1{%
+  \bbl@warning{%
+    Some functions for '#1' are tentative.\\%
+    They might not work as expected and their behavior\\%
+    could change in the future.\\%
+    Reported}}
+\def\@nolanerr#1{%
+  \bbl@error
+    {You haven't defined the language '#1' yet.\\%
+     Perhaps you misspelled it or your installation\\%
+     is not complete}%
+    {Your command will be ignored, type <return> to proceed}}
+\def\@nopatterns#1{%
+  \bbl@warning
+    {No hyphenation patterns were preloaded for\\%
+     the language '#1' into the format.\\%
+     Please, configure your TeX system to add them and\\%
+     rebuild the format. Now I will use the patterns\\%
+     preloaded for \bbl@nulllanguage\space instead}}
+\let\bbl@usehooks\@gobbletwo
+\ifx\bbl@onlyswitch\@empty\endinput\fi
+  % Here ended switch.def
 %    \end{macrocode}
 %
-% Another way to extend the list of `known' options for \babel\ was
-% to create the file \file{bblopts.cfg} in which one can add option
-% declarations. However, this mechanism is deprecated -- if you
-% want an alternative name for a language, just create a new |.ldf|
-% file loading the actual one. You can also set the name
-% of the file with the package option |config=<name>|, which will
-% load |<name>.cfg| instead.
+% Here ended the now discarded |switch.def|. Here also (currently) ends
+% the \textsf{base} option.
 %
 %    \begin{macrocode}
-\ifx\bbl@opt@config\@nnil
-  \@ifpackagewith{babel}{noconfigs}{}%
-    {\InputIfFileExists{bblopts.cfg}%
-      {\typeout{*************************************^^J%
-               * Local config file bblopts.cfg used^^J%
-               *}}%
-      {}}%
-\else
-  \InputIfFileExists{\bbl@opt@config.cfg}%
-    {\typeout{*************************************^^J%
-             * Local config file \bbl@opt@config.cfg used^^J%
-             *}}%
-    {\bbl@error{%
-       Local config file '\bbl@opt@config.cfg' not found}{%
-       Perhaps you misspelled it.}}%
+\ifx\directlua\@undefined\else
+  \ifx\bbl@luapatterns\@undefined
+    \input luababel.def
+  \fi
+\fi
+<@Basic macros@>
+\bbl@trace{Compatibility with language.def}
+\ifx\bbl@languages\@undefined
+  \ifx\directlua\@undefined
+    \openin1 = language.def % TODO. Remove hardcoded number
+    \ifeof1
+      \closein1
+      \message{I couldn't find the file language.def}
+    \else
+      \closein1
+      \begingroup
+        \def\addlanguage#1#2#3#4#5{%
+          \expandafter\ifx\csname lang@#1\endcsname\relax\else
+            \global\expandafter\let\csname l@#1\expandafter\endcsname
+              \csname lang@#1\endcsname
+          \fi}%
+        \def\uselanguage#1{}%
+        \input language.def
+      \endgroup
+    \fi
+  \fi
+  \chardef\l@english\z@
 \fi
 %    \end{macrocode}
 %
-% Recognizing global options in packages not having a closed set of
-% them is not trivial, as for them to be processed they must be
-% defined explicitly. So, package options not yet taken into
-% account and stored in |bbl@language@opts| are assumed to be
-% languages (note this list also contains the language given with
-% |main|). If not declared above, the names of the option and the
-% file are the same.
+%  \begin{macro}{\addto}
+% It takes two arguments, a \meta{control sequence} and \TeX-code to
+% be added to the \meta{control sequence}.
+%
+% If the \meta{control sequence} has not been defined before it is
+% defined now.  The control sequence could also expand to |\relax|,
+% in which case a circular definition results. The net result is a
+% stack overflow.  Note there is an inconsistency, because the
+% assignment in the last branch is global. 
 %
 %    \begin{macrocode}
-\let\bbl@tempc\relax
-\bbl@foreach\bbl@language@opts{%
-  \ifcase\bbl@iniflag  % Default
-    \bbl@ifunset{ds@#1}%
-      {\DeclareOption{#1}{\bbl@load@language{#1}}}%
-      {}%
-  \or    % provide=*
-    \@gobble % case 2 same as 1
-  \or    % provide+=*
-    \bbl@ifunset{ds@#1}%
-      {\IfFileExists{#1.ldf}{}%
-        {\IfFileExists{babel-#1.tex}{}{\@namedef{ds@#1}{}}}}%
-      {}%
-    \bbl@ifunset{ds@#1}%
-      {\def\bbl@tempc{#1}%
-       \DeclareOption{#1}{%
-         \ifnum\bbl@iniflag>\@ne
-           \bbl@ldfinit
-           \babelprovide[import]{#1}%
-           \bbl@afterldf{}%
-         \else
-           \bbl@load@language{#1}%
-         \fi}}%
-      {}%
-  \or    % provide*=*
-    \def\bbl@tempc{#1}%
-    \bbl@ifunset{ds@#1}%
-      {\DeclareOption{#1}{%
-         \bbl@ldfinit
-         \babelprovide[import]{#1}%
-         \bbl@afterldf{}}}%
-      {}%
+\def\addto#1#2{%
+  \ifx#1\@undefined
+    \def#1{#2}%
+  \else
+    \ifx#1\relax
+      \def#1{#2}%
+    \else
+      {\toks@\expandafter{#1#2}%
+       \xdef#1{\the\toks@}}%
+    \fi
   \fi}
 %    \end{macrocode}
 %
-% Now, we make sure an option is explicitly declared for any language
-% set as global option, by checking if an |ldf| exists. The previous
-% step was, in fact, somewhat redundant, but that way we minimize
-% accessing the file system just to see if the option could be a
-% language.
+%  \end{macro}
+%
+% The macro |\initiate@active@char| below takes all the necessary
+% actions to make its argument a shorthand character. The real work
+% is performed once for each character. But first we define a little
+% tool. TODO. Always used with additional expansions. Move them here?
+% Move the macro to basic?
 %
 %    \begin{macrocode}
-\let\bbl@tempb\@nnil
-\bbl@foreach\@classoptionslist{%
-  \bbl@ifunset{ds@#1}%
-    {\IfFileExists{#1.ldf}%
-      {\def\bbl@tempb{#1}%
-       \DeclareOption{#1}{%
-         \ifnum\bbl@iniflag>\@ne
-           \bbl@ldfinit
-           \babelprovide[import]{#1}%
-           \bbl@afterldf{}%
-         \else
-           \bbl@load@language{#1}%
-         \fi}}%
-      {\IfFileExists{babel-#1.tex}% TODO. Copypaste pattern
-        {\def\bbl@tempb{#1}%
-         \DeclareOption{#1}{%
-           \ifnum\bbl@iniflag>\@ne
-             \bbl@ldfinit
-             \babelprovide[import]{#1}%
-             \bbl@afterldf{}%
-           \else
-             \bbl@load@language{#1}%
-           \fi}}%
-         {}}}%
-    {}}
+\def\bbl@withactive#1#2{%
+  \begingroup
+    \lccode`~=`#2\relax
+    \lowercase{\endgroup#1~}}
 %    \end{macrocode}
 %
-%    If a main language has been set, store it for the third pass.
+%  \begin{macro}{\bbl@redefine}
+%
+% To redefine a command, we save the old meaning of the macro. Then
+% we redefine it to call the original macro with the `sanitized'
+% argument. The reason why we do it this way is that we don't want
+% to redefine the \LaTeX\ macros completely in case their
+% definitions change (they have changed in the past). A macro named
+% |\macro| will be saved new control sequences named |\org@macro|.
 %
 %    \begin{macrocode}
-\ifnum\bbl@iniflag=\z@\else
-  \ifx\bbl@opt@main\@nnil
-    \ifx\bbl@tempc\relax
-      \let\bbl@opt@main\bbl@tempb
-    \else
-      \let\bbl@opt@main\bbl@tempc
-    \fi
-  \fi
-\fi
-\ifx\bbl@opt@main\@nnil\else
-  \expandafter
-  \let\expandafter\bbl@loadmain\csname ds@\bbl@opt@main\endcsname
-  \expandafter\let\csname ds@\bbl@opt@main\endcsname\@empty
-\fi
+\def\bbl@redefine#1{%
+  \edef\bbl@tempa{\bbl@stripslash#1}%
+  \expandafter\let\csname org@\bbl@tempa\endcsname#1%
+  \expandafter\def\csname\bbl@tempa\endcsname}
+\@onlypreamble\bbl@redefine
 %    \end{macrocode}
 %
-% And we are done, because all options for this pass has been
-% declared. Those already processed in the first pass are just
-% ignored.
+%  \end{macro}
 %
-% The options have to be processed in the order in which the user
-% specified them (except, of course, global options, which \LaTeX{}
-% processes before):
+%  \begin{macro}{\bbl@redefine@long}
+%    This version of |\babel@redefine| can be used to redefine |\long|
+%    commands such as |\ifthenelse|.
 %
 %    \begin{macrocode}
-\def\AfterBabelLanguage#1{%
-  \bbl@ifsamestring\CurrentOption{#1}{\global\bbl@add\bbl@afterlang}{}}
-\DeclareOption*{}
-\ProcessOptions*
+\def\bbl@redefine@long#1{%
+  \edef\bbl@tempa{\bbl@stripslash#1}%
+  \expandafter\let\csname org@\bbl@tempa\endcsname#1%
+  \expandafter\long\expandafter\def\csname\bbl@tempa\endcsname}
+\@onlypreamble\bbl@redefine@long
 %    \end{macrocode}
 %
-% This finished the second pass. Now the third one begins, which
-% loads the main language set with the key |main|. A warning is
-% raised if the main language is not the same as the last named
-% one, or if the value of the key |main| is not a language. Then
-% execute directly the option (because it could be used only in
-% |main|). After loading all languages, we deactivate
-% |\AfterBabelLanguage|.
+%  \end{macro}
 %
-%    \begin{macrocode}
-\bbl@trace{Option 'main'}
-\ifx\bbl@opt@main\@nnil
-  \edef\bbl@tempa{\@classoptionslist,\bbl@language@opts}
-  \let\bbl@tempc\@empty
-  \bbl@for\bbl@tempb\bbl@tempa{%
-    \bbl@xin@{,\bbl@tempb,}{,\bbl@loaded,}%
-    \ifin@\edef\bbl@tempc{\bbl@tempb}\fi}
-  \def\bbl@tempa#1,#2\@nnil{\def\bbl@tempb{#1}}
-  \expandafter\bbl@tempa\bbl@loaded,\@nnil
-  \ifx\bbl@tempb\bbl@tempc\else
-    \bbl@warning{%
-      Last declared language option is '\bbl@tempc',\\%
-      but the last processed one was '\bbl@tempb'.\\%
-      The main language can't be set as both a global\\%
-      and a package option. Use 'main=\bbl@tempc' as\\%
-      option. Reported}%
-  \fi
-\else
-  \ifodd\bbl@iniflag  % case 1,3
-    \bbl@ldfinit
-    \let\CurrentOption\bbl@opt@main
-    \ifx\bbl@opt@provide\@nnil
-      \bbl@exp{\\\babelprovide[import,main]{\bbl@opt@main}}%
-    \else
-      \bbl@exp{\\\bbl@forkv{\@nameuse{@raw@opt@babel.sty}}}{%
-        \bbl@xin@{,provide,}{,#1,}%
-        \ifin@
-          \def\bbl@opt@provide{#2}%
-          \bbl@replace\bbl@opt@provide{;}{,}%
-        \fi}%
-      \bbl@exp{%
-        \\\babelprovide[\bbl@opt@provide,import,main]{\bbl@opt@main}}%
-    \fi
-    \bbl@afterldf{}%
-  \else % case 0,2
-    \chardef\bbl@iniflag\z@  % Force ldf 
-    \expandafter\let\csname ds@\bbl@opt@main\endcsname\bbl@loadmain
-    \ExecuteOptions{\bbl@opt@main}
-    \DeclareOption*{}%
-    \ProcessOptions*
-  \fi
-\fi
-\def\AfterBabelLanguage{%
-  \bbl@error
-    {Too late for \string\AfterBabelLanguage}%
-    {Languages have been loaded, so I can do nothing}}
-%    \end{macrocode}
-%      
-% In order to catch the case where the user forgot to specify a
-% language we check whether |\bbl@main@language|, has become
-% defined. If not, no language has been loaded and an error
-% message is displayed.
+% \begin{macro}{\bbl@redefinerobust}
+% For commands that are redefined, but which \textit{might} be
+% robust we need a slightly more intelligent macro. A robust
+% command |foo| is defined to expand to |\protect|\verb*|\foo |. So
+% it is necessary to check whether \verb*|\foo | exists. The result
+% is that the command that is being redefined is always robust
+% afterwards.  Therefore all we need to do now is define \verb*|\foo |.
 %
 %    \begin{macrocode}
-\ifx\bbl@main@language\@undefined
-  \bbl@info{%
-    You haven't specified a language. I'll use 'nil'\\%
-    as the main language. Reported}
-    \bbl@load@language{nil}
-\fi
-%</package>
-%<*core>
+\def\bbl@redefinerobust#1{%
+  \edef\bbl@tempa{\bbl@stripslash#1}%
+  \bbl@ifunset{\bbl@tempa\space}%
+    {\expandafter\let\csname org@\bbl@tempa\endcsname#1%
+     \bbl@exp{\def\\#1{\\\protect\<\bbl@tempa\space>}}}%
+    {\bbl@exp{\let\<org@\bbl@tempa>\<\bbl@tempa\space>}}%
+    \@namedef{\bbl@tempa\space}}
+\@onlypreamble\bbl@redefinerobust
 %    \end{macrocode}
 %
-% \section{The kernel of Babel (\texttt{babel.def}, common)}
-%
-% The kernel of the \babel\ system is currently stored in
-% \file{babel.def}. The file \file{babel.def} contains most of the
-% code. The file \file{hyphen.cfg} is a file that can be loaded into
-% the format, which is necessary when you want to be able to switch
-% hyphenation patterns.
-%
-% Because plain \TeX\ users might want to use some of the features of
-% the \babel{} system too, care has to be taken that plain \TeX\ can
-% process the files. For this reason the current format will have to
-% be checked in a number of places. Some of the code below is common
-% to plain \TeX\ and \LaTeX, some of it is for the \LaTeX\ case only.
+%  \end{macro}
 %
-% Plain formats based on etex (etex, xetex, luatex) don't load
-% |hyphen.cfg| but |etex.src|, which follows a different naming
-% convention, so we need to define the babel names. It presumes
-% |language.def| exists and it is the same file used when formats were
-% created.
+% \subsection{Hooks}
 %
-% \subsection{Tools}
+% Admittedly, the current implementation is a somewhat simplistic and
+% does very little to catch errors, but it is meant for developers,
+% after all. |\bbl@usehooks| is the commands used by \babel{} to execute
+% hooks defined for an event.
 %
 %    \begin{macrocode}
-\ifx\ldf@quit\@undefined\else
-\endinput\fi % Same line!
-<@Make sure ProvidesFile is defined@>
-\ProvidesFile{babel.def}[<@date@> <@version@> Babel common definitions]
+\bbl@trace{Hooks}
+\newcommand\AddBabelHook[3][]{%
+  \bbl@ifunset{bbl@hk@#2}{\EnableBabelHook{#2}}{}%
+  \def\bbl@tempa##1,#3=##2,##3\@empty{\def\bbl@tempb{##2}}%
+  \expandafter\bbl@tempa\bbl@evargs,#3=,\@empty
+  \bbl@ifunset{bbl@ev@#2@#3@#1}%
+    {\bbl@csarg\bbl@add{ev@#3@#1}{\bbl@elth{#2}}}%
+    {\bbl@csarg\let{ev@#2@#3@#1}\relax}%
+  \bbl@csarg\newcommand{ev@#2@#3@#1}[\bbl@tempb]}
+\newcommand\EnableBabelHook[1]{\bbl@csarg\let{hk@#1}\@firstofone}
+\newcommand\DisableBabelHook[1]{\bbl@csarg\let{hk@#1}\@gobble}
+\def\bbl@usehooks#1#2{%
+  \ifx\UseHook\@undefined\else\UseHook{babel/*/#1}\fi
+  \def\bbl@elth##1{%
+    \bbl@cs{hk@##1}{\bbl@cs{ev@##1@#1@}#2}}%
+  \bbl@cs{ev@#1@}%
+  \ifx\languagename\@undefined\else % Test required for Plain (?)
+    \ifx\UseHook\@undefined\else\UseHook{babel/\languagename/#1}\fi
+    \def\bbl@elth##1{%
+      \bbl@cs{hk@##1}{\bbl@cl{ev@##1@#1}#2}}%
+    \bbl@cl{ev@#1}%
+  \fi}
 %    \end{macrocode}
 %
-% The file |babel.def| expects some definitions made in the \LaTeXe{}
-% style file. So, in Plain{} we must provide at least
-% some predefined values as well some tools to set them (even if not
-% all options are available). There are no package options, and
-% therefore and alternative mechanism is provided. For the moment,
-% only |\babeloptionstrings| and |\babeloptionmath| are provided,
-% which can be defined before loading \babel. |\BabelModifiers| can be
-% set too (but not sure it works).
+% To ensure forward compatibility, arguments in hooks are set
+% implicitly. So, if a further argument is added in the future,
+% there is no need to change the existing code. Note events
+% intended for \textsf{hyphen.cfg} are also loaded (just in
+% case you need them for some reason).
 %
 %    \begin{macrocode}
-\ifx\AtBeginDocument\@undefined  % TODO. change test.
-  <@Emulate LaTeX@>
-  \def\languagename{english}%
-  \let\bbl@opt@shorthands\@nnil
-  \def\bbl@ifshorthand#1#2#3{#2}%
-  \let\bbl@language@opts\@empty
-  \ifx\babeloptionstrings\@undefined
-    \let\bbl@opt@strings\@nnil
-  \else
-    \let\bbl@opt@strings\babeloptionstrings
-  \fi
-  \def\BabelStringsDefault{generic}
-  \def\bbl@tempa{normal}
-  \ifx\babeloptionmath\bbl@tempa
-    \def\bbl@mathnormal{\noexpand\textormath}
-  \fi
-  \def\AfterBabelLanguage#1#2{}
-  \ifx\BabelModifiers\@undefined\let\BabelModifiers\relax\fi
-  \let\bbl@afterlang\relax
-  \def\bbl@opt@safe{BR}
-  \ifx\@uclclist\@undefined\let\@uclclist\@empty\fi
-  \ifx\bbl@trace\@undefined\def\bbl@trace#1{}\fi
-  \expandafter\newif\csname ifbbl@single\endcsname
-  \chardef\bbl@bidimode\z@
+\def\bbl@evargs{,% <- don't delete this comma
+  everylanguage=1,loadkernel=1,loadpatterns=1,loadexceptions=1,%
+  adddialect=2,patterns=2,defaultcommands=0,encodedcommands=2,write=0,%
+  beforeextras=0,afterextras=0,stopcommands=0,stringprocess=0,%
+  hyphenation=2,initiateactive=3,afterreset=0,foreign=0,foreign*=0,%
+  beforestart=0,languagename=2}
+\ifx\NewHook\@undefined\else
+  \def\bbl@tempa#1=#2\@@{\NewHook{babel/#1}}
+  \bbl@foreach\bbl@evargs{\bbl@tempa#1\@@}
 \fi
 %    \end{macrocode}
 %
-% And continue.
-%
-% \section{Multiple languages}
+% \begin{macro}{\babelensure}
 %
-% This is not a separate file (\texttt{switch.def}) anymore.
+% The user command just parses the optional argument and creates a
+% new macro named |\bbl@e@|\m{language}. We register a hook at the
+% |afterextras| event which just executes this macro in a
+% ``complete'' selection (which, if undefined, is |\relax| and does
+% nothing). This part is somewhat involved because we have to make
+% sure things are expanded the correct number of times.
 %
-% Plain \TeX\ version~3.0 provides the primitive |\language| that
-% is used to store the current language. When used with a pre-3.0
-% version this function has to be implemented by allocating a
-% counter.
+% The macro |\bbl@e@|\m{language} contains
+% |\bbl@ensure|\marg{include}\marg{exclude}\marg{fontenc}, which in in
+% turn loops over the macros names in |\bbl@captionslist|, excluding
+% (with the help of |\in@|) those in the |exclude| list. If the
+% |fontenc| is given (and not |\relax|), the |\fontencoding| is also
+% added. Then we loop over the |include| list, but if the macro
+% already contains |\foreignlanguage|, nothing is done.  Note this
+% macro (1) is not restricted to the preamble, and (2) changes are
+% local.
 %
 %    \begin{macrocode}
-<@Define core switching macros@>
+\bbl@trace{Defining babelensure}
+\newcommand\babelensure[2][]{%  TODO - revise test files
+  \AddBabelHook{babel-ensure}{afterextras}{%
+    \ifcase\bbl@select@type
+      \bbl@cl{e}%
+    \fi}%
+  \begingroup
+    \let\bbl@ens@include\@empty
+    \let\bbl@ens@exclude\@empty
+    \def\bbl@ens@fontenc{\relax}%
+    \def\bbl@tempb##1{%
+      \ifx\@empty##1\else\noexpand##1\expandafter\bbl@tempb\fi}%
+    \edef\bbl@tempa{\bbl@tempb#1\@empty}%
+    \def\bbl@tempb##1=##2\@@{\@namedef{bbl@ens@##1}{##2}}%
+    \bbl@foreach\bbl@tempa{\bbl@tempb##1\@@}%
+    \def\bbl@tempc{\bbl@ensure}%
+    \expandafter\bbl@add\expandafter\bbl@tempc\expandafter{%
+      \expandafter{\bbl@ens@include}}%
+    \expandafter\bbl@add\expandafter\bbl@tempc\expandafter{%
+      \expandafter{\bbl@ens@exclude}}%
+    \toks@\expandafter{\bbl@tempc}%
+    \bbl@exp{%
+  \endgroup
+  \def\<bbl@e@#2>{\the\toks@{\bbl@ens@fontenc}}}}
+\def\bbl@ensure#1#2#3{% 1: include 2: exclude 3: fontenc
+  \def\bbl@tempb##1{% elt for (excluding) \bbl@captionslist list
+    \ifx##1\@undefined % 3.32 - Don't assume the macro exists
+      \edef##1{\noexpand\bbl@nocaption
+        {\bbl@stripslash##1}{\languagename\bbl@stripslash##1}}%
+    \fi
+    \ifx##1\@empty\else
+      \in@{##1}{#2}%
+      \ifin@\else
+        \bbl@ifunset{bbl@ensure@\languagename}%
+          {\bbl@exp{%
+            \\\DeclareRobustCommand\<bbl@ensure@\languagename>[1]{%
+              \\\foreignlanguage{\languagename}%
+              {\ifx\relax#3\else
+                \\\fontencoding{#3}\\\selectfont
+               \fi
+               ########1}}}}%
+          {}%
+        \toks@\expandafter{##1}%
+        \edef##1{%
+           \bbl@csarg\noexpand{ensure@\languagename}%
+           {\the\toks@}}%
+      \fi
+      \expandafter\bbl@tempb
+    \fi}%
+  \expandafter\bbl@tempb\bbl@captionslist\today\@empty
+  \def\bbl@tempa##1{% elt for include list
+    \ifx##1\@empty\else
+      \bbl@csarg\in@{ensure@\languagename\expandafter}\expandafter{##1}%
+      \ifin@\else
+        \bbl@tempb##1\@empty
+      \fi
+      \expandafter\bbl@tempa
+    \fi}%
+  \bbl@tempa#1\@empty}
+\def\bbl@captionslist{%
+  \prefacename\refname\abstractname\bibname\chaptername\appendixname
+  \contentsname\listfigurename\listtablename\indexname\figurename
+  \tablename\partname\enclname\ccname\headtoname\pagename\seename
+  \alsoname\proofname\glossaryname}
 %    \end{macrocode}
 %
-% \begin{macro}{\adddialect}
-% The macro |\adddialect| can be used to add the name of a dialect
-% or variant language, for which an already defined hyphenation
-% table can be used.
+%    \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@version{<@version@>}
-\def\bbl@date{<@date@>}
-\def\adddialect#1#2{%
-  \global\chardef#1#2\relax
-  \bbl@usehooks{adddialect}{{#1}{#2}}%
-  \begingroup
-    \count@#1\relax
-    \def\bbl@elt##1##2##3##4{%
-      \ifnum\count@=##2\relax
-        \edef\bbl@tempa{\expandafter\@gobbletwo\string#1}%
-        \bbl@info{Hyphen rules for '\expandafter\@gobble\bbl@tempa'
-                  set to \expandafter\string\csname l@##1\endcsname\\%
-                  (\string\language\the\count@). Reported}%
-        \def\bbl@elt####1####2####3####4{}%
-      \fi}%
-    \bbl@cs{languages}%
-  \endgroup}
-%    \end{macrocode}
+% \subsection{Setting up language files}
 %
-%  \end{macro}
+% \begin{macro}{\LdfInit}
 %
-%    |\bbl@iflanguage| executes code only if the language |l@|
-%    exists. Otherwise raises and error.
+% |\LdfInit| macro takes two arguments. The first
+% argument is the name of the language that will be defined in the
+% language definition file; the second argument is either a control
+% sequence or a string from which a control sequence should be
+% constructed. The existence of the control sequence indicates that
+% the file has been processed before.
 %
-%    The argument of |\bbl@fixname| has to be a macro name, as it may get
-%    ``fixed'' if casing (lc/uc) is wrong. It's an attempt to fix a
-%    long-standing bug when |\foreignlanguage| and the like appear in
-%    a |\MakeXXXcase|. However, a lowercase form is not imposed to
-%    improve backward compatibility (perhaps you defined a language
-%    named |MYLANG|, but unfortunately mixed case names cannot be
-%    trapped). Note |l@| is encapsulated, so that its case does not
-%    change.
+% At the start of processing a language definition file we always
+% check the category code of the at-sign. We make sure that it is
+% a `letter' during the processing of the file. We also save its
+% name as the last called option, even if not loaded.
 %
-%    \begin{macrocode}
-\def\bbl@fixname#1{%
-  \begingroup
-    \def\bbl@tempe{l@}%
-    \edef\bbl@tempd{\noexpand\@ifundefined{\noexpand\bbl@tempe#1}}%
-    \bbl@tempd
-      {\lowercase\expandafter{\bbl@tempd}%
-         {\uppercase\expandafter{\bbl@tempd}%
-           \@empty
-           {\edef\bbl@tempd{\def\noexpand#1{#1}}%
-            \uppercase\expandafter{\bbl@tempd}}}%
-         {\edef\bbl@tempd{\def\noexpand#1{#1}}%
-          \lowercase\expandafter{\bbl@tempd}}}%
-      \@empty
-    \edef\bbl@tempd{\endgroup\def\noexpand#1{#1}}%
-  \bbl@tempd
-  \bbl@exp{\\\bbl@usehooks{languagename}{{\languagename}{#1}}}}
-\def\bbl@iflanguage#1{%
-  \@ifundefined{l@#1}{\@nolanerr{#1}\@gobble}\@firstofone}
-%    \end{macrocode}
+% Another character that needs to have the correct category code
+% during processing of language definition files is the equals sign,
+% `=', because it is sometimes used in constructions with the
+% |\let| primitive. Therefore we store its current catcode and
+% restore it later on.
 %
-% After a name has been ‘fixed’, the selectors will try to load the
-% language. If even the fixed name is not defined, will load it on the
-% fly, either based on its name, or if activated, its BCP47 code.
+% Now we check whether we should perhaps stop the processing of
+% this file. To do this we first need to check whether the second
+% argument that is passed to |\LdfInit| is a control sequence. We
+% do that by looking at the first token after passing |#2| through
+% |string|. When it is equal to |\@backslashchar| we are dealing
+% with a control sequence which we can compare with |\@undefined|.
+%
+% If so, we call |\ldf@quit| to set the main language, restore the
+% category code of the @-sign and call |\endinput|
+%
+% When |#2| was \emph{not} a control sequence we construct one and
+% compare it with |\relax|.
+%
+% Finally we check |\originalTeX|.
 %
-% We first need a couple of macros for a simple BCP 47 look up. It also
-% makes sure, with |\bbl@bcpcase|, casing is the correct one, so that
-% sr-latn-ba becomes fr-Latn-BA. Note |#4| may contain some
-% |\@empty|'s, but they are eventually removed. |\bbl@bcplookup| either
-% returns the found |ini| or it is |\relax|.
-% 
 %    \begin{macrocode}
-\def\bbl@bcpcase#1#2#3#4\@@#5{%
-  \ifx\@empty#3%
-    \uppercase{\def#5{#1#2}}%
+\bbl@trace{Macros for setting language files up}
+\def\bbl@ldfinit{%
+  \let\bbl@screset\@empty
+  \let\BabelStrings\bbl@opt@string
+  \let\BabelOptions\@empty
+  \let\BabelLanguages\relax
+  \ifx\originalTeX\@undefined
+    \let\originalTeX\@empty
   \else
-    \uppercase{\def#5{#1}}%
-    \lowercase{\edef#5{#5#2#3#4}}%
+    \originalTeX
   \fi}
-\def\bbl@bcplookup#1-#2-#3-#4\@@{%
-  \let\bbl@bcp\relax
-  \lowercase{\def\bbl@tempa{#1}}%
-  \ifx\@empty#2%
-    \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
-  \else\ifx\@empty#3%
-    \bbl@bcpcase#2\@empty\@empty\@@\bbl@tempb
-    \IfFileExists{babel-\bbl@tempa-\bbl@tempb.ini}%
-      {\edef\bbl@bcp{\bbl@tempa-\bbl@tempb}}%
-      {}%
-    \ifx\bbl@bcp\relax   
-      \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
+\def\LdfInit#1#2{%
+  \chardef\atcatcode=\catcode`\@
+  \catcode`\@=11\relax
+  \chardef\eqcatcode=\catcode`\=
+  \catcode`\==12\relax
+  \expandafter\if\expandafter\@backslashchar
+                 \expandafter\@car\string#2\@nil
+    \ifx#2\@undefined\else
+      \ldf@quit{#1}%
     \fi
   \else
-    \bbl@bcpcase#2\@empty\@empty\@@\bbl@tempb
-    \bbl@bcpcase#3\@empty\@empty\@@\bbl@tempc
-    \IfFileExists{babel-\bbl@tempa-\bbl@tempb-\bbl@tempc.ini}%
-      {\edef\bbl@bcp{\bbl@tempa-\bbl@tempb-\bbl@tempc}}%
-      {}%
-    \ifx\bbl@bcp\relax   
-      \IfFileExists{babel-\bbl@tempa-\bbl@tempc.ini}%
-        {\edef\bbl@bcp{\bbl@tempa-\bbl@tempc}}%
-        {}%
-    \fi
-    \ifx\bbl@bcp\relax   
-      \IfFileExists{babel-\bbl@tempa-\bbl@tempc.ini}%
-        {\edef\bbl@bcp{\bbl@tempa-\bbl@tempc}}%
-        {}%
-    \fi
-    \ifx\bbl@bcp\relax   
-      \IfFileExists{babel-\bbl@tempa.ini}{\let\bbl@bcp\bbl@tempa}{}%
-    \fi
-  \fi\fi}
-\let\bbl@initoload\relax
-\def\bbl@provide@locale{%
-  \ifx\babelprovide\@undefined
-    \bbl@error{For a language to be defined on the fly 'base'\\%
-               is not enough, and the whole package must be\\%
-               loaded. Either delete the 'base' option or\\%
-               request the languages explicitly}%
-              {See the manual for further details.}%
-  \fi
-% TODO. Option to search if loaded, with \LocaleForEach
-  \let\bbl@auxname\languagename % Still necessary. TODO
-  \bbl@ifunset{bbl@bcp@map@\languagename}{}% Move uplevel??
-    {\edef\languagename{\@nameuse{bbl@bcp@map@\languagename}}}% 
-  \ifbbl@bcpallowed
-    \expandafter\ifx\csname date\languagename\endcsname\relax
-      \expandafter
-      \bbl@bcplookup\languagename-\@empty-\@empty-\@empty\@@
-      \ifx\bbl@bcp\relax\else  % Returned by \bbl@bcplookup
-        \edef\languagename{\bbl@bcp@prefix\bbl@bcp}%
-        \edef\localename{\bbl@bcp@prefix\bbl@bcp}%
-        \expandafter\ifx\csname date\languagename\endcsname\relax
-          \let\bbl@initoload\bbl@bcp
-          \bbl@exp{\\\babelprovide[\bbl@autoload@bcpoptions]{\languagename}}%
-          \let\bbl@initoload\relax
-        \fi
-        \bbl@csarg\xdef{bcp@map@\bbl@bcp}{\localename}%
-      \fi
+    \expandafter\ifx\csname#2\endcsname\relax\else
+      \ldf@quit{#1}%
     \fi
   \fi
-  \expandafter\ifx\csname date\languagename\endcsname\relax
-    \IfFileExists{babel-\languagename.tex}%
-      {\bbl@exp{\\\babelprovide[\bbl@autoload@options]{\languagename}}}%
-      {}%
-  \fi}
+  \bbl@ldfinit}
 %    \end{macrocode}
 %
-%  \begin{macro}{\iflanguage}
-% Users might want to test (in a private package for instance)
-% which language is currently active. For this we provide a test
-% macro, |\iflanguage|, that has three arguments.  It checks
-% whether the first argument is a known language. If so, it
-% compares the first argument with the value of |\language|. Then,
-% depending on the result of the comparison, it executes either the
-% second or the third argument.
+%  \end{macro}
+%
+%  \begin{macro}{\ldf@quit}
+%    This macro interrupts the processing of a language definition file.
 %
 %    \begin{macrocode}
-\def\iflanguage#1{%
-  \bbl@iflanguage{#1}{%
-    \ifnum\csname l@#1\endcsname=\language
-      \expandafter\@firstoftwo
-    \else
-      \expandafter\@secondoftwo
-    \fi}}
+\def\ldf@quit#1{%
+  \expandafter\main@language\expandafter{#1}%
+  \catcode`\@=\atcatcode \let\atcatcode\relax
+  \catcode`\==\eqcatcode \let\eqcatcode\relax
+  \endinput}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \subsection{Selecting the language}
-%
-%  \begin{macro}{\selectlanguage}
+%  \begin{macro}{\ldf@finish}
+%    This macro takes one argument. It is the name of the language
+%    that was defined in the language definition file.
 %
-% The macro |\selectlanguage| checks whether the language is
-% already defined before it performs its actual task, which is to
-% update |\language| and activate language-specific definitions.
+%    We load the local configuration file if one is present, we set
+%    the main language (taking into account that the argument might be
+%    a control sequence that needs to be expanded) and reset the
+%    category code of the @-sign.
 %
 %    \begin{macrocode}
-\let\bbl@select@type\z@
-\edef\selectlanguage{%
-  \noexpand\protect
-  \expandafter\noexpand\csname selectlanguage \endcsname}
+\def\bbl@afterldf#1{% TODO. Merge into the next macro? Unused elsewhere
+  \bbl@afterlang
+  \let\bbl@afterlang\relax
+  \let\BabelModifiers\relax
+  \let\bbl@screset\relax}%
+\def\ldf@finish#1{%
+  \loadlocalcfg{#1}%
+  \bbl@afterldf{#1}%
+  \expandafter\main@language\expandafter{#1}%
+  \catcode`\@=\atcatcode \let\atcatcode\relax
+  \catcode`\==\eqcatcode \let\eqcatcode\relax}
 %    \end{macrocode}
 %
-% Because the command |\selectlanguage| could be used in a moving
-% argument it expands to \verb*=\protect\selectlanguage =.
-% Therefore, we have to make sure that a macro |\protect| exists.
-% If it doesn't it is |\let| to |\relax|.
+%  \end{macro}
+%
+%    After the preamble of the document the commands |\LdfInit|,
+%    |\ldf@quit| and |\ldf@finish| are no longer needed. Therefore
+%    they are turned into warning messages in \LaTeX.
 %
 %    \begin{macrocode}
-\ifx\@undefined\protect\let\protect\relax\fi
+\@onlypreamble\LdfInit
+\@onlypreamble\ldf@quit
+\@onlypreamble\ldf@finish
 %    \end{macrocode}
 %
-% The following definition is preserved for backwards compatibility
-% (eg, \textsf{arabi}, \textsf{koma}). It is related to a trick for
-% 2.09, now discarded.
+%  \begin{macro}{\main@language}
+%  \begin{macro}{\bbl@main@language}
+%    This command should be used in the various language definition
+%    files. It stores its argument in |\bbl@main@language|; to be used
+%    to switch to the correct language at the beginning of the
+%    document.
 %
 %    \begin{macrocode}
-\let\xstring\string
+\def\main@language#1{%
+  \def\bbl@main@language{#1}%
+  \let\languagename\bbl@main@language % TODO. Set localename
+  \bbl@id@assign
+  \bbl@patterns{\languagename}}
 %    \end{macrocode}
 %
-% \end{macro}
+% We also have to make sure that some code gets executed at the
+% beginning of the document, either when the |aux| file is read or,
+% if it does not exist, when the |\AtBeginDocument| is executed.
+% Languages do not set |\pagedir|, so we set here for the whole
+% document to the main |\bodydir|.
 %
-%    Since version 3.5 \babel\ writes entries to the auxiliary files in
-%    order to typeset table of contents etc. in the correct language
-%    environment.
-%
-% \begin{macro}{\bbl@pop@language}
+%    \begin{macrocode}
+\def\bbl@beforestart{%
+  \def\@nolanerr##1{%
+    \bbl@warning{Undefined language '##1' in aux.\\Reported}}%
+  \bbl@usehooks{beforestart}{}%
+  \global\let\bbl@beforestart\relax}
+\AtBeginDocument{%
+  {\@nameuse{bbl@beforestart}}%  Group!
+  \if@filesw
+    \providecommand\babel@aux[2]{}%
+    \immediate\write\@mainaux{%
+      \string\providecommand\string\babel@aux[2]{}}%
+    \immediate\write\@mainaux{\string\@nameuse{bbl@beforestart}}%
+  \fi
+  \expandafter\selectlanguage\expandafter{\bbl@main@language}%
+  \ifbbl@single  % must go after the line above.
+    \renewcommand\selectlanguage[1]{}%
+    \renewcommand\foreignlanguage[2]{#2}%
+    \global\let\babel@aux\@gobbletwo  % Also as flag
+  \fi
+  \ifcase\bbl@engine\or\pagedir\bodydir\fi} % TODO - a better place
+%    \end{macrocode}
 %
-% \emph{But} when the language change happens \emph{inside} a group
-% the end of the group doesn't write anything to the auxiliary
-% files. Therefore we need \TeX's |aftergroup| mechanism to help
-% us. The command |\aftergroup| stores the token immediately
-% following it to be executed when the current group is closed. So
-% we define a temporary control sequence |\bbl@pop@language| to be
-% executed at the end of the group. It calls |\bbl@set@language|
-% with the name of the current language as its argument.
+%  \end{macro}
+%  \end{macro}
 %
-% \begin{macro}{\bbl@language@stack}
-% The previous solution works for one level of nesting groups, but
-% as soon as more levels are used it is no longer adequate. For
-% that case we need to keep track of the nested languages using a
-% stack mechanism. This stack is called |\bbl@language@stack| and
-% initially empty.
+% A bit of optimization. Select in heads/foots the language only if
+% necessary.
 %
 %    \begin{macrocode}
-\def\bbl@language@stack{}
+\def\select@language@x#1{%
+  \ifcase\bbl@select@type
+    \bbl@ifsamestring\languagename{#1}{}{\select@language{#1}}%
+  \else
+    \select@language{#1}%
+  \fi}
 %    \end{macrocode}
 %
-% When using a stack we need a mechanism to push an element on the
-% stack and to retrieve the information afterwards.
+% \subsection{Shorthands}
 %
-% \begin{macro}{\bbl@push@language}
-% \begin{macro}{\bbl@pop@language}
-% The stack is simply a list of languagenames, separated with a `+'
-% sign; the push function can be simple:
+%  \begin{macro}{\bbl@add@special}
+%    The macro |\bbl@add@special| is used to add a new character (or
+%    single character control sequence) to the macro |\dospecials|
+%    (and |\@sanitize| if \LaTeX\ is used). It is used only at one
+%    place, namely when |\initiate@active@char| is called (which is
+%    ignored if the char has been made active before).  Because
+%    |\@sanitize| can be undefined, we put the definition inside a
+%    conditional.
+%
+%    Items are added to the lists without checking its existence or
+%    the original catcode. It does not hurt, but should be fixed. It's
+%    already done with |\nfss@catcodes|, added in 3.10.
 %
 %    \begin{macrocode}
-\def\bbl@push@language{%
-  \ifx\languagename\@undefined\else
-    \ifx\currentgrouplevel\@undefined
-      \xdef\bbl@language@stack{\languagename+\bbl@language@stack}%
-    \else
-      \ifnum\currentgrouplevel=\z@
-        \xdef\bbl@language@stack{\languagename+}%
+\bbl@trace{Shorhands}
+\def\bbl@add@special#1{% 1:a macro like \", \?, etc.
+  \bbl@add\dospecials{\do#1}% test @sanitize = \relax, for back. compat.
+  \bbl@ifunset{@sanitize}{}{\bbl@add\@sanitize{\@makeother#1}}%
+  \ifx\nfss@catcodes\@undefined\else % TODO - same for above
+    \begingroup
+      \catcode`#1\active
+      \nfss@catcodes
+      \ifnum\catcode`#1=\active
+        \endgroup
+        \bbl@add\nfss@catcodes{\@makeother#1}%
       \else
-        \xdef\bbl@language@stack{\languagename+\bbl@language@stack}%
-      \fi    
-    \fi
+        \endgroup
+      \fi
   \fi}
 %    \end{macrocode}
 %
-% Retrieving information from the stack is a little bit less simple, as
-% we need to remove the element from the stack while storing it in the
-% macro |\languagename|. For this we first define a helper function.
-%  \begin{macro}{\bbl@pop@lang}
-%    This macro stores its first element (which is delimited by the
-%    `+'-sign) in |\languagename| and stores the rest of the string
-%    in |\bbl@language@stack|.
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@pop@lang#1+#2\@@{%
-  \edef\languagename{#1}%
-  \xdef\bbl@language@stack{#2}}
-%    \end{macrocode}
+%  \begin{macro}{\bbl@remove@special}
 %
-%  \end{macro}
-% The reason for the somewhat weird arrangement of arguments to the
-% helper function is the fact it is called in the following way.
-% This means that before |\bbl@pop@lang| is executed \TeX\ first
-% \emph{expands} the stack, stored in |\bbl@language@stack|. The
-% result of that is that the argument string of |\bbl@pop@lang|
-% contains one or more language names, each followed by a `+'-sign
-% (zero language names won't occur as this macro will only be
-% called after something has been pushed on the stack).
+%    The companion of the former macro is |\bbl@remove@special|.  It
+%    removes a character from the set macros |\dospecials| and
+%    |\@sanitize|, but it is not used at all in the \babel{} core.
 %
 %    \begin{macrocode}
-\let\bbl@ifrestoring\@secondoftwo
-\def\bbl@pop@language{%
-  \expandafter\bbl@pop@lang\bbl@language@stack\@@
-  \let\bbl@ifrestoring\@firstoftwo
-  \expandafter\bbl@set@language\expandafter{\languagename}%
-  \let\bbl@ifrestoring\@secondoftwo}
+\def\bbl@remove@special#1{%
+  \begingroup
+    \def\x##1##2{\ifnum`#1=`##2\noexpand\@empty
+                 \else\noexpand##1\noexpand##2\fi}%
+    \def\do{\x\do}%
+    \def\@makeother{\x\@makeother}%
+  \edef\x{\endgroup
+    \def\noexpand\dospecials{\dospecials}%
+    \expandafter\ifx\csname @sanitize\endcsname\relax\else
+      \def\noexpand\@sanitize{\@sanitize}%
+    \fi}%
+  \x}
 %    \end{macrocode}
 %
-% Once the name of the previous language is retrieved from the stack,
-% it is fed to |\bbl@set@language| to do the actual work of
-% switching everything that needs switching.
-%  \end{macro}
-%  \end{macro}
 %  \end{macro}
 %
-% An alternative way to identify languages (in the \babel{} sense)
-% with a numerical value is introduced in 3.30. This is one of the
-% first steps for a new interface based on the concept of locale,
-% which explains the name of |\localeid|. This means |\l@...| will be
-% reserved for hyphenation patterns (so that two locales can share the
-% same rules).
+%  \begin{macro}{\initiate@active@char}
+%    A language definition file can call this macro to make a
+%    character active. This macro takes one argument, the character
+%    that is to be made active. When the character was already active
+%    this macro does nothing. Otherwise, this macro defines the
+%    control sequence |\normal@char|\m{char} to expand to the
+%    character in its `normal state' and it defines the active
+%    character to expand to |\normal@char|\m{char} by default
+%    (\m{char} being the character to be made active). Later its
+%    definition can be changed to expand to |\active@char|\m{char}
+%    by calling |\bbl@activate{|\m{char}|}|.
 %
-%    \begin{macrocode}
-\chardef\localeid\z@
-\def\bbl@id@last{0}    % No real need for a new counter
-\def\bbl@id@assign{%
-  \bbl@ifunset{bbl@id@@\languagename}%
-    {\count@\bbl@id@last\relax
-     \advance\count@\@ne
-     \bbl@csarg\chardef{id@@\languagename}\count@
-     \edef\bbl@id@last{\the\count@}%
-     \ifcase\bbl@engine\or
-       \directlua{
-         Babel = Babel or {}
-         Babel.locale_props = Babel.locale_props or {}
-         Babel.locale_props[\bbl@id@last] = {}
-         Babel.locale_props[\bbl@id@last].name = '\languagename'
-        }%
-      \fi}%
-    {}%
-    \chardef\localeid\bbl@cl{id@}}
-%    \end{macrocode}
+%    For example, to make the double quote character active one could
+%    have |\initiate@active@char{"}| in a language definition file.
+%    This defines |"| as |\active@prefix "\active@char"| (where the
+%    first |"| is the character with its original catcode, when the
+%    shorthand is created, and |\active@char"| is a single token). In
+%    protected contexts, it expands to |\protect "| or |\noexpand "|
+%    (ie, with the original |"|); otherwise |\active@char"| is
+%    executed. This macro in turn expands to |\normal@char"| in
+%    ``safe'' contexts (eg, |\label|), but |\user@active"| in normal
+%    ``unsafe'' ones. The latter search a definition in the user,
+%    language and system levels, in this order, but if none is found,
+%    |\normal@char"| is used.  However, a deactivated shorthand (with
+%    |\bbl@deactivate| is defined as |\active@prefix "\normal@char"|.
 %
-% The unprotected part of |\selectlanguage|.
+%    The following macro is used to define shorthands in the three
+%    levels. It takes 4 arguments: the (string'ed) character,
+%    |\<level>@group|, |<level>@active| and |<next-level>@active|
+%    (except in |system|).
 %
 %    \begin{macrocode}
-\expandafter\def\csname selectlanguage \endcsname#1{%
-  \ifnum\bbl@hymapsel=\@cclv\let\bbl@hymapsel\tw@\fi
-  \bbl@push@language
-  \aftergroup\bbl@pop@language
-  \bbl@set@language{#1}}
+\def\bbl@active@def#1#2#3#4{%
+  \@namedef{#3#1}{%
+    \expandafter\ifx\csname#2@sh@#1@\endcsname\relax
+      \bbl@afterelse\bbl@sh@select#2#1{#3@arg#1}{#4#1}%
+    \else
+      \bbl@afterfi\csname#2@sh@#1@\endcsname
+    \fi}%
 %    \end{macrocode}
 %
-%  \end{macro}
+%    When there is also no current-level shorthand with an argument we
+%    will check whether there is a next-level  defined shorthand for
+%    this active character.
 %
-%  \begin{macro}{\bbl@set@language}
+%    \begin{macrocode}
+  \long\@namedef{#3@arg#1}##1{%
+    \expandafter\ifx\csname#2@sh@#1@\string##1@\endcsname\relax
+      \bbl@afterelse\csname#4#1\endcsname##1%
+    \else
+      \bbl@afterfi\csname#2@sh@#1@\string##1@\endcsname
+    \fi}}%
+%    \end{macrocode}
 %
-% The macro |\bbl@set@language| takes care of switching the language
-% environment \emph{and} of writing entries on the auxiliary files.
-% For historial reasons, language names can be either |language| of
-% |\language|. To catch either form a trick is used, but
-% unfortunately as a side effect the catcodes of letters in
-% |\languagename| are messed up. This is a bug, but preserved for
-% backwards compatibility. The list of auxiliary files can be
-% extended by redefining |\BabelContentsFiles|, but make sure they
-% are loaded inside a group (as |aux|, |toc|, |lof|, and |lot| do)
-% or the last language of the document will remain active
-% afterwards.
+%    |\initiate@active@char| calls |\@initiate@active@char| with 3
+%    arguments. All of them are the same character with different
+%    catcodes: active, other (|\string|'ed) and the original one.
+%    This trick simplifies the code a lot.
 %
-% We also write a command to change the current language in the
-% auxiliary files.
+%    \begin{macrocode}
+\def\initiate@active@char#1{%
+  \bbl@ifunset{active@char\string#1}%
+    {\bbl@withactive
+      {\expandafter\@initiate@active@char\expandafter}#1\string#1#1}%
+    {}}
+%    \end{macrocode}
 %
-% |\bbl@savelastskip| is used to deal with skips before the write
-% whatsit (as suggested by U Fischer). Adapted from \textsf{hyperref},
-% but it might fail, so I'll consider it a temporary hack, while I
-% study other options (the ideal, but very likely unfeasible except
-% perhaps in \luatex, is to avoid the |\write| altogether when not
-% needed).
+%   The very first thing to do is saving the original catcode and the
+%   original definition, even if not active, which is possible
+%   (undefined characters require a special treatement to avoid
+%   making them |\relax| and preserving some degree of protection).
 %
 %    \begin{macrocode}
-\def\BabelContentsFiles{toc,lof,lot}
-\def\bbl@set@language#1{% from selectlanguage, pop@
-  % The old buggy way. Preserved for compatibility.
-  \edef\languagename{%
-    \ifnum\escapechar=\expandafter`\string#1\@empty
-    \else\string#1\@empty\fi}%
-  \ifcat\relax\noexpand#1%
-    \expandafter\ifx\csname date\languagename\endcsname\relax
-      \edef\languagename{#1}%
-      \let\localename\languagename
-    \else
-      \bbl@info{Using '\string\language' instead of 'language' is\\%
-                deprecated. If what you want is to use a\\%
-                macro containing the actual locale, make\\%
-                sure it does not not match any language.\\%
-                Reported}%
-      \ifx\scantokens\@undefined
-         \def\localename{??}%
-      \else
-        \scantokens\expandafter{\expandafter
-          \def\expandafter\localename\expandafter{\languagename}}%
-      \fi
-    \fi
+\def\@initiate@active@char#1#2#3{%
+  \bbl@csarg\edef{oricat@#2}{\catcode`#2=\the\catcode`#2\relax}%
+  \ifx#1\@undefined
+    \bbl@csarg\def{oridef@#2}{\def#1{\active@prefix#1\@undefined}}%
   \else
-    \def\localename{#1}% This one has the correct catcodes
+    \bbl@csarg\let{oridef@@#2}#1%
+    \bbl@csarg\edef{oridef@#2}{%
+      \let\noexpand#1%
+      \expandafter\noexpand\csname bbl@oridef@@#2\endcsname}%
   \fi
-  \select@language{\languagename}%
-  % write to auxs
-  \expandafter\ifx\csname date\languagename\endcsname\relax\else
-    \if@filesw
-      \ifx\babel@aux\@gobbletwo\else % Set if single in the first, redundant
-        \bbl@savelastskip
-        \protected@write\@auxout{}{\string\babel@aux{\bbl@auxname}{}}%
-        \bbl@restorelastskip
-      \fi
-      \bbl@usehooks{write}{}%
-    \fi
-  \fi}
-%
-\let\bbl@restorelastskip\relax
-\def\bbl@savelastskip{%
-  \let\bbl@restorelastskip\relax
-  \ifvmode
-    \ifdim\lastskip=\z@
-      \let\bbl@restorelastskip\nobreak
-    \else
-      \bbl@exp{%
-        \def\\\bbl@restorelastskip{%
-          \skip@=\the\lastskip
-          \\\nobreak \vskip-\skip@ \vskip\skip@}}%
-    \fi
-  \fi}
-%
-\newif\ifbbl@bcpallowed
-\bbl@bcpallowedfalse
-\def\select@language#1{% from set@, babel@aux
-  % set hymap
-  \ifnum\bbl@hymapsel=\@cclv\chardef\bbl@hymapsel4\relax\fi
-  % set name
-  \edef\languagename{#1}%
-  \bbl@fixname\languagename
-  % TODO. name@map must be here?
-  \bbl@provide@locale
-  \bbl@iflanguage\languagename{%
-     \expandafter\ifx\csname date\languagename\endcsname\relax
-      \bbl@error
-        {Unknown language '\languagename'. Either you have\\%
-         misspelled its name, it has not been installed,\\%
-         or you requested it in a previous run. Fix its name,\\%
-         install it or just rerun the file, respectively. In\\%
-         some cases, you may need to remove the aux file}%
-        {You may proceed, but expect wrong results}%
-    \else
-      % set type
-      \let\bbl@select@type\z@
-      \expandafter\bbl@switch\expandafter{\languagename}%
-    \fi}}
-\def\babel@aux#1#2{%
-  \select@language{#1}%
-  \bbl@foreach\BabelContentsFiles{% \relax -> don't assume vertical mode
-    \@writefile{##1}{\babel@toc{#1}{#2}\relax}}}% TODO - plain?
-\def\babel@toc#1#2{%
-  \select@language{#1}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% First, check if the user asks for a known language. If so,
-% update the value of |\language| and call |\originalTeX|
-% to bring \TeX\ in a certain pre-defined state.
-%
-% The name of the language is stored in the control sequence
-% |\languagename|.
-%
-% Then we have to \emph{re}define |\originalTeX| to compensate for
-% the things that have been activated.  To save memory space for
-% the macro definition of |\originalTeX|, we construct the control
-% sequence name for the |\noextras|\langvar\ command at definition
-% time by expanding the |\csname| primitive.
-%
-% Now activate the language-specific definitions. This is done by
-% constructing the names of three macros by concatenating three
-% words with the argument of |\selectlanguage|, and calling these
-% macros. \nb{What if \cs{hyphenation} was used in |extras|? Patch
-% temporarily |\set@hyphenmins| and hyphenation. It can be done in
-% hooks if necessary.}
-%
-% The switching of the values of |\lefthyphenmin| and
-% |\righthyphenmin| is somewhat different. First we save their
-% current values, then we check if |\|\langvar|hyphenmins| is
-% defined. If it is not, we set default values (2 and 3), otherwise
-% the values in |\|\langvar|hyphenmins| will be used.
+%    If the character is already active we provide the default
+%    expansion under this shorthand mechanism. Otherwise we write a
+%    message in the transcript file, and define |\normal@char|\m{char}
+%    to expand to the character in its default state. If the character
+%    is mathematically active when \babel{} is loaded (for example
+%    |'|) the normal expansion is somewhat different to avoid an
+%    infinite loop (but it does not prevent the loop if the mathcode
+%    is set to |"8000| \textit{a posteriori}).
 %
 %    \begin{macrocode}
-\newif\ifbbl@usedategroup
-\def\bbl@switch#1{%  from select@, foreign@
-  % make sure there is info for the language if so requested
-  \bbl@ensureinfo{#1}%
-  % restore
-  \originalTeX
-  \expandafter\def\expandafter\originalTeX\expandafter{%
-    \csname noextras#1\endcsname
-    \let\originalTeX\@empty
-    \babel@beginsave}%
-  \bbl@usehooks{afterreset}{}%
-  \languageshorthands{none}%
-  % set the locale id
-  \bbl@id@assign
-  % switch captions, date
-  % No text is supposed to be added here, so we remove any
-  % spurious spaces.  
-  \bbl@bsphack
-    \ifcase\bbl@select@type
-      \csname captions#1\endcsname\relax
-      \csname date#1\endcsname\relax
-    \else
-      \bbl@xin@{,captions,}{,\bbl@select@opts,}%
-      \ifin@
-        \csname captions#1\endcsname\relax
-      \fi
-      \bbl@xin@{,date,}{,\bbl@select@opts,}%
-      \ifin@  % if \foreign... within \<lang>date
-        \csname date#1\endcsname\relax
-      \fi
-    \fi
-  \bbl@esphack
-  % switch extras
-  \bbl@usehooks{beforeextras}{}%
-  \csname extras#1\endcsname\relax
-  \bbl@usehooks{afterextras}{}%
-  %  > babel-ensure
-  %  > babel-sh-<short>
-  %  > babel-bidi
-  %  > babel-fontspec
-  % hyphenation - case mapping
-  \ifcase\bbl@opt@hyphenmap\or
-    \def\BabelLower##1##2{\lccode##1=##2\relax}%
-    \ifnum\bbl@hymapsel>4\else
-      \csname\languagename @bbl@hyphenmap\endcsname
-    \fi
-    \chardef\bbl@opt@hyphenmap\z@
+  \ifx#1#3\relax
+    \expandafter\let\csname normal@char#2\endcsname#3%
   \else
-    \ifnum\bbl@hymapsel>\bbl@opt@hyphenmap\else
-      \csname\languagename @bbl@hyphenmap\endcsname
+    \bbl@info{Making #2 an active character}%
+    \ifnum\mathcode`#2=\ifodd\bbl@engine"1000000 \else"8000 \fi
+      \@namedef{normal@char#2}{%
+        \textormath{#3}{\csname bbl@oridef@@#2\endcsname}}%
+    \else
+      \@namedef{normal@char#2}{#3}%
     \fi
-  \fi
-  \let\bbl@hymapsel\@cclv
-  % hyphenation - select rules
-  \ifnum\csname l@\languagename\endcsname=\l@unhyphenated
-    \edef\bbl@tempa{u}%
-  \else
-    \edef\bbl@tempa{\bbl@cl{lnbrk}}%
-  \fi
-  % linebreaking - handle u, e, k (v in the future)
-  \bbl@xin@{/u}{/\bbl@tempa}%
-  \ifin@\else\bbl@xin@{/e}{/\bbl@tempa}\fi % elongated forms 
-  \ifin@\else\bbl@xin@{/k}{/\bbl@tempa}\fi % only kashida
-  \ifin@\else\bbl@xin@{/v}{/\bbl@tempa}\fi % variable font
-  \ifin@
-    % unhyphenated/kashida/elongated = allow stretching
-    \language\l@unhyphenated
-    \babel@savevariable\emergencystretch
-    \emergencystretch\maxdimen
-    \babel@savevariable\hbadness
-    \hbadness\@M
-  \else
-    % other = select patterns
-    \bbl@patterns{#1}%
-  \fi
-  % hyphenation - mins
-  \babel@savevariable\lefthyphenmin
-  \babel@savevariable\righthyphenmin
-  \expandafter\ifx\csname #1hyphenmins\endcsname\relax
-    \set@hyphenmins\tw@\thr@@\relax
-  \else
-    \expandafter\expandafter\expandafter\set@hyphenmins
-      \csname #1hyphenmins\endcsname\relax
-  \fi}
 %    \end{macrocode}
 %
-% \begin{environment}{otherlanguage}
-% The \Lenv{otherlanguage} environment can be used as an
-% alternative to using the |\selectlanguage| declarative
-% command. When you are typesetting a document which mixes
-% left-to-right and right-to-left typesetting you have to use this
-% environment in order to let things work as you expect them to.
-%
-% The |\ignorespaces| command is necessary to hide the environment
-% when it is entered in horizontal mode.
+%    To prevent problems with the loading of other packages after
+%    \babel\ we reset the catcode of the character to the original one
+%    at the end of the package and of each language file (except with
+%    \textsf{KeepShorthandsActive}). It is re-activate again at
+%    |\begin{document}|.  We also need to make sure that the
+%    shorthands are active during the processing of the \file{.aux}
+%    file. Otherwise some citations may give unexpected results in
+%    the printout when a shorthand was used in the optional argument
+%    of |\bibitem| for example. Then we make it active (not strictly
+%    necessary, but done for backward compatibility).
 %
 %    \begin{macrocode}
-\long\def\otherlanguage#1{%
-  \ifnum\bbl@hymapsel=\@cclv\let\bbl@hymapsel\thr@@\fi
-  \csname selectlanguage \endcsname{#1}%
-  \ignorespaces}
+    \bbl@restoreactive{#2}%
+    \AtBeginDocument{%
+      \catcode`#2\active
+      \if@filesw
+        \immediate\write\@mainaux{\catcode`\string#2\active}%
+      \fi}%
+    \expandafter\bbl@add@special\csname#2\endcsname
+    \catcode`#2\active
+  \fi
 %    \end{macrocode}
 %
-% The |\endotherlanguage| part of the environment tries to hide
-% itself when it is called in horizontal mode.
+%    Now we have set |\normal@char|\m{char}, we must define
+%    |\active@char|\m{char}, to be executed when the character is
+%    activated.  We define the first level expansion of
+%    |\active@char|\m{char} to check the status of the |@safe@actives|
+%    flag. If it is set to true we expand to the `normal' version of
+%    this character, otherwise we call |\user@active|\m{char} to start
+%    the search of a definition in the user, language and system
+%    levels (or eventually |normal@char|\m{char}).
 %
 %    \begin{macrocode}
-\long\def\endotherlanguage{%
-  \global\@ignoretrue\ignorespaces}
-%    \end{macrocode}
-%
-%  \end{environment}
-%
-% \begin{environment}{otherlanguage*}
-% The \Lenv{otherlanguage} environment is meant to be used when a
-% large part of text from a different language needs to be typeset,
-% but without changing the translation of words such as `figure'.
-% This environment makes use of |\foreign@language|.
-%
-%    \begin{macrocode}
-\expandafter\def\csname otherlanguage*\endcsname{%
-  \@ifnextchar[\bbl@otherlanguage@s{\bbl@otherlanguage@s[]}}
-\def\bbl@otherlanguage@s[#1]#2{%
-  \ifnum\bbl@hymapsel=\@cclv\chardef\bbl@hymapsel4\relax\fi
-  \def\bbl@select@opts{#1}%
-  \foreign@language{#2}}
+  \let\bbl@tempa\@firstoftwo
+  \if\string^#2%
+    \def\bbl@tempa{\noexpand\textormath}%
+  \else
+    \ifx\bbl@mathnormal\@undefined\else
+      \let\bbl@tempa\bbl@mathnormal
+    \fi
+  \fi
+  \expandafter\edef\csname active@char#2\endcsname{%
+    \bbl@tempa
+      {\noexpand\if@safe@actives
+         \noexpand\expandafter
+         \expandafter\noexpand\csname normal@char#2\endcsname
+       \noexpand\else
+         \noexpand\expandafter
+         \expandafter\noexpand\csname bbl@doactive#2\endcsname
+       \noexpand\fi}%
+     {\expandafter\noexpand\csname normal@char#2\endcsname}}%
+  \bbl@csarg\edef{doactive#2}{%
+    \expandafter\noexpand\csname user@active#2\endcsname}%
 %    \end{macrocode}
 %
-% At the end of the environment we need to switch off the extra
-% definitions. The grouping mechanism of the environment will take
-% care of resetting the correct hyphenation rules and ``extras''.
+%    We now define the default values which the shorthand is set to
+%    when activated or deactivated. It is set to the deactivated form
+%    (globally), so that the character expands to
+%    \begin{center}
+%    |\active@prefix| \m{char} |\normal@char|\m{char}
+%    \end{center}
+%    (where |\active@char|\m{char} is \emph{one} control sequence!).
 %
 %    \begin{macrocode}
-\expandafter\let\csname endotherlanguage*\endcsname\relax
+  \bbl@csarg\edef{active@#2}{%
+    \noexpand\active@prefix\noexpand#1%
+    \expandafter\noexpand\csname active@char#2\endcsname}%
+  \bbl@csarg\edef{normal@#2}{%
+    \noexpand\active@prefix\noexpand#1%
+    \expandafter\noexpand\csname normal@char#2\endcsname}%
+  \expandafter\let\expandafter#1\csname bbl@normal@#2\endcsname
 %    \end{macrocode}
 %
-%  \end{environment}
-%
-% \begin{macro}{\foreignlanguage}
-%
-% The |\foreignlanguage| command is another substitute for the
-% |\selectlanguage| command. This command takes two arguments, the
-% first argument is the name of the language to use for typesetting
-% the text specified in the second argument.
-%
-% Unlike |\selectlanguage| this command doesn't switch
-% \emph{everything}, it only switches the hyphenation rules and the
-% extra definitions for the language specified. It does this within
-% a group and assumes the |\extras|\langvar\ command doesn't make
-% any |\global| changes. The coding is very similar to part of
-% |\selectlanguage|.
+%    The next level of the code checks whether a user has defined a
+%    shorthand for himself with this character. First we check for a
+%    single character shorthand. If that doesn't exist we check for a
+%    shorthand with an argument.
 %
-% |\bbl@beforeforeign| is a trick to fix a bug in bidi
-% texts. |\foreignlanguage| is supposed to be a `text' command, and
-% therefore it must emit a |\leavevmode|, but it does not, and
-% therefore the indent is placed on the opposite margin. For
-% backward compatibility, however, it is done only if a
-% right-to-left script is requested; otherwise, it is no-op.
+%    \begin{macrocode}
+  \bbl@active@def#2\user@group{user@active}{language@active}%
+  \bbl@active@def#2\language@group{language@active}{system@active}%
+  \bbl@active@def#2\system@group{system@active}{normal@char}%
+%    \end{macrocode}
 %
-% (3.11) |\foreignlanguage*| is a temporary, experimental macro for
-% a few lines with a different script direction, while preserving
-% the paragraph format (thank the braces around |\par|, things like
-% |\hangindent| are not reset). Do not use it in production,
-% because its semantics and its syntax may change (and very likely
-% will, or even it could be removed altogether). Currently it
-% enters in vmode and then selects the language (which in turn sets the
-% paragraph direction).
+%    In order to do the right thing when a shorthand with an argument
+%    is used by itself at the end of the line we provide a definition
+%    for the case of an empty argument. For that case we let the
+%    shorthand character expand to its non-active self. Also, When a
+%    shorthand combination such as |''| ends up in a heading \TeX\
+%    would see |\protect'\protect'|. To prevent this from happening a
+%    couple of shorthand needs to be defined at user level.
 %
-% (3.11) Also experimental are the hook |foreign| and |foreign*|.
-% With them you can redefine |\BabelText| which by default does
-% nothing. Its behavior is not well defined yet. So, use it in
-% horizontal mode only if you do not want surprises.
+%    \begin{macrocode}
+  \expandafter\edef\csname\user@group @sh@#2@@\endcsname
+    {\expandafter\noexpand\csname normal@char#2\endcsname}%
+  \expandafter\edef\csname\user@group @sh@#2@\string\protect@\endcsname
+    {\expandafter\noexpand\csname user@active#2\endcsname}%
+%    \end{macrocode}
 %
-% In other words, at the beginning of a paragraph |\foreignlanguage|
-% enters into hmode with the surrounding lang, and with
-% |\foreignlanguage*| with the new lang.
+%    Finally, a couple of special cases are taken care of.  (1) If we
+%    are making the right quote (|'|) active we need to change |\pr@m@s| as
+%    well.  Also, make sure that a single |'| in math mode `does the
+%    right thing'.  (2) If we are using the caret (|^|) as a shorthand
+%    character special care should be taken to make sure math still
+%    works. Therefore an extra level of expansion is introduced with a
+%    check for math mode on the upper level.
 %
 %    \begin{macrocode}
-\providecommand\bbl@beforeforeign{}
-\edef\foreignlanguage{%
-  \noexpand\protect
-  \expandafter\noexpand\csname foreignlanguage \endcsname}
-\expandafter\def\csname foreignlanguage \endcsname{%
-  \@ifstar\bbl@foreign@s\bbl@foreign@x}
-\providecommand\bbl@foreign@x[3][]{%
-  \begingroup
-    \def\bbl@select@opts{#1}%
-    \let\BabelText\@firstofone
-    \bbl@beforeforeign
-    \foreign@language{#2}%
-    \bbl@usehooks{foreign}{}%
-    \BabelText{#3}% Now in horizontal mode!
-  \endgroup}
-\def\bbl@foreign@s#1#2{% TODO - \shapemode, \@setpar, ?\@@par
-  \begingroup
-    {\par}%
-    \let\bbl@select@opts\@empty
-    \let\BabelText\@firstofone
-    \foreign@language{#1}%
-    \bbl@usehooks{foreign*}{}%
-    \bbl@dirparastext
-    \BabelText{#2}% Still in vertical mode!
-    {\par}%
-  \endgroup}
+  \if\string'#2%
+    \let\prim@s\bbl@prim@s
+    \let\active@math@prime#1%
+  \fi
+  \bbl@usehooks{initiateactive}{{#1}{#2}{#3}}}
 %    \end{macrocode}
 %
-%  \end{macro}
+%    The following package options control the behavior of shorthands
+%    in math mode.
 %
-%  \begin{macro}{\foreign@language}
+%    \begin{macrocode}
+%<<*More package options>>
+\DeclareOption{math=active}{}
+\DeclareOption{math=normal}{\def\bbl@mathnormal{\noexpand\textormath}}
+%<</More package options>>
+%    \end{macrocode}
 %
-% This macro does the work for |\foreignlanguage| and the
-% \Lenv{otherlanguage*} environment. First we need to store the name
-% of the language and check that it is a known language. Then it
-% just calls |bbl@switch|.
+%    Initiating a shorthand makes active the char. That is not
+%    strictly necessary but it is still done for backward
+%    compatibility. So we need to restore the original catcode at the
+%    end of package \textit{and} and the end of the |ldf|.
 %
 %    \begin{macrocode}
-\def\foreign@language#1{%
-  % set name
-  \edef\languagename{#1}%
-  \ifbbl@usedategroup
-    \bbl@add\bbl@select@opts{,date,}%
-    \bbl@usedategroupfalse
-  \fi
-  \bbl@fixname\languagename
-  % TODO. name@map here?
-  \bbl@provide@locale
-  \bbl@iflanguage\languagename{%
-    \expandafter\ifx\csname date\languagename\endcsname\relax
-      \bbl@warning   % TODO - why a warning, not an error?
-        {Unknown language '#1'. Either you have\\%
-         misspelled its name, it has not been installed,\\%
-         or you requested it in a previous run. Fix its name,\\%
-         install it or just rerun the file, respectively. In\\%
-         some cases, you may need to remove the aux file.\\%
-         I'll proceed, but expect wrong results.\\%
-         Reported}%
-    \fi
-    % set type
-    \let\bbl@select@type\@ne
-    \expandafter\bbl@switch\expandafter{\languagename}}}
+\@ifpackagewith{babel}{KeepShorthandsActive}%
+  {\let\bbl@restoreactive\@gobble}%
+  {\def\bbl@restoreactive#1{%
+     \bbl@exp{%
+       \\\AfterBabelLanguage\\\CurrentOption
+         {\catcode`#1=\the\catcode`#1\relax}%
+       \\\AtEndOfPackage
+         {\catcode`#1=\the\catcode`#1\relax}}}%
+   \AtEndOfPackage{\let\bbl@restoreactive\@gobble}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \begin{macro}{\bbl@patterns}
-%
-% This macro selects the hyphenation patterns by changing the
-% \cs{language} register.  If special hyphenation patterns
-% are available specifically for the current font encoding,
-% use them instead of the default.
+%  \begin{macro}{\bbl@sh@select}
+%    This command helps the shorthand supporting macros to select how
+%    to proceed. Note that this macro needs to be expandable as do all
+%    the shorthand macros in order for them to work in expansion-only
+%    environments such as the argument of |\hyphenation|.
 %
-% It also sets hyphenation exceptions, but only once, because they
-% are global (here language |\lccode|'s has been set, too).
-% |\bbl@hyphenation@| is set to relax until the very first
-% |\babelhyphenation|, so do nothing with this value. If the
-% exceptions for a language (by its number, not its name, so that
-% |:ENC| is taken into account) has been set, then use
-% |\hyphenation| with both global and language exceptions and empty
-% the latter to mark they must not be set again.
+%    This macro expects the name of a group of shorthands in its first
+%    argument and a shorthand character in its second argument. It
+%    will expand to either |\bbl@firstcs| or |\bbl@scndcs|. Hence two
+%    more arguments need to follow it.
 %
 %    \begin{macrocode}
-\let\bbl@hyphlist\@empty
-\let\bbl@hyphenation@\relax
-\let\bbl@pttnlist\@empty
-\let\bbl@patterns@\relax
-\let\bbl@hymapsel=\@cclv
-\def\bbl@patterns#1{%
-  \language=\expandafter\ifx\csname l@#1:\f@encoding\endcsname\relax
-      \csname l@#1\endcsname
-      \edef\bbl@tempa{#1}%
-    \else
-      \csname l@#1:\f@encoding\endcsname
-      \edef\bbl@tempa{#1:\f@encoding}%
-    \fi
-  \@expandtwoargs\bbl@usehooks{patterns}{{#1}{\bbl@tempa}}%
-  %  > luatex
-  \@ifundefined{bbl@hyphenation@}{}{% Can be \relax!
-    \begingroup
-      \bbl@xin@{,\number\language,}{,\bbl@hyphlist}%
-      \ifin@\else
-        \@expandtwoargs\bbl@usehooks{hyphenation}{{#1}{\bbl@tempa}}%
-        \hyphenation{%
-          \bbl@hyphenation@
-          \@ifundefined{bbl@hyphenation@#1}%
-            \@empty
-            {\space\csname bbl@hyphenation@#1\endcsname}}%
-        \xdef\bbl@hyphlist{\bbl@hyphlist\number\language,}%
-      \fi
-    \endgroup}}
+\def\bbl@sh@select#1#2{%
+  \expandafter\ifx\csname#1@sh@#2@sel\endcsname\relax
+    \bbl@afterelse\bbl@scndcs
+  \else
+    \bbl@afterfi\csname#1@sh@#2@sel\endcsname
+  \fi}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \begin{environment}{hyphenrules}
-%
-% The environment \Lenv{hyphenrules} can be used to select
-% \emph{just} the hyphenation rules. This environment does
-% \emph{not} change |\languagename| and when the hyphenation rules
-% specified were not loaded it has no effect. Note however,
-% |\lccode|'s and font encodings are not set at all, so in most
-% cases you should use |otherlanguage*|.
+%  \begin{macro}{\active@prefix}
+%    The command |\active@prefix| which is used in the expansion of
+%    active characters has a function similar to |\OT1-cmd| in that it
+%    |\protect|s the active character whenever |\protect| is
+%    \emph{not} |\@typeset@protect|. The |\@gobble| is needed to remove
+%    a token such as |\activechar:| (when the double colon was the
+%    active character to be dealt with). There are two definitions,
+%    depending of |\ifincsname| is available. If there is, the
+%    expansion will be more robust.
 %
 %    \begin{macrocode}
-\def\hyphenrules#1{%
-  \edef\bbl@tempf{#1}%
-  \bbl@fixname\bbl@tempf
-  \bbl@iflanguage\bbl@tempf{%
-    \expandafter\bbl@patterns\expandafter{\bbl@tempf}%
-    \ifx\languageshorthands\@undefined\else
-      \languageshorthands{none}%
-    \fi
-    \expandafter\ifx\csname\bbl@tempf hyphenmins\endcsname\relax
-      \set@hyphenmins\tw@\thr@@\relax
-    \else
-      \expandafter\expandafter\expandafter\set@hyphenmins
-      \csname\bbl@tempf hyphenmins\endcsname\relax
-    \fi}}
-\let\endhyphenrules\@empty
+\begingroup
+\bbl@ifunset{ifincsname}% TODO. Ugly. Correct? Only Plain?
+  {\gdef\active@prefix#1{%
+     \ifx\protect\@typeset@protect
+     \else
+       \ifx\protect\@unexpandable@protect
+         \noexpand#1%
+       \else
+         \protect#1%
+       \fi
+       \expandafter\@gobble
+     \fi}}
+  {\gdef\active@prefix#1{%
+     \ifincsname
+       \string#1%
+       \expandafter\@gobble
+     \else
+       \ifx\protect\@typeset@protect
+       \else
+         \ifx\protect\@unexpandable@protect
+           \noexpand#1%
+         \else
+           \protect#1%
+         \fi
+         \expandafter\expandafter\expandafter\@gobble
+       \fi
+     \fi}}
+\endgroup
 %    \end{macrocode}
 %
-%  \end{environment}
+%  \end{macro}
 %
-% \begin{macro}{\providehyphenmins}
-% The macro |\providehyphenmins| should be used in the language
-% definition files to provide a \emph{default} setting for the
-% hyphenation parameters |\lefthyphenmin| and |\righthyphenmin|. If
-% the macro |\|\langvar|hyphenmins| is already defined this command
-% has no effect.
+%  \begin{macro}{\if@safe@actives}
+%    In some circumstances it is necessary to be able to change the
+%    expansion of an active character on the fly. For this purpose the
+%    switch |@safe@actives| is available. The setting of this switch
+%    should be checked in the first level expansion of
+%    |\active@char|\m{char}.
 %
 %    \begin{macrocode}
-\def\providehyphenmins#1#2{%
-  \expandafter\ifx\csname #1hyphenmins\endcsname\relax
-    \@namedef{#1hyphenmins}{#2}%
-  \fi}
+\newif\if@safe@actives
+\@safe@activesfalse
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\set@hyphenmins}
-%    This macro sets the values of |\lefthyphenmin| and
-%    |\righthyphenmin|. It expects two values as its argument.
+%  \begin{macro}{\bbl@restore@actives}
+%    When the output routine kicks in while the
+%    active characters were made ``safe'' this must be undone in
+%    the headers to prevent unexpected typeset results. For this
+%    situation we define a command to make them ``unsafe'' again.
 %
 %    \begin{macrocode}
-\def\set@hyphenmins#1#2{%
-  \lefthyphenmin#1\relax
-  \righthyphenmin#2\relax}
+\def\bbl@restore@actives{\if@safe@actives\@safe@activesfalse\fi}
 %    \end{macrocode}
 %
-% \end{macro}
+%  \end{macro}
 %
-% \begin{macro}{\ProvidesLanguage}
-% The identification code for each file is something that was
-% introduced in \LaTeXe. When the command |\ProvidesFile| does not
-% exist, a dummy definition is provided temporarily. For use in the
-% language definition file the command |\ProvidesLanguage| is
-% defined by \babel.
+%  \begin{macro}{\bbl@activate}
+%  \begin{macro}{\bbl@deactivate}
 %
-% Depending on the format, ie, on if the former is defined, we use
-% a similar definition or not.
+%    Both macros take one argument, like |\initiate@active@char|. The
+%    macro is used to change the definition of an active character to
+%    expand to |\active@char|\m{char} in the case of |\bbl@activate|,
+%    or |\normal@char|\m{char} in the case of |\bbl@deactivate|.
 %
 %    \begin{macrocode}
-\ifx\ProvidesFile\@undefined
-  \def\ProvidesLanguage#1[#2 #3 #4]{%
-    \wlog{Language: #1 #4 #3 <#2>}%
-    }
-\else
-  \def\ProvidesLanguage#1{%
-    \begingroup
-      \catcode`\ 10 %
-      \@makeother\/%
-      \@ifnextchar[%]
-        {\@provideslanguage{#1}}{\@provideslanguage{#1}[]}}
-  \def\@provideslanguage#1[#2]{%
-    \wlog{Language: #1 #2}%
-    \expandafter\xdef\csname ver@#1.ldf\endcsname{#2}%
-    \endgroup}
-\fi
+\chardef\bbl@activated\z@
+\def\bbl@activate#1{%
+  \chardef\bbl@activated\@ne
+  \bbl@withactive{\expandafter\let\expandafter}#1%
+    \csname bbl@active@\string#1\endcsname}
+\def\bbl@deactivate#1{%
+  \chardef\bbl@activated\tw@
+  \bbl@withactive{\expandafter\let\expandafter}#1%
+    \csname bbl@normal@\string#1\endcsname}
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-%  \begin{macro}{\originalTeX}
-%    The macro|\originalTeX| should be known to \TeX\ at this moment.
-%    As it has to be expandable we |\let| it to |\@empty| instead of
-%    |\relax|.
+%  \begin{macro}{\bbl@firstcs}
+%  \begin{macro}{\bbl@scndcs}
+%
+% These macros are used only as a trick when declaring shorthands.
 %
 %    \begin{macrocode}
-\ifx\originalTeX\@undefined\let\originalTeX\@empty\fi
+\def\bbl@firstcs#1#2{\csname#1\endcsname}
+\def\bbl@scndcs#1#2{\csname#2\endcsname}
 %    \end{macrocode}
 %
-%    Because this part of the code can be included in a format, we
-%    make sure that the macro which initializes the save mechanism,
-%    |\babel@beginsave|, is not considered to be undefined.
+%  \end{macro}
+%  \end{macro}
+%
+%  \begin{macro}{\declare@shorthand}
+%    The command |\declare@shorthand| is used to declare a shorthand
+%    on a certain level. It takes three arguments:
+%    \begin{enumerate}
+%    \item a name for the collection of shorthands, i.e. `system', or
+%      `dutch';
+%    \item the character (sequence) that makes up the shorthand,
+%      i.e. |~| or |"a|;
+%    \item the code to be executed when the shorthand is encountered.
+%    \end{enumerate}
 %
+% The auxiliary macro |\babel@texpdf| improves the interoperativity with
+% \textsf{hyperref} and takes 4 arguments: (1) The \TeX{} code in text
+% mode, (2) the string for \textsf{hyperref}, (3) the \TeX{} code in
+% math mode, and (4), which is currently ignored, but it's meant for a
+% string in math mode, like a minus sign instead of an hyphen
+% (currently \textsf{hyperref} doesn't discriminate the mode). This
+% macro may be used in |ldf| files.
+
 %    \begin{macrocode}
-\ifx\babel@beginsave\@undefined\let\babel@beginsave\relax\fi
+\def\babel@texpdf#1#2#3#4{%
+  \ifx\texorpdfstring\@undefined
+    \textormath{#1}{#3}%
+  \else
+    \texorpdfstring{\textormath{#1}{#3}}{#2}%
+    % \texorpdfstring{\textormath{#1}{#3}}{\textormath{#2}{#4}}%
+  \fi}
+%
+\def\declare@shorthand#1#2{\@decl@short{#1}#2\@nil}
+\def\@decl@short#1#2#3\@nil#4{%
+  \def\bbl@tempa{#3}%
+  \ifx\bbl@tempa\@empty
+    \expandafter\let\csname #1@sh@\string#2@sel\endcsname\bbl@scndcs
+    \bbl@ifunset{#1@sh@\string#2@}{}%
+      {\def\bbl@tempa{#4}%
+       \expandafter\ifx\csname#1@sh@\string#2@\endcsname\bbl@tempa
+       \else
+         \bbl@info
+           {Redefining #1 shorthand \string#2\\%
+            in language \CurrentOption}%
+       \fi}%
+    \@namedef{#1@sh@\string#2@}{#4}%
+  \else
+    \expandafter\let\csname #1@sh@\string#2@sel\endcsname\bbl@firstcs
+    \bbl@ifunset{#1@sh@\string#2@\string#3@}{}%
+      {\def\bbl@tempa{#4}%
+       \expandafter\ifx\csname#1@sh@\string#2@\string#3@\endcsname\bbl@tempa
+       \else
+         \bbl@info
+           {Redefining #1 shorthand \string#2\string#3\\%
+            in language \CurrentOption}%
+       \fi}%
+    \@namedef{#1@sh@\string#2@\string#3@}{#4}%
+  \fi}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% A few macro names are reserved for future releases of \babel, which
-% will use the concept of `locale':
+%  \begin{macro}{\textormath}
+%    Some of the shorthands that will be declared by the language
+%    definition files have to be usable in both text and mathmode. To
+%    achieve this the helper macro |\textormath| is provided.
 %
 %    \begin{macrocode}
-\providecommand\setlocale{%
-  \bbl@error
-    {Not yet available}%
-    {Find an armchair, sit down and wait}}
-\let\uselocale\setlocale
-\let\locale\setlocale
-\let\selectlocale\setlocale
-\let\localename\setlocale
-\let\textlocale\setlocale
-\let\textlanguage\setlocale
-\let\languagetext\setlocale
+\def\textormath{%
+  \ifmmode
+    \expandafter\@secondoftwo
+  \else
+    \expandafter\@firstoftwo
+  \fi}
 %    \end{macrocode}
 %
-% \subsection{Errors}
+%  \end{macro}
 %
-% \begin{macro}{\@nolanerr}
-% \begin{macro}{\@nopatterns}
+%  \begin{macro}{\user@group}
+%  \begin{macro}{\language@group}
+%  \begin{macro}{\system@group}
+%    The current concept of `shorthands' supports three levels or
+%    groups of shorthands. For each level the name of the level or
+%    group is stored in a macro. The default is to have a user group;
+%    use language group `english' and have a system group called
+%    `system'.
 %
-% The \babel\ package will signal an error when a documents tries
-% to select a language that hasn't been defined earlier. When a
-% user selects a language for which no hyphenation patterns were
-% loaded into the format he will be given a warning about that
-% fact. We revert to the patterns for |\language|=0 in that case.
-% In most formats that will be (US)english, but it might also be
-% empty.
+%    \begin{macrocode}
+\def\user@group{user}
+\def\language@group{english} % TODO. I don't like defaults
+\def\system@group{system}
+%    \end{macrocode}
 %
-% \begin{macro}{\@noopterr}
-% When the package was loaded without options not everything will
-% work as expected. An error message is issued in that case.
+%  \end{macro}
+%  \end{macro}
+%  \end{macro}
 %
-% When the format knows about |\PackageError| it must be \LaTeXe,
-% so we can safely use its error handling interface. Otherwise
-% we'll have to `keep it simple'.
+%  \begin{macro}{\useshorthands}
 %
-% Infos are not written to the console, but on the other hand many
-% people think warnings are errors, so a further message type is
-% defined: an important info which is sent to the console.
+%    This is the user level macro. It initializes and activates the
+%    character for use as a shorthand character (ie, it's active in the
+%    preamble). Languages can deactivate shorthands, so a starred
+%    version is also provided which activates them always after the
+%    language has been switched.
 %
 %    \begin{macrocode}
-\edef\bbl@nulllanguage{\string\language=0}
-\ifx\PackageError\@undefined  % TODO. Move to Plain
-  \def\bbl@error#1#2{%
-    \begingroup
-      \newlinechar=`\^^J
-      \def\\{^^J(babel) }%
-      \errhelp{#2}\errmessage{\\#1}%
-    \endgroup}
-  \def\bbl@warning#1{%
-    \begingroup
-      \newlinechar=`\^^J
-      \def\\{^^J(babel) }%
-      \message{\\#1}%
-    \endgroup}
-  \let\bbl@infowarn\bbl@warning
-  \def\bbl@info#1{%
-    \begingroup
-      \newlinechar=`\^^J
-      \def\\{^^J}%
-      \wlog{#1}%
-    \endgroup}
-\fi
-\def\bbl@nocaption{\protect\bbl@nocaption@i}
-\def\bbl@nocaption@i#1#2{% 1: text to be printed 2: caption macro \langXname
-  \global\@namedef{#2}{\textbf{?#1?}}%
-  \@nameuse{#2}%
-  \edef\bbl@tempa{#1}%
-  \bbl@sreplace\bbl@tempa{name}{}%
-  \bbl@warning{% TODO.
-    \@backslashchar#1 not set for '\languagename'. Please,\\%
-    define it after the language has been loaded\\%
-    (typically in the preamble) with:\\% 
-    \string\setlocalecaption{\languagename}{\bbl@tempa}{..}\\%
-    Reported}}
-\def\bbl@tentative{\protect\bbl@tentative@i}
-\def\bbl@tentative@i#1{%
-  \bbl@warning{%
-    Some functions for '#1' are tentative.\\%
-    They might not work as expected and their behavior\\%
-    could change in the future.\\%
-    Reported}}
-\def\@nolanerr#1{%
-  \bbl@error
-    {You haven't defined the language '#1' yet.\\%
-     Perhaps you misspelled it or your installation\\%
-     is not complete}%
-    {Your command will be ignored, type <return> to proceed}}
-\def\@nopatterns#1{%
-  \bbl@warning
-    {No hyphenation patterns were preloaded for\\%
-     the language '#1' into the format.\\%
-     Please, configure your TeX system to add them and\\%
-     rebuild the format. Now I will use the patterns\\%
-     preloaded for \bbl@nulllanguage\space instead}}
-\let\bbl@usehooks\@gobbletwo
-\ifx\bbl@onlyswitch\@empty\endinput\fi
-  % Here ended switch.def
+\def\useshorthands{%
+  \@ifstar\bbl@usesh@s{\bbl@usesh@x{}}}
+\def\bbl@usesh@s#1{%
+  \bbl@usesh@x
+    {\AddBabelHook{babel-sh-\string#1}{afterextras}{\bbl@activate{#1}}}%
+    {#1}}
+\def\bbl@usesh@x#1#2{%
+  \bbl@ifshorthand{#2}%
+    {\def\user@group{user}%
+     \initiate@active@char{#2}%
+     #1%
+     \bbl@activate{#2}}%
+    {\bbl@error
+       {I can't declare a shorthand turned off (\string#2)}
+       {Sorry, but you can't use shorthands which have been\\%
+        turned off in the package options}}}
 %    \end{macrocode}
 %
-% Here ended |switch.def|.
-%
-%    \begin{macrocode}
-\ifx\directlua\@undefined\else
-  \ifx\bbl@luapatterns\@undefined
-    \input luababel.def
-  \fi
-\fi
-<@Basic macros@>
-\bbl@trace{Compatibility with language.def}
-\ifx\bbl@languages\@undefined
-  \ifx\directlua\@undefined
-    \openin1 = language.def % TODO. Remove hardcoded number
-    \ifeof1
-      \closein1
-      \message{I couldn't find the file language.def}
-    \else
-      \closein1
-      \begingroup
-        \def\addlanguage#1#2#3#4#5{%
-          \expandafter\ifx\csname lang@#1\endcsname\relax\else
-            \global\expandafter\let\csname l@#1\expandafter\endcsname
-              \csname lang@#1\endcsname
-          \fi}%
-        \def\uselanguage#1{}%
-        \input language.def
-      \endgroup
-    \fi
-  \fi
-  \chardef\l@english\z@
-\fi
-%    \end{macrocode}
+%  \end{macro}
 %
-%  \begin{macro}{\addto}
-% It takes two arguments, a \meta{control sequence} and \TeX-code to
-% be added to the \meta{control sequence}.
+%  \begin{macro}{\defineshorthand}
 %
-% If the \meta{control sequence} has not been defined before it is
-% defined now.  The control sequence could also expand to |\relax|,
-% in which case a circular definition results. The net result is a
-% stack overflow.  Note there is an inconsistency, because the
-% assignment in the last branch is global. 
+%    Currently we only support two groups of user level shorthands,
+%    named internally |user| and |user@<lang>| (language-dependent
+%    user shorthands). By default, only the first one is taken into
+%    account, but if the former is also used (in the optional argument
+%    of |\defineshorthand|) a new level is inserted for it
+%    (|user@generic|, done by |\bbl@set@user@generic|); we make also
+%    sure |{}| and |\protect| are taken into account in this new top
+%    level.
 %
 %    \begin{macrocode}
-\def\addto#1#2{%
-  \ifx#1\@undefined
-    \def#1{#2}%
-  \else
-    \ifx#1\relax
-      \def#1{#2}%
-    \else
-      {\toks@\expandafter{#1#2}%
-       \xdef#1{\the\toks@}}%
+\def\user@language@group{user@\language@group}
+\def\bbl@set@user@generic#1#2{%
+  \bbl@ifunset{user@generic@active#1}%
+    {\bbl@active@def#1\user@language@group{user@active}{user@generic@active}%
+     \bbl@active@def#1\user@group{user@generic@active}{language@active}%
+     \expandafter\edef\csname#2@sh@#1@@\endcsname{%
+       \expandafter\noexpand\csname normal@char#1\endcsname}%
+     \expandafter\edef\csname#2@sh@#1@\string\protect@\endcsname{%
+       \expandafter\noexpand\csname user@active#1\endcsname}}%
+  \@empty}
+\newcommand\defineshorthand[3][user]{%
+  \edef\bbl@tempa{\zap@space#1 \@empty}%
+  \bbl@for\bbl@tempb\bbl@tempa{%
+    \if*\expandafter\@car\bbl@tempb\@nil
+      \edef\bbl@tempb{user@\expandafter\@gobble\bbl@tempb}%
+      \@expandtwoargs
+        \bbl@set@user@generic{\expandafter\string\@car#2\@nil}\bbl@tempb
     \fi
-  \fi}
+    \declare@shorthand{\bbl@tempb}{#2}{#3}}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% The macro |\initiate@active@char| below takes all the necessary
-% actions to make its argument a shorthand character. The real work
-% is performed once for each character. But first we define a little
-% tool. TODO. Always used with additional expansions. Move them here?
-% Move the macro to basic?
+%  \begin{macro}{\languageshorthands}
+%
+%    A user level command to change the language from which shorthands
+%    are used. Unfortunately, \babel{} currently does not keep track
+%    of defined groups, and therefore there is no way to catch a
+%    possible change in casing to fix it in the same way languages names
+%    are fixed. [TODO].
 %
 %    \begin{macrocode}
-\def\bbl@withactive#1#2{%
-  \begingroup
-    \lccode`~=`#2\relax
-    \lowercase{\endgroup#1~}}
+\def\languageshorthands#1{\def\language@group{#1}}
 %    \end{macrocode}
 %
-%  \begin{macro}{\bbl@redefine}
+%  \end{macro}
+%
+%  \begin{macro}{\aliasshorthand}
+%    First the new shorthand needs to be initialized. Then, we define
+%    the new shorthand in terms of the original one, but note with
+%    |\aliasshorthands{"}{/}| is |\active@prefix /\active@char/|, so we
+%    still need to let the lattest to |\active@char"|.
 %
-% To redefine a command, we save the old meaning of the macro. Then
-% we redefine it to call the original macro with the `sanitized'
-% argument. The reason why we do it this way is that we don't want
-% to redefine the \LaTeX\ macros completely in case their
-% definitions change (they have changed in the past). A macro named
-% |\macro| will be saved new control sequences named |\org@macro|.
 %
 %    \begin{macrocode}
-\def\bbl@redefine#1{%
-  \edef\bbl@tempa{\bbl@stripslash#1}%
-  \expandafter\let\csname org@\bbl@tempa\endcsname#1%
-  \expandafter\def\csname\bbl@tempa\endcsname}
-\@onlypreamble\bbl@redefine
+\def\aliasshorthand#1#2{%
+  \bbl@ifshorthand{#2}%
+    {\expandafter\ifx\csname active@char\string#2\endcsname\relax
+       \ifx\document\@notprerr
+         \@notshorthand{#2}%
+       \else
+         \initiate@active@char{#2}%
+         \expandafter\let\csname active@char\string#2\expandafter\endcsname
+           \csname active@char\string#1\endcsname
+         \expandafter\let\csname normal@char\string#2\expandafter\endcsname
+           \csname normal@char\string#1\endcsname
+         \bbl@activate{#2}%
+       \fi
+     \fi}%
+    {\bbl@error
+       {Cannot declare a shorthand turned off (\string#2)}
+       {Sorry, but you cannot use shorthands which have been\\%
+        turned off in the package options}}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\bbl@redefine@long}
-%    This version of |\babel@redefine| can be used to redefine |\long|
-%    commands such as |\ifthenelse|.
+%  \begin{macro}{\@notshorthand}
 %
 %    \begin{macrocode}
-\def\bbl@redefine@long#1{%
-  \edef\bbl@tempa{\bbl@stripslash#1}%
-  \expandafter\let\csname org@\bbl@tempa\endcsname#1%
-  \expandafter\long\expandafter\def\csname\bbl@tempa\endcsname}
-\@onlypreamble\bbl@redefine@long
+\def\@notshorthand#1{%
+  \bbl@error{%
+    The character '\string #1' should be made a shorthand character;\\%
+    add the command \string\useshorthands\string{#1\string} to
+    the preamble.\\%
+    I will ignore your instruction}%
+   {You may proceed, but expect unexpected results}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-% \begin{macro}{\bbl@redefinerobust}
-% For commands that are redefined, but which \textit{might} be
-% robust we need a slightly more intelligent macro. A robust
-% command |foo| is defined to expand to |\protect|\verb*|\foo |. So
-% it is necessary to check whether \verb*|\foo | exists. The result
-% is that the command that is being redefined is always robust
-% afterwards.  Therefore all we need to do now is define \verb*|\foo |.
+%  \begin{macro}{\shorthandon}
+%  \begin{macro}{\shorthandoff}
+%    The first level definition of these macros just passes the
+%    argument on to |\bbl@switch@sh|, adding |\@nil| at the end to
+%    denote the end of the list of characters.
 %
 %    \begin{macrocode}
-\def\bbl@redefinerobust#1{%
-  \edef\bbl@tempa{\bbl@stripslash#1}%
-  \bbl@ifunset{\bbl@tempa\space}%
-    {\expandafter\let\csname org@\bbl@tempa\endcsname#1%
-     \bbl@exp{\def\\#1{\\\protect\<\bbl@tempa\space>}}}%
-    {\bbl@exp{\let\<org@\bbl@tempa>\<\bbl@tempa\space>}}%
-    \@namedef{\bbl@tempa\space}}
-\@onlypreamble\bbl@redefinerobust
+\newcommand*\shorthandon[1]{\bbl@switch@sh\@ne#1\@nnil}
+\DeclareRobustCommand*\shorthandoff{%
+  \@ifstar{\bbl@shorthandoff\tw@}{\bbl@shorthandoff\z@}}
+\def\bbl@shorthandoff#1#2{\bbl@switch@sh#1#2\@nnil}
 %    \end{macrocode}
 %
-%  \end{macro}
+%  \begin{macro}{\bbl@switch@sh}
 %
-% \subsection{Hooks}
+%    The macro |\bbl@switch@sh| takes the list of characters apart one
+%    by one and subsequently switches the category code of the
+%    shorthand character according to the first argument of
+%    |\bbl@switch@sh|.
 %
-% Admittedly, the current implementation is a somewhat simplistic and
-% does very little to catch errors, but it is meant for developers,
-% after all. |\bbl@usehooks| is the commands used by \babel{} to execute
-% hooks defined for an event.
+%    But before any of this switching takes place we make sure that the
+%    character we are dealing with is known as a shorthand character.
+%    If it is, a macro such as |\active@char"| should exist.
 %
-%    \begin{macrocode}
-\bbl@trace{Hooks}
-\newcommand\AddBabelHook[3][]{%
-  \bbl@ifunset{bbl@hk@#2}{\EnableBabelHook{#2}}{}%
-  \def\bbl@tempa##1,#3=##2,##3\@empty{\def\bbl@tempb{##2}}%
-  \expandafter\bbl@tempa\bbl@evargs,#3=,\@empty
-  \bbl@ifunset{bbl@ev@#2@#3@#1}%
-    {\bbl@csarg\bbl@add{ev@#3@#1}{\bbl@elth{#2}}}%
-    {\bbl@csarg\let{ev@#2@#3@#1}\relax}%
-  \bbl@csarg\newcommand{ev@#2@#3@#1}[\bbl@tempb]}
-\newcommand\EnableBabelHook[1]{\bbl@csarg\let{hk@#1}\@firstofone}
-\newcommand\DisableBabelHook[1]{\bbl@csarg\let{hk@#1}\@gobble}
-\def\bbl@usehooks#1#2{%
-  \ifx\UseHook\@undefined\else\UseHook{babel/#1}\fi
-  \def\bbl@elth##1{%
-    \bbl@cs{hk@##1}{\bbl@cs{ev@##1@#1@}#2}}%
-  \bbl@cs{ev@#1@}%
-  \ifx\languagename\@undefined\else % Test required for Plain (?)
-    \ifx\UseHook\@undefined\else\UseHook{babel/#1/\languagename}\fi
-    \def\bbl@elth##1{%
-      \bbl@cs{hk@##1}{\bbl@cl{ev@##1@#1}#2}}%
-    \bbl@cl{ev@#1}%
+%    Switching off and on is easy -- we just set the category code to
+%    `other' (12) and |\active|. With the starred version, the original
+%    catcode and the original definition, saved in
+%    |@initiate@active@char|, are restored.
+%
+%    \begin{macrocode}
+\def\bbl@switch@sh#1#2{%
+  \ifx#2\@nnil\else
+    \bbl@ifunset{bbl@active@\string#2}%
+      {\bbl@error
+         {I can't switch '\string#2' on or off--not a shorthand}%
+         {This character is not a shorthand. Maybe you made\\%
+          a typing mistake? I will ignore your instruction.}}%
+      {\ifcase#1%   off, on, off*
+         \catcode`#212\relax
+       \or
+         \catcode`#2\active
+         \bbl@ifunset{bbl@shdef@\string#2}%
+           {}%
+           {\bbl@withactive{\expandafter\let\expandafter}#2%
+              \csname bbl@shdef@\string#2\endcsname
+            \bbl@csarg\let{shdef@\string#2}\relax}%
+         \ifcase\bbl@activated\or
+           \bbl@activate{#2}%
+         \else
+           \bbl@deactivate{#2}%
+         \fi
+       \or
+         \bbl@ifunset{bbl@shdef@\string#2}%
+           {\bbl@withactive{\bbl@csarg\let{shdef@\string#2}}#2}%
+           {}%
+         \csname bbl@oricat@\string#2\endcsname
+         \csname bbl@oridef@\string#2\endcsname
+       \fi}%
+    \bbl@afterfi\bbl@switch@sh#1%
   \fi}
 %    \end{macrocode}
 %
-% To ensure forward compatibility, arguments in hooks are set
-% implicitly. So, if a further argument is added in the future,
-% there is no need to change the existing code. Note events
-% intended for \textsf{hyphen.cfg} are also loaded (just in
-% case you need them for some reason).
+%  \end{macro}
+%  \end{macro}
+%  \end{macro}
+%
+% Note the value is that at the expansion time; eg, in the preample
+% shorhands are usually deactivated.
 %
 %    \begin{macrocode}
-\def\bbl@evargs{,% <- don't delete this comma
-  everylanguage=1,loadkernel=1,loadpatterns=1,loadexceptions=1,%
-  adddialect=2,patterns=2,defaultcommands=0,encodedcommands=2,write=0,%
-  beforeextras=0,afterextras=0,stopcommands=0,stringprocess=0,%
-  hyphenation=2,initiateactive=3,afterreset=0,foreign=0,foreign*=0,%
-  beforestart=0,languagename=2}
-\ifx\NewHook\@undefined\else
-  \def\bbl@tempa#1=#2\@@{\NewHook{babel/#1}}
-  \bbl@foreach\bbl@evargs{\bbl@tempa#1\@@}
+\def\babelshorthand{\active@prefix\babelshorthand\bbl@putsh}
+\def\bbl@putsh#1{%
+  \bbl@ifunset{bbl@active@\string#1}%
+     {\bbl@putsh@i#1\@empty\@nnil}%
+     {\csname bbl@active@\string#1\endcsname}}
+\def\bbl@putsh@i#1#2\@nnil{%
+  \csname\language@group @sh@\string#1@%
+    \ifx\@empty#2\else\string#2@\fi\endcsname}
+\ifx\bbl@opt@shorthands\@nnil\else
+  \let\bbl@s@initiate@active@char\initiate@active@char
+  \def\initiate@active@char#1{%
+    \bbl@ifshorthand{#1}{\bbl@s@initiate@active@char{#1}}{}}
+  \let\bbl@s@switch@sh\bbl@switch@sh
+  \def\bbl@switch@sh#1#2{%
+    \ifx#2\@nnil\else
+      \bbl@afterfi
+      \bbl@ifshorthand{#2}{\bbl@s@switch@sh#1{#2}}{\bbl@switch@sh#1}%
+    \fi}
+  \let\bbl@s@activate\bbl@activate
+  \def\bbl@activate#1{%
+    \bbl@ifshorthand{#1}{\bbl@s@activate{#1}}{}}
+  \let\bbl@s@deactivate\bbl@deactivate
+  \def\bbl@deactivate#1{%
+    \bbl@ifshorthand{#1}{\bbl@s@deactivate{#1}}{}}
 \fi
 %    \end{macrocode}
 %
-% \begin{macro}{\babelensure}
+% You may want to test if a character is a shorthand. Note it does not
+% test whether the shorthand is on or off.
 %
-% The user command just parses the optional argument and creates a
-% new macro named |\bbl@e@|\m{language}. We register a hook at the
-% |afterextras| event which just executes this macro in a
-% ``complete'' selection (which, if undefined, is |\relax| and does
-% nothing). This part is somewhat involved because we have to make
-% sure things are expanded the correct number of times.
+%    \begin{macrocode}
+\newcommand\ifbabelshorthand[3]{\bbl@ifunset{bbl@active@\string#1}{#3}{#2}}
+%    \end{macrocode}
 %
-% The macro |\bbl@e@|\m{language} contains
-% |\bbl@ensure|\marg{include}\marg{exclude}\marg{fontenc}, which in in
-% turn loops over the macros names in |\bbl@captionslist|, excluding
-% (with the help of |\in@|) those in the |exclude| list. If the
-% |fontenc| is given (and not |\relax|), the |\fontencoding| is also
-% added. Then we loop over the |include| list, but if the macro
-% already contains |\foreignlanguage|, nothing is done.  Note this
-% macro (1) is not restricted to the preamble, and (2) changes are
-% local.
+%  \begin{macro}{\bbl@prim@s}
+%  \begin{macro}{\bbl@pr@m@s}
+%
+% One of the internal macros that are involved in substituting |\prime|
+% for each right quote in mathmode is |\prim@s|. This checks if the
+% next character is a right quote. When the right quote is active, the
+% definition of this macro needs to be adapted to look also for an
+% active right quote; the hat could be active, too.
 %
 %    \begin{macrocode}
-\bbl@trace{Defining babelensure}
-\newcommand\babelensure[2][]{%  TODO - revise test files
-  \AddBabelHook{babel-ensure}{afterextras}{%
-    \ifcase\bbl@select@type
-      \bbl@cl{e}%
-    \fi}%
-  \begingroup
-    \let\bbl@ens@include\@empty
-    \let\bbl@ens@exclude\@empty
-    \def\bbl@ens@fontenc{\relax}%
-    \def\bbl@tempb##1{%
-      \ifx\@empty##1\else\noexpand##1\expandafter\bbl@tempb\fi}%
-    \edef\bbl@tempa{\bbl@tempb#1\@empty}%
-    \def\bbl@tempb##1=##2\@@{\@namedef{bbl@ens@##1}{##2}}%
-    \bbl@foreach\bbl@tempa{\bbl@tempb##1\@@}%
-    \def\bbl@tempc{\bbl@ensure}%
-    \expandafter\bbl@add\expandafter\bbl@tempc\expandafter{%
-      \expandafter{\bbl@ens@include}}%
-    \expandafter\bbl@add\expandafter\bbl@tempc\expandafter{%
-      \expandafter{\bbl@ens@exclude}}%
-    \toks@\expandafter{\bbl@tempc}%
-    \bbl@exp{%
-  \endgroup
-  \def\<bbl@e@#2>{\the\toks@{\bbl@ens@fontenc}}}}
-\def\bbl@ensure#1#2#3{% 1: include 2: exclude 3: fontenc
-  \def\bbl@tempb##1{% elt for (excluding) \bbl@captionslist list
-    \ifx##1\@undefined % 3.32 - Don't assume the macro exists
-      \edef##1{\noexpand\bbl@nocaption
-        {\bbl@stripslash##1}{\languagename\bbl@stripslash##1}}%
-    \fi
-    \ifx##1\@empty\else
-      \in@{##1}{#2}%
-      \ifin@\else
-        \bbl@ifunset{bbl@ensure@\languagename}%
-          {\bbl@exp{%
-            \\\DeclareRobustCommand\<bbl@ensure@\languagename>[1]{%
-              \\\foreignlanguage{\languagename}%
-              {\ifx\relax#3\else
-                \\\fontencoding{#3}\\\selectfont
-               \fi
-               ########1}}}}%
-          {}%
-        \toks@\expandafter{##1}%
-        \edef##1{%
-           \bbl@csarg\noexpand{ensure@\languagename}%
-           {\the\toks@}}%
-      \fi
-      \expandafter\bbl@tempb
-    \fi}%
-  \expandafter\bbl@tempb\bbl@captionslist\today\@empty
-  \def\bbl@tempa##1{% elt for include list
-    \ifx##1\@empty\else
-      \bbl@csarg\in@{ensure@\languagename\expandafter}\expandafter{##1}%
-      \ifin@\else
-        \bbl@tempb##1\@empty
-      \fi
-      \expandafter\bbl@tempa
-    \fi}%
-  \bbl@tempa#1\@empty}
-\def\bbl@captionslist{%
-  \prefacename\refname\abstractname\bibname\chaptername\appendixname
-  \contentsname\listfigurename\listtablename\indexname\figurename
-  \tablename\partname\enclname\ccname\headtoname\pagename\seename
-  \alsoname\proofname\glossaryname}
+\def\bbl@prim@s{%
+  \prime\futurelet\@let@token\bbl@pr@m@s}
+\def\bbl@if@primes#1#2{%
+  \ifx#1\@let@token
+    \expandafter\@firstoftwo
+  \else\ifx#2\@let@token
+    \bbl@afterelse\expandafter\@firstoftwo
+  \else
+    \bbl@afterfi\expandafter\@secondoftwo
+  \fi\fi}
+\begingroup
+  \catcode`\^=7  \catcode`\*=\active  \lccode`\*=`\^
+  \catcode`\'=12 \catcode`\"=\active  \lccode`\"=`\'
+  \lowercase{%
+    \gdef\bbl@pr@m@s{%
+      \bbl@if@primes"'%
+        \pr@@@s
+        {\bbl@if@primes*^\pr@@@t\egroup}}}
+\endgroup
 %    \end{macrocode}
 %
-%    \end{macro}
+%  \end{macro}
+%  \end{macro}
 %
-% \subsection{Setting up language files}
+%    Usually the |~| is active and expands to \verb*=\penalty\@M\ =.
+%    When it is written to the \file{.aux} file it is written
+%    expanded. To prevent that and to be able to use the character |~|
+%    as a start character for a shorthand, it is redefined here as a
+%    one character shorthand on system level. The system declaration
+%    is in most cases redundant (when |~| is still a non-break space),
+%    and in some cases is inconvenient (if |~| has been redefined);
+%    however, for backward compatibility it is maintained (some
+%    existing documents may rely on the \babel{} value).
 %
-% \begin{macro}{\LdfInit}
+%    \begin{macrocode}
+\initiate@active@char{~}
+\declare@shorthand{system}{~}{\leavevmode\nobreak\ }
+\bbl@activate{~}
+%    \end{macrocode}
 %
-% |\LdfInit| macro takes two arguments. The first
-% argument is the name of the language that will be defined in the
-% language definition file; the second argument is either a control
-% sequence or a string from which a control sequence should be
-% constructed. The existence of the control sequence indicates that
-% the file has been processed before.
+%  \begin{macro}{\OT1dqpos}
+%  \begin{macro}{\T1dqpos}
+%    The position of the double quote character is different for the
+%    OT1 and T1 encodings. It will later be selected using the
+%    |\f@encoding| macro. Therefore we define two macros here to store
+%    the position of the character in these encodings.
 %
-% At the start of processing a language definition file we always
-% check the category code of the at-sign. We make sure that it is
-% a `letter' during the processing of the file. We also save its
-% name as the last called option, even if not loaded.
+%    \begin{macrocode}
+\expandafter\def\csname OT1dqpos\endcsname{127}
+\expandafter\def\csname T1dqpos\endcsname{4}
+%    \end{macrocode}
 %
-% Another character that needs to have the correct category code
-% during processing of language definition files is the equals sign,
-% `=', because it is sometimes used in constructions with the
-% |\let| primitive. Therefore we store its current catcode and
-% restore it later on.
-%
-% Now we check whether we should perhaps stop the processing of
-% this file. To do this we first need to check whether the second
-% argument that is passed to |\LdfInit| is a control sequence. We
-% do that by looking at the first token after passing |#2| through
-% |string|. When it is equal to |\@backslashchar| we are dealing
-% with a control sequence which we can compare with |\@undefined|.
-%
-% If so, we call |\ldf@quit| to set the main language, restore the
-% category code of the @-sign and call |\endinput|
-%
-% When |#2| was \emph{not} a control sequence we construct one and
-% compare it with |\relax|.
-%
-% Finally we check |\originalTeX|.
+%    When the macro |\f@encoding| is undefined (as it is in plain
+%    \TeX) we define it here to expand to \texttt{OT1}
 %
 %    \begin{macrocode}
-\bbl@trace{Macros for setting language files up}
-\def\bbl@ldfinit{%
-  \let\bbl@screset\@empty
-  \let\BabelStrings\bbl@opt@string
-  \let\BabelOptions\@empty
-  \let\BabelLanguages\relax
-  \ifx\originalTeX\@undefined
-    \let\originalTeX\@empty
-  \else
-    \originalTeX
-  \fi}
-\def\LdfInit#1#2{%
-  \chardef\atcatcode=\catcode`\@
-  \catcode`\@=11\relax
-  \chardef\eqcatcode=\catcode`\=
-  \catcode`\==12\relax
-  \expandafter\if\expandafter\@backslashchar
-                 \expandafter\@car\string#2\@nil
-    \ifx#2\@undefined\else
-      \ldf@quit{#1}%
-    \fi
-  \else
-    \expandafter\ifx\csname#2\endcsname\relax\else
-      \ldf@quit{#1}%
-    \fi
-  \fi
-  \bbl@ldfinit}
+\ifx\f@encoding\@undefined
+  \def\f@encoding{OT1}
+\fi
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-%  \begin{macro}{\ldf@quit}
-%    This macro interrupts the processing of a language definition file.
+% \subsection{Language attributes}
 %
-%    \begin{macrocode}
-\def\ldf@quit#1{%
-  \expandafter\main@language\expandafter{#1}%
-  \catcode`\@=\atcatcode \let\atcatcode\relax
-  \catcode`\==\eqcatcode \let\eqcatcode\relax
-  \endinput}
-%    \end{macrocode}
+%    Language attributes provide a means to give the user control over
+%    which features of the language definition files he wants to
+%    enable.
+%  \begin{macro}{\languageattribute}
 %
-%  \end{macro}
+%    The macro |\languageattribute| checks whether its arguments are
+%    valid and then activates the selected language attribute.
+%    First check whether the language is known, and then process each
+%    attribute in the list.
 %
-%  \begin{macro}{\ldf@finish}
-%    This macro takes one argument. It is the name of the language
-%    that was defined in the language definition file.
+%    \begin{macrocode}
+\bbl@trace{Language attributes}
+\newcommand\languageattribute[2]{%
+  \def\bbl@tempc{#1}%
+  \bbl@fixname\bbl@tempc
+  \bbl@iflanguage\bbl@tempc{%
+    \bbl@vforeach{#2}{%
+%    \end{macrocode}
 %
-%    We load the local configuration file if one is present, we set
-%    the main language (taking into account that the argument might be
-%    a control sequence that needs to be expanded) and reset the
-%    category code of the @-sign.
+%    We want to make sure that each attribute is selected only once;
+%    therefore we store the already selected attributes in
+%    |\bbl@known@attribs|. When that control sequence is not yet
+%    defined this attribute is certainly not selected before.
 %
 %    \begin{macrocode}
-\def\bbl@afterldf#1{% TODO. Merge into the next macro? Unused elsewhere
-  \bbl@afterlang
-  \let\bbl@afterlang\relax
-  \let\BabelModifiers\relax
-  \let\bbl@screset\relax}%
-\def\ldf@finish#1{%
-  \loadlocalcfg{#1}%
-  \bbl@afterldf{#1}%
-  \expandafter\main@language\expandafter{#1}%
-  \catcode`\@=\atcatcode \let\atcatcode\relax
-  \catcode`\==\eqcatcode \let\eqcatcode\relax}
+      \ifx\bbl@known@attribs\@undefined
+        \in@false
+      \else
+        \bbl@xin@{,\bbl@tempc-##1,}{,\bbl@known@attribs,}%
+      \fi
+      \ifin@
+        \bbl@warning{%
+          You have more than once selected the attribute '##1'\\%
+          for language #1. Reported}%
+      \else
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%    After the preamble of the document the commands |\LdfInit|,
-%    |\ldf@quit| and |\ldf@finish| are no longer needed. Therefore
-%    they are turned into warning messages in \LaTeX.
+%    When we end up here the attribute is not selected before. So, we
+%    add it to the list of selected attributes and execute the
+%    associated \TeX-code.
 %
 %    \begin{macrocode}
-\@onlypreamble\LdfInit
-\@onlypreamble\ldf@quit
-\@onlypreamble\ldf@finish
+        \bbl@exp{%
+          \\\bbl@add@list\\\bbl@known@attribs{\bbl@tempc-##1}}%
+        \edef\bbl@tempa{\bbl@tempc-##1}%
+        \expandafter\bbl@ifknown@ttrib\expandafter{\bbl@tempa}\bbl@attributes%
+        {\csname\bbl@tempc @attr@##1\endcsname}%
+        {\@attrerr{\bbl@tempc}{##1}}%
+     \fi}}}
+\@onlypreamble\languageattribute
 %    \end{macrocode}
 %
-%  \begin{macro}{\main@language}
-%  \begin{macro}{\bbl@main@language}
-%    This command should be used in the various language definition
-%    files. It stores its argument in |\bbl@main@language|; to be used
-%    to switch to the correct language at the beginning of the
-%    document.
+%    The error text to be issued when an unknown attribute is
+%    selected.
 %
 %    \begin{macrocode}
-\def\main@language#1{%
-  \def\bbl@main@language{#1}%
-  \let\languagename\bbl@main@language % TODO. Set localename
-  \bbl@id@assign
-  \bbl@patterns{\languagename}}
+\newcommand*{\@attrerr}[2]{%
+  \bbl@error
+    {The attribute #2 is unknown for language #1.}%
+    {Your command will be ignored, type <return> to proceed}}
 %    \end{macrocode}
 %
-% We also have to make sure that some code gets executed at the
-% beginning of the document, either when the |aux| file is read or,
-% if it does not exist, when the |\AtBeginDocument| is executed.
-% Languages do not set |\pagedir|, so we set here for the whole
-% document to the main |\bodydir|.
+%  \end{macro}
+%
+%  \begin{macro}{\bbl@declare@ttribute}
+%    This command adds the new language/attribute combination to the
+%    list of known attributes.
+%
+%    Then it defines a control sequence to be executed when the
+%    attribute is used in a document. The result of this should be
+%    that the macro |\extras...| for the current language is extended,
+%    otherwise the attribute will not work as its code is removed from
+%    memory at |\begin{document}|.
 %
 %    \begin{macrocode}
-\def\bbl@beforestart{%
-  \def\@nolanerr##1{%
-    \bbl@warning{Undefined language '##1' in aux.\\Reported}}%
-  \bbl@usehooks{beforestart}{}%
-  \global\let\bbl@beforestart\relax}
-\AtBeginDocument{%
-  {\@nameuse{bbl@beforestart}}%  Group!
-  \if@filesw
-    \providecommand\babel@aux[2]{}%
-    \immediate\write\@mainaux{%
-      \string\providecommand\string\babel@aux[2]{}}%
-    \immediate\write\@mainaux{\string\@nameuse{bbl@beforestart}}%
-  \fi
-  \expandafter\selectlanguage\expandafter{\bbl@main@language}%
-  \ifbbl@single  % must go after the line above.
-    \renewcommand\selectlanguage[1]{}%
-    \renewcommand\foreignlanguage[2]{#2}%
-    \global\let\babel@aux\@gobbletwo  % Also as flag
+\def\bbl@declare@ttribute#1#2#3{%
+  \bbl@xin@{,#2,}{,\BabelModifiers,}%
+  \ifin@
+    \AfterBabelLanguage{#1}{\languageattribute{#1}{#2}}%
   \fi
-  \ifcase\bbl@engine\or\pagedir\bodydir\fi} % TODO - a better place
+  \bbl@add@list\bbl@attributes{#1-#2}%
+  \expandafter\def\csname#1@attr@#2\endcsname{#3}}
 %    \end{macrocode}
 %
 %  \end{macro}
-%  \end{macro}
 %
-% A bit of optimization. Select in heads/foots the language only if
-% necessary.
+%  \begin{macro}{\bbl@ifattributeset}
+%    This internal macro has 4 arguments. It can be used to interpret
+%    \TeX\ code based on whether a certain attribute was set. This
+%    command should appear inside the argument to |\AtBeginDocument|
+%    because the attributes are set in the document preamble,
+%    \emph{after} \babel\ is loaded.
+%
+%    The first argument is the language, the second argument the
+%    attribute being checked, and the third and fourth arguments are
+%    the true and false clauses.
 %
 %    \begin{macrocode}
-\def\select@language@x#1{%
-  \ifcase\bbl@select@type
-    \bbl@ifsamestring\languagename{#1}{}{\select@language{#1}}%
+\def\bbl@ifattributeset#1#2#3#4{%
+  \ifx\bbl@known@attribs\@undefined
+    \in@false
   \else
-    \select@language{#1}%
+    \bbl@xin@{,#1-#2,}{,\bbl@known@attribs,}%
+  \fi
+  \ifin@
+    \bbl@afterelse#3%
+  \else
+    \bbl@afterfi#4%
   \fi}
 %    \end{macrocode}
 %
-% \subsection{Shorthands}
+%  \end{macro}
 %
-%  \begin{macro}{\bbl@add@special}
-%    The macro |\bbl@add@special| is used to add a new character (or
-%    single character control sequence) to the macro |\dospecials|
-%    (and |\@sanitize| if \LaTeX\ is used). It is used only at one
-%    place, namely when |\initiate@active@char| is called (which is
-%    ignored if the char has been made active before).  Because
-%    |\@sanitize| can be undefined, we put the definition inside a
-%    conditional.
+%  \begin{macro}{\bbl@ifknown@ttrib}
+%    An internal macro to check whether a given language/attribute is
+%    known. The macro takes 4 arguments, the language/attribute, the
+%    attribute list, the \TeX-code to be executed when the attribute
+%    is known and the \TeX-code to be executed otherwise.
 %
-%    Items are added to the lists without checking its existence or
-%    the original catcode. It does not hurt, but should be fixed. It's
-%    already done with |\nfss@catcodes|, added in 3.10.
+%    We first assume the attribute is unknown. Then we loop over the
+%    list of known attributes, trying to find a match. 
 %
 %    \begin{macrocode}
-\bbl@trace{Shorhands}
-\def\bbl@add@special#1{% 1:a macro like \", \?, etc.
-  \bbl@add\dospecials{\do#1}% test @sanitize = \relax, for back. compat.
-  \bbl@ifunset{@sanitize}{}{\bbl@add\@sanitize{\@makeother#1}}%
-  \ifx\nfss@catcodes\@undefined\else % TODO - same for above
-    \begingroup
-      \catcode`#1\active
-      \nfss@catcodes
-      \ifnum\catcode`#1=\active
-        \endgroup
-        \bbl@add\nfss@catcodes{\@makeother#1}%
-      \else
-        \endgroup
-      \fi
-  \fi}
+\def\bbl@ifknown@ttrib#1#2{%
+  \let\bbl@tempa\@secondoftwo
+  \bbl@loopx\bbl@tempb{#2}{%
+    \expandafter\in@\expandafter{\expandafter,\bbl@tempb,}{,#1,}%
+    \ifin@
+      \let\bbl@tempa\@firstoftwo
+    \else
+    \fi}%
+  \bbl@tempa}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\bbl@remove@special}
-%
-%    The companion of the former macro is |\bbl@remove@special|.  It
-%    removes a character from the set macros |\dospecials| and
-%    |\@sanitize|, but it is not used at all in the \babel{} core.
+%  \begin{macro}{\bbl@clear@ttribs}
+%    This macro removes all the attribute code from \LaTeX's memory at
+%    |\begin{document}| time (if any is present).
 %
 %    \begin{macrocode}
-\def\bbl@remove@special#1{%
-  \begingroup
-    \def\x##1##2{\ifnum`#1=`##2\noexpand\@empty
-                 \else\noexpand##1\noexpand##2\fi}%
-    \def\do{\x\do}%
-    \def\@makeother{\x\@makeother}%
-  \edef\x{\endgroup
-    \def\noexpand\dospecials{\dospecials}%
-    \expandafter\ifx\csname @sanitize\endcsname\relax\else
-      \def\noexpand\@sanitize{\@sanitize}%
-    \fi}%
-  \x}
+\def\bbl@clear@ttribs{%
+  \ifx\bbl@attributes\@undefined\else
+    \bbl@loopx\bbl@tempa{\bbl@attributes}{%
+      \expandafter\bbl@clear@ttrib\bbl@tempa.
+      }%
+    \let\bbl@attributes\@undefined
+  \fi}
+\def\bbl@clear@ttrib#1-#2.{%
+  \expandafter\let\csname#1@attr@#2\endcsname\@undefined}
+\AtBeginDocument{\bbl@clear@ttribs}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\initiate@active@char}
-%    A language definition file can call this macro to make a
-%    character active. This macro takes one argument, the character
-%    that is to be made active. When the character was already active
-%    this macro does nothing. Otherwise, this macro defines the
-%    control sequence |\normal@char|\m{char} to expand to the
-%    character in its `normal state' and it defines the active
-%    character to expand to |\normal@char|\m{char} by default
-%    (\m{char} being the character to be made active). Later its
-%    definition can be changed to expand to |\active@char|\m{char}
-%    by calling |\bbl@activate{|\m{char}|}|.
+% \subsection{Support for saving macro definitions}
 %
-%    For example, to make the double quote character active one could
-%    have |\initiate@active@char{"}| in a language definition file.
-%    This defines |"| as |\active@prefix "\active@char"| (where the
-%    first |"| is the character with its original catcode, when the
-%    shorthand is created, and |\active@char"| is a single token). In
-%    protected contexts, it expands to |\protect "| or |\noexpand "|
-%    (ie, with the original |"|); otherwise |\active@char"| is
-%    executed. This macro in turn expands to |\normal@char"| in
-%    ``safe'' contexts (eg, |\label|), but |\user@active"| in normal
-%    ``unsafe'' ones. The latter search a definition in the user,
-%    language and system levels, in this order, but if none is found,
-%    |\normal@char"| is used.  However, a deactivated shorthand (with
-%    |\bbl@deactivate| is defined as |\active@prefix "\normal@char"|.
+%  To save the meaning of control sequences using |\babel@save|, we
+%  use temporary control sequences.  To save hash table entries for
+%  these control sequences, we don't use the name of the control
+%  sequence to be saved to construct the temporary name.  Instead we
+%  simply use the value of a counter, which is reset to zero each time
+%  we begin to save new values.  This works well because we release
+%  the saved meanings before we begin to save a new set of control
+%  sequence meanings (see |\selectlanguage| and |\originalTeX|). Note
+%  undefined macros are not undefined any more when saved -- they are
+%  |\relax|'ed.
 %
-%    The following macro is used to define shorthands in the three
-%    levels. It takes 4 arguments: the (string'ed) character,
-%    |\<level>@group|, |<level>@active| and |<next-level>@active|
-%    (except in |system|).
+%  \begin{macro}{\babel@savecnt}
+%  \begin{macro}{\babel@beginsave}
+%    The initialization of a new save cycle: reset the counter to
+%    zero.
 %
 %    \begin{macrocode}
-\def\bbl@active@def#1#2#3#4{%
-  \@namedef{#3#1}{%
-    \expandafter\ifx\csname#2@sh@#1@\endcsname\relax
-      \bbl@afterelse\bbl@sh@select#2#1{#3@arg#1}{#4#1}%
-    \else
-      \bbl@afterfi\csname#2@sh@#1@\endcsname
-    \fi}%
+\bbl@trace{Macros for saving definitions}
+\def\babel@beginsave{\babel@savecnt\z@}
 %    \end{macrocode}
 %
-%    When there is also no current-level shorthand with an argument we
-%    will check whether there is a next-level  defined shorthand for
-%    this active character.
+%    Before it's forgotten, allocate the counter and initialize all.
 %
 %    \begin{macrocode}
-  \long\@namedef{#3@arg#1}##1{%
-    \expandafter\ifx\csname#2@sh@#1@\string##1@\endcsname\relax
-      \bbl@afterelse\csname#4#1\endcsname##1%
-    \else
-      \bbl@afterfi\csname#2@sh@#1@\string##1@\endcsname
-    \fi}}%
+\newcount\babel@savecnt
+\babel@beginsave
 %    \end{macrocode}
 %
-%    |\initiate@active@char| calls |\@initiate@active@char| with 3
-%    arguments. All of them are the same character with different
-%    catcodes: active, other (|\string|'ed) and the original one.
-%    This trick simplifies the code a lot.
+%  \end{macro}
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\initiate@active@char#1{%
-  \bbl@ifunset{active@char\string#1}%
-    {\bbl@withactive
-      {\expandafter\@initiate@active@char\expandafter}#1\string#1#1}%
-    {}}
-%    \end{macrocode}
+%  \begin{macro}{\babel@save}
+%  \begin{macro}{\babel@savevariable}
 %
-%   The very first thing to do is saving the original catcode and the
-%   original definition, even if not active, which is possible
-%   (undefined characters require a special treatement to avoid
-%   making them |\relax| and preserving some degree of protection).
+% The macro |\babel@save|\meta{csname} saves the current meaning of the
+% control sequence \meta{csname} to
+% |\originalTeX|\footnote{\cs{originalTeX} has to be expandable,
+% i.\,e.\ you shouldn't let it to \cs{relax}.}. To do this, we let the
+% current meaning to a temporary control sequence, the restore commands
+% are appended to |\originalTeX| and the counter is incremented. The
+% macro |\babel@savevariable|\meta{variable} saves the value of the
+% variable. \meta{variable} can be anything allowed after the |\the|
+% primitive.
 %
 %    \begin{macrocode}
-\def\@initiate@active@char#1#2#3{%
-  \bbl@csarg\edef{oricat@#2}{\catcode`#2=\the\catcode`#2\relax}%
-  \ifx#1\@undefined
-    \bbl@csarg\def{oridef@#2}{\def#1{\active@prefix#1\@undefined}}%
-  \else
-    \bbl@csarg\let{oridef@@#2}#1%
-    \bbl@csarg\edef{oridef@#2}{%
-      \let\noexpand#1%
-      \expandafter\noexpand\csname bbl@oridef@@#2\endcsname}%
-  \fi
+\def\babel@save#1{%
+  \expandafter\let\csname babel@\number\babel@savecnt\endcsname#1\relax
+  \toks@\expandafter{\originalTeX\let#1=}%
+  \bbl@exp{%
+    \def\\\originalTeX{\the\toks@\<babel@\number\babel@savecnt>\relax}}%
+  \advance\babel@savecnt\@ne}
+\def\babel@savevariable#1{%
+  \toks@\expandafter{\originalTeX #1=}%
+  \bbl@exp{\def\\\originalTeX{\the\toks@\the#1\relax}}}
 %    \end{macrocode}
 %
-%    If the character is already active we provide the default
-%    expansion under this shorthand mechanism. Otherwise we write a
-%    message in the transcript file, and define |\normal@char|\m{char}
-%    to expand to the character in its default state. If the character
-%    is mathematically active when \babel{} is loaded (for example
-%    |'|) the normal expansion is somewhat different to avoid an
-%    infinite loop (but it does not prevent the loop if the mathcode
-%    is set to |"8000| \textit{a posteriori}).
+%  \end{macro}
+%  \end{macro}
+%
+%  \begin{macro}{\bbl@frenchspacing}
+%  \begin{macro}{\bbl@nonfrenchspacing}
+% Some languages need to have |\frenchspacing| in effect. Others
+% don't want that. The command |\bbl@frenchspacing| switches it on
+% when it isn't already in effect and |\bbl@nonfrenchspacing|
+% switches it off if necessary. A more refined way to switch the
+% catcodes is done with |ini| files. Here an auxiliary macro is
+% defined, but the main part is in |\babelprovide|. This new method
+% should be ideally the default one.
 %
 %    \begin{macrocode}
-  \ifx#1#3\relax
-    \expandafter\let\csname normal@char#2\endcsname#3%
+\def\bbl@frenchspacing{%
+  \ifnum\the\sfcode`\.=\@m
+    \let\bbl@nonfrenchspacing\relax
   \else
-    \bbl@info{Making #2 an active character}%
-    \ifnum\mathcode`#2=\ifodd\bbl@engine"1000000 \else"8000 \fi
-      \@namedef{normal@char#2}{%
-        \textormath{#3}{\csname bbl@oridef@@#2\endcsname}}%
-    \else
-      \@namedef{normal@char#2}{#3}%
-    \fi
+    \frenchspacing
+    \let\bbl@nonfrenchspacing\nonfrenchspacing
+  \fi}
+\let\bbl@nonfrenchspacing\nonfrenchspacing
+\let\bbl@elt\relax
+\edef\bbl@fs@chars{%
+  \bbl@elt{\string.}\@m{3000}\bbl@elt{\string?}\@m{3000}%
+  \bbl@elt{\string!}\@m{3000}\bbl@elt{\string:}\@m{2000}%
+  \bbl@elt{\string;}\@m{1500}\bbl@elt{\string,}\@m{1250}}
+\def\bbl@pre@fs{%
+  \def\bbl@elt##1##2##3{\sfcode`##1=\the\sfcode`##1\relax}%
+  \edef\bbl@save@sfcodes{\bbl@fs@chars}}%
+\def\bbl@post@fs{%
+  \bbl@save@sfcodes
+  \edef\bbl@tempa{\bbl@cl{frspc}}%
+  \edef\bbl@tempa{\expandafter\@car\bbl@tempa\@nil}%
+  \if u\bbl@tempa          % do nothing
+  \else\if n\bbl@tempa     % non french
+    \def\bbl@elt##1##2##3{%
+      \ifnum\sfcode`##1=##2\relax
+        \babel@savevariable{\sfcode`##1}%
+        \sfcode`##1=##3\relax
+      \fi}%
+    \bbl@fs@chars
+  \else\if y\bbl@tempa     % french
+    \def\bbl@elt##1##2##3{%
+      \ifnum\sfcode`##1=##3\relax
+        \babel@savevariable{\sfcode`##1}%
+        \sfcode`##1=##2\relax
+      \fi}%
+    \bbl@fs@chars
+  \fi\fi\fi}
 %    \end{macrocode}
 %
-%    To prevent problems with the loading of other packages after
-%    \babel\ we reset the catcode of the character to the original one
-%    at the end of the package and of each language file (except with
-%    \textsf{KeepShorthandsActive}). It is re-activate again at
-%    |\begin{document}|.  We also need to make sure that the
-%    shorthands are active during the processing of the \file{.aux}
-%    file. Otherwise some citations may give unexpected results in
-%    the printout when a shorthand was used in the optional argument
-%    of |\bibitem| for example. Then we make it active (not strictly
-%    necessary, but done for backward compatibility).
+%  \end{macro}
+%  \end{macro}
 %
-%    \begin{macrocode}
-    \bbl@restoreactive{#2}%
-    \AtBeginDocument{%
-      \catcode`#2\active
-      \if@filesw
-        \immediate\write\@mainaux{\catcode`\string#2\active}%
-      \fi}%
-    \expandafter\bbl@add@special\csname#2\endcsname
-    \catcode`#2\active
-  \fi
+% \subsection{Short tags}
+%
+% \begin{macro}{\babeltags}
+% This macro is straightforward. After zapping spaces, we
+% loop over the list and define the macros |\text|\m{tag} and
+% |\|\m{tag}. Definitions are first expanded so that they don't
+% contain |\csname| but the actual macro.
+%
+%   \begin{macrocode}
+\bbl@trace{Short tags}
+\def\babeltags#1{%
+  \edef\bbl@tempa{\zap@space#1 \@empty}%
+  \def\bbl@tempb##1=##2\@@{%
+    \edef\bbl@tempc{%
+      \noexpand\newcommand
+      \expandafter\noexpand\csname ##1\endcsname{%
+        \noexpand\protect
+        \expandafter\noexpand\csname otherlanguage*\endcsname{##2}}
+      \noexpand\newcommand
+      \expandafter\noexpand\csname text##1\endcsname{%
+        \noexpand\foreignlanguage{##2}}}
+    \bbl@tempc}%
+  \bbl@for\bbl@tempa\bbl@tempa{%
+    \expandafter\bbl@tempb\bbl@tempa\@@}}
 %    \end{macrocode}
 %
-%    Now we have set |\normal@char|\m{char}, we must define
-%    |\active@char|\m{char}, to be executed when the character is
-%    activated.  We define the first level expansion of
-%    |\active@char|\m{char} to check the status of the |@safe@actives|
-%    flag. If it is set to true we expand to the `normal' version of
-%    this character, otherwise we call |\user@active|\m{char} to start
-%    the search of a definition in the user, language and system
-%    levels (or eventually |normal@char|\m{char}).
+% \end{macro}
 %
-%    \begin{macrocode}
-  \let\bbl@tempa\@firstoftwo
-  \if\string^#2%
-    \def\bbl@tempa{\noexpand\textormath}%
-  \else
-    \ifx\bbl@mathnormal\@undefined\else
-      \let\bbl@tempa\bbl@mathnormal
-    \fi
-  \fi
-  \expandafter\edef\csname active@char#2\endcsname{%
-    \bbl@tempa
-      {\noexpand\if@safe@actives
-         \noexpand\expandafter
-         \expandafter\noexpand\csname normal@char#2\endcsname
-       \noexpand\else
-         \noexpand\expandafter
-         \expandafter\noexpand\csname bbl@doactive#2\endcsname
-       \noexpand\fi}%
-     {\expandafter\noexpand\csname normal@char#2\endcsname}}%
-  \bbl@csarg\edef{doactive#2}{%
-    \expandafter\noexpand\csname user@active#2\endcsname}%
-%    \end{macrocode}
+% \subsection{Hyphens}
 %
-%    We now define the default values which the shorthand is set to
-%    when activated or deactivated. It is set to the deactivated form
-%    (globally), so that the character expands to
-%    \begin{center}
-%    |\active@prefix| \m{char} |\normal@char|\m{char}
-%    \end{center}
-%    (where |\active@char|\m{char} is \emph{one} control sequence!).
+% \begin{macro}{\babelhyphenation}
+%
+% This macro saves hyphenation exceptions. Two macros are used to
+% store them: |\bbl@hyphenation@| for the global ones and
+% |\bbl@hyphenation<lang>| for language ones. See |\bbl@patterns|
+% above for further details. We make sure there is a space between
+% words when multiple commands are used.
 %
 %    \begin{macrocode}
-  \bbl@csarg\edef{active@#2}{%
-    \noexpand\active@prefix\noexpand#1%
-    \expandafter\noexpand\csname active@char#2\endcsname}%
-  \bbl@csarg\edef{normal@#2}{%
-    \noexpand\active@prefix\noexpand#1%
-    \expandafter\noexpand\csname normal@char#2\endcsname}%
-  \expandafter\let\expandafter#1\csname bbl@normal@#2\endcsname
+\bbl@trace{Hyphens}
+\@onlypreamble\babelhyphenation
+\AtEndOfPackage{%
+  \newcommand\babelhyphenation[2][\@empty]{%
+    \ifx\bbl@hyphenation@\relax
+      \let\bbl@hyphenation@\@empty
+    \fi
+    \ifx\bbl@hyphlist\@empty\else
+      \bbl@warning{%
+        You must not intermingle \string\selectlanguage\space and\\%
+        \string\babelhyphenation\space or some exceptions will not\\%
+        be taken into account. Reported}%
+    \fi
+    \ifx\@empty#1%
+      \protected@edef\bbl@hyphenation@{\bbl@hyphenation@\space#2}%
+    \else
+      \bbl@vforeach{#1}{%
+        \def\bbl@tempa{##1}%
+        \bbl@fixname\bbl@tempa
+        \bbl@iflanguage\bbl@tempa{%
+          \bbl@csarg\protected@edef{hyphenation@\bbl@tempa}{%
+            \bbl@ifunset{bbl@hyphenation@\bbl@tempa}%
+              {}%
+              {\csname bbl@hyphenation@\bbl@tempa\endcsname\space}%
+            #2}}}%
+    \fi}}
 %    \end{macrocode}
 %
-%    The next level of the code checks whether a user has defined a
-%    shorthand for himself with this character. First we check for a
-%    single character shorthand. If that doesn't exist we check for a
-%    shorthand with an argument.
+%  \end{macro}
 %
-%    \begin{macrocode}
-  \bbl@active@def#2\user@group{user@active}{language@active}%
-  \bbl@active@def#2\language@group{language@active}{system@active}%
-  \bbl@active@def#2\system@group{system@active}{normal@char}%
-%    \end{macrocode}
+%  \begin{macro}{\bbl@allowhyphens}
 %
-%    In order to do the right thing when a shorthand with an argument
-%    is used by itself at the end of the line we provide a definition
-%    for the case of an empty argument. For that case we let the
-%    shorthand character expand to its non-active self. Also, When a
-%    shorthand combination such as |''| ends up in a heading \TeX\
-%    would see |\protect'\protect'|. To prevent this from happening a
-%    couple of shorthand needs to be defined at user level.
+% This macro makes hyphenation possible. Basically its definition
+% is nothing more than |\nobreak| |\hskip| \texttt{0pt plus
+% 0pt}\footnote{\TeX\ begins and ends a word for hyphenation at a
+% glue node. The penalty prevents a linebreak at this glue node.}.
 %
 %    \begin{macrocode}
-  \expandafter\edef\csname\user@group @sh@#2@@\endcsname
-    {\expandafter\noexpand\csname normal@char#2\endcsname}%
-  \expandafter\edef\csname\user@group @sh@#2@\string\protect@\endcsname
-    {\expandafter\noexpand\csname user@active#2\endcsname}%
+\def\bbl@allowhyphens{\ifvmode\else\nobreak\hskip\z@skip\fi}
+\def\bbl@t@one{T1}
+\def\allowhyphens{\ifx\cf@encoding\bbl@t@one\else\bbl@allowhyphens\fi}
 %    \end{macrocode}
 %
-%    Finally, a couple of special cases are taken care of.  (1) If we
-%    are making the right quote (|'|) active we need to change |\pr@m@s| as
-%    well.  Also, make sure that a single |'| in math mode `does the
-%    right thing'.  (2) If we are using the caret (|^|) as a shorthand
-%    character special care should be taken to make sure math still
-%    works. Therefore an extra level of expansion is introduced with a
-%    check for math mode on the upper level.
+%  \end{macro}
 %
-%    \begin{macrocode}
-  \if\string'#2%
-    \let\prim@s\bbl@prim@s
-    \let\active@math@prime#1%
-  \fi
-  \bbl@usehooks{initiateactive}{{#1}{#2}{#3}}}
-%    \end{macrocode}
+% \begin{macro}{\babelhyphen}
 %
-%    The following package options control the behavior of shorthands
-%    in math mode.
+% Macros to insert common hyphens. Note the space before |@| in
+% |\babelhyphen|. Instead of protecting it with
+% |\DeclareRobustCommand|, which could insert a |\relax|, we use
+% the same procedure as shorthands, with |\active@prefix|.
 %
 %    \begin{macrocode}
-%<<*More package options>>
-\DeclareOption{math=active}{}
-\DeclareOption{math=normal}{\def\bbl@mathnormal{\noexpand\textormath}}
-%<</More package options>>
+\newcommand\babelnullhyphen{\char\hyphenchar\font}
+\def\babelhyphen{\active@prefix\babelhyphen\bbl@hyphen}
+\def\bbl@hyphen{%
+  \@ifstar{\bbl@hyphen@i @}{\bbl@hyphen@i\@empty}}
+\def\bbl@hyphen@i#1#2{%
+  \bbl@ifunset{bbl@hy@#1#2\@empty}%
+    {\csname bbl@#1usehyphen\endcsname{\discretionary{#2}{}{#2}}}%
+    {\csname bbl@hy@#1#2\@empty\endcsname}}
 %    \end{macrocode}
 %
-%    Initiating a shorthand makes active the char. That is not
-%    strictly necessary but it is still done for backward
-%    compatibility. So we need to restore the original catcode at the
-%    end of package \textit{and} and the end of the |ldf|.
+% The following two commands are used to wrap the ``hyphen'' and
+% set the behavior of the rest of the word -- the version with a
+% single |@| is used when further hyphenation is allowed, while
+% that with |@@| if no more hyphens are allowed. In both cases, if
+% the hyphen is preceded by a positive space, breaking after the
+% hyphen is disallowed.
+%
+% There should not be a discretionary after a hyphen at the
+% beginning of a word, so it is prevented if preceded by a
+% skip. Unfortunately, this does handle cases like ``(-suffix)''.
+% |\nobreak| is always preceded by |\leavevmode|, in case the
+% shorthand starts a paragraph.
 %
 %    \begin{macrocode}
-\@ifpackagewith{babel}{KeepShorthandsActive}%
-  {\let\bbl@restoreactive\@gobble}%
-  {\def\bbl@restoreactive#1{%
-     \bbl@exp{%
-       \\\AfterBabelLanguage\\\CurrentOption
-         {\catcode`#1=\the\catcode`#1\relax}%
-       \\\AtEndOfPackage
-         {\catcode`#1=\the\catcode`#1\relax}}}%
-   \AtEndOfPackage{\let\bbl@restoreactive\@gobble}}
+\def\bbl@usehyphen#1{%
+  \leavevmode
+  \ifdim\lastskip>\z@\mbox{#1}\else\nobreak#1\fi
+  \nobreak\hskip\z@skip}
+\def\bbl@@usehyphen#1{%
+  \leavevmode\ifdim\lastskip>\z@\mbox{#1}\else#1\fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\bbl@sh@select}
-%    This command helps the shorthand supporting macros to select how
-%    to proceed. Note that this macro needs to be expandable as do all
-%    the shorthand macros in order for them to work in expansion-only
-%    environments such as the argument of |\hyphenation|.
-%
-%    This macro expects the name of a group of shorthands in its first
-%    argument and a shorthand character in its second argument. It
-%    will expand to either |\bbl@firstcs| or |\bbl@scndcs|. Hence two
-%    more arguments need to follow it.
+%    The following macro inserts the hyphen char.
 %
 %    \begin{macrocode}
-\def\bbl@sh@select#1#2{%
-  \expandafter\ifx\csname#1@sh@#2@sel\endcsname\relax
-    \bbl@afterelse\bbl@scndcs
+\def\bbl@hyphenchar{%
+  \ifnum\hyphenchar\font=\m@ne
+    \babelnullhyphen
   \else
-    \bbl@afterfi\csname#1@sh@#2@sel\endcsname
+    \char\hyphenchar\font
   \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\active@prefix}
-%    The command |\active@prefix| which is used in the expansion of
-%    active characters has a function similar to |\OT1-cmd| in that it
-%    |\protect|s the active character whenever |\protect| is
-%    \emph{not} |\@typeset@protect|. The |\@gobble| is needed to remove
-%    a token such as |\activechar:| (when the double colon was the
-%    active character to be dealt with). There are two definitions,
-%    depending of |\ifincsname| is available. If there is, the
-%    expansion will be more robust.
+%    Finally, we define the hyphen ``types''. Their names will not
+%    change, so you may use them in |ldf|'s. After a space, the
+%    |\mbox| in |\bbl@hy@nobreak| is redundant.
 %
 %    \begin{macrocode}
-\begingroup
-\bbl@ifunset{ifincsname}% TODO. Ugly. Correct?
-  {\gdef\active@prefix#1{%
-     \ifx\protect\@typeset@protect
-     \else
-       \ifx\protect\@unexpandable@protect
-         \noexpand#1%
-       \else
-         \protect#1%
-       \fi
-       \expandafter\@gobble
-     \fi}}
-  {\gdef\active@prefix#1{%
-     \ifincsname
-       \string#1%
-       \expandafter\@gobble
-     \else
-       \ifx\protect\@typeset@protect
-       \else
-         \ifx\protect\@unexpandable@protect
-           \noexpand#1%
-         \else
-           \protect#1%
-         \fi
-         \expandafter\expandafter\expandafter\@gobble
-       \fi
-     \fi}}
-\endgroup
+\def\bbl@hy@soft{\bbl@usehyphen{\discretionary{\bbl@hyphenchar}{}{}}}
+\def\bbl@hy@@soft{\bbl@@usehyphen{\discretionary{\bbl@hyphenchar}{}{}}}
+\def\bbl@hy@hard{\bbl@usehyphen\bbl@hyphenchar}
+\def\bbl@hy@@hard{\bbl@@usehyphen\bbl@hyphenchar}
+\def\bbl@hy@nobreak{\bbl@usehyphen{\mbox{\bbl@hyphenchar}}}
+\def\bbl@hy@@nobreak{\mbox{\bbl@hyphenchar}}
+\def\bbl@hy@repeat{%
+  \bbl@usehyphen{%
+    \discretionary{\bbl@hyphenchar}{\bbl@hyphenchar}{\bbl@hyphenchar}}}
+\def\bbl@hy@@repeat{%
+  \bbl@@usehyphen{%
+    \discretionary{\bbl@hyphenchar}{\bbl@hyphenchar}{\bbl@hyphenchar}}}
+\def\bbl@hy@empty{\hskip\z@skip}
+\def\bbl@hy@@empty{\discretionary{}{}{}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\if@safe@actives}
-%    In some circumstances it is necessary to be able to change the
-%    expansion of an active character on the fly. For this purpose the
-%    switch |@safe@actives| is available. The setting of this switch
-%    should be checked in the first level expansion of
-%    |\active@char|\m{char}.
+%  \begin{macro}{\bbl@disc}
+%    For some languages the macro |\bbl@disc| is used to ease the
+%    insertion of discretionaries for letters that behave `abnormally'
+%    at a breakpoint.
 %
 %    \begin{macrocode}
-\newif\if@safe@actives
-\@safe@activesfalse
+\def\bbl@disc#1#2{\nobreak\discretionary{#2-}{}{#1}\bbl@allowhyphens}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\bbl@restore@actives}
-%    When the output routine kicks in while the
-%    active characters were made ``safe'' this must be undone in
-%    the headers to prevent unexpected typeset results. For this
-%    situation we define a command to make them ``unsafe'' again.
-%
-%    \begin{macrocode}
-\def\bbl@restore@actives{\if@safe@actives\@safe@activesfalse\fi}
-%    \end{macrocode}
+% \subsection{Multiencoding strings}
 %
-%  \end{macro}
+% The aim following commands is to provide a commom interface for
+% strings in several encodings. They also contains several hooks which
+% can be used by \luatex{} and \xetex. The code is organized here with
+% pseudo-guards, so we start with the basic commands.
 %
-%  \begin{macro}{\bbl@activate}
-%  \begin{macro}{\bbl@deactivate}
+%  \paragraph{Tools}
 %
-%    Both macros take one argument, like |\initiate@active@char|. The
-%    macro is used to change the definition of an active character to
-%    expand to |\active@char|\m{char} in the case of |\bbl@activate|,
-%    or |\normal@char|\m{char} in the case of |\bbl@deactivate|.
+% But first, a couple of tools. The first one makes global a local
+% variable. This is not the best solution, but it works.
 %
 %    \begin{macrocode}
-\chardef\bbl@activated\z@
-\def\bbl@activate#1{%
-  \chardef\bbl@activated\@ne
-  \bbl@withactive{\expandafter\let\expandafter}#1%
-    \csname bbl@active@\string#1\endcsname}
-\def\bbl@deactivate#1{%
-  \chardef\bbl@activated\tw@
-  \bbl@withactive{\expandafter\let\expandafter}#1%
-    \csname bbl@normal@\string#1\endcsname}
+\bbl@trace{Multiencoding strings}
+\def\bbl@toglobal#1{\global\let#1#1}
+\def\bbl@recatcode#1{% TODO. Used only once?
+  \@tempcnta="7F
+  \def\bbl@tempa{%
+    \ifnum\@tempcnta>"FF\else
+      \catcode\@tempcnta=#1\relax
+      \advance\@tempcnta\@ne
+      \expandafter\bbl@tempa
+    \fi}%
+  \bbl@tempa}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\bbl@firstcs}
-%  \begin{macro}{\bbl@scndcs}
-%
-% These macros are used only as a trick when declaring shorthands.
+% The second one. We need to patch |\@uclclist|, but it is done once
+% and only if |\SetCase| is used or if strings are encoded.  The code
+% is far from satisfactory for several reasons, including the fact
+% |\@uclclist| is not a list any more. Therefore a package option is
+% added to ignore it. Instead of gobbling the macro
+% getting the next two elements (usually |\reserved@a|), we pass it as
+% argument to |\bbl@uclc|. The parser is restarted inside
+% |\|\m{lang}|@bbl@uclc| because we do not know how many expansions
+% are necessary (depends on whether strings are encoded). The last
+% part is tricky -- when uppercasing, we have:
+%\begin{verbatim}
+% \let\bbl@tolower\@empty\bbl@toupper\@empty
+%\end{verbatim}
+% and starts over (and similarly when lowercasing).
 %
 %    \begin{macrocode}
-\def\bbl@firstcs#1#2{\csname#1\endcsname}
-\def\bbl@scndcs#1#2{\csname#2\endcsname}
+\@ifpackagewith{babel}{nocase}%
+  {\let\bbl@patchuclc\relax}%
+  {\def\bbl@patchuclc{%
+    \global\let\bbl@patchuclc\relax
+    \g@addto@macro\@uclclist{\reserved@b{\reserved@b\bbl@uclc}}%
+    \gdef\bbl@uclc##1{%
+      \let\bbl@encoded\bbl@encoded@uclc
+      \bbl@ifunset{\languagename @bbl@uclc}% and resumes it
+        {##1}%
+        {\let\bbl@tempa##1\relax % Used by LANG@bbl@uclc
+         \csname\languagename @bbl@uclc\endcsname}%
+      {\bbl@tolower\@empty}{\bbl@toupper\@empty}}%
+    \gdef\bbl@tolower{\csname\languagename @bbl@lc\endcsname}%
+    \gdef\bbl@toupper{\csname\languagename @bbl@uc\endcsname}}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\declare@shorthand}
-%    The command |\declare@shorthand| is used to declare a shorthand
-%    on a certain level. It takes three arguments:
-%    \begin{enumerate}
-%    \item a name for the collection of shorthands, i.e. `system', or
-%      `dutch';
-%    \item the character (sequence) that makes up the shorthand,
-%      i.e. |~| or |"a|;
-%    \item the code to be executed when the shorthand is encountered.
-%    \end{enumerate}
-%
-% The auxiliary macro |\babel@texpdf| improves the interoperativity with
-% \textsf{hyperref} and takes 4 arguments: (1) The \TeX{} code in text
-% mode, (2) the string for \textsf{hyperref}, (3) the \TeX{} code in
-% math mode, and (4), which is currently ignored, but it's meant for a
-% string in math mode, like a minus sign instead of an hyphen
-% (currently \textsf{hyperref} doesn't discriminate the mode). This
-% macro may be used in |ldf| files.
-
 %    \begin{macrocode}
-\def\babel@texpdf#1#2#3#4{%
-  \ifx\texorpdfstring\@undefined
-    \textormath{#1}{#3}%
-  \else
-    \texorpdfstring{\textormath{#1}{#3}}{#2}%
-    % \texorpdfstring{\textormath{#1}{#3}}{\textormath{#2}{#4}}%
-  \fi}
-%
-\def\declare@shorthand#1#2{\@decl@short{#1}#2\@nil}
-\def\@decl@short#1#2#3\@nil#4{%
-  \def\bbl@tempa{#3}%
-  \ifx\bbl@tempa\@empty
-    \expandafter\let\csname #1@sh@\string#2@sel\endcsname\bbl@scndcs
-    \bbl@ifunset{#1@sh@\string#2@}{}%
-      {\def\bbl@tempa{#4}%
-       \expandafter\ifx\csname#1@sh@\string#2@\endcsname\bbl@tempa
-       \else
-         \bbl@info
-           {Redefining #1 shorthand \string#2\\%
-            in language \CurrentOption}%
-       \fi}%
-    \@namedef{#1@sh@\string#2@}{#4}%
-  \else
-    \expandafter\let\csname #1@sh@\string#2@sel\endcsname\bbl@firstcs
-    \bbl@ifunset{#1@sh@\string#2@\string#3@}{}%
-      {\def\bbl@tempa{#4}%
-       \expandafter\ifx\csname#1@sh@\string#2@\string#3@\endcsname\bbl@tempa
-       \else
-         \bbl@info
-           {Redefining #1 shorthand \string#2\string#3\\%
-            in language \CurrentOption}%
-       \fi}%
-    \@namedef{#1@sh@\string#2@\string#3@}{#4}%
-  \fi}
+%<<*More package options>>
+\DeclareOption{nocase}{}
+%<</More package options>>
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\textormath}
-%    Some of the shorthands that will be declared by the language
-%    definition files have to be usable in both text and mathmode. To
-%    achieve this the helper macro |\textormath| is provided.
+% The following package options control the behavior of |\SetString|.
 %
 %    \begin{macrocode}
-\def\textormath{%
-  \ifmmode
-    \expandafter\@secondoftwo
-  \else
-    \expandafter\@firstoftwo
-  \fi}
+%<<*More package options>>
+\let\bbl@opt@strings\@nnil % accept strings=value
+\DeclareOption{strings}{\def\bbl@opt@strings{\BabelStringsDefault}}
+\DeclareOption{strings=encoded}{\let\bbl@opt@strings\relax}
+\def\BabelStringsDefault{generic}
+%<</More package options>>
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\user@group}
-%  \begin{macro}{\language@group}
-%  \begin{macro}{\system@group}
-%    The current concept of `shorthands' supports three levels or
-%    groups of shorthands. For each level the name of the level or
-%    group is stored in a macro. The default is to have a user group;
-%    use language group `english' and have a system group called
-%    `system'.
+% \paragraph{Main command} This is the main command. With the first
+% use it is redefined to omit the basic setup in subsequent blocks.
+% We make sure strings contain actual letters in the range 128-255,
+% not active characters.
 %
 %    \begin{macrocode}
-\def\user@group{user}
-\def\language@group{english} % TODO. I don't like defaults
-\def\system@group{system}
+\@onlypreamble\StartBabelCommands
+\def\StartBabelCommands{%
+  \begingroup
+  \bbl@recatcode{11}%
+  <@Macros local to BabelCommands@>
+  \def\bbl@provstring##1##2{%
+    \providecommand##1{##2}%
+    \bbl@toglobal##1}%
+  \global\let\bbl@scafter\@empty
+  \let\StartBabelCommands\bbl@startcmds
+  \ifx\BabelLanguages\relax
+     \let\BabelLanguages\CurrentOption
+  \fi
+  \begingroup
+  \let\bbl@screset\@nnil % local flag - disable 1st stopcommands
+  \StartBabelCommands}
+\def\bbl@startcmds{%
+  \ifx\bbl@screset\@nnil\else
+    \bbl@usehooks{stopcommands}{}%
+  \fi
+  \endgroup
+  \begingroup
+  \@ifstar
+    {\ifx\bbl@opt@strings\@nnil
+       \let\bbl@opt@strings\BabelStringsDefault
+     \fi
+     \bbl@startcmds@i}%
+    \bbl@startcmds@i}
+\def\bbl@startcmds@i#1#2{%
+  \edef\bbl@L{\zap@space#1 \@empty}%
+  \edef\bbl@G{\zap@space#2 \@empty}%
+  \bbl@startcmds@ii}
+\let\bbl@startcommands\StartBabelCommands
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%  \end{macro}
+% Parse the encoding info to get the label, input, and font parts.
 %
-%  \begin{macro}{\useshorthands}
+% Select the behavior of |\SetString|. Thre are two main cases,
+% depending of if there is an optional argument: without it and
+% |strings=encoded|, strings are defined
+% always; otherwise, they are set only if they are still undefined
+% (ie, fallback values). With labelled blocks and
+% |strings=encoded|, define the strings, but with another value,
+% define strings only if the current label or font encoding is the
+% value of |strings|; otherwise (ie, no |strings| or a block whose
+% label is not in |strings=|) do nothing.
 %
-%    This is the user level macro. It initializes and activates the
-%    character for use as a shorthand character (ie, it's active in the
-%    preamble). Languages can deactivate shorthands, so a starred
-%    version is also provided which activates them always after the
-%    language has been switched.
+% We presume the current block is not loaded, and therefore set
+% (above) a couple of default values to gobble the arguments. Then,
+% these macros are redefined if necessary according to several
+% parameters.
 %
 %    \begin{macrocode}
-\def\useshorthands{%
-  \@ifstar\bbl@usesh@s{\bbl@usesh@x{}}}
-\def\bbl@usesh@s#1{%
-  \bbl@usesh@x
-    {\AddBabelHook{babel-sh-\string#1}{afterextras}{\bbl@activate{#1}}}%
-    {#1}}
-\def\bbl@usesh@x#1#2{%
-  \bbl@ifshorthand{#2}%
-    {\def\user@group{user}%
-     \initiate@active@char{#2}%
-     #1%
-     \bbl@activate{#2}}%
-    {\bbl@error
-       {I can't declare a shorthand turned off (\string#2)}
-       {Sorry, but you can't use shorthands which have been\\%
-        turned off in the package options}}}
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-%  \begin{macro}{\defineshorthand}
-%
-%    Currently we only support two groups of user level shorthands,
-%    named internally |user| and |user@<lang>| (language-dependent
-%    user shorthands). By default, only the first one is taken into
-%    account, but if the former is also used (in the optional argument
-%    of |\defineshorthand|) a new level is inserted for it
-%    (|user@generic|, done by |\bbl@set@user@generic|); we make also
-%    sure |{}| and |\protect| are taken into account in this new top
-%    level.
+\newcommand\bbl@startcmds@ii[1][\@empty]{%
+  \let\SetString\@gobbletwo
+  \let\bbl@stringdef\@gobbletwo
+  \let\AfterBabelCommands\@gobble
+  \ifx\@empty#1%
+    \def\bbl@sc@label{generic}%
+    \def\bbl@encstring##1##2{%
+      \ProvideTextCommandDefault##1{##2}%
+      \bbl@toglobal##1%
+      \expandafter\bbl@toglobal\csname\string?\string##1\endcsname}%
+    \let\bbl@sctest\in@true
+  \else
+    \let\bbl@sc@charset\space % <- zapped below
+    \let\bbl@sc@fontenc\space % <-   "      "
+    \def\bbl@tempa##1=##2\@nil{%
+      \bbl@csarg\edef{sc@\zap@space##1 \@empty}{##2 }}%
+    \bbl@vforeach{label=#1}{\bbl@tempa##1\@nil}%
+    \def\bbl@tempa##1 ##2{% space -> comma
+      ##1%
+      \ifx\@empty##2\else\ifx,##1,\else,\fi\bbl@afterfi\bbl@tempa##2\fi}%
+    \edef\bbl@sc@fontenc{\expandafter\bbl@tempa\bbl@sc@fontenc\@empty}%
+    \edef\bbl@sc@label{\expandafter\zap@space\bbl@sc@label\@empty}%
+    \edef\bbl@sc@charset{\expandafter\zap@space\bbl@sc@charset\@empty}%
+    \def\bbl@encstring##1##2{%
+      \bbl@foreach\bbl@sc@fontenc{%
+        \bbl@ifunset{T@####1}%
+          {}%
+          {\ProvideTextCommand##1{####1}{##2}%
+           \bbl@toglobal##1%
+           \expandafter
+           \bbl@toglobal\csname####1\string##1\endcsname}}}%
+    \def\bbl@sctest{%
+      \bbl@xin@{,\bbl@opt@strings,}{,\bbl@sc@label,\bbl@sc@fontenc,}}%
+  \fi
+  \ifx\bbl@opt@strings\@nnil         % ie, no strings key -> defaults
+  \else\ifx\bbl@opt@strings\relax    % ie, strings=encoded
+    \let\AfterBabelCommands\bbl@aftercmds
+    \let\SetString\bbl@setstring
+    \let\bbl@stringdef\bbl@encstring
+  \else       % ie, strings=value
+  \bbl@sctest
+  \ifin@
+    \let\AfterBabelCommands\bbl@aftercmds
+    \let\SetString\bbl@setstring
+    \let\bbl@stringdef\bbl@provstring
+  \fi\fi\fi
+  \bbl@scswitch
+  \ifx\bbl@G\@empty
+    \def\SetString##1##2{%
+      \bbl@error{Missing group for string \string##1}%
+        {You must assign strings to some category, typically\\%
+         captions or extras, but you set none}}%
+  \fi
+  \ifx\@empty#1%
+    \bbl@usehooks{defaultcommands}{}%
+  \else
+    \@expandtwoargs
+    \bbl@usehooks{encodedcommands}{{\bbl@sc@charset}{\bbl@sc@fontenc}}%
+  \fi}
+%    \end{macrocode}
 %
-%    \begin{macrocode}
-\def\user@language@group{user@\language@group}
-\def\bbl@set@user@generic#1#2{%
-  \bbl@ifunset{user@generic@active#1}%
-    {\bbl@active@def#1\user@language@group{user@active}{user@generic@active}%
-     \bbl@active@def#1\user@group{user@generic@active}{language@active}%
-     \expandafter\edef\csname#2@sh@#1@@\endcsname{%
-       \expandafter\noexpand\csname normal@char#1\endcsname}%
-     \expandafter\edef\csname#2@sh@#1@\string\protect@\endcsname{%
-       \expandafter\noexpand\csname user@active#1\endcsname}}%
-  \@empty}
-\newcommand\defineshorthand[3][user]{%
-  \edef\bbl@tempa{\zap@space#1 \@empty}%
-  \bbl@for\bbl@tempb\bbl@tempa{%
-    \if*\expandafter\@car\bbl@tempb\@nil
-      \edef\bbl@tempb{user@\expandafter\@gobble\bbl@tempb}%
-      \@expandtwoargs
-        \bbl@set@user@generic{\expandafter\string\@car#2\@nil}\bbl@tempb
-    \fi
-    \declare@shorthand{\bbl@tempb}{#2}{#3}}}
+% There are two versions of |\bbl@scswitch|. The first version is used
+% when |ldf|s are read, and it makes sure |\|\m{group}\m{language} is
+% reset, but only once (|\bbl@screset| is used to keep track of this).
+% The second version is used in the preamble and packages loaded after
+% \babel{} and does nothing.
+%
+% The macro |\bbl@forlang| loops |\bbl@L| but its body is executed only
+% if the value is in |\BabelLanguages| (inside \babel) or
+% |\date|\m{language} is defined (after \babel{} has been loaded).
+% There are also two version of |\bbl@forlang|. The first one skips the
+% current iteration if the language is not in |\BabelLanguages| (used
+% in |ldf|s), and the second one skips undefined languages (after
+% \babel{} has been loaded) .
+%
+%   \begin{macrocode}
+\def\bbl@forlang#1#2{%
+  \bbl@for#1\bbl@L{%
+    \bbl@xin@{,#1,}{,\BabelLanguages,}%
+    \ifin@#2\relax\fi}}
+\def\bbl@scswitch{%
+  \bbl@forlang\bbl@tempa{%
+    \ifx\bbl@G\@empty\else
+      \ifx\SetString\@gobbletwo\else
+        \edef\bbl@GL{\bbl@G\bbl@tempa}%
+        \bbl@xin@{,\bbl@GL,}{,\bbl@screset,}%
+        \ifin@\else
+          \global\expandafter\let\csname\bbl@GL\endcsname\@undefined
+          \xdef\bbl@screset{\bbl@screset,\bbl@GL}%
+        \fi
+      \fi
+    \fi}}
+\AtEndOfPackage{%
+  \def\bbl@forlang#1#2{\bbl@for#1\bbl@L{\bbl@ifunset{date#1}{}{#2}}}%
+  \let\bbl@scswitch\relax}
+\@onlypreamble\EndBabelCommands
+\def\EndBabelCommands{%
+  \bbl@usehooks{stopcommands}{}%
+  \endgroup
+  \endgroup
+  \bbl@scafter}
+\let\bbl@endcommands\EndBabelCommands
 %    \end{macrocode}
 %
-%  \end{macro}
+% Now we define commands to be used inside |\StartBabelCommands|.
 %
-%  \begin{macro}{\languageshorthands}
+% \paragraph{Strings} The following macro is the actual definition
+% of |\SetString| when it is ``active''
 %
-%    A user level command to change the language from which shorthands
-%    are used. Unfortunately, \babel{} currently does not keep track
-%    of defined groups, and therefore there is no way to catch a
-%    possible change in casing to fix it in the same way languages names
-%    are fixed. [TODO].
+% First save the ``switcher''. Create it if undefined. Strings are
+% defined only if undefined (ie, like |\providescommmand|). With
+% the event |stringprocess| you can preprocess the string by
+% manipulating the value of |\BabelString|. If there are several
+% hooks assigned to this event, preprocessing is done in the same
+% order as defined.  Finally, the string is set.
 %
 %    \begin{macrocode}
-\def\languageshorthands#1{\def\language@group{#1}}
+\def\bbl@setstring#1#2{% eg, \prefacename{<string>}
+  \bbl@forlang\bbl@tempa{%
+    \edef\bbl@LC{\bbl@tempa\bbl@stripslash#1}%
+    \bbl@ifunset{\bbl@LC}% eg, \germanchaptername
+      {\bbl@exp{%
+         \global\\\bbl@add\<\bbl@G\bbl@tempa>{\\\bbl@scset\\#1\<\bbl@LC>}}}%
+      {}%
+    \def\BabelString{#2}%
+    \bbl@usehooks{stringprocess}{}%
+    \expandafter\bbl@stringdef
+      \csname\bbl@LC\expandafter\endcsname\expandafter{\BabelString}}}
 %    \end{macrocode}
 %
-%  \end{macro}
+%     Now, some addtional stuff to be used when encoded strings are
+%     used. Captions then include |\bbl@encoded| for string to be
+%     expanded in case transformations. It is |\relax| by default, but
+%     in |\MakeUppercase| and |\MakeLowercase| its value is a modified
+%     expandable |\@changed@cmd|.
 %
-%  \begin{macro}{\aliasshorthand}
-%    First the new shorthand needs to be initialized. Then, we define
-%    the new shorthand in terms of the original one, but note with
-%    |\aliasshorthands{"}{/}| is |\active@prefix /\active@char/|, so we
-%    still need to let the lattest to |\active@char"|.
+%    \begin{macrocode}
+\ifx\bbl@opt@strings\relax
+  \def\bbl@scset#1#2{\def#1{\bbl@encoded#2}}
+  \bbl@patchuclc
+  \let\bbl@encoded\relax
+  \def\bbl@encoded@uclc#1{%
+    \@inmathwarn#1%
+    \expandafter\ifx\csname\cf@encoding\string#1\endcsname\relax
+      \expandafter\ifx\csname ?\string#1\endcsname\relax
+        \TextSymbolUnavailable#1%
+      \else
+        \csname ?\string#1\endcsname
+      \fi
+    \else
+      \csname\cf@encoding\string#1\endcsname
+    \fi}
+\else
+  \def\bbl@scset#1#2{\def#1{#2}}
+\fi
+%    \end{macrocode}
 %
+% Define |\SetStringLoop|, which is actually set inside
+% |\StartBabelCommands|. The current definition is somewhat complicated
+% because we need a count, but |\count@| is not under our control
+% (remember |\SetString| may call hooks). Instead of defining a
+% dedicated count, we just ``pre-expand'' its value.
 %
 %    \begin{macrocode}
-\def\aliasshorthand#1#2{%
-  \bbl@ifshorthand{#2}%
-    {\expandafter\ifx\csname active@char\string#2\endcsname\relax
-       \ifx\document\@notprerr
-         \@notshorthand{#2}%
-       \else
-         \initiate@active@char{#2}%
-         \expandafter\let\csname active@char\string#2\expandafter\endcsname
-           \csname active@char\string#1\endcsname
-         \expandafter\let\csname normal@char\string#2\expandafter\endcsname
-           \csname normal@char\string#1\endcsname
-         \bbl@activate{#2}%
-       \fi
-     \fi}%
-    {\bbl@error
-       {Cannot declare a shorthand turned off (\string#2)}
-       {Sorry, but you cannot use shorthands which have been\\%
-        turned off in the package options}}}
+%<<*Macros local to BabelCommands>>
+\def\SetStringLoop##1##2{%
+    \def\bbl@templ####1{\expandafter\noexpand\csname##1\endcsname}%
+    \count@\z@
+    \bbl@loop\bbl@tempa{##2}{% empty items and spaces are ok
+      \advance\count@\@ne
+      \toks@\expandafter{\bbl@tempa}%
+      \bbl@exp{%
+        \\\SetString\bbl@templ{\romannumeral\count@}{\the\toks@}%
+        \count@=\the\count@\relax}}}%
+%<</Macros local to BabelCommands>>
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\@notshorthand}
+% \paragraph{Delaying code} Now the definition of |\AfterBabelCommands|
+% when it is activated.
 %
 %    \begin{macrocode}
-\def\@notshorthand#1{%
-  \bbl@error{%
-    The character '\string #1' should be made a shorthand character;\\%
-    add the command \string\useshorthands\string{#1\string} to
-    the preamble.\\%
-    I will ignore your instruction}%
-   {You may proceed, but expect unexpected results}}
+\def\bbl@aftercmds#1{%
+  \toks@\expandafter{\bbl@scafter#1}%
+  \xdef\bbl@scafter{\the\toks@}}
 %    \end{macrocode}
 %
-%  \end{macro}
+% \paragraph{Case mapping}
 %
-%  \begin{macro}{\shorthandon}
-%  \begin{macro}{\shorthandoff}
-%    The first level definition of these macros just passes the
-%    argument on to |\bbl@switch@sh|, adding |\@nil| at the end to
-%    denote the end of the list of characters.
+% The command |\SetCase| provides a way to change the behavior of
+% |\MakeUppercase| and |\MakeLowercase|. |\bbl@tempa| is set by the
+% patched |\@uclclist| to the parsing command.
 %
 %    \begin{macrocode}
-\newcommand*\shorthandon[1]{\bbl@switch@sh\@ne#1\@nnil}
-\DeclareRobustCommand*\shorthandoff{%
-  \@ifstar{\bbl@shorthandoff\tw@}{\bbl@shorthandoff\z@}}
-\def\bbl@shorthandoff#1#2{\bbl@switch@sh#1#2\@nnil}
+%<<*Macros local to BabelCommands>>
+  \newcommand\SetCase[3][]{%
+    \bbl@patchuclc
+    \bbl@forlang\bbl@tempa{%
+      \expandafter\bbl@encstring
+        \csname\bbl@tempa @bbl@uclc\endcsname{\bbl@tempa##1}%
+      \expandafter\bbl@encstring
+        \csname\bbl@tempa @bbl@uc\endcsname{##2}%
+      \expandafter\bbl@encstring
+        \csname\bbl@tempa @bbl@lc\endcsname{##3}}}%
+%<</Macros local to BabelCommands>>
 %    \end{macrocode}
 %
-%  \begin{macro}{\bbl@switch@sh}
-%
-%    The macro |\bbl@switch@sh| takes the list of characters apart one
-%    by one and subsequently switches the category code of the
-%    shorthand character according to the first argument of
-%    |\bbl@switch@sh|.
+% Macros to deal with case mapping for hyphenation. To decide if the
+% document is monolingual or multilingual, we make a rough guess --
+% just see if there is a comma in the languages list, built in the
+% first pass of the package options.
 %
-%    But before any of this switching takes place we make sure that the
-%    character we are dealing with is known as a shorthand character.
-%    If it is, a macro such as |\active@char"| should exist.
+%    \begin{macrocode}
+%<<*Macros local to BabelCommands>>
+  \newcommand\SetHyphenMap[1]{%
+    \bbl@forlang\bbl@tempa{%
+      \expandafter\bbl@stringdef
+        \csname\bbl@tempa @bbl@hyphenmap\endcsname{##1}}}%
+%<</Macros local to BabelCommands>>
+%    \end{macrocode}
 %
-%    Switching off and on is easy -- we just set the category code to
-%    `other' (12) and |\active|. With the starred version, the original
-%    catcode and the original definition, saved in
-%    |@initiate@active@char|, are restored.
+%   There are 3 helper macros which do most of the work for you.
 %
-%    \begin{macrocode}
-\def\bbl@switch@sh#1#2{%
-  \ifx#2\@nnil\else
-    \bbl@ifunset{bbl@active@\string#2}%
-      {\bbl@error
-         {I can't switch '\string#2' on or off--not a shorthand}%
-         {This character is not a shorthand. Maybe you made\\%
-          a typing mistake? I will ignore your instruction.}}%
-      {\ifcase#1%   off, on, off*
-         \catcode`#212\relax
-       \or
-         \catcode`#2\active
-         \bbl@ifunset{bbl@shdef@\string#2}%
-           {}%
-           {\bbl@withactive{\expandafter\let\expandafter}#2%
-              \csname bbl@shdef@\string#2\endcsname
-            \bbl@csarg\let{shdef@\string#2}\relax}%
-         \ifcase\bbl@activated\or
-           \bbl@activate{#2}%
-         \else
-           \bbl@deactivate{#2}%
-         \fi
-       \or
-         \bbl@ifunset{bbl@shdef@\string#2}%
-           {\bbl@withactive{\bbl@csarg\let{shdef@\string#2}}#2}%
-           {}%
-         \csname bbl@oricat@\string#2\endcsname
-         \csname bbl@oridef@\string#2\endcsname
-       \fi}%
-    \bbl@afterfi\bbl@switch@sh#1%
+%   \begin{macrocode}
+\newcommand\BabelLower[2]{% one to one.
+  \ifnum\lccode#1=#2\else
+    \babel@savevariable{\lccode#1}%
+    \lccode#1=#2\relax
   \fi}
+\newcommand\BabelLowerMM[4]{% many-to-many
+  \@tempcnta=#1\relax
+  \@tempcntb=#4\relax
+  \def\bbl@tempa{%
+    \ifnum\@tempcnta>#2\else
+      \@expandtwoargs\BabelLower{\the\@tempcnta}{\the\@tempcntb}%
+      \advance\@tempcnta#3\relax
+      \advance\@tempcntb#3\relax
+      \expandafter\bbl@tempa
+    \fi}%
+  \bbl@tempa}
+\newcommand\BabelLowerMO[4]{% many-to-one
+  \@tempcnta=#1\relax
+  \def\bbl@tempa{%
+    \ifnum\@tempcnta>#2\else
+      \@expandtwoargs\BabelLower{\the\@tempcnta}{#4}%
+      \advance\@tempcnta#3
+      \expandafter\bbl@tempa
+    \fi}%
+  \bbl@tempa}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%  \end{macro}
-%
-% Note the value is that at the expansion time; eg, in the preample
-% shorhands are usually deactivated.
+% The following package options control the behavior of
+% hyphenation mapping.
 %
 %    \begin{macrocode}
-\def\babelshorthand{\active@prefix\babelshorthand\bbl@putsh}
-\def\bbl@putsh#1{%
-  \bbl@ifunset{bbl@active@\string#1}%
-     {\bbl@putsh@i#1\@empty\@nnil}%
-     {\csname bbl@active@\string#1\endcsname}}
-\def\bbl@putsh@i#1#2\@nnil{%
-  \csname\language@group @sh@\string#1@%
-    \ifx\@empty#2\else\string#2@\fi\endcsname}
-\ifx\bbl@opt@shorthands\@nnil\else
-  \let\bbl@s@initiate@active@char\initiate@active@char
-  \def\initiate@active@char#1{%
-    \bbl@ifshorthand{#1}{\bbl@s@initiate@active@char{#1}}{}}
-  \let\bbl@s@switch@sh\bbl@switch@sh
-  \def\bbl@switch@sh#1#2{%
-    \ifx#2\@nnil\else
-      \bbl@afterfi
-      \bbl@ifshorthand{#2}{\bbl@s@switch@sh#1{#2}}{\bbl@switch@sh#1}%
-    \fi}
-  \let\bbl@s@activate\bbl@activate
-  \def\bbl@activate#1{%
-    \bbl@ifshorthand{#1}{\bbl@s@activate{#1}}{}}
-  \let\bbl@s@deactivate\bbl@deactivate
-  \def\bbl@deactivate#1{%
-    \bbl@ifshorthand{#1}{\bbl@s@deactivate{#1}}{}}
-\fi
+%<<*More package options>>
+\DeclareOption{hyphenmap=off}{\chardef\bbl@opt@hyphenmap\z@}
+\DeclareOption{hyphenmap=first}{\chardef\bbl@opt@hyphenmap\@ne}
+\DeclareOption{hyphenmap=select}{\chardef\bbl@opt@hyphenmap\tw@}
+\DeclareOption{hyphenmap=other}{\chardef\bbl@opt@hyphenmap\thr@@}
+\DeclareOption{hyphenmap=other*}{\chardef\bbl@opt@hyphenmap4\relax}
+%<</More package options>>
 %    \end{macrocode}
 %
-% You may want to test if a character is a shorthand. Note it does not
-% test whether the shorthand is on or off.
+%    Initial setup to provide a default behavior if |hypenmap|
+%    is not set.
 %
 %    \begin{macrocode}
-\newcommand\ifbabelshorthand[3]{\bbl@ifunset{bbl@active@\string#1}{#3}{#2}}
+\AtEndOfPackage{%
+  \ifx\bbl@opt@hyphenmap\@undefined
+    \bbl@xin@{,}{\bbl@language@opts}%
+    \chardef\bbl@opt@hyphenmap\ifin@4\else\@ne\fi
+  \fi}
 %    \end{macrocode}
 %
-%  \begin{macro}{\bbl@prim@s}
-%  \begin{macro}{\bbl@pr@m@s}
-%
-% One of the internal macros that are involved in substituting |\prime|
-% for each right quote in mathmode is |\prim@s|. This checks if the
-% next character is a right quote. When the right quote is active, the
-% definition of this macro needs to be adapted to look also for an
-% active right quote; the hat could be active, too.
+% This sections ends with a general tool for resetting the caption
+% names with a unique interface. With the old way, which mixes the
+% switcher and the string, we convert it to the new one, which
+% separates these two steps.
 %
 %    \begin{macrocode}
-\def\bbl@prim@s{%
-  \prime\futurelet\@let@token\bbl@pr@m@s}
-\def\bbl@if@primes#1#2{%
-  \ifx#1\@let@token
-    \expandafter\@firstoftwo
-  \else\ifx#2\@let@token
-    \bbl@afterelse\expandafter\@firstoftwo
+\newcommand\setlocalecaption{%  TODO. Catch typos. What about ensure?
+  \@ifstar\bbl@setcaption@s\bbl@setcaption@x}
+\def\bbl@setcaption@x#1#2#3{%  language caption-name string
+  \bbl@trim@def\bbl@tempa{#2}%
+  \bbl@xin@{.template}{\bbl@tempa}%
+  \ifin@
+    \bbl@ini@captions@template{#3}{#1}%
   \else
-    \bbl@afterfi\expandafter\@secondoftwo
-  \fi\fi}
-\begingroup
-  \catcode`\^=7  \catcode`\*=\active  \lccode`\*=`\^
-  \catcode`\'=12 \catcode`\"=\active  \lccode`\"=`\'
-  \lowercase{%
-    \gdef\bbl@pr@m@s{%
-      \bbl@if@primes"'%
-        \pr@@@s
-        {\bbl@if@primes*^\pr@@@t\egroup}}}
-\endgroup
+    \edef\bbl@tempd{%
+      \expandafter\expandafter\expandafter
+      \strip@prefix\expandafter\meaning\csname captions#1\endcsname}%
+    \bbl@xin@
+      {\expandafter\string\csname #2name\endcsname}%
+      {\bbl@tempd}%
+    \ifin@ % Renew caption
+      \bbl@xin@{\string\bbl@scset}{\bbl@tempd}% 
+      \ifin@
+        \bbl@exp{%
+          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
+            {\\\bbl@scset\<#2name>\<#1#2name>}%
+            {}}%
+      \else % Old way converts to new way
+        \bbl@ifunset{#1#2name}%
+          {\bbl@exp{%
+            \\\bbl@add\<captions#1>{\def\<#2name>{\<#1#2name>}}%
+            \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
+              {\def\<#2name>{\<#1#2name>}}%
+              {}}}%
+          {}%
+      \fi
+    \else
+      \bbl@xin@{\string\bbl@scset}{\bbl@tempd}% New
+      \ifin@ % New way
+        \bbl@exp{%
+          \\\bbl@add\<captions#1>{\\\bbl@scset\<#2name>\<#1#2name>}%
+          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
+            {\\\bbl@scset\<#2name>\<#1#2name>}%
+            {}}%
+      \else  % Old way, but defined in the new way
+        \bbl@exp{%
+          \\\bbl@add\<captions#1>{\def\<#2name>{\<#1#2name>}}%      
+          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
+            {\def\<#2name>{\<#1#2name>}}%
+            {}}%
+      \fi%
+    \fi
+    \@namedef{#1#2name}{#3}%
+    \toks@\expandafter{\bbl@captionslist}%
+    \bbl@exp{\\\in@{\<#2name>}{\the\toks@}}%
+    \ifin@\else
+      \bbl@exp{\\\bbl@add\\\bbl@captionslist{\<#2name>}}%
+      \bbl@toglobal\bbl@captionslist
+    \fi
+  \fi}
+% \def\bbl@setcaption@s#1#2#3{}  % TODO. Not yet implemented
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
+% \subsection{Macros common to a number of languages}
 %
-%    Usually the |~| is active and expands to \verb*=\penalty\@M\ =.
-%    When it is written to the \file{.aux} file it is written
-%    expanded. To prevent that and to be able to use the character |~|
-%    as a start character for a shorthand, it is redefined here as a
-%    one character shorthand on system level. The system declaration
-%    is in most cases redundant (when |~| is still a non-break space),
-%    and in some cases is inconvenient (if |~| has been redefined);
-%    however, for backward compatibility it is maintained (some
-%    existing documents may rely on the \babel{} value).
+%  \begin{macro}{\set@low@box}
+%
+% The following macro is used to lower quotes to the same level as
+% the comma.  It prepares its argument in box register~0.
 %
 %    \begin{macrocode}
-\initiate@active@char{~}
-\declare@shorthand{system}{~}{\leavevmode\nobreak\ }
-\bbl@activate{~}
+\bbl@trace{Macros related to glyphs}
+\def\set@low@box#1{\setbox\tw@\hbox{,}\setbox\z@\hbox{#1}%
+    \dimen\z@\ht\z@ \advance\dimen\z@ -\ht\tw@%
+    \setbox\z@\hbox{\lower\dimen\z@ \box\z@}\ht\z@\ht\tw@ \dp\z@\dp\tw@}
 %    \end{macrocode}
 %
-%  \begin{macro}{\OT1dqpos}
-%  \begin{macro}{\T1dqpos}
-%    The position of the double quote character is different for the
-%    OT1 and T1 encodings. It will later be selected using the
-%    |\f@encoding| macro. Therefore we define two macros here to store
-%    the position of the character in these encodings.
+%  \end{macro}
+%
+%  \begin{macro}{\save@sf@q}
+%    The macro |\save@sf@q| is used to save and reset the current
+%    space factor.
 %
 %    \begin{macrocode}
-\expandafter\def\csname OT1dqpos\endcsname{127}
-\expandafter\def\csname T1dqpos\endcsname{4}
+\def\save@sf@q#1{\leavevmode
+  \begingroup
+    \edef\@SF{\spacefactor\the\spacefactor}#1\@SF
+  \endgroup}
 %    \end{macrocode}
 %
-%    When the macro |\f@encoding| is undefined (as it is in plain
-%    \TeX) we define it here to expand to \texttt{OT1}
-%
-%    \begin{macrocode}
-\ifx\f@encoding\@undefined
-  \def\f@encoding{OT1}
-\fi
-%    \end{macrocode}
-%
-%  \end{macro}
 %  \end{macro}
 %
-% \subsection{Language attributes}
-%
-%    Language attributes provide a means to give the user control over
-%    which features of the language definition files he wants to
-%    enable.
-%  \begin{macro}{\languageattribute}
+% \subsection{Making glyphs available}
 %
-%    The macro |\languageattribute| checks whether its arguments are
-%    valid and then activates the selected language attribute.
-%    First check whether the language is known, and then process each
-%    attribute in the list.
+% This section makes a number of glyphs available that either do not
+% exist in the \texttt{OT1} encoding and have to be `faked', or
+% that are not accessible through \file{T1enc.def}.
 %
-%    \begin{macrocode}
-\bbl@trace{Language attributes}
-\newcommand\languageattribute[2]{%
-  \def\bbl@tempc{#1}%
-  \bbl@fixname\bbl@tempc
-  \bbl@iflanguage\bbl@tempc{%
-    \bbl@vforeach{#2}{%
-%    \end{macrocode}
+% \subsubsection{Quotation marks}
 %
-%    We want to make sure that each attribute is selected only once;
-%    therefore we store the already selected attributes in
-%    |\bbl@known@attribs|. When that control sequence is not yet
-%    defined this attribute is certainly not selected before.
+%  \begin{macro}{\quotedblbase}
+% In the \texttt{T1} encoding the opening double quote at the
+% baseline is available as a separate character, accessible via
+% |\quotedblbase|. In the \texttt{OT1} encoding it is not
+% available, therefore we make it available by lowering the normal
+% open quote character to the baseline.
 %
 %    \begin{macrocode}
-      \ifx\bbl@known@attribs\@undefined
-        \in@false
-      \else
-        \bbl@xin@{,\bbl@tempc-##1,}{,\bbl@known@attribs,}%
-      \fi
-      \ifin@
-        \bbl@warning{%
-          You have more than once selected the attribute '##1'\\%
-          for language #1. Reported}%
-      \else
+\ProvideTextCommand{\quotedblbase}{OT1}{%
+  \save@sf@q{\set@low@box{\textquotedblright\/}%
+    \box\z@\kern-.04em\bbl@allowhyphens}}
 %    \end{macrocode}
 %
-%    When we end up here the attribute is not selected before. So, we
-%    add it to the list of selected attributes and execute the
-%    associated \TeX-code.
+% Make sure that when an encoding other than \texttt{OT1} or
+% \texttt{T1} is used this glyph can still be typeset.
 %
 %    \begin{macrocode}
-        \bbl@exp{%
-          \\\bbl@add@list\\\bbl@known@attribs{\bbl@tempc-##1}}%
-        \edef\bbl@tempa{\bbl@tempc-##1}%
-        \expandafter\bbl@ifknown@ttrib\expandafter{\bbl@tempa}\bbl@attributes%
-        {\csname\bbl@tempc @attr@##1\endcsname}%
-        {\@attrerr{\bbl@tempc}{##1}}%
-     \fi}}}
-\@onlypreamble\languageattribute
+\ProvideTextCommandDefault{\quotedblbase}{%
+  \UseTextSymbol{OT1}{\quotedblbase}}
 %    \end{macrocode}
 %
-%    The error text to be issued when an unknown attribute is
-%    selected.
+%  \end{macro}
+%
+%  \begin{macro}{\quotesinglbase}
+%    We also need the single quote character at the baseline.
 %
 %    \begin{macrocode}
-\newcommand*{\@attrerr}[2]{%
-  \bbl@error
-    {The attribute #2 is unknown for language #1.}%
-    {Your command will be ignored, type <return> to proceed}}
+\ProvideTextCommand{\quotesinglbase}{OT1}{%
+  \save@sf@q{\set@low@box{\textquoteright\/}%
+    \box\z@\kern-.04em\bbl@allowhyphens}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\bbl@declare@ttribute}
-%    This command adds the new language/attribute combination to the
-%    list of known attributes.
-%
-%    Then it defines a control sequence to be executed when the
-%    attribute is used in a document. The result of this should be
-%    that the macro |\extras...| for the current language is extended,
-%    otherwise the attribute will not work as its code is removed from
-%    memory at |\begin{document}|.
+%    Make sure that when an encoding other than \texttt{OT1} or
+%    \texttt{T1} is used this glyph can still be typeset.
 %
 %    \begin{macrocode}
-\def\bbl@declare@ttribute#1#2#3{%
-  \bbl@xin@{,#2,}{,\BabelModifiers,}%
-  \ifin@
-    \AfterBabelLanguage{#1}{\languageattribute{#1}{#2}}%
-  \fi
-  \bbl@add@list\bbl@attributes{#1-#2}%
-  \expandafter\def\csname#1@attr@#2\endcsname{#3}}
+\ProvideTextCommandDefault{\quotesinglbase}{%
+  \UseTextSymbol{OT1}{\quotesinglbase}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %
-%  \begin{macro}{\bbl@ifattributeset}
-%    This internal macro has 4 arguments. It can be used to interpret
-%    \TeX\ code based on whether a certain attribute was set. This
-%    command should appear inside the argument to |\AtBeginDocument|
-%    because the attributes are set in the document preamble,
-%    \emph{after} \babel\ is loaded.
-%
-%    The first argument is the language, the second argument the
-%    attribute being checked, and the third and fourth arguments are
-%    the true and false clauses.
+%  \begin{macro}{\guillemetleft}
+%  \begin{macro}{\guillemetright}
+% The guillemet characters are not available in \texttt{OT1}
+% encoding. They are faked. (Wrong names with o preserved for
+% compatibility.)
 %
 %    \begin{macrocode}
-\def\bbl@ifattributeset#1#2#3#4{%
-  \ifx\bbl@known@attribs\@undefined
-    \in@false
+\ProvideTextCommand{\guillemetleft}{OT1}{%
+  \ifmmode
+    \ll
   \else
-    \bbl@xin@{,#1-#2,}{,\bbl@known@attribs,}%
-  \fi
-  \ifin@
-    \bbl@afterelse#3%
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle\ll$}\bbl@allowhyphens}%
+  \fi}
+\ProvideTextCommand{\guillemetright}{OT1}{%
+  \ifmmode
+    \gg
   \else
-    \bbl@afterfi#4%
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle\gg$}\bbl@allowhyphens}%
+  \fi}
+\ProvideTextCommand{\guillemotleft}{OT1}{%
+  \ifmmode
+    \ll
+  \else
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle\ll$}\bbl@allowhyphens}%
+  \fi}
+\ProvideTextCommand{\guillemotright}{OT1}{%
+  \ifmmode
+    \gg
+  \else
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle\gg$}\bbl@allowhyphens}%
   \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\bbl@ifknown@ttrib}
-%    An internal macro to check whether a given language/attribute is
-%    known. The macro takes 4 arguments, the language/attribute, the
-%    attribute list, the \TeX-code to be executed when the attribute
-%    is known and the \TeX-code to be executed otherwise.
-%
-%    We first assume the attribute is unknown. Then we loop over the
-%    list of known attributes, trying to find a match. 
+% Make sure that when an encoding other than \texttt{OT1} or
+% \texttt{T1} is used these glyphs can still be typeset.
 %
 %    \begin{macrocode}
-\def\bbl@ifknown@ttrib#1#2{%
-  \let\bbl@tempa\@secondoftwo
-  \bbl@loopx\bbl@tempb{#2}{%
-    \expandafter\in@\expandafter{\expandafter,\bbl@tempb,}{,#1,}%
-    \ifin@
-      \let\bbl@tempa\@firstoftwo
-    \else
-    \fi}%
-  \bbl@tempa}
+\ProvideTextCommandDefault{\guillemetleft}{%
+  \UseTextSymbol{OT1}{\guillemetleft}}
+\ProvideTextCommandDefault{\guillemetright}{%
+  \UseTextSymbol{OT1}{\guillemetright}}
+\ProvideTextCommandDefault{\guillemotleft}{%
+  \UseTextSymbol{OT1}{\guillemotleft}}
+\ProvideTextCommandDefault{\guillemotright}{%
+  \UseTextSymbol{OT1}{\guillemotright}}
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-%  \begin{macro}{\bbl@clear@ttribs}
-%    This macro removes all the attribute code from \LaTeX's memory at
-%    |\begin{document}| time (if any is present).
+%  \begin{macro}{\guilsinglleft}
+%  \begin{macro}{\guilsinglright}
+%    The single guillemets are not available in \texttt{OT1}
+%    encoding. They are faked.
 %
 %    \begin{macrocode}
-\def\bbl@clear@ttribs{%
-  \ifx\bbl@attributes\@undefined\else
-    \bbl@loopx\bbl@tempa{\bbl@attributes}{%
-      \expandafter\bbl@clear@ttrib\bbl@tempa.
-      }%
-    \let\bbl@attributes\@undefined
+\ProvideTextCommand{\guilsinglleft}{OT1}{%
+  \ifmmode
+    <%
+  \else
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle<$}\bbl@allowhyphens}%
+  \fi}
+\ProvideTextCommand{\guilsinglright}{OT1}{%
+  \ifmmode
+    >%
+  \else
+    \save@sf@q{\nobreak
+      \raise.2ex\hbox{$\scriptscriptstyle>$}\bbl@allowhyphens}%
   \fi}
-\def\bbl@clear@ttrib#1-#2.{%
-  \expandafter\let\csname#1@attr@#2\endcsname\@undefined}
-\AtBeginDocument{\bbl@clear@ttribs}
 %    \end{macrocode}
 %
-%  \end{macro}
+% Make sure that when an encoding other than \texttt{OT1} or
+% \texttt{T1} is used these glyphs can still be typeset.
 %
-% \subsection{Support for saving macro definitions}
+%    \begin{macrocode}
+\ProvideTextCommandDefault{\guilsinglleft}{%
+  \UseTextSymbol{OT1}{\guilsinglleft}}
+\ProvideTextCommandDefault{\guilsinglright}{%
+  \UseTextSymbol{OT1}{\guilsinglright}}
+%    \end{macrocode}
 %
-%  To save the meaning of control sequences using |\babel@save|, we
-%  use temporary control sequences.  To save hash table entries for
-%  these control sequences, we don't use the name of the control
-%  sequence to be saved to construct the temporary name.  Instead we
-%  simply use the value of a counter, which is reset to zero each time
-%  we begin to save new values.  This works well because we release
-%  the saved meanings before we begin to save a new set of control
-%  sequence meanings (see |\selectlanguage| and |\originalTeX|). Note
-%  undefined macros are not undefined any more when saved -- they are
-%  |\relax|'ed.
+%  \end{macro}
+%  \end{macro}
 %
-%  \begin{macro}{\babel@savecnt}
-%  \begin{macro}{\babel@beginsave}
-%    The initialization of a new save cycle: reset the counter to
-%    zero.
+% \subsubsection{Letters}
+%
+%  \begin{macro}{\ij}
+%  \begin{macro}{\IJ}
+% The dutch language uses the letter `ij'. It is available in
+% \texttt{T1} encoded fonts, but not in the \texttt{OT1} encoded
+% fonts. Therefore we fake it for the \texttt{OT1} encoding.
 %
 %    \begin{macrocode}
-\bbl@trace{Macros for saving definitions}
-\def\babel@beginsave{\babel@savecnt\z@}
+\DeclareTextCommand{\ij}{OT1}{%
+  i\kern-0.02em\bbl@allowhyphens j}
+\DeclareTextCommand{\IJ}{OT1}{%
+  I\kern-0.02em\bbl@allowhyphens J}
+\DeclareTextCommand{\ij}{T1}{\char188}
+\DeclareTextCommand{\IJ}{T1}{\char156}
 %    \end{macrocode}
 %
-%    Before it's forgotten, allocate the counter and initialize all.
+%    Make sure that when an encoding other than \texttt{OT1} or
+%    \texttt{T1} is used these glyphs can still be typeset.
 %
 %    \begin{macrocode}
-\newcount\babel@savecnt
-\babel@beginsave
+\ProvideTextCommandDefault{\ij}{%
+  \UseTextSymbol{OT1}{\ij}}
+\ProvideTextCommandDefault{\IJ}{%
+  \UseTextSymbol{OT1}{\IJ}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %  \end{macro}
 %
-%  \begin{macro}{\babel@save}
-%  \begin{macro}{\babel@savevariable}
+% \begin{macro}{\dj}
+% \begin{macro}{\DJ}
+% The croatian language needs the letters |\dj| and |\DJ|; they are
+% available in the \texttt{T1} encoding, but not in the
+% \texttt{OT1} encoding by default.
 %
-% The macro |\babel@save|\meta{csname} saves the current meaning of the
-% control sequence \meta{csname} to
-% |\originalTeX|\footnote{\cs{originalTeX} has to be expandable,
-% i.\,e.\ you shouldn't let it to \cs{relax}.}. To do this, we let the
-% current meaning to a temporary control sequence, the restore commands
-% are appended to |\originalTeX| and the counter is incremented. The
-% macro |\babel@savevariable|\meta{variable} saves the value of the
-% variable. \meta{variable} can be anything allowed after the |\the|
-% primitive.
+% Some code to construct these glyphs for the \texttt{OT1} encoding
+% was made available to me by Stipčević Mario,
+% (\texttt{stipcevic@olimp.irb.hr}).
 %
 %    \begin{macrocode}
-\def\babel@save#1{%
-  \expandafter\let\csname babel@\number\babel@savecnt\endcsname#1\relax
-  \toks@\expandafter{\originalTeX\let#1=}%
-  \bbl@exp{%
-    \def\\\originalTeX{\the\toks@\<babel@\number\babel@savecnt>\relax}}%
-  \advance\babel@savecnt\@ne}
-\def\babel@savevariable#1{%
-  \toks@\expandafter{\originalTeX #1=}%
-  \bbl@exp{\def\\\originalTeX{\the\toks@\the#1\relax}}}
-%    \end{macrocode}
+\def\crrtic@{\hrule height0.1ex width0.3em}
+\def\crttic@{\hrule height0.1ex width0.33em}
+\def\ddj@{%
+  \setbox0\hbox{d}\dimen@=\ht0
+  \advance\dimen@1ex
+  \dimen@.45\dimen@
+  \dimen@ii\expandafter\rem@pt\the\fontdimen\@ne\font\dimen@
+  \advance\dimen@ii.5ex
+  \leavevmode\rlap{\raise\dimen@\hbox{\kern\dimen@ii\vbox{\crrtic@}}}}
+\def\DDJ@{%
+  \setbox0\hbox{D}\dimen@=.55\ht0
+  \dimen@ii\expandafter\rem@pt\the\fontdimen\@ne\font\dimen@
+  \advance\dimen@ii.15ex %            correction for the dash position
+  \advance\dimen@ii-.15\fontdimen7\font %     correction for cmtt font
+  \dimen\thr@@\expandafter\rem@pt\the\fontdimen7\font\dimen@
+  \leavevmode\rlap{\raise\dimen@\hbox{\kern\dimen@ii\vbox{\crttic@}}}}
 %
-%  \end{macro}
-%  \end{macro}
+\DeclareTextCommand{\dj}{OT1}{\ddj@ d}
+\DeclareTextCommand{\DJ}{OT1}{\DDJ@ D}
+%    \end{macrocode}
 %
-%  \begin{macro}{\bbl@frenchspacing}
-%  \begin{macro}{\bbl@nonfrenchspacing}
-% Some languages need to have |\frenchspacing| in effect. Others
-% don't want that. The command |\bbl@frenchspacing| switches it on
-% when it isn't already in effect and |\bbl@nonfrenchspacing|
-% switches it off if necessary. A more refined way to switch the
-% catcodes is done with |ini| files. Here an auxiliary macro is
-% defined, but the main part is in |\babelprovide|. This new method
-% should be ideally the default one.
+%    Make sure that when an encoding other than \texttt{OT1} or
+%    \texttt{T1} is used these glyphs can still be typeset.
 %
 %    \begin{macrocode}
-\def\bbl@frenchspacing{%
-  \ifnum\the\sfcode`\.=\@m
-    \let\bbl@nonfrenchspacing\relax
-  \else
-    \frenchspacing
-    \let\bbl@nonfrenchspacing\nonfrenchspacing
-  \fi}
-\let\bbl@nonfrenchspacing\nonfrenchspacing
-\let\bbl@elt\relax
-\edef\bbl@fs@chars{%
-  \bbl@elt{\string.}\@m{3000}\bbl@elt{\string?}\@m{3000}%
-  \bbl@elt{\string!}\@m{3000}\bbl@elt{\string:}\@m{2000}%
-  \bbl@elt{\string;}\@m{1500}\bbl@elt{\string,}\@m{1250}}
-\def\bbl@pre@fs{%
-  \def\bbl@elt##1##2##3{\sfcode`##1=\the\sfcode`##1\relax}%
-  \edef\bbl@save@sfcodes{\bbl@fs@chars}}%
-\def\bbl@post@fs{%
-  \bbl@save@sfcodes
-  \edef\bbl@tempa{\bbl@cl{frspc}}%
-  \edef\bbl@tempa{\expandafter\@car\bbl@tempa\@nil}%
-  \if u\bbl@tempa          % do nothing
-  \else\if n\bbl@tempa     % non french
-    \def\bbl@elt##1##2##3{%
-      \ifnum\sfcode`##1=##2\relax
-        \babel@savevariable{\sfcode`##1}%
-        \sfcode`##1=##3\relax
-      \fi}%
-    \bbl@fs@chars
-  \else\if y\bbl@tempa     % french
-    \def\bbl@elt##1##2##3{%
-      \ifnum\sfcode`##1=##3\relax
-        \babel@savevariable{\sfcode`##1}%
-        \sfcode`##1=##2\relax
-      \fi}%
-    \bbl@fs@chars
-  \fi\fi\fi}
+\ProvideTextCommandDefault{\dj}{%
+  \UseTextSymbol{OT1}{\dj}}
+\ProvideTextCommandDefault{\DJ}{%
+  \UseTextSymbol{OT1}{\DJ}}
 %    \end{macrocode}
 %
 %  \end{macro}
 %  \end{macro}
 %
-% \subsection{Short tags}
-%
-% \begin{macro}{\babeltags}
-% This macro is straightforward. After zapping spaces, we
-% loop over the list and define the macros |\text|\m{tag} and
-% |\|\m{tag}. Definitions are first expanded so that they don't
-% contain |\csname| but the actual macro.
+%  \begin{macro}{\SS}
+%    For the \texttt{T1} encoding |\SS| is defined and selects a
+%    specific glyph from the font, but for other encodings it is not
+%    available. Therefore we make it available here.
 %
-%   \begin{macrocode}
-\bbl@trace{Short tags}
-\def\babeltags#1{%
-  \edef\bbl@tempa{\zap@space#1 \@empty}%
-  \def\bbl@tempb##1=##2\@@{%
-    \edef\bbl@tempc{%
-      \noexpand\newcommand
-      \expandafter\noexpand\csname ##1\endcsname{%
-        \noexpand\protect
-        \expandafter\noexpand\csname otherlanguage*\endcsname{##2}}
-      \noexpand\newcommand
-      \expandafter\noexpand\csname text##1\endcsname{%
-        \noexpand\foreignlanguage{##2}}}
-    \bbl@tempc}%
-  \bbl@for\bbl@tempa\bbl@tempa{%
-    \expandafter\bbl@tempb\bbl@tempa\@@}}
+%    \begin{macrocode}
+\DeclareTextCommand{\SS}{OT1}{SS}
+\ProvideTextCommandDefault{\SS}{\UseTextSymbol{OT1}{\SS}}
 %    \end{macrocode}
 %
-% \end{macro}
+%  \end{macro}
 %
-% \subsection{Hyphens}
+% \subsubsection{Shorthands for quotation marks}
 %
-% \begin{macro}{\babelhyphenation}
+%    Shorthands are provided for a number of different quotation
+%    marks, which make them usable both outside and inside mathmode.
+%    They are defined with |\ProvideTextCommandDefault|, but this is
+%    very likely not required because their definitions are based on
+%    encoding-dependent macros.
 %
-% This macro saves hyphenation exceptions. Two macros are used to
-% store them: |\bbl@hyphenation@| for the global ones and
-% |\bbl@hyphenation<lang>| for language ones. See |\bbl@patterns|
-% above for further details. We make sure there is a space between
-% words when multiple commands are used.
+%  \begin{macro}{\glq}
+%  \begin{macro}{\grq}
+%
+%    The `german' single quotes.
 %
 %    \begin{macrocode}
-\bbl@trace{Hyphens}
-\@onlypreamble\babelhyphenation
-\AtEndOfPackage{%
-  \newcommand\babelhyphenation[2][\@empty]{%
-    \ifx\bbl@hyphenation@\relax
-      \let\bbl@hyphenation@\@empty
-    \fi
-    \ifx\bbl@hyphlist\@empty\else
-      \bbl@warning{%
-        You must not intermingle \string\selectlanguage\space and\\%
-        \string\babelhyphenation\space or some exceptions will not\\%
-        be taken into account. Reported}%
-    \fi
-    \ifx\@empty#1%
-      \protected@edef\bbl@hyphenation@{\bbl@hyphenation@\space#2}%
-    \else
-      \bbl@vforeach{#1}{%
-        \def\bbl@tempa{##1}%
-        \bbl@fixname\bbl@tempa
-        \bbl@iflanguage\bbl@tempa{%
-          \bbl@csarg\protected@edef{hyphenation@\bbl@tempa}{%
-            \bbl@ifunset{bbl@hyphenation@\bbl@tempa}%
-              {}%
-              {\csname bbl@hyphenation@\bbl@tempa\endcsname\space}%
-            #2}}}%
-    \fi}}
+\ProvideTextCommandDefault{\glq}{%
+  \textormath{\quotesinglbase}{\mbox{\quotesinglbase}}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-%  \begin{macro}{\bbl@allowhyphens}
-%
-% This macro makes hyphenation possible. Basically its definition
-% is nothing more than |\nobreak| |\hskip| \texttt{0pt plus
-% 0pt}\footnote{\TeX\ begins and ends a word for hyphenation at a
-% glue node. The penalty prevents a linebreak at this glue node.}.
+%    The definition of |\grq| depends on the fontencoding. With
+%    \texttt{T1} encoding no extra kerning is needed.
 %
 %    \begin{macrocode}
-\def\bbl@allowhyphens{\ifvmode\else\nobreak\hskip\z@skip\fi}
-\def\bbl@t@one{T1}
-\def\allowhyphens{\ifx\cf@encoding\bbl@t@one\else\bbl@allowhyphens\fi}
+\ProvideTextCommand{\grq}{T1}{%
+  \textormath{\kern\z@\textquoteleft}{\mbox{\textquoteleft}}}
+\ProvideTextCommand{\grq}{TU}{%
+  \textormath{\textquoteleft}{\mbox{\textquoteleft}}}
+\ProvideTextCommand{\grq}{OT1}{%
+  \save@sf@q{\kern-.0125em
+    \textormath{\textquoteleft}{\mbox{\textquoteleft}}%
+    \kern.07em\relax}}
+\ProvideTextCommandDefault{\grq}{\UseTextSymbol{OT1}\grq}
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-% \begin{macro}{\babelhyphen}
+%  \begin{macro}{\glqq}
+%  \begin{macro}{\grqq}
 %
-% Macros to insert common hyphens. Note the space before |@| in
-% |\babelhyphen|. Instead of protecting it with
-% |\DeclareRobustCommand|, which could insert a |\relax|, we use
-% the same procedure as shorthands, with |\active@prefix|.
+%    The `german' double quotes.
 %
 %    \begin{macrocode}
-\newcommand\babelnullhyphen{\char\hyphenchar\font}
-\def\babelhyphen{\active@prefix\babelhyphen\bbl@hyphen}
-\def\bbl@hyphen{%
-  \@ifstar{\bbl@hyphen@i @}{\bbl@hyphen@i\@empty}}
-\def\bbl@hyphen@i#1#2{%
-  \bbl@ifunset{bbl@hy@#1#2\@empty}%
-    {\csname bbl@#1usehyphen\endcsname{\discretionary{#2}{}{#2}}}%
-    {\csname bbl@hy@#1#2\@empty\endcsname}}
+\ProvideTextCommandDefault{\glqq}{%
+  \textormath{\quotedblbase}{\mbox{\quotedblbase}}}
 %    \end{macrocode}
 %
-% The following two commands are used to wrap the ``hyphen'' and
-% set the behavior of the rest of the word -- the version with a
-% single |@| is used when further hyphenation is allowed, while
-% that with |@@| if no more hyphens are allowed. In both cases, if
-% the hyphen is preceded by a positive space, breaking after the
-% hyphen is disallowed.
-%
-% There should not be a discretionary after a hyphen at the
-% beginning of a word, so it is prevented if preceded by a
-% skip. Unfortunately, this does handle cases like ``(-suffix)''.
-% |\nobreak| is always preceded by |\leavevmode|, in case the
-% shorthand starts a paragraph.
+%    The definition of |\grqq| depends on the fontencoding. With
+%    \texttt{T1} encoding no extra kerning is needed.
 %
 %    \begin{macrocode}
-\def\bbl@usehyphen#1{%
-  \leavevmode
-  \ifdim\lastskip>\z@\mbox{#1}\else\nobreak#1\fi
-  \nobreak\hskip\z@skip}
-\def\bbl@@usehyphen#1{%
-  \leavevmode\ifdim\lastskip>\z@\mbox{#1}\else#1\fi}
+\ProvideTextCommand{\grqq}{T1}{%
+  \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}}
+\ProvideTextCommand{\grqq}{TU}{%
+  \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}}
+\ProvideTextCommand{\grqq}{OT1}{%
+  \save@sf@q{\kern-.07em
+    \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}%
+    \kern.07em\relax}}
+\ProvideTextCommandDefault{\grqq}{\UseTextSymbol{OT1}\grqq}
 %    \end{macrocode}
 %
-%    The following macro inserts the hyphen char.
+%  \end{macro}
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@hyphenchar{%
-  \ifnum\hyphenchar\font=\m@ne
-    \babelnullhyphen
-  \else
-    \char\hyphenchar\font
-  \fi}
-%    \end{macrocode}
+%  \begin{macro}{\flq}
+%  \begin{macro}{\frq}
 %
-%    Finally, we define the hyphen ``types''. Their names will not
-%    change, so you may use them in |ldf|'s. After a space, the
-%    |\mbox| in |\bbl@hy@nobreak| is redundant.
+%    The `french' single guillemets.
 %
 %    \begin{macrocode}
-\def\bbl@hy@soft{\bbl@usehyphen{\discretionary{\bbl@hyphenchar}{}{}}}
-\def\bbl@hy@@soft{\bbl@@usehyphen{\discretionary{\bbl@hyphenchar}{}{}}}
-\def\bbl@hy@hard{\bbl@usehyphen\bbl@hyphenchar}
-\def\bbl@hy@@hard{\bbl@@usehyphen\bbl@hyphenchar}
-\def\bbl@hy@nobreak{\bbl@usehyphen{\mbox{\bbl@hyphenchar}}}
-\def\bbl@hy@@nobreak{\mbox{\bbl@hyphenchar}}
-\def\bbl@hy@repeat{%
-  \bbl@usehyphen{%
-    \discretionary{\bbl@hyphenchar}{\bbl@hyphenchar}{\bbl@hyphenchar}}}
-\def\bbl@hy@@repeat{%
-  \bbl@@usehyphen{%
-    \discretionary{\bbl@hyphenchar}{\bbl@hyphenchar}{\bbl@hyphenchar}}}
-\def\bbl@hy@empty{\hskip\z@skip}
-\def\bbl@hy@@empty{\discretionary{}{}{}}
+\ProvideTextCommandDefault{\flq}{%
+  \textormath{\guilsinglleft}{\mbox{\guilsinglleft}}}
+\ProvideTextCommandDefault{\frq}{%
+  \textormath{\guilsinglright}{\mbox{\guilsinglright}}}
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-%  \begin{macro}{\bbl@disc}
-%    For some languages the macro |\bbl@disc| is used to ease the
-%    insertion of discretionaries for letters that behave `abnormally'
-%    at a breakpoint.
+%  \begin{macro}{\flqq}
+%  \begin{macro}{\frqq}
+%
+%    The `french' double guillemets.
 %
 %    \begin{macrocode}
-\def\bbl@disc#1#2{\nobreak\discretionary{#2-}{}{#1}\bbl@allowhyphens}
+\ProvideTextCommandDefault{\flqq}{%
+  \textormath{\guillemetleft}{\mbox{\guillemetleft}}}
+\ProvideTextCommandDefault{\frqq}{%
+  \textormath{\guillemetright}{\mbox{\guillemetright}}}
 %    \end{macrocode}
 %
 %  \end{macro}
+%  \end{macro}
 %
-% \subsection{Multiencoding strings}
+% \subsubsection{Umlauts and tremas}
 %
-% The aim following commands is to provide a commom interface for
-% strings in several encodings. They also contains several hooks which
-% can be used by \luatex{} and \xetex. The code is organized here with
-% pseudo-guards, so we start with the basic commands.
+%    The command |\"| needs to have a different effect for different
+%    languages. For German for instance, the `umlaut' should be
+%    positioned lower than the default position for placing it over
+%    the letters a, o, u, A, O and U. When placed over an e, i, E or I
+%    it can retain its normal position. For Dutch the same glyph is
+%    always placed in the lower position.
 %
-%  \paragraph{Tools}
+%  \begin{macro}{\umlauthigh}
 %
-% But first, a couple of tools. The first one makes global a local
-% variable. This is not the best solution, but it works.
+%  \begin{macro}{\umlautlow}
+%    To be able to provide both positions of |\"| we provide two
+%    commands to switch the positioning, the default will be
+%    |\umlauthigh| (the normal positioning).
 %
 %    \begin{macrocode}
-\bbl@trace{Multiencoding strings}
-\def\bbl@toglobal#1{\global\let#1#1}
-\def\bbl@recatcode#1{% TODO. Used only once?
-  \@tempcnta="7F
-  \def\bbl@tempa{%
-    \ifnum\@tempcnta>"FF\else
-      \catcode\@tempcnta=#1\relax
-      \advance\@tempcnta\@ne
-      \expandafter\bbl@tempa
-    \fi}%
-  \bbl@tempa}
+\def\umlauthigh{%
+  \def\bbl@umlauta##1{\leavevmode\bgroup%
+      \expandafter\accent\csname\f@encoding dqpos\endcsname
+      ##1\bbl@allowhyphens\egroup}%
+  \let\bbl@umlaute\bbl@umlauta}
+\def\umlautlow{%
+  \def\bbl@umlauta{\protect\lower@umlaut}}
+\def\umlautelow{%
+  \def\bbl@umlaute{\protect\lower@umlaut}}
+\umlauthigh
 %    \end{macrocode}
 %
-% The second one. We need to patch |\@uclclist|, but it is done once
-% and only if |\SetCase| is used or if strings are encoded.  The code
-% is far from satisfactory for several reasons, including the fact
-% |\@uclclist| is not a list any more. Therefore a package option is
-% added to ignore it. Instead of gobbling the macro
-% getting the next two elements (usually |\reserved@a|), we pass it as
-% argument to |\bbl@uclc|. The parser is restarted inside
-% |\|\m{lang}|@bbl@uclc| because we do not know how many expansions
-% are necessary (depends on whether strings are encoded). The last
-% part is tricky -- when uppercasing, we have:
-%\begin{verbatim}
-% \let\bbl@tolower\@empty\bbl@toupper\@empty
-%\end{verbatim}
-% and starts over (and similarly when lowercasing).
+%  \end{macro}
+%  \end{macro}
+%
+%  \begin{macro}{\lower@umlaut}
+%    The command |\lower@umlaut| is used to position the |\"| closer
+%    to the letter.
+%
+%    We want the umlaut character lowered, nearer to the letter. To do
+%    this we need an extra \meta{dimen} register.
 %
 %    \begin{macrocode}
-\@ifpackagewith{babel}{nocase}%
-  {\let\bbl@patchuclc\relax}%
-  {\def\bbl@patchuclc{%
-    \global\let\bbl@patchuclc\relax
-    \g@addto@macro\@uclclist{\reserved@b{\reserved@b\bbl@uclc}}%
-    \gdef\bbl@uclc##1{%
-      \let\bbl@encoded\bbl@encoded@uclc
-      \bbl@ifunset{\languagename @bbl@uclc}% and resumes it
-        {##1}%
-        {\let\bbl@tempa##1\relax % Used by LANG@bbl@uclc
-         \csname\languagename @bbl@uclc\endcsname}%
-      {\bbl@tolower\@empty}{\bbl@toupper\@empty}}%
-    \gdef\bbl@tolower{\csname\languagename @bbl@lc\endcsname}%
-    \gdef\bbl@toupper{\csname\languagename @bbl@uc\endcsname}}}
+\expandafter\ifx\csname U@D\endcsname\relax
+  \csname newdimen\endcsname\U@D
+\fi
 %    \end{macrocode}
 %
+%    The following code fools \TeX's \texttt{make\_accent} procedure
+%    about the current x-height of the font to force another placement
+%    of the umlaut character.
+%    First we have to save the current x-height of the font, because
+%    we'll change this font dimension and this is always done
+%    globally.
+%
+%    Then we compute the new x-height in such a way that the umlaut
+%    character is lowered to the base character.  The value of
+%    \texttt{.45ex} depends on the \MF\ parameters with which the
+%    fonts were built.  (Just try out, which value will look best.)
+%    If the new x-height is too low, it is not changed.
+%    Finally we call the |\accent| primitive, reset the old x-height
+%    and insert the base character in the argument.
+%
 %    \begin{macrocode}
-%<<*More package options>>
-\DeclareOption{nocase}{}
-%<</More package options>>
+\def\lower@umlaut#1{%
+  \leavevmode\bgroup
+    \U@D 1ex%
+    {\setbox\z@\hbox{%
+      \expandafter\char\csname\f@encoding dqpos\endcsname}%
+      \dimen@ -.45ex\advance\dimen@\ht\z@
+      \ifdim 1ex<\dimen@ \fontdimen5\font\dimen@ \fi}%
+    \expandafter\accent\csname\f@encoding dqpos\endcsname
+    \fontdimen5\font\U@D #1%
+  \egroup}
 %    \end{macrocode}
 %
-% The following package options control the behavior of |\SetString|.
+%  \end{macro}
+%
+% For all vowels we declare |\"| to be a composite command which
+% uses |\bbl@umlauta| or |\bbl@umlaute| to position the umlaut
+% character. We need to be sure that these definitions override the
+% ones that are provided when the package \pkg{fontenc} with
+% option \Lopt{OT1} is used. Therefore these declarations are
+% postponed until the beginning of the document. Note these
+% definitions only apply to some languages, but
+% babel sets them for \textit{all} languages -- you may want to
+% redefine |\bbl@umlauta| and/or |\bbl@umlaute| for a language
+% in the corresponding |ldf| (using the babel switching mechanism,
+% of course).
 %
 %    \begin{macrocode}
-%<<*More package options>>
-\let\bbl@opt@strings\@nnil % accept strings=value
-\DeclareOption{strings}{\def\bbl@opt@strings{\BabelStringsDefault}}
-\DeclareOption{strings=encoded}{\let\bbl@opt@strings\relax}
-\def\BabelStringsDefault{generic}
-%<</More package options>>
+\AtBeginDocument{%
+  \DeclareTextCompositeCommand{\"}{OT1}{a}{\bbl@umlauta{a}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{e}{\bbl@umlaute{e}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{i}{\bbl@umlaute{\i}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{\i}{\bbl@umlaute{\i}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{o}{\bbl@umlauta{o}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{u}{\bbl@umlauta{u}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{A}{\bbl@umlauta{A}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{E}{\bbl@umlaute{E}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{I}{\bbl@umlaute{I}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{O}{\bbl@umlauta{O}}%
+  \DeclareTextCompositeCommand{\"}{OT1}{U}{\bbl@umlauta{U}}}
 %    \end{macrocode}
 %
-% \paragraph{Main command} This is the main command. With the first
-% use it is redefined to omit the basic setup in subsequent blocks.
-% We make sure strings contain actual letters in the range 128-255,
-% not active characters.
+% Finally, make sure the default hyphenrules are defined (even if
+% empty). For internal use, another empty |\language| is defined.
+% Currently used in Amharic.
 %
 %    \begin{macrocode}
-\@onlypreamble\StartBabelCommands
-\def\StartBabelCommands{%
-  \begingroup
-  \bbl@recatcode{11}%
-  <@Macros local to BabelCommands@>
-  \def\bbl@provstring##1##2{%
-    \providecommand##1{##2}%
-    \bbl@toglobal##1}%
-  \global\let\bbl@scafter\@empty
-  \let\StartBabelCommands\bbl@startcmds
-  \ifx\BabelLanguages\relax
-     \let\BabelLanguages\CurrentOption
-  \fi
-  \begingroup
-  \let\bbl@screset\@nnil % local flag - disable 1st stopcommands
-  \StartBabelCommands}
-\def\bbl@startcmds{%
-  \ifx\bbl@screset\@nnil\else
-    \bbl@usehooks{stopcommands}{}%
-  \fi
-  \endgroup
-  \begingroup
-  \@ifstar
-    {\ifx\bbl@opt@strings\@nnil
-       \let\bbl@opt@strings\BabelStringsDefault
-     \fi
-     \bbl@startcmds@i}%
-    \bbl@startcmds@i}
-\def\bbl@startcmds@i#1#2{%
-  \edef\bbl@L{\zap@space#1 \@empty}%
-  \edef\bbl@G{\zap@space#2 \@empty}%
-  \bbl@startcmds@ii}
-\let\bbl@startcommands\StartBabelCommands
+\ifx\l@english\@undefined
+  \chardef\l@english\z@
+\fi
+% The following is used to cancel rules in ini files (see Amharic).
+\ifx\l@unhyphenated\@undefined
+  \newlanguage\l@unhyphenated
+\fi
 %    \end{macrocode}
 %
-% Parse the encoding info to get the label, input, and font parts.
-%
-% Select the behavior of |\SetString|. Thre are two main cases,
-% depending of if there is an optional argument: without it and
-% |strings=encoded|, strings are defined
-% always; otherwise, they are set only if they are still undefined
-% (ie, fallback values). With labelled blocks and
-% |strings=encoded|, define the strings, but with another value,
-% define strings only if the current label or font encoding is the
-% value of |strings|; otherwise (ie, no |strings| or a block whose
-% label is not in |strings=|) do nothing.
+% \subsection{Layout}
 %
-% We presume the current block is not loaded, and therefore set
-% (above) a couple of default values to gobble the arguments. Then,
-% these macros are redefined if necessary according to several
-% parameters.
+% Layout is mainly intended to set bidi documents, but there is at
+% least a tool useful in general.
 %
 %    \begin{macrocode}
-\newcommand\bbl@startcmds@ii[1][\@empty]{%
-  \let\SetString\@gobbletwo
-  \let\bbl@stringdef\@gobbletwo
-  \let\AfterBabelCommands\@gobble
-  \ifx\@empty#1%
-    \def\bbl@sc@label{generic}%
-    \def\bbl@encstring##1##2{%
-      \ProvideTextCommandDefault##1{##2}%
-      \bbl@toglobal##1%
-      \expandafter\bbl@toglobal\csname\string?\string##1\endcsname}%
-    \let\bbl@sctest\in@true
-  \else
-    \let\bbl@sc@charset\space % <- zapped below
-    \let\bbl@sc@fontenc\space % <-   "      "
-    \def\bbl@tempa##1=##2\@nil{%
-      \bbl@csarg\edef{sc@\zap@space##1 \@empty}{##2 }}%
-    \bbl@vforeach{label=#1}{\bbl@tempa##1\@nil}%
-    \def\bbl@tempa##1 ##2{% space -> comma
-      ##1%
-      \ifx\@empty##2\else\ifx,##1,\else,\fi\bbl@afterfi\bbl@tempa##2\fi}%
-    \edef\bbl@sc@fontenc{\expandafter\bbl@tempa\bbl@sc@fontenc\@empty}%
-    \edef\bbl@sc@label{\expandafter\zap@space\bbl@sc@label\@empty}%
-    \edef\bbl@sc@charset{\expandafter\zap@space\bbl@sc@charset\@empty}%
-    \def\bbl@encstring##1##2{%
-      \bbl@foreach\bbl@sc@fontenc{%
-        \bbl@ifunset{T@####1}%
-          {}%
-          {\ProvideTextCommand##1{####1}{##2}%
-           \bbl@toglobal##1%
-           \expandafter
-           \bbl@toglobal\csname####1\string##1\endcsname}}}%
-    \def\bbl@sctest{%
-      \bbl@xin@{,\bbl@opt@strings,}{,\bbl@sc@label,\bbl@sc@fontenc,}}%
-  \fi
-  \ifx\bbl@opt@strings\@nnil         % ie, no strings key -> defaults
-  \else\ifx\bbl@opt@strings\relax    % ie, strings=encoded
-    \let\AfterBabelCommands\bbl@aftercmds
-    \let\SetString\bbl@setstring
-    \let\bbl@stringdef\bbl@encstring
-  \else       % ie, strings=value
-  \bbl@sctest
-  \ifin@
-    \let\AfterBabelCommands\bbl@aftercmds
-    \let\SetString\bbl@setstring
-    \let\bbl@stringdef\bbl@provstring
-  \fi\fi\fi
-  \bbl@scswitch
-  \ifx\bbl@G\@empty
-    \def\SetString##1##2{%
-      \bbl@error{Missing group for string \string##1}%
-        {You must assign strings to some category, typically\\%
-         captions or extras, but you set none}}%
-  \fi
-  \ifx\@empty#1%
-    \bbl@usehooks{defaultcommands}{}%
-  \else
-    \@expandtwoargs
-    \bbl@usehooks{encodedcommands}{{\bbl@sc@charset}{\bbl@sc@fontenc}}%
-  \fi}
-%    \end{macrocode}
-%
-% There are two versions of |\bbl@scswitch|. The first version is used
-% when |ldf|s are read, and it makes sure |\|\m{group}\m{language} is
-% reset, but only once (|\bbl@screset| is used to keep track of this).
-% The second version is used in the preamble and packages loaded after
-% \babel{} and does nothing.
-%
-% The macro |\bbl@forlang| loops |\bbl@L| but its body is executed only
-% if the value is in |\BabelLanguages| (inside \babel) or
-% |\date|\m{language} is defined (after \babel{} has been loaded).
-% There are also two version of |\bbl@forlang|. The first one skips the
-% current iteration if the language is not in |\BabelLanguages| (used
-% in |ldf|s), and the second one skips undefined languages (after
-% \babel{} has been loaded) .
-%
-%   \begin{macrocode}
-\def\bbl@forlang#1#2{%
-  \bbl@for#1\bbl@L{%
-    \bbl@xin@{,#1,}{,\BabelLanguages,}%
-    \ifin@#2\relax\fi}}
-\def\bbl@scswitch{%
-  \bbl@forlang\bbl@tempa{%
-    \ifx\bbl@G\@empty\else
-      \ifx\SetString\@gobbletwo\else
-        \edef\bbl@GL{\bbl@G\bbl@tempa}%
-        \bbl@xin@{,\bbl@GL,}{,\bbl@screset,}%
-        \ifin@\else
-          \global\expandafter\let\csname\bbl@GL\endcsname\@undefined
-          \xdef\bbl@screset{\bbl@screset,\bbl@GL}%
-        \fi
-      \fi
-    \fi}}
-\AtEndOfPackage{%
-  \def\bbl@forlang#1#2{\bbl@for#1\bbl@L{\bbl@ifunset{date#1}{}{#2}}}%
-  \let\bbl@scswitch\relax}
-\@onlypreamble\EndBabelCommands
-\def\EndBabelCommands{%
-  \bbl@usehooks{stopcommands}{}%
-  \endgroup
-  \endgroup
-  \bbl@scafter}
-\let\bbl@endcommands\EndBabelCommands
-%    \end{macrocode}
-%
-% Now we define commands to be used inside |\StartBabelCommands|.
-%
-% \paragraph{Strings} The following macro is the actual definition
-% of |\SetString| when it is ``active''
-%
-% First save the ``switcher''. Create it if undefined. Strings are
-% defined only if undefined (ie, like |\providescommmand|). With
-% the event |stringprocess| you can preprocess the string by
-% manipulating the value of |\BabelString|. If there are several
-% hooks assigned to this event, preprocessing is done in the same
-% order as defined.  Finally, the string is set.
-%
-%    \begin{macrocode}
-\def\bbl@setstring#1#2{% eg, \prefacename{<string>}
-  \bbl@forlang\bbl@tempa{%
-    \edef\bbl@LC{\bbl@tempa\bbl@stripslash#1}%
-    \bbl@ifunset{\bbl@LC}% eg, \germanchaptername
-      {\bbl@exp{%
-         \global\\\bbl@add\<\bbl@G\bbl@tempa>{\\\bbl@scset\\#1\<\bbl@LC>}}}%
-      {}%
-    \def\BabelString{#2}%
-    \bbl@usehooks{stringprocess}{}%
-    \expandafter\bbl@stringdef
-      \csname\bbl@LC\expandafter\endcsname\expandafter{\BabelString}}}
+\bbl@trace{Bidi layout}
+\providecommand\IfBabelLayout[3]{#3}%
+\newcommand\BabelPatchSection[1]{%
+  \@ifundefined{#1}{}{%
+    \bbl@exp{\let\<bbl@ss@#1>\<#1>}%
+    \@namedef{#1}{%
+      \@ifstar{\bbl@presec@s{#1}}%
+              {\@dblarg{\bbl@presec@x{#1}}}}}}
+\def\bbl@presec@x#1[#2]#3{%
+  \bbl@exp{%
+    \\\select@language@x{\bbl@main@language}%
+    \\\bbl@cs{sspre@#1}%
+    \\\bbl@cs{ss@#1}%
+      [\\\foreignlanguage{\languagename}{\unexpanded{#2}}]%
+      {\\\foreignlanguage{\languagename}{\unexpanded{#3}}}%
+    \\\select@language@x{\languagename}}}
+\def\bbl@presec@s#1#2{%
+  \bbl@exp{%
+    \\\select@language@x{\bbl@main@language}%
+    \\\bbl@cs{sspre@#1}%
+    \\\bbl@cs{ss@#1}*%
+      {\\\foreignlanguage{\languagename}{\unexpanded{#2}}}%
+    \\\select@language@x{\languagename}}}
+\IfBabelLayout{sectioning}%
+  {\BabelPatchSection{part}%
+   \BabelPatchSection{chapter}%
+   \BabelPatchSection{section}%
+   \BabelPatchSection{subsection}%
+   \BabelPatchSection{subsubsection}%
+   \BabelPatchSection{paragraph}%
+   \BabelPatchSection{subparagraph}%
+   \def\babel@toc#1{%
+     \select@language@x{\bbl@main@language}}}{}
+\IfBabelLayout{captions}%
+  {\BabelPatchSection{caption}}{}
 %    \end{macrocode}
 %
-%     Now, some addtional stuff to be used when encoded strings are
-%     used. Captions then include |\bbl@encoded| for string to be
-%     expanded in case transformations. It is |\relax| by default, but
-%     in |\MakeUppercase| and |\MakeLowercase| its value is a modified
-%     expandable |\@changed@cmd|.
+% \subsection{Load engine specific macros}
 %
 %    \begin{macrocode}
-\ifx\bbl@opt@strings\relax
-  \def\bbl@scset#1#2{\def#1{\bbl@encoded#2}}
-  \bbl@patchuclc
-  \let\bbl@encoded\relax
-  \def\bbl@encoded@uclc#1{%
-    \@inmathwarn#1%
-    \expandafter\ifx\csname\cf@encoding\string#1\endcsname\relax
-      \expandafter\ifx\csname ?\string#1\endcsname\relax
-        \TextSymbolUnavailable#1%
-      \else
-        \csname ?\string#1\endcsname
-      \fi
-    \else
-      \csname\cf@encoding\string#1\endcsname
-    \fi}
-\else
-  \def\bbl@scset#1#2{\def#1{#2}}
+\bbl@trace{Input engine specific macros}
+\ifcase\bbl@engine
+  \input txtbabel.def
+\or
+  \input luababel.def
+\or
+  \input xebabel.def
 \fi
 %    \end{macrocode}
 %
-% Define |\SetStringLoop|, which is actually set inside
-% |\StartBabelCommands|. The current definition is somewhat complicated
-% because we need a count, but |\count@| is not under our control
-% (remember |\SetString| may call hooks). Instead of defining a
-% dedicated count, we just ``pre-expand'' its value.
-%
-%    \begin{macrocode}
-%<<*Macros local to BabelCommands>>
-\def\SetStringLoop##1##2{%
-    \def\bbl@templ####1{\expandafter\noexpand\csname##1\endcsname}%
-    \count@\z@
-    \bbl@loop\bbl@tempa{##2}{% empty items and spaces are ok
-      \advance\count@\@ne
-      \toks@\expandafter{\bbl@tempa}%
-      \bbl@exp{%
-        \\\SetString\bbl@templ{\romannumeral\count@}{\the\toks@}%
-        \count@=\the\count@\relax}}}%
-%<</Macros local to BabelCommands>>
-%    \end{macrocode}
-%
-% \paragraph{Delaying code} Now the definition of |\AfterBabelCommands|
-% when it is activated.
-%
-%    \begin{macrocode}
-\def\bbl@aftercmds#1{%
-  \toks@\expandafter{\bbl@scafter#1}%
-  \xdef\bbl@scafter{\the\toks@}}
-%    \end{macrocode}
-%
-% \paragraph{Case mapping}
-%
-% The command |\SetCase| provides a way to change the behavior of
-% |\MakeUppercase| and |\MakeLowercase|. |\bbl@tempa| is set by the
-% patched |\@uclclist| to the parsing command.
-%
-%    \begin{macrocode}
-%<<*Macros local to BabelCommands>>
-  \newcommand\SetCase[3][]{%
-    \bbl@patchuclc
-    \bbl@forlang\bbl@tempa{%
-      \expandafter\bbl@encstring
-        \csname\bbl@tempa @bbl@uclc\endcsname{\bbl@tempa##1}%
-      \expandafter\bbl@encstring
-        \csname\bbl@tempa @bbl@uc\endcsname{##2}%
-      \expandafter\bbl@encstring
-        \csname\bbl@tempa @bbl@lc\endcsname{##3}}}%
-%<</Macros local to BabelCommands>>
-%    \end{macrocode}
+% \subsection{Creating and modifying languages}
 %
-% Macros to deal with case mapping for hyphenation. To decide if the
-% document is monolingual or multilingual, we make a rough guess --
-% just see if there is a comma in the languages list, built in the
-% first pass of the package options.
+% |\babelprovide| is a general purpose tool for creating and modifying
+% languages. It creates the language infrastructure, and loads, if
+% requested, an |ini| file. It may be used in conjunction to previouly
+% loaded |ldf| files.
 %
 %    \begin{macrocode}
-%<<*Macros local to BabelCommands>>
-  \newcommand\SetHyphenMap[1]{%
-    \bbl@forlang\bbl@tempa{%
-      \expandafter\bbl@stringdef
-        \csname\bbl@tempa @bbl@hyphenmap\endcsname{##1}}}%
-%<</Macros local to BabelCommands>>
-%    \end{macrocode}
-%
-%   There are 3 helper macros which do most of the work for you.
-%
-%   \begin{macrocode}
-\newcommand\BabelLower[2]{% one to one.
-  \ifnum\lccode#1=#2\else
-    \babel@savevariable{\lccode#1}%
-    \lccode#1=#2\relax
-  \fi}
-\newcommand\BabelLowerMM[4]{% many-to-many
-  \@tempcnta=#1\relax
-  \@tempcntb=#4\relax
-  \def\bbl@tempa{%
-    \ifnum\@tempcnta>#2\else
-      \@expandtwoargs\BabelLower{\the\@tempcnta}{\the\@tempcntb}%
-      \advance\@tempcnta#3\relax
-      \advance\@tempcntb#3\relax
-      \expandafter\bbl@tempa
-    \fi}%
-  \bbl@tempa}
-\newcommand\BabelLowerMO[4]{% many-to-one
-  \@tempcnta=#1\relax
-  \def\bbl@tempa{%
-    \ifnum\@tempcnta>#2\else
-      \@expandtwoargs\BabelLower{\the\@tempcnta}{#4}%
-      \advance\@tempcnta#3
-      \expandafter\bbl@tempa
+\bbl@trace{Creating languages and reading ini files}
+\let\bbl@extend@ini\@gobble
+\newcommand\babelprovide[2][]{%
+  \let\bbl@savelangname\languagename
+  \edef\bbl@savelocaleid{\the\localeid}%
+  % Set name and locale id
+  \edef\languagename{#2}%
+  \bbl@id@assign
+  % Initialize keys
+  \let\bbl@KVP@captions\@nil
+  \let\bbl@KVP@date\@nil
+  \let\bbl@KVP@import\@nil
+  \let\bbl@KVP@main\@nil
+  \let\bbl@KVP@script\@nil
+  \let\bbl@KVP@language\@nil
+  \let\bbl@KVP@hyphenrules\@nil
+  \let\bbl@KVP@linebreaking\@nil
+  \let\bbl@KVP@justification\@nil
+  \let\bbl@KVP@mapfont\@nil
+  \let\bbl@KVP@maparabic\@nil
+  \let\bbl@KVP@mapdigits\@nil
+  \let\bbl@KVP@intraspace\@nil
+  \let\bbl@KVP@intrapenalty\@nil
+  \let\bbl@KVP@onchar\@nil
+  \let\bbl@KVP@transforms\@nil
+  \global\let\bbl@release@transforms\@empty
+  \let\bbl@KVP@alph\@nil
+  \let\bbl@KVP@Alph\@nil
+  \let\bbl@KVP@labels\@nil
+  \bbl@csarg\let{KVP@labels*}\@nil
+  \global\let\bbl@inidata\@empty
+  \global\let\bbl@extend@ini\@gobble
+  \gdef\bbl@key@list{;}% 
+  \bbl@forkv{#1}{%  TODO - error handling
+    \in@{/}{##1}%
+    \ifin@
+      \global\let\bbl@extend@ini\bbl@extend@ini@aux
+      \bbl@renewinikey##1\@@{##2}%
+    \else
+      \bbl@csarg\def{KVP@##1}{##2}%
     \fi}%
-  \bbl@tempa}
-%    \end{macrocode}
-%
-% The following package options control the behavior of
-% hyphenation mapping.
-%
-%    \begin{macrocode}
-%<<*More package options>>
-\DeclareOption{hyphenmap=off}{\chardef\bbl@opt@hyphenmap\z@}
-\DeclareOption{hyphenmap=first}{\chardef\bbl@opt@hyphenmap\@ne}
-\DeclareOption{hyphenmap=select}{\chardef\bbl@opt@hyphenmap\tw@}
-\DeclareOption{hyphenmap=other}{\chardef\bbl@opt@hyphenmap\thr@@}
-\DeclareOption{hyphenmap=other*}{\chardef\bbl@opt@hyphenmap4\relax}
-%<</More package options>>
-%    \end{macrocode}
-%
-%    Initial setup to provide a default behavior if |hypenmap|
-%    is not set.
-%
-%    \begin{macrocode}
-\AtEndOfPackage{%
-  \ifx\bbl@opt@hyphenmap\@undefined
-    \bbl@xin@{,}{\bbl@language@opts}%
-    \chardef\bbl@opt@hyphenmap\ifin@4\else\@ne\fi
-  \fi}
-%    \end{macrocode}
-%
-% This sections ends with a general tool for resetting the caption
-% names with a unique interface. With the old way, which mixes the
-% switcher and the string, we convert it to the new one, which
-% separates these two steps.
-%
-%    \begin{macrocode}
-\newcommand\setlocalecaption{%  TODO. Catch typos. What about ensure?
-  \@ifstar\bbl@setcaption@s\bbl@setcaption@x}
-\def\bbl@setcaption@x#1#2#3{%  language caption-name string
-  \bbl@trim@def\bbl@tempa{#2}%
-  \bbl@xin@{.template}{\bbl@tempa}%
-  \ifin@
-    \bbl@ini@captions@template{#3}{#1}%
+  \chardef\bbl@howloaded=% 0:none; 1:ldf without ini; 2:ini
+    \bbl@ifunset{date#2}\z@{\bbl@ifunset{bbl@llevel@#2}\@ne\tw@}%
+  % == init ==
+  \ifx\bbl@screset\@undefined
+    \bbl@ldfinit
+  \fi
+  % ==
+  \let\bbl@lbkflag\relax % \@empty = do setup linebreak
+  \ifcase\bbl@howloaded
+    \let\bbl@lbkflag\@empty % new
   \else
-    \edef\bbl@tempd{%
-      \expandafter\expandafter\expandafter
-      \strip@prefix\expandafter\meaning\csname captions#1\endcsname}%
-    \bbl@xin@
-      {\expandafter\string\csname #2name\endcsname}%
-      {\bbl@tempd}%
-    \ifin@ % Renew caption
-      \bbl@xin@{\string\bbl@scset}{\bbl@tempd}% 
-      \ifin@
-        \bbl@exp{%
-          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
-            {\\\bbl@scset\<#2name>\<#1#2name>}%
-            {}}%
-      \else % Old way converts to new way
-        \bbl@ifunset{#1#2name}%
-          {\bbl@exp{%
-            \\\bbl@add\<captions#1>{\def\<#2name>{\<#1#2name>}}%
-            \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
-              {\def\<#2name>{\<#1#2name>}}%
-              {}}}%
-          {}%
-      \fi
-    \else
-      \bbl@xin@{\string\bbl@scset}{\bbl@tempd}% New
-      \ifin@ % New way
-        \bbl@exp{%
-          \\\bbl@add\<captions#1>{\\\bbl@scset\<#2name>\<#1#2name>}%
-          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
-            {\\\bbl@scset\<#2name>\<#1#2name>}%
-            {}}%
-      \else  % Old way, but defined in the new way
-        \bbl@exp{%
-          \\\bbl@add\<captions#1>{\def\<#2name>{\<#1#2name>}}%      
-          \\\bbl@ifsamestring{\bbl@tempa}{\languagename}%
-            {\def\<#2name>{\<#1#2name>}}%
-            {}}%
-      \fi%
+    \ifx\bbl@KVP@hyphenrules\@nil\else
+       \let\bbl@lbkflag\@empty
     \fi
-    \@namedef{#1#2name}{#3}%
-    \toks@\expandafter{\bbl@captionslist}%
-    \bbl@exp{\\\in@{\<#2name>}{\the\toks@}}%
-    \ifin@\else
-      \bbl@exp{\\\bbl@add\\\bbl@captionslist{\<#2name>}}%
-      \bbl@toglobal\bbl@captionslist
+    \ifx\bbl@KVP@import\@nil\else
+      \let\bbl@lbkflag\@empty
     \fi
-  \fi}
-% \def\bbl@setcaption@s#1#2#3{}  % TODO. Not yet implemented
-%    \end{macrocode}
-%
-% \subsection{Macros common to a number of languages}
-%
-%  \begin{macro}{\set@low@box}
-%
-% The following macro is used to lower quotes to the same level as
-% the comma.  It prepares its argument in box register~0.
-%
-%    \begin{macrocode}
-\bbl@trace{Macros related to glyphs}
-\def\set@low@box#1{\setbox\tw@\hbox{,}\setbox\z@\hbox{#1}%
-    \dimen\z@\ht\z@ \advance\dimen\z@ -\ht\tw@%
-    \setbox\z@\hbox{\lower\dimen\z@ \box\z@}\ht\z@\ht\tw@ \dp\z@\dp\tw@}
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-%  \begin{macro}{\save@sf@q}
-%    The macro |\save@sf@q| is used to save and reset the current
-%    space factor.
-%
-%    \begin{macrocode}
-\def\save@sf@q#1{\leavevmode
-  \begingroup
-    \edef\@SF{\spacefactor\the\spacefactor}#1\@SF
-  \endgroup}
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-% \subsection{Making glyphs available}
-%
-% This section makes a number of glyphs available that either do not
-% exist in the \texttt{OT1} encoding and have to be `faked', or
-% that are not accessible through \file{T1enc.def}.
-%
-% \subsubsection{Quotation marks}
-%
-%  \begin{macro}{\quotedblbase}
-% In the \texttt{T1} encoding the opening double quote at the
-% baseline is available as a separate character, accessible via
-% |\quotedblbase|. In the \texttt{OT1} encoding it is not
-% available, therefore we make it available by lowering the normal
-% open quote character to the baseline.
-%
-%    \begin{macrocode}
-\ProvideTextCommand{\quotedblbase}{OT1}{%
-  \save@sf@q{\set@low@box{\textquotedblright\/}%
-    \box\z@\kern-.04em\bbl@allowhyphens}}
-%    \end{macrocode}
-%
-% Make sure that when an encoding other than \texttt{OT1} or
-% \texttt{T1} is used this glyph can still be typeset.
-%
-%    \begin{macrocode}
-\ProvideTextCommandDefault{\quotedblbase}{%
-  \UseTextSymbol{OT1}{\quotedblbase}}
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-%  \begin{macro}{\quotesinglbase}
-%    We also need the single quote character at the baseline.
-%
-%    \begin{macrocode}
-\ProvideTextCommand{\quotesinglbase}{OT1}{%
-  \save@sf@q{\set@low@box{\textquoteright\/}%
-    \box\z@\kern-.04em\bbl@allowhyphens}}
-%    \end{macrocode}
-%
-%    Make sure that when an encoding other than \texttt{OT1} or
-%    \texttt{T1} is used this glyph can still be typeset.
-%
-%    \begin{macrocode}
-\ProvideTextCommandDefault{\quotesinglbase}{%
-  \UseTextSymbol{OT1}{\quotesinglbase}}
-%    \end{macrocode}
-%
-%  \end{macro}
-%
-%  \begin{macro}{\guillemetleft}
-%  \begin{macro}{\guillemetright}
-% The guillemet characters are not available in \texttt{OT1}
-% encoding. They are faked. (Wrong names with o preserved for
-% compatibility.)
-%
-%    \begin{macrocode}
-\ProvideTextCommand{\guillemetleft}{OT1}{%
-  \ifmmode
-    \ll
-  \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle\ll$}\bbl@allowhyphens}%
-  \fi}
-\ProvideTextCommand{\guillemetright}{OT1}{%
-  \ifmmode
-    \gg
-  \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle\gg$}\bbl@allowhyphens}%
-  \fi}
-\ProvideTextCommand{\guillemotleft}{OT1}{%
-  \ifmmode
-    \ll
-  \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle\ll$}\bbl@allowhyphens}%
-  \fi}
-\ProvideTextCommand{\guillemotright}{OT1}{%
-  \ifmmode
-    \gg
-  \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle\gg$}\bbl@allowhyphens}%
-  \fi}
-%    \end{macrocode}
-%
-% Make sure that when an encoding other than \texttt{OT1} or
-% \texttt{T1} is used these glyphs can still be typeset.
-%
-%    \begin{macrocode}
-\ProvideTextCommandDefault{\guillemetleft}{%
-  \UseTextSymbol{OT1}{\guillemetleft}}
-\ProvideTextCommandDefault{\guillemetright}{%
-  \UseTextSymbol{OT1}{\guillemetright}}
-\ProvideTextCommandDefault{\guillemotleft}{%
-  \UseTextSymbol{OT1}{\guillemotleft}}
-\ProvideTextCommandDefault{\guillemotright}{%
-  \UseTextSymbol{OT1}{\guillemotright}}
-%    \end{macrocode}
-%
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\guilsinglleft}
-%  \begin{macro}{\guilsinglright}
-%    The single guillemets are not available in \texttt{OT1}
-%    encoding. They are faked.
-%
-%    \begin{macrocode}
-\ProvideTextCommand{\guilsinglleft}{OT1}{%
-  \ifmmode
-    <%
-  \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle<$}\bbl@allowhyphens}%
-  \fi}
-\ProvideTextCommand{\guilsinglright}{OT1}{%
-  \ifmmode
-    >%
+  \fi
+  % == import, captions ==
+  \ifx\bbl@KVP@import\@nil\else
+    \bbl@exp{\\\bbl@ifblank{\bbl@KVP@import}}%
+      {\ifx\bbl@initoload\relax
+         \begingroup
+           \def\BabelBeforeIni##1##2{\gdef\bbl@KVP@import{##1}\endinput}%
+           \bbl@input@texini{#2}%
+         \endgroup
+       \else
+         \xdef\bbl@KVP@import{\bbl@initoload}%
+       \fi}%
+      {}%
+  \fi
+  \ifx\bbl@KVP@captions\@nil
+    \let\bbl@KVP@captions\bbl@KVP@import
+  \fi
+  % == 
+  \ifx\bbl@KVP@transforms\@nil\else
+    \bbl@replace\bbl@KVP@transforms{ }{,}%
+  \fi
+  % == Load ini ==
+  \ifcase\bbl@howloaded
+    \bbl@provide@new{#2}%
   \else
-    \save@sf@q{\nobreak
-      \raise.2ex\hbox{$\scriptscriptstyle>$}\bbl@allowhyphens}%
+    \bbl@ifblank{#1}%
+      {}%  With \bbl@load@basic below
+      {\bbl@provide@renew{#2}}%
+  \fi
+  % Post tasks
+  % ----------
+  % == subsequent calls after the first provide for a locale ==
+  \ifx\bbl@inidata\@empty\else
+    \bbl@extend@ini{#2}%
+  \fi
+  % == ensure captions ==
+  \ifx\bbl@KVP@captions\@nil\else
+    \bbl@ifunset{bbl@extracaps@#2}%
+      {\bbl@exp{\\\babelensure[exclude=\\\today]{#2}}}%
+      {\bbl@exp{\\\babelensure[exclude=\\\today,
+                include=\[bbl@extracaps@#2]}]{#2}}%
+    \bbl@ifunset{bbl@ensure@\languagename}%
+      {\bbl@exp{%
+        \\\DeclareRobustCommand\<bbl@ensure@\languagename>[1]{%
+          \\\foreignlanguage{\languagename}%
+          {####1}}}}%
+      {}%
+    \bbl@exp{%
+       \\\bbl@toglobal\<bbl@ensure@\languagename>%
+       \\\bbl@toglobal\<bbl@ensure@\languagename\space>}%
+  \fi
+  % ==
+  % At this point all parameters are defined if 'import'. Now we
+  % execute some code depending on them. But what about if nothing was
+  % imported? We just set the basic parameters, but still loading the
+  % whole ini file.
+  \bbl@load@basic{#2}%
+  % == script, language ==
+  % Override the values from ini or defines them
+  \ifx\bbl@KVP@script\@nil\else
+    \bbl@csarg\edef{sname@#2}{\bbl@KVP@script}%
+  \fi
+  \ifx\bbl@KVP@language\@nil\else
+    \bbl@csarg\edef{lname@#2}{\bbl@KVP@language}%
+  \fi
+   % == onchar ==
+  \ifx\bbl@KVP@onchar\@nil\else
+    \bbl@luahyphenate
+    \directlua{
+      if Babel.locale_mapped == nil then
+        Babel.locale_mapped = true
+        Babel.linebreaking.add_before(Babel.locale_map)
+        Babel.loc_to_scr = {}
+        Babel.chr_to_loc = Babel.chr_to_loc or {}
+      end}%
+    \bbl@xin@{ ids }{ \bbl@KVP@onchar\space}%
+    \ifin@
+      \ifx\bbl@starthyphens\@undefined % Needed if no explicit selection
+        \AddBabelHook{babel-onchar}{beforestart}{{\bbl@starthyphens}}%
+      \fi
+      \bbl@exp{\\\bbl@add\\\bbl@starthyphens
+        {\\\bbl@patterns@lua{\languagename}}}%
+      % TODO - error/warning if no script
+      \directlua{
+        if Babel.script_blocks['\bbl@cl{sbcp}'] then
+          Babel.loc_to_scr[\the\localeid] =
+            Babel.script_blocks['\bbl@cl{sbcp}']
+          Babel.locale_props[\the\localeid].lc = \the\localeid\space
+          Babel.locale_props[\the\localeid].lg = \the\@nameuse{l@\languagename}\space
+        end
+      }%
+    \fi
+    \bbl@xin@{ fonts }{ \bbl@KVP@onchar\space}%
+    \ifin@
+      \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
+      \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
+      \directlua{
+        if Babel.script_blocks['\bbl@cl{sbcp}'] then
+          Babel.loc_to_scr[\the\localeid] =
+            Babel.script_blocks['\bbl@cl{sbcp}']
+        end}%
+      \ifx\bbl@mapselect\@undefined  % TODO. almost the same as mapfont
+        \AtBeginDocument{%
+          \bbl@patchfont{{\bbl@mapselect}}%
+          {\selectfont}}%
+        \def\bbl@mapselect{%
+          \let\bbl@mapselect\relax
+          \edef\bbl@prefontid{\fontid\font}}%
+        \def\bbl@mapdir##1{%
+          {\def\languagename{##1}%
+           \let\bbl@ifrestoring\@firstoftwo % To avoid font warning
+           \bbl@switchfont
+           \directlua{
+             Babel.locale_props[\the\csname bbl@id@@##1\endcsname]%
+                     ['/\bbl@prefontid'] = \fontid\font\space}}}%
+      \fi
+      \bbl@exp{\\\bbl@add\\\bbl@mapselect{\\\bbl@mapdir{\languagename}}}%
+    \fi
+    % TODO - catch non-valid values
+  \fi
+  % == mapfont ==
+  % For bidi texts, to switch the font based on direction
+  \ifx\bbl@KVP@mapfont\@nil\else
+    \bbl@ifsamestring{\bbl@KVP@mapfont}{direction}{}%
+      {\bbl@error{Option '\bbl@KVP@mapfont' unknown for\\%
+                  mapfont. Use 'direction'.%
+                 {See the manual for details.}}}%
+    \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
+    \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
+    \ifx\bbl@mapselect\@undefined % TODO. See onchar.
+      \AtBeginDocument{%
+        \bbl@patchfont{{\bbl@mapselect}}%
+        {\selectfont}}%
+      \def\bbl@mapselect{%
+        \let\bbl@mapselect\relax
+        \edef\bbl@prefontid{\fontid\font}}%
+      \def\bbl@mapdir##1{%
+        {\def\languagename{##1}%
+         \let\bbl@ifrestoring\@firstoftwo % avoid font warning
+         \bbl@switchfont
+         \directlua{Babel.fontmap
+           [\the\csname bbl@wdir@##1\endcsname]%
+           [\bbl@prefontid]=\fontid\font}}}%
+    \fi
+    \bbl@exp{\\\bbl@add\\\bbl@mapselect{\\\bbl@mapdir{\languagename}}}%
+  \fi
+  % == Line breaking: intraspace, intrapenalty ==
+  % For CJK, East Asian, Southeast Asian, if interspace in ini
+  \ifx\bbl@KVP@intraspace\@nil\else % We can override the ini or set
+    \bbl@csarg\edef{intsp@#2}{\bbl@KVP@intraspace}%
+  \fi
+  \bbl@provide@intraspace
+  % == Line breaking: CJK quotes ==
+  \ifcase\bbl@engine\or
+    \bbl@xin@{/c}{/\bbl@cl{lnbrk}}%
+    \ifin@
+      \bbl@ifunset{bbl@quote@\languagename}{}%
+        {\directlua{
+           Babel.locale_props[\the\localeid].cjk_quotes = {}
+           local cs = 'op'
+           for c in string.utfvalues(%
+               [[\csname bbl@quote@\languagename\endcsname]]) do
+             if Babel.cjk_characters[c].c == 'qu' then
+               Babel.locale_props[\the\localeid].cjk_quotes[c] = cs
+             end
+             cs = ( cs == 'op') and 'cl' or 'op'
+           end
+        }}%
+    \fi
+  \fi
+  % == Line breaking: justification ==
+  \ifx\bbl@KVP@justification\@nil\else
+     \let\bbl@KVP@linebreaking\bbl@KVP@justification
+  \fi
+  \ifx\bbl@KVP@linebreaking\@nil\else
+    \bbl@xin@{,\bbl@KVP@linebreaking,}{,elongated,kashida,cjk,unhyphenated,}%
+    \ifin@
+      \bbl@csarg\xdef
+        {lnbrk@\languagename}{\expandafter\@car\bbl@KVP@linebreaking\@nil}%
+    \fi
+  \fi
+  \bbl@xin@{/e}{/\bbl@cl{lnbrk}}%
+  \ifin@\else\bbl@xin@{/k}{/\bbl@cl{lnbrk}}\fi
+  \ifin@\bbl@arabicjust\fi
+  % == Line breaking: hyphenate.other.(locale|script) ==
+  \ifx\bbl@lbkflag\@empty
+    \bbl@ifunset{bbl@hyotl@\languagename}{}%
+      {\bbl@csarg\bbl@replace{hyotl@\languagename}{ }{,}%
+       \bbl@startcommands*{\languagename}{}%
+         \bbl@csarg\bbl@foreach{hyotl@\languagename}{%
+           \ifcase\bbl@engine
+             \ifnum##1<257
+               \SetHyphenMap{\BabelLower{##1}{##1}}%
+             \fi
+           \else
+             \SetHyphenMap{\BabelLower{##1}{##1}}%
+           \fi}%
+       \bbl@endcommands}%
+    \bbl@ifunset{bbl@hyots@\languagename}{}%
+      {\bbl@csarg\bbl@replace{hyots@\languagename}{ }{,}%
+       \bbl@csarg\bbl@foreach{hyots@\languagename}{%
+         \ifcase\bbl@engine
+           \ifnum##1<257
+             \global\lccode##1=##1\relax
+           \fi
+         \else
+           \global\lccode##1=##1\relax
+         \fi}}%
+  \fi
+  % == Counters: maparabic ==
+  % Native digits, if provided in ini (TeX level, xe and lua)
+  \ifcase\bbl@engine\else
+    \bbl@ifunset{bbl@dgnat@\languagename}{}%
+      {\expandafter\ifx\csname bbl@dgnat@\languagename\endcsname\@empty\else
+        \expandafter\expandafter\expandafter
+        \bbl@setdigits\csname bbl@dgnat@\languagename\endcsname
+        \ifx\bbl@KVP@maparabic\@nil\else
+          \ifx\bbl@latinarabic\@undefined
+            \expandafter\let\expandafter\@arabic
+              \csname bbl@counter@\languagename\endcsname
+          \else    % ie, if layout=counters, which redefines \@arabic
+            \expandafter\let\expandafter\bbl@latinarabic
+              \csname bbl@counter@\languagename\endcsname
+          \fi
+        \fi
+      \fi}%
+  \fi
+  % == Counters: mapdigits ==
+  % Native digits (lua level).
+  \ifodd\bbl@engine
+    \ifx\bbl@KVP@mapdigits\@nil\else
+      \bbl@ifunset{bbl@dgnat@\languagename}{}%
+        {\RequirePackage{luatexbase}%
+         \bbl@activate@preotf
+         \directlua{
+           Babel = Babel or {}  %%% -> presets in luababel
+           Babel.digits_mapped = true
+           Babel.digits = Babel.digits or {}
+           Babel.digits[\the\localeid] =
+             table.pack(string.utfvalue('\bbl@cl{dgnat}'))
+           if not Babel.numbers then
+             function Babel.numbers(head)
+               local LOCALE = Babel.attr_locale
+               local GLYPH = node.id'glyph'
+               local inmath = false
+               for item in node.traverse(head) do
+                 if not inmath and item.id == GLYPH then
+                   local temp = node.get_attribute(item, LOCALE)
+                   if Babel.digits[temp] then
+                     local chr = item.char
+                     if chr > 47 and chr < 58 then
+                       item.char = Babel.digits[temp][chr-47]
+                     end
+                   end
+                 elseif item.id == node.id'math' then
+                   inmath = (item.subtype == 0)
+                 end
+               end
+               return head
+             end
+           end
+        }}%
+    \fi
+  \fi
+  % == Counters: alph, Alph ==
+  % What if extras<lang> contains a \babel@save\@alph? It won't be
+  % restored correctly when exiting the language, so we ignore 
+  % this change with the \bbl@alph@saved trick.
+  \ifx\bbl@KVP@alph\@nil\else
+    \bbl@extras@wrap{\\\bbl@alph@saved}%
+      {\let\bbl@alph@saved\@alph}%
+      {\let\@alph\bbl@alph@saved
+       \babel@save\@alph}%
+    \bbl@exp{%
+      \\\bbl@add\<extras\languagename>{%
+        \let\\\@alph\<bbl@cntr@\bbl@KVP@alph @\languagename>}}%
+  \fi
+  \ifx\bbl@KVP@Alph\@nil\else
+    \bbl@extras@wrap{\\\bbl@Alph@saved}%
+      {\let\bbl@Alph@saved\@Alph}%
+      {\let\@Alph\bbl@Alph@saved
+       \babel@save\@Alph}%
+    \bbl@exp{%
+      \\\bbl@add\<extras\languagename>{%
+        \let\\\@Alph\<bbl@cntr@\bbl@KVP@Alph @\languagename>}}%
+  \fi
+  % == require.babel in ini ==
+  % To load or reaload the babel-*.tex, if require.babel in ini
+  \ifx\bbl@beforestart\relax\else  % But not in doc aux or body
+    \bbl@ifunset{bbl@rqtex@\languagename}{}%
+      {\expandafter\ifx\csname bbl@rqtex@\languagename\endcsname\@empty\else
+         \let\BabelBeforeIni\@gobbletwo
+         \chardef\atcatcode=\catcode`\@
+         \catcode`\@=11\relax
+         \bbl@input@texini{\bbl@cs{rqtex@\languagename}}%
+         \catcode`\@=\atcatcode
+         \let\atcatcode\relax
+         \global\bbl@csarg\let{rqtex@\languagename}\relax
+       \fi}%
+  \fi
+  % == frenchspacing ==
+  \ifcase\bbl@howloaded\in@true\else\in@false\fi
+  \ifin@\else\bbl@xin@{typography/frenchspacing}{\bbl@key@list}\fi
+  \ifin@
+    \bbl@extras@wrap{\\\bbl@pre@fs}%
+      {\bbl@pre@fs}%
+      {\bbl@post@fs}%
+  \fi
+  % == Release saved transforms ==
+  \bbl@release@transforms\relax % \relax closes the last item.
+  % == main ==
+  \ifx\bbl@KVP@main\@nil  % Restore only if not 'main'
+    \let\languagename\bbl@savelangname
+    \chardef\localeid\bbl@savelocaleid\relax
   \fi}
 %    \end{macrocode}
 %
-% Make sure that when an encoding other than \texttt{OT1} or
-% \texttt{T1} is used these glyphs can still be typeset.
+% Depending on whether or not the language exists (based on
+% |\date<language>|), we define two macros. Remember
+% |\bbl@startcommands| opens a group.
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\guilsinglleft}{%
-  \UseTextSymbol{OT1}{\guilsinglleft}}
-\ProvideTextCommandDefault{\guilsinglright}{%
-  \UseTextSymbol{OT1}{\guilsinglright}}
-%    \end{macrocode}
-%
-%  \end{macro}
-%  \end{macro}
-%
-% \subsubsection{Letters}
-%
-%  \begin{macro}{\ij}
-%  \begin{macro}{\IJ}
-% The dutch language uses the letter `ij'. It is available in
-% \texttt{T1} encoded fonts, but not in the \texttt{OT1} encoded
-% fonts. Therefore we fake it for the \texttt{OT1} encoding.
+\def\bbl@provide@new#1{%
+  \@namedef{date#1}{}% marks lang exists - required by \StartBabelCommands
+  \@namedef{extras#1}{}%
+  \@namedef{noextras#1}{}%
+  \bbl@startcommands*{#1}{captions}%
+    \ifx\bbl@KVP@captions\@nil %      and also if import, implicit
+      \def\bbl@tempb##1{%             elt for \bbl@captionslist
+        \ifx##1\@empty\else
+          \bbl@exp{%
+            \\\SetString\\##1{%
+              \\\bbl@nocaption{\bbl@stripslash##1}{#1\bbl@stripslash##1}}}%
+          \expandafter\bbl@tempb
+        \fi}%
+      \expandafter\bbl@tempb\bbl@captionslist\@empty
+    \else
+      \ifx\bbl@initoload\relax
+        \bbl@read@ini{\bbl@KVP@captions}2%  % Here letters cat = 11
+      \else
+        \bbl@read@ini{\bbl@initoload}2%     % Same
+      \fi
+    \fi
+  \StartBabelCommands*{#1}{date}%
+    \ifx\bbl@KVP@import\@nil
+      \bbl@exp{%
+        \\\SetString\\\today{\\\bbl@nocaption{today}{#1today}}}%
+    \else
+      \bbl@savetoday
+      \bbl@savedate
+    \fi
+  \bbl@endcommands
+  \bbl@load@basic{#1}%
+  % == hyphenmins == (only if new)
+  \bbl@exp{%
+    \gdef\<#1hyphenmins>{%
+      {\bbl@ifunset{bbl@lfthm@#1}{2}{\bbl@cs{lfthm@#1}}}%
+      {\bbl@ifunset{bbl@rgthm@#1}{3}{\bbl@cs{rgthm@#1}}}}}%
+  % == hyphenrules (also in renew) == 
+  \bbl@provide@hyphens{#1}%
+  \ifx\bbl@KVP@main\@nil\else
+     \expandafter\main@language\expandafter{#1}%
+  \fi}
 %
-%    \begin{macrocode}
-\DeclareTextCommand{\ij}{OT1}{%
-  i\kern-0.02em\bbl@allowhyphens j}
-\DeclareTextCommand{\IJ}{OT1}{%
-  I\kern-0.02em\bbl@allowhyphens J}
-\DeclareTextCommand{\ij}{T1}{\char188}
-\DeclareTextCommand{\IJ}{T1}{\char156}
+\def\bbl@provide@renew#1{%
+  \ifx\bbl@KVP@captions\@nil\else
+    \StartBabelCommands*{#1}{captions}%
+      \bbl@read@ini{\bbl@KVP@captions}2%   % Here all letters cat = 11
+    \EndBabelCommands
+  \fi
+  \ifx\bbl@KVP@import\@nil\else
+    \StartBabelCommands*{#1}{date}%
+      \bbl@savetoday
+      \bbl@savedate
+    \EndBabelCommands
+  \fi
+  % == hyphenrules (also in new) ==
+  \ifx\bbl@lbkflag\@empty
+    \bbl@provide@hyphens{#1}%
+  \fi}
 %    \end{macrocode}
 %
-%    Make sure that when an encoding other than \texttt{OT1} or
-%    \texttt{T1} is used these glyphs can still be typeset.
+% Load the basic parameters (ids, typography, counters, and a few
+% more), while captions and dates are left out. But it may happen some
+% data has been loaded before automatically, so we first discard the
+% saved values. (TODO. But preserving previous values would be useful.)
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\ij}{%
-  \UseTextSymbol{OT1}{\ij}}
-\ProvideTextCommandDefault{\IJ}{%
-  \UseTextSymbol{OT1}{\IJ}}
+\def\bbl@load@basic#1{%
+  \ifcase\bbl@howloaded\or\or
+    \ifcase\csname bbl@llevel@\languagename\endcsname
+      \bbl@csarg\let{lname@\languagename}\relax
+    \fi
+  \fi
+  \bbl@ifunset{bbl@lname@#1}% 
+    {\def\BabelBeforeIni##1##2{%
+       \begingroup
+         \let\bbl@ini@captions@aux\@gobbletwo
+         \def\bbl@inidate ####1.####2.####3.####4\relax ####5####6{}%
+         \bbl@read@ini{##1}1%
+         \ifx\bbl@initoload\relax\endinput\fi
+       \endgroup}%
+     \begingroup       % boxed, to avoid extra spaces:
+       \ifx\bbl@initoload\relax
+         \bbl@input@texini{#1}%
+       \else
+         \setbox\z@\hbox{\BabelBeforeIni{\bbl@initoload}{}}%
+       \fi
+     \endgroup}%
+    {}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-% \begin{macro}{\dj}
-% \begin{macro}{\DJ}
-% The croatian language needs the letters |\dj| and |\DJ|; they are
-% available in the \texttt{T1} encoding, but not in the
-% \texttt{OT1} encoding by default.
-%
-% Some code to construct these glyphs for the \texttt{OT1} encoding
-% was made available to me by Stipčević Mario,
-% (\texttt{stipcevic@olimp.irb.hr}).
+% The |hyphenrules| option is handled with an auxiliary macro.
 %
 %    \begin{macrocode}
-\def\crrtic@{\hrule height0.1ex width0.3em}
-\def\crttic@{\hrule height0.1ex width0.33em}
-\def\ddj@{%
-  \setbox0\hbox{d}\dimen@=\ht0
-  \advance\dimen@1ex
-  \dimen@.45\dimen@
-  \dimen@ii\expandafter\rem@pt\the\fontdimen\@ne\font\dimen@
-  \advance\dimen@ii.5ex
-  \leavevmode\rlap{\raise\dimen@\hbox{\kern\dimen@ii\vbox{\crrtic@}}}}
-\def\DDJ@{%
-  \setbox0\hbox{D}\dimen@=.55\ht0
-  \dimen@ii\expandafter\rem@pt\the\fontdimen\@ne\font\dimen@
-  \advance\dimen@ii.15ex %            correction for the dash position
-  \advance\dimen@ii-.15\fontdimen7\font %     correction for cmtt font
-  \dimen\thr@@\expandafter\rem@pt\the\fontdimen7\font\dimen@
-  \leavevmode\rlap{\raise\dimen@\hbox{\kern\dimen@ii\vbox{\crttic@}}}}
-%
-\DeclareTextCommand{\dj}{OT1}{\ddj@ d}
-\DeclareTextCommand{\DJ}{OT1}{\DDJ@ D}
+\def\bbl@provide@hyphens#1{%
+  \let\bbl@tempa\relax
+  \ifx\bbl@KVP@hyphenrules\@nil\else
+    \bbl@replace\bbl@KVP@hyphenrules{ }{,}%
+    \bbl@foreach\bbl@KVP@hyphenrules{%
+      \ifx\bbl@tempa\relax    %  if not yet found
+        \bbl@ifsamestring{##1}{+}%
+          {{\bbl@exp{\\\addlanguage\<l@##1>}}}%
+          {}%
+        \bbl@ifunset{l@##1}%
+          {}%
+          {\bbl@exp{\let\bbl@tempa\<l@##1>}}%
+      \fi}%
+  \fi
+  \ifx\bbl@tempa\relax %         if no opt or no language in opt found
+    \ifx\bbl@KVP@import\@nil
+      \ifx\bbl@initoload\relax\else
+        \bbl@exp{%               and hyphenrules is not empty
+          \\\bbl@ifblank{\bbl@cs{hyphr@#1}}%
+            {}%
+            {\let\\\bbl@tempa\<l@\bbl@cl{hyphr}>}}%
+      \fi 
+    \else % if importing
+      \bbl@exp{%                    and hyphenrules is not empty
+        \\\bbl@ifblank{\bbl@cs{hyphr@#1}}%
+          {}%
+          {\let\\\bbl@tempa\<l@\bbl@cl{hyphr}>}}%
+    \fi
+  \fi
+  \bbl@ifunset{bbl@tempa}%       ie, relax or undefined
+    {\bbl@ifunset{l@#1}%         no hyphenrules found - fallback
+       {\bbl@exp{\\\adddialect\<l@#1>\language}}%
+       {}}%                      so, l@<lang> is ok - nothing to do
+    {\bbl@exp{\\\adddialect\<l@#1>\bbl@tempa}}}% found in opt list or ini
 %    \end{macrocode}
 %
-%    Make sure that when an encoding other than \texttt{OT1} or
-%    \texttt{T1} is used these glyphs can still be typeset.
+% The reader of |babel-...tex| files. We reset temporarily some
+% catcodes.
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\dj}{%
-  \UseTextSymbol{OT1}{\dj}}
-\ProvideTextCommandDefault{\DJ}{%
-  \UseTextSymbol{OT1}{\DJ}}
+\def\bbl@input@texini#1{%
+  \bbl@bsphack
+    \bbl@exp{%
+      \catcode`\\\%=14 \catcode`\\\\=0
+      \catcode`\\\{=1  \catcode`\\\}=2 
+      \lowercase{\\\InputIfFileExists{babel-#1.tex}{}{}}%
+      \catcode`\\\%=\the\catcode`\%\relax
+      \catcode`\\\\=\the\catcode`\\\relax
+      \catcode`\\\{=\the\catcode`\{\relax
+      \catcode`\\\}=\the\catcode`\}\relax}%
+  \bbl@esphack}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\SS}
-%    For the \texttt{T1} encoding |\SS| is defined and selects a
-%    specific glyph from the font, but for other encodings it is not
-%    available. Therefore we make it available here.
+% The following macros read and store |ini| files (but don't process
+% them). For each line, there are 3 possible actions: ignore if starts
+% with |;|, switch section if starts with |[|, and store otherwise.
+% There are used in the first step of |\bbl@read@ini|.
 %
 %    \begin{macrocode}
-\DeclareTextCommand{\SS}{OT1}{SS}
-\ProvideTextCommandDefault{\SS}{\UseTextSymbol{OT1}{\SS}}
+\def\bbl@iniline#1\bbl@iniline{%
+  \@ifnextchar[\bbl@inisect{\@ifnextchar;\bbl@iniskip\bbl@inistore}#1\@@}% ]
+\def\bbl@inisect[#1]#2\@@{\def\bbl@section{#1}} 
+\def\bbl@iniskip#1\@@{}%      if starts with ;
+\def\bbl@inistore#1=#2\@@{%      full (default)
+  \bbl@trim@def\bbl@tempa{#1}%
+  \bbl@trim\toks@{#2}%
+  \bbl@xin@{;\bbl@section/\bbl@tempa;}{\bbl@key@list}%
+  \ifin@\else
+    \bbl@exp{%
+      \\\g@addto@macro\\\bbl@inidata{%
+        \\\bbl@elt{\bbl@section}{\bbl@tempa}{\the\toks@}}}%
+  \fi}
+\def\bbl@inistore@min#1=#2\@@{%  minimal (maybe set in \bbl@read@ini)
+  \bbl@trim@def\bbl@tempa{#1}%
+  \bbl@trim\toks@{#2}%
+  \bbl@xin@{.identification.}{.\bbl@section.}%
+  \ifin@
+    \bbl@exp{\\\g@addto@macro\\\bbl@inidata{%
+      \\\bbl@elt{identification}{\bbl@tempa}{\the\toks@}}}%
+  \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% \subsubsection{Shorthands for quotation marks}
-%
-%    Shorthands are provided for a number of different quotation
-%    marks, which make them usable both outside and inside mathmode.
-%    They are defined with |\ProvideTextCommandDefault|, but this is
-%    very likely not required because their definitions are based on
-%    encoding-dependent macros.
+% Now, the ‘main loop’, which \textbf{**must be executed inside a
+% group**}. At this point, |\bbl@inidata| may contain data declared in
+% |\babelprovide|, with ‘slashed’ keys. There are 3 steps: first read
+% the ini file and store it; then traverse the stored values, and
+% process some groups if required (date, captions, labels, counters);
+% finally, ‘export’ some values by defining global macros
+% (identification, typography, characters, numbers). The second
+% argument is 0 when called to read the minimal data for fonts; with
+% |\babelprovide| it's either 1 or 2.
 %
-%  \begin{macro}{\glq}
-%  \begin{macro}{\grq}
+%    \begin{macrocode}
+\ifx\bbl@readstream\@undefined
+  \csname newread\endcsname\bbl@readstream
+\fi
+\def\bbl@read@ini#1#2{%
+  \global\let\bbl@extend@ini\@gobble
+  \openin\bbl@readstream=babel-#1.ini
+  \ifeof\bbl@readstream
+    \bbl@error
+      {There is no ini file for the requested language\\%
+       (#1). Perhaps you misspelled it or your installation\\%
+       is not complete.}%
+      {Fix the name or reinstall babel.}%
+  \else
+    % == Store ini data in \bbl@inidata ==
+    \catcode`\[=12 \catcode`\]=12 \catcode`\==12 \catcode`\&=12
+    \catcode`\;=12 \catcode`\|=12 \catcode`\%=14 \catcode`\-=12
+    \bbl@info{Importing
+                \ifcase#2font and identification \or basic \fi
+                 data for \languagename\\%
+              from babel-#1.ini. Reported}%
+    \ifnum#2=\z@
+      \global\let\bbl@inidata\@empty
+      \let\bbl@inistore\bbl@inistore@min    % Remember it's local
+    \fi
+    \def\bbl@section{identification}%
+    \bbl@exp{\\\bbl@inistore tag.ini=#1\\\@@}%
+    \bbl@inistore load.level=#2\@@
+    \loop
+    \if T\ifeof\bbl@readstream F\fi T\relax % Trick, because inside \loop
+      \endlinechar\m@ne
+      \read\bbl@readstream to \bbl@line
+      \endlinechar`\^^M
+      \ifx\bbl@line\@empty\else
+        \expandafter\bbl@iniline\bbl@line\bbl@iniline
+      \fi
+    \repeat
+    % == Process stored data ==
+    \bbl@csarg\xdef{lini@\languagename}{#1}%
+    \bbl@read@ini@aux
+    % == 'Export' data ==
+    \bbl@ini@exports{#2}%
+    \global\bbl@csarg\let{inidata@\languagename}\bbl@inidata
+    \global\let\bbl@inidata\@empty
+    \bbl@exp{\\\bbl@add@list\\\bbl@ini@loaded{\languagename}}%
+    \bbl@toglobal\bbl@ini@loaded
+  \fi}
+\def\bbl@read@ini@aux{%
+  \let\bbl@savestrings\@empty
+  \let\bbl@savetoday\@empty
+  \let\bbl@savedate\@empty
+  \def\bbl@elt##1##2##3{%
+    \def\bbl@section{##1}%
+    \in@{=date.}{=##1}% Find a better place
+    \ifin@
+      \bbl@ini@calendar{##1}%
+    \fi
+    \bbl@ifunset{bbl@inikv@##1}{}%
+      {\csname bbl@inikv@##1\endcsname{##2}{##3}}}%
+  \bbl@inidata}
+%    \end{macrocode}
 %
-%    The `german' single quotes.
+% A variant to be used when the ini file has been already loaded,
+% because it's not the first |\babelprovide| for this language.
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\glq}{%
-  \textormath{\quotesinglbase}{\mbox{\quotesinglbase}}}
+\def\bbl@extend@ini@aux#1{%
+  \bbl@startcommands*{#1}{captions}%
+    % Activate captions/... and modify exports
+    \bbl@csarg\def{inikv@captions.licr}##1##2{%
+      \setlocalecaption{#1}{##1}{##2}}%
+    \def\bbl@inikv@captions##1##2{%
+      \bbl@ini@captions@aux{##1}{##2}}%
+    \def\bbl@stringdef##1##2{\gdef##1{##2}}% 
+    \def\bbl@exportkey##1##2##3{%
+      \bbl@ifunset{bbl@@kv@##2}{}%
+        {\expandafter\ifx\csname bbl@@kv@##2\endcsname\@empty\else
+           \bbl@exp{\global\let\<bbl@##1@\languagename>\<bbl@@kv@##2>}%
+         \fi}}%
+    % As with \bbl@read@ini, but with some changes
+    \bbl@read@ini@aux
+    \bbl@ini@exports\tw@
+    % Update inidata@lang by pretending the ini is read.
+    \def\bbl@elt##1##2##3{%
+      \def\bbl@section{##1}%
+      \bbl@iniline##2=##3\bbl@iniline}%
+    \csname bbl@inidata@#1\endcsname
+    \global\bbl@csarg\let{inidata@#1}\bbl@inidata
+  \StartBabelCommands*{#1}{date}% And from the import stuff
+    \def\bbl@stringdef##1##2{\gdef##1{##2}}%
+    \bbl@savetoday
+    \bbl@savedate
+  \bbl@endcommands}
 %    \end{macrocode}
 %
-%    The definition of |\grq| depends on the fontencoding. With
-%    \texttt{T1} encoding no extra kerning is needed.
+% A somewhat hackish tool to handle calendar sections. To be improved.
 %
 %    \begin{macrocode}
-\ProvideTextCommand{\grq}{T1}{%
-  \textormath{\kern\z@\textquoteleft}{\mbox{\textquoteleft}}}
-\ProvideTextCommand{\grq}{TU}{%
-  \textormath{\textquoteleft}{\mbox{\textquoteleft}}}
-\ProvideTextCommand{\grq}{OT1}{%
-  \save@sf@q{\kern-.0125em
-    \textormath{\textquoteleft}{\mbox{\textquoteleft}}%
-    \kern.07em\relax}}
-\ProvideTextCommandDefault{\grq}{\UseTextSymbol{OT1}\grq}
+\def\bbl@ini@calendar#1{%
+ \lowercase{\def\bbl@tempa{=#1=}}%
+ \bbl@replace\bbl@tempa{=date.gregorian}{}%
+ \bbl@replace\bbl@tempa{=date.}{}%
+ \in@{.licr=}{#1=}%
+ \ifin@
+   \ifcase\bbl@engine
+     \bbl@replace\bbl@tempa{.licr=}{}%
+   \else
+     \let\bbl@tempa\relax
+   \fi
+ \fi
+ \ifx\bbl@tempa\relax\else
+   \bbl@replace\bbl@tempa{=}{}%
+   \bbl@exp{%
+     \def\<bbl@inikv@#1>####1####2{% 
+       \\\bbl@inidate####1...\relax{####2}{\bbl@tempa}}}%
+ \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\glqq}
-%  \begin{macro}{\grqq}
-%
-%    The `german' double quotes.
+% A key with a slash in |\babelprovide| replaces the value in the |ini|
+% file (which is ignored altogether). The mechanism is simple (but
+% suboptimal): add the data to the |ini| one (at this point the |ini|
+% file has not yet been read), and define a dummy macro. When the |ini|
+% file is read, just skip the corresponding key and reset the macro (in
+% |\bbl@inistore| above).
+% 
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\glqq}{%
-  \textormath{\quotedblbase}{\mbox{\quotedblbase}}}
+\def\bbl@renewinikey#1/#2\@@#3{%
+  \edef\bbl@tempa{\zap@space #1 \@empty}%   section
+  \edef\bbl@tempb{\zap@space #2 \@empty}%   key
+  \bbl@trim\toks@{#3}%                      value
+  \bbl@exp{%
+    \edef\\\bbl@key@list{\bbl@key@list \bbl@tempa/\bbl@tempb;}%
+    \\\g@addto@macro\\\bbl@inidata{%
+       \\\bbl@elt{\bbl@tempa}{\bbl@tempb}{\the\toks@}}}}%
 %    \end{macrocode}
 %
-%    The definition of |\grqq| depends on the fontencoding. With
-%    \texttt{T1} encoding no extra kerning is needed.
+% The previous assignments are local, so we need to export them. If
+% the value is empty, we can provide a default value.
 %
 %    \begin{macrocode}
-\ProvideTextCommand{\grqq}{T1}{%
-  \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}}
-\ProvideTextCommand{\grqq}{TU}{%
-  \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}}
-\ProvideTextCommand{\grqq}{OT1}{%
-  \save@sf@q{\kern-.07em
-    \textormath{\textquotedblleft}{\mbox{\textquotedblleft}}%
-    \kern.07em\relax}}
-\ProvideTextCommandDefault{\grqq}{\UseTextSymbol{OT1}\grqq}
+\def\bbl@exportkey#1#2#3{%
+  \bbl@ifunset{bbl@@kv@#2}%
+    {\bbl@csarg\gdef{#1@\languagename}{#3}}%
+    {\expandafter\ifx\csname bbl@@kv@#2\endcsname\@empty
+       \bbl@csarg\gdef{#1@\languagename}{#3}%
+     \else
+       \bbl@exp{\global\let\<bbl@#1@\languagename>\<bbl@@kv@#2>}%
+     \fi}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\flq}
-%  \begin{macro}{\frq}
-%
-%    The `french' single guillemets.
+% Key-value pairs are treated differently depending on the section in
+% the |ini| file. The following macros are the readers for
+% |identification| and |typography|. Note |\bbl@ini@exports|
+% is called always (via |\bbl@inisec|), while |\bbl@after@ini| must be
+% called explicitly after |\bbl@read@ini| if necessary.
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\flq}{%
-  \textormath{\guilsinglleft}{\mbox{\guilsinglleft}}}
-\ProvideTextCommandDefault{\frq}{%
-  \textormath{\guilsinglright}{\mbox{\guilsinglright}}}
-%    \end{macrocode}
+\def\bbl@iniwarning#1{%
+  \bbl@ifunset{bbl@@kv@identification.warning#1}{}%
+    {\bbl@warning{%
+       From babel-\bbl@cs{lini@\languagename}.ini:\\%
+       \bbl@cs{@kv@identification.warning#1}\\%
+       Reported }}}
 %
-%  \end{macro}
-%  \end{macro}
+\let\bbl@release@transforms\@empty
 %
-%  \begin{macro}{\flqq}
-%  \begin{macro}{\frqq}
+\def\bbl@ini@exports#1{%
+  % Identification always exported
+  \bbl@iniwarning{}%
+  \ifcase\bbl@engine
+    \bbl@iniwarning{.pdflatex}%
+  \or
+    \bbl@iniwarning{.lualatex}%
+  \or
+    \bbl@iniwarning{.xelatex}%
+  \fi%
+  \bbl@exportkey{llevel}{identification.load.level}{}%
+  \bbl@exportkey{elname}{identification.name.english}{}%
+  \bbl@exp{\\\bbl@exportkey{lname}{identification.name.opentype}%
+    {\csname bbl@elname@\languagename\endcsname}}%
+  \bbl@exportkey{tbcp}{identification.tag.bcp47}{}%
+  \bbl@exportkey{lbcp}{identification.language.tag.bcp47}{}%
+  \bbl@exportkey{lotf}{identification.tag.opentype}{dflt}%
+  \bbl@exportkey{esname}{identification.script.name}{}%
+  \bbl@exp{\\\bbl@exportkey{sname}{identification.script.name.opentype}%
+    {\csname bbl@esname@\languagename\endcsname}}%
+  \bbl@exportkey{sbcp}{identification.script.tag.bcp47}{}%
+  \bbl@exportkey{sotf}{identification.script.tag.opentype}{DFLT}%
+  % Also maps bcp47 -> languagename
+  \ifbbl@bcptoname
+    \bbl@csarg\xdef{bcp@map@\bbl@cl{tbcp}}{\languagename}%
+  \fi
+  % Conditional
+  \ifnum#1>\z@         % 0 = only info, 1, 2 = basic, (re)new
+    \bbl@exportkey{lnbrk}{typography.linebreaking}{h}%
+    \bbl@exportkey{hyphr}{typography.hyphenrules}{}%
+    \bbl@exportkey{lfthm}{typography.lefthyphenmin}{2}%
+    \bbl@exportkey{rgthm}{typography.righthyphenmin}{3}%         
+    \bbl@exportkey{prehc}{typography.prehyphenchar}{}%
+    \bbl@exportkey{hyotl}{typography.hyphenate.other.locale}{}%
+    \bbl@exportkey{hyots}{typography.hyphenate.other.script}{}%
+    \bbl@exportkey{intsp}{typography.intraspace}{}%
+    \bbl@exportkey{frspc}{typography.frenchspacing}{u}%
+    \bbl@exportkey{chrng}{characters.ranges}{}%
+    \bbl@exportkey{quote}{characters.delimiters.quotes}{}%
+    \bbl@exportkey{dgnat}{numbers.digits.native}{}%
+    \ifnum#1=\tw@           % only (re)new
+      \bbl@exportkey{rqtex}{identification.require.babel}{}%
+      \bbl@toglobal\bbl@savetoday
+      \bbl@toglobal\bbl@savedate
+      \bbl@savestrings
+    \fi
+  \fi}
+%    \end{macrocode}
 %
-%    The `french' double guillemets.
+% A shared handler for key=val lines to be stored in
+% |\bbl@@kv@<section>.<key>|.
 %
 %    \begin{macrocode}
-\ProvideTextCommandDefault{\flqq}{%
-  \textormath{\guillemetleft}{\mbox{\guillemetleft}}}
-\ProvideTextCommandDefault{\frqq}{%
-  \textormath{\guillemetright}{\mbox{\guillemetright}}}
+\def\bbl@inikv#1#2{%     key=value
+  \toks@{#2}%            This hides #'s from ini values
+  \bbl@csarg\edef{@kv@\bbl@section.#1}{\the\toks@}}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-% \subsubsection{Umlauts and tremas}
-%
-%    The command |\"| needs to have a different effect for different
-%    languages. For German for instance, the `umlaut' should be
-%    positioned lower than the default position for placing it over
-%    the letters a, o, u, A, O and U. When placed over an e, i, E or I
-%    it can retain its normal position. For Dutch the same glyph is
-%    always placed in the lower position.
+% By default, the following sections are just read. Actions are taken
+% later.
 %
-%  \begin{macro}{\umlauthigh}
+%    \begin{macrocode}
+\let\bbl@inikv@identification\bbl@inikv
+\let\bbl@inikv@typography\bbl@inikv
+\let\bbl@inikv@characters\bbl@inikv
+\let\bbl@inikv@numbers\bbl@inikv
+%    \end{macrocode}
 %
-%  \begin{macro}{\umlautlow}
-%    To be able to provide both positions of |\"| we provide two
-%    commands to switch the positioning, the default will be
-%    |\umlauthigh| (the normal positioning).
+% Additive numerals require an additional definition. When |.1| is
+% found, two macros are defined -- the basic one, without |.1| called
+% by |\localenumeral|, and another one preserving the trailing |.1| for
+% the ‘units’. 
 %
 %    \begin{macrocode}
-\def\umlauthigh{%
-  \def\bbl@umlauta##1{\leavevmode\bgroup%
-      \expandafter\accent\csname\f@encoding dqpos\endcsname
-      ##1\bbl@allowhyphens\egroup}%
-  \let\bbl@umlaute\bbl@umlauta}
-\def\umlautlow{%
-  \def\bbl@umlauta{\protect\lower@umlaut}}
-\def\umlautelow{%
-  \def\bbl@umlaute{\protect\lower@umlaut}}
-\umlauthigh
+\def\bbl@inikv@counters#1#2{%
+  \bbl@ifsamestring{#1}{digits}%
+    {\bbl@error{The counter name 'digits' is reserved for mapping\\%
+                decimal digits}%
+               {Use another name.}}%
+    {}%
+  \def\bbl@tempc{#1}%
+  \bbl@trim@def{\bbl@tempb*}{#2}%
+  \in@{.1$}{#1$}%
+  \ifin@
+    \bbl@replace\bbl@tempc{.1}{}%
+    \bbl@csarg\protected@xdef{cntr@\bbl@tempc @\languagename}{%
+      \noexpand\bbl@alphnumeral{\bbl@tempc}}%
+  \fi
+  \in@{.F.}{#1}%
+  \ifin@\else\in@{.S.}{#1}\fi
+  \ifin@
+    \bbl@csarg\protected@xdef{cntr@#1@\languagename}{\bbl@tempb*}%
+  \else
+    \toks@{}% Required by \bbl@buildifcase, which returns \bbl@tempa
+    \expandafter\bbl@buildifcase\bbl@tempb* \\ % Space after \\
+    \bbl@csarg{\global\expandafter\let}{cntr@#1@\languagename}\bbl@tempa
+  \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%  \end{macro}
-%
-%  \begin{macro}{\lower@umlaut}
-%    The command |\lower@umlaut| is used to position the |\"| closer
-%    to the letter.
-%
-%    We want the umlaut character lowered, nearer to the letter. To do
-%    this we need an extra \meta{dimen} register.
+% Now |captions| and |captions.licr|, depending on the engine. And
+% below also for dates. They rely on a few auxiliary macros. It is
+% expected the ini file provides the complete set in Unicode and LICR,
+% in that order.
 %
 %    \begin{macrocode}
-\expandafter\ifx\csname U@D\endcsname\relax
-  \csname newdimen\endcsname\U@D
+\ifcase\bbl@engine
+  \bbl@csarg\def{inikv@captions.licr}#1#2{%
+    \bbl@ini@captions@aux{#1}{#2}}
+\else
+  \def\bbl@inikv@captions#1#2{%
+    \bbl@ini@captions@aux{#1}{#2}}
 \fi
 %    \end{macrocode}
 %
-%    The following code fools \TeX's \texttt{make\_accent} procedure
-%    about the current x-height of the font to force another placement
-%    of the umlaut character.
-%    First we have to save the current x-height of the font, because
-%    we'll change this font dimension and this is always done
-%    globally.
-%
-%    Then we compute the new x-height in such a way that the umlaut
-%    character is lowered to the base character.  The value of
-%    \texttt{.45ex} depends on the \MF\ parameters with which the
-%    fonts were built.  (Just try out, which value will look best.)
-%    If the new x-height is too low, it is not changed.
-%    Finally we call the |\accent| primitive, reset the old x-height
-%    and insert the base character in the argument.
+% The auxiliary macro for captions define |\<caption>name|.
 %
 %    \begin{macrocode}
-\def\lower@umlaut#1{%
-  \leavevmode\bgroup
-    \U@D 1ex%
-    {\setbox\z@\hbox{%
-      \expandafter\char\csname\f@encoding dqpos\endcsname}%
-      \dimen@ -.45ex\advance\dimen@\ht\z@
-      \ifdim 1ex<\dimen@ \fontdimen5\font\dimen@ \fi}%
-    \expandafter\accent\csname\f@encoding dqpos\endcsname
-    \fontdimen5\font\U@D #1%
-  \egroup}
+\def\bbl@ini@captions@template#1#2{% string language tempa=capt-name
+  \bbl@replace\bbl@tempa{.template}{}%
+  \def\bbl@toreplace{#1{}}%
+  \bbl@replace\bbl@toreplace{[ ]}{\nobreakspace{}}%
+  \bbl@replace\bbl@toreplace{[[}{\csname}%
+  \bbl@replace\bbl@toreplace{[}{\csname the}% 
+  \bbl@replace\bbl@toreplace{]]}{name\endcsname{}}%
+  \bbl@replace\bbl@toreplace{]}{\endcsname{}}% 
+  \bbl@xin@{,\bbl@tempa,}{,chapter,appendix,part,}%
+  \ifin@
+    \@nameuse{bbl@patch\bbl@tempa}%
+    \global\bbl@csarg\let{\bbl@tempa fmt@#2}\bbl@toreplace
+  \fi 
+  \bbl@xin@{,\bbl@tempa,}{,figure,table,}%
+  \ifin@
+    \toks@\expandafter{\bbl@toreplace}%
+    \bbl@exp{\gdef\<fnum@\bbl@tempa>{\the\toks@}}%
+  \fi}
+\def\bbl@ini@captions@aux#1#2{%
+  \bbl@trim@def\bbl@tempa{#1}%
+  \bbl@xin@{.template}{\bbl@tempa}%
+  \ifin@
+    \bbl@ini@captions@template{#2}\languagename
+  \else
+    \bbl@ifblank{#2}%
+      {\bbl@exp{%
+         \toks@{\\\bbl@nocaption{\bbl@tempa}{\languagename\bbl@tempa name}}}}%
+      {\bbl@trim\toks@{#2}}%
+    \bbl@exp{%
+      \\\bbl@add\\\bbl@savestrings{%
+        \\\SetString\<\bbl@tempa name>{\the\toks@}}}%
+    \toks@\expandafter{\bbl@captionslist}%
+    \bbl@exp{\\\in@{\<\bbl@tempa name>}{\the\toks@}}%
+    \ifin@\else
+      \bbl@exp{%
+        \\\bbl@add\<bbl@extracaps@\languagename>{\<\bbl@tempa name>}%
+        \\\bbl@toglobal\<bbl@extracaps@\languagename>}%
+    \fi
+  \fi}
 %    \end{macrocode}
 %
-%  \end{macro}
-%
-% For all vowels we declare |\"| to be a composite command which
-% uses |\bbl@umlauta| or |\bbl@umlaute| to position the umlaut
-% character. We need to be sure that these definitions override the
-% ones that are provided when the package \pkg{fontenc} with
-% option \Lopt{OT1} is used. Therefore these declarations are
-% postponed until the beginning of the document. Note these
-% definitions only apply to some languages, but
-% babel sets them for \textit{all} languages -- you may want to
-% redefine |\bbl@umlauta| and/or |\bbl@umlaute| for a language
-% in the corresponding |ldf| (using the babel switching mechanism,
-% of course).
-%
+% \textbf{Labels.} Captions must contain just strings, no
+% format at all, so there is new group in ini files. 
+% 
 %    \begin{macrocode}
-\AtBeginDocument{%
-  \DeclareTextCompositeCommand{\"}{OT1}{a}{\bbl@umlauta{a}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{e}{\bbl@umlaute{e}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{i}{\bbl@umlaute{\i}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{\i}{\bbl@umlaute{\i}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{o}{\bbl@umlauta{o}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{u}{\bbl@umlauta{u}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{A}{\bbl@umlauta{A}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{E}{\bbl@umlaute{E}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{I}{\bbl@umlaute{I}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{O}{\bbl@umlauta{O}}%
-  \DeclareTextCompositeCommand{\"}{OT1}{U}{\bbl@umlauta{U}}}
+\def\bbl@list@the{%
+  part,chapter,section,subsection,subsubsection,paragraph,%
+  subparagraph,enumi,enumii,enumiii,enumiv,equation,figure,%
+  table,page,footnote,mpfootnote,mpfn}
+\def\bbl@map@cnt#1{%  #1:roman,etc, // #2:enumi,etc
+  \bbl@ifunset{bbl@map@#1@\languagename}%
+    {\@nameuse{#1}}%
+    {\@nameuse{bbl@map@#1@\languagename}}}
+\def\bbl@inikv@labels#1#2{%
+  \in@{.map}{#1}%
+  \ifin@
+    \ifx\bbl@KVP@labels\@nil\else
+      \bbl@xin@{ map }{ \bbl@KVP@labels\space}%
+      \ifin@
+        \def\bbl@tempc{#1}%
+        \bbl@replace\bbl@tempc{.map}{}%
+        \in@{,#2,}{,arabic,roman,Roman,alph,Alph,fnsymbol,}%
+        \bbl@exp{%
+          \gdef\<bbl@map@\bbl@tempc @\languagename>%
+            {\ifin@\<#2>\else\\\localecounter{#2}\fi}}%
+        \bbl@foreach\bbl@list@the{%
+          \bbl@ifunset{the##1}{}%
+            {\bbl@exp{\let\\\bbl@tempd\<the##1>}%
+             \bbl@exp{%
+               \\\bbl@sreplace\<the##1>%
+                 {\<\bbl@tempc>{##1}}{\\\bbl@map@cnt{\bbl@tempc}{##1}}%
+               \\\bbl@sreplace\<the##1>%
+                 {\<\@empty @\bbl@tempc>\<c@##1>}{\\\bbl@map@cnt{\bbl@tempc}{##1}}}%
+             \expandafter\ifx\csname the##1\endcsname\bbl@tempd\else
+               \toks@\expandafter\expandafter\expandafter{%
+                 \csname the##1\endcsname}%
+               \expandafter\xdef\csname the##1\endcsname{{\the\toks@}}%
+             \fi}}%
+      \fi
+    \fi
+  %
+  \else
+    %
+    % The following code is still under study. You can test it and make
+    % suggestions. Eg, enumerate.2 = ([enumi]).([enumii]). It's
+    % language dependent.
+    \in@{enumerate.}{#1}%
+    \ifin@
+      \def\bbl@tempa{#1}%
+      \bbl@replace\bbl@tempa{enumerate.}{}%
+      \def\bbl@toreplace{#2}%
+      \bbl@replace\bbl@toreplace{[ ]}{\nobreakspace{}}%
+      \bbl@replace\bbl@toreplace{[}{\csname the}% 
+      \bbl@replace\bbl@toreplace{]}{\endcsname{}}% 
+      \toks@\expandafter{\bbl@toreplace}%
+      % TODO. Execute only once:
+      \bbl@exp{%
+        \\\bbl@add\<extras\languagename>{%
+          \\\babel@save\<labelenum\romannumeral\bbl@tempa>%
+          \def\<labelenum\romannumeral\bbl@tempa>{\the\toks@}}%
+        \\\bbl@toglobal\<extras\languagename>}%
+    \fi
+  \fi}
 %    \end{macrocode}
 %
-% Finally, make sure the default hyphenrules are defined (even if
-% empty). For internal use, another empty |\language| is defined.
-% Currently used in Amharic.
+% To show correctly some captions in a few languages, we need to patch
+% some internal macros, because the order is hardcoded. For example, in
+% Japanese the chapter number is surrounded by two string, while in
+% Hungarian is placed after. These replacement works in many classes,
+% but not all. Actually, the following lines are somewhat tentative.
 %
 %    \begin{macrocode}
-\ifx\l@english\@undefined
-  \chardef\l@english\z@
-\fi
-% The following is used to cancel rules in ini files (see Amharic).
-\ifx\l@unhyphenated\@undefined
-  \newlanguage\l@unhyphenated
+\def\bbl@chaptype{chapter}
+\ifx\@makechapterhead\@undefined
+  \let\bbl@patchchapter\relax
+\else\ifx\thechapter\@undefined
+  \let\bbl@patchchapter\relax
+\else\ifx\ps@headings\@undefined
+  \let\bbl@patchchapter\relax
+\else
+  \def\bbl@patchchapter{%
+    \global\let\bbl@patchchapter\relax
+    \gdef\bbl@chfmt{%
+      \bbl@ifunset{bbl@\bbl@chaptype fmt@\languagename}%
+        {\@chapapp\space\thechapter}
+        {\@nameuse{bbl@\bbl@chaptype fmt@\languagename}}}
+    \bbl@add\appendix{\def\bbl@chaptype{appendix}}% Not harmful, I hope
+    \bbl@sreplace\ps@headings{\@chapapp\ \thechapter}{\bbl@chfmt}%
+    \bbl@sreplace\chaptermark{\@chapapp\ \thechapter}{\bbl@chfmt}%
+    \bbl@sreplace\@makechapterhead{\@chapapp\space\thechapter}{\bbl@chfmt}%
+    \bbl@toglobal\appendix
+    \bbl@toglobal\ps@headings
+    \bbl@toglobal\chaptermark
+    \bbl@toglobal\@makechapterhead}
+  \let\bbl@patchappendix\bbl@patchchapter
+\fi\fi\fi
+\ifx\@part\@undefined
+  \let\bbl@patchpart\relax
+\else
+  \def\bbl@patchpart{%
+    \global\let\bbl@patchpart\relax
+    \gdef\bbl@partformat{%
+      \bbl@ifunset{bbl@partfmt@\languagename}%
+        {\partname\nobreakspace\thepart}
+        {\@nameuse{bbl@partfmt@\languagename}}}
+    \bbl@sreplace\@part{\partname\nobreakspace\thepart}{\bbl@partformat}%
+    \bbl@toglobal\@part}
 \fi
 %    \end{macrocode}
 %
-% \subsection{Layout}
-%
-% Layout is mainly intended to set bidi documents, but there is at
-% least a tool useful in general.
-%
-%    \begin{macrocode}
-\bbl@trace{Bidi layout}
-\providecommand\IfBabelLayout[3]{#3}%
-\newcommand\BabelPatchSection[1]{%
-  \@ifundefined{#1}{}{%
-    \bbl@exp{\let\<bbl@ss@#1>\<#1>}%
-    \@namedef{#1}{%
-      \@ifstar{\bbl@presec@s{#1}}%
-              {\@dblarg{\bbl@presec@x{#1}}}}}}
-\def\bbl@presec@x#1[#2]#3{%
-  \bbl@exp{%
-    \\\select@language@x{\bbl@main@language}%
-    \\\bbl@cs{sspre@#1}%
-    \\\bbl@cs{ss@#1}%
-      [\\\foreignlanguage{\languagename}{\unexpanded{#2}}]%
-      {\\\foreignlanguage{\languagename}{\unexpanded{#3}}}%
-    \\\select@language@x{\languagename}}}
-\def\bbl@presec@s#1#2{%
-  \bbl@exp{%
-    \\\select@language@x{\bbl@main@language}%
-    \\\bbl@cs{sspre@#1}%
-    \\\bbl@cs{ss@#1}*%
-      {\\\foreignlanguage{\languagename}{\unexpanded{#2}}}%
-    \\\select@language@x{\languagename}}}
-\IfBabelLayout{sectioning}%
-  {\BabelPatchSection{part}%
-   \BabelPatchSection{chapter}%
-   \BabelPatchSection{section}%
-   \BabelPatchSection{subsection}%
-   \BabelPatchSection{subsubsection}%
-   \BabelPatchSection{paragraph}%
-   \BabelPatchSection{subparagraph}%
-   \def\babel@toc#1{%
-     \select@language@x{\bbl@main@language}}}{}
-\IfBabelLayout{captions}%
-  {\BabelPatchSection{caption}}{}
-%    \end{macrocode}
-%
-% \subsection{Load engine specific macros}
+% \textbf{Date.} TODO. Document
 %
 %    \begin{macrocode}
-\bbl@trace{Input engine specific macros}
-\ifcase\bbl@engine
-  \input txtbabel.def
-\or
-  \input luababel.def
-\or
-  \input xebabel.def
-\fi
+% Arguments are _not_ protected.
+\let\bbl@calendar\@empty
+\DeclareRobustCommand\localedate[1][]{\bbl@localedate{#1}}
+\def\bbl@localedate#1#2#3#4{%
+  \begingroup
+    \ifx\@empty#1\@empty\else
+      \let\bbl@ld@calendar\@empty
+      \let\bbl@ld@variant\@empty
+      \edef\bbl@tempa{\zap@space#1 \@empty}%
+      \def\bbl@tempb##1=##2\@@{\@namedef{bbl@ld@##1}{##2}}%
+      \bbl@foreach\bbl@tempa{\bbl@tempb##1\@@}%
+      \edef\bbl@calendar{%
+        \bbl@ld@calendar
+        \ifx\bbl@ld@variant\@empty\else
+          .\bbl@ld@variant
+        \fi}%
+      \bbl@replace\bbl@calendar{gregorian}{}%
+    \fi
+    \bbl@cased
+      {\@nameuse{bbl@date@\languagename @\bbl@calendar}{#2}{#3}{#4}}%
+  \endgroup}
+% eg: 1=months, 2=wide, 3=1, 4=dummy, 5=value, 6=calendar
+\def\bbl@inidate#1.#2.#3.#4\relax#5#6{% TODO - ignore with 'captions'
+  \bbl@trim@def\bbl@tempa{#1.#2}%
+  \bbl@ifsamestring{\bbl@tempa}{months.wide}%      to savedate
+    {\bbl@trim@def\bbl@tempa{#3}%
+     \bbl@trim\toks@{#5}%
+     \@temptokena\expandafter{\bbl@savedate}%
+     \bbl@exp{%   Reverse order - in ini last wins
+       \def\\\bbl@savedate{%
+         \\\SetString\<month\romannumeral\bbl@tempa#6name>{\the\toks@}%
+         \the\@temptokena}}}%
+    {\bbl@ifsamestring{\bbl@tempa}{date.long}%     defined now
+      {\lowercase{\def\bbl@tempb{#6}}%
+       \bbl@trim@def\bbl@toreplace{#5}%
+       \bbl@TG@@date
+       \bbl@ifunset{bbl@date@\languagename @}%
+         {\bbl@exp{% TODO. Move to a better place.
+            \gdef\<\languagename date>{\\\protect\<\languagename date >}%
+            \gdef\<\languagename date >####1####2####3{%
+              \\\bbl@usedategrouptrue
+              \<bbl@ensure@\languagename>{%
+                \\\localedate{####1}{####2}{####3}}}%
+            \\\bbl@add\\\bbl@savetoday{%
+              \\\SetString\\\today{%
+                \<\languagename date>%
+                   {\\\the\year}{\\\the\month}{\\\the\day}}}}}%
+         {}%      
+       \global\bbl@csarg\let{date@\languagename @}\bbl@toreplace
+       \ifx\bbl@tempb\@empty\else
+         \global\bbl@csarg\let{date@\languagename @\bbl@tempb}\bbl@toreplace
+       \fi}%
+      {}}}
 %    \end{macrocode}
 %
-% \subsection{Creating and modifying languages}
-%
-% |\babelprovide| is a general purpose tool for creating and modifying
-% languages. It creates the language infrastructure, and loads, if
-% requested, an |ini| file. It may be used in conjunction to previouly
-% loaded |ldf| files.
+% \textbf{Dates} will require some macros for the basic formatting.
+% They may be redefined by language, so ``semi-public'' names (camel
+% case) are used. Oddly enough, the CLDR places particles like “de”
+% inconsistently in either in the date or in the month name. Note after
+% |\bbl@replace| |\toks@| contains the resulting string, which is used
+% by |\bbl@replace@finish@iii| (this implicit behavior doesn't seem a
+% good idea, but it’s efficient).
 %
 %    \begin{macrocode}
-\bbl@trace{Creating languages and reading ini files}
-\let\bbl@extend@ini\@gobble
-\newcommand\babelprovide[2][]{%
-  \let\bbl@savelangname\languagename
-  \edef\bbl@savelocaleid{\the\localeid}%
-  % Set name and locale id
-  \edef\languagename{#2}%
-  \bbl@id@assign
-  % Initialize keys
-  \let\bbl@KVP@captions\@nil
-  \let\bbl@KVP@date\@nil
-  \let\bbl@KVP@import\@nil
-  \let\bbl@KVP@main\@nil
-  \let\bbl@KVP@script\@nil
-  \let\bbl@KVP@language\@nil
-  \let\bbl@KVP@hyphenrules\@nil
-  \let\bbl@KVP@linebreaking\@nil
-  \let\bbl@KVP@justification\@nil
-  \let\bbl@KVP@mapfont\@nil
-  \let\bbl@KVP@maparabic\@nil
-  \let\bbl@KVP@mapdigits\@nil
-  \let\bbl@KVP@intraspace\@nil
-  \let\bbl@KVP@intrapenalty\@nil
-  \let\bbl@KVP@onchar\@nil
-  \let\bbl@KVP@transforms\@nil
-  \global\let\bbl@release@transforms\@empty
-  \let\bbl@KVP@alph\@nil
-  \let\bbl@KVP@Alph\@nil
-  \let\bbl@KVP@labels\@nil
-  \bbl@csarg\let{KVP@labels*}\@nil
-  \global\let\bbl@inidata\@empty
-  \global\let\bbl@extend@ini\@gobble
-  \gdef\bbl@key@list{;}% 
-  \bbl@forkv{#1}{%  TODO - error handling
-    \in@{/}{##1}%
-    \ifin@
-      \global\let\bbl@extend@ini\bbl@extend@ini@aux
-      \bbl@renewinikey##1\@@{##2}%
-    \else
-      \bbl@csarg\def{KVP@##1}{##2}%
-    \fi}%
-  \chardef\bbl@howloaded=% 0:none; 1:ldf without ini; 2:ini
-    \bbl@ifunset{date#2}\z@{\bbl@ifunset{bbl@llevel@#2}\@ne\tw@}%
-  % == init ==
-  \ifx\bbl@screset\@undefined
-    \bbl@ldfinit
-  \fi
-  % ==
-  \let\bbl@lbkflag\relax % \@empty = do setup linebreak
-  \ifcase\bbl@howloaded
-    \let\bbl@lbkflag\@empty % new
-  \else
-    \ifx\bbl@KVP@hyphenrules\@nil\else
-       \let\bbl@lbkflag\@empty
-    \fi
-    \ifx\bbl@KVP@import\@nil\else
-      \let\bbl@lbkflag\@empty
-    \fi
-  \fi
-  % == import, captions ==
-  \ifx\bbl@KVP@import\@nil\else
-    \bbl@exp{\\\bbl@ifblank{\bbl@KVP@import}}%
-      {\ifx\bbl@initoload\relax
-         \begingroup
-           \def\BabelBeforeIni##1##2{\gdef\bbl@KVP@import{##1}\endinput}%
-           \bbl@input@texini{#2}%
-         \endgroup
-       \else
-         \xdef\bbl@KVP@import{\bbl@initoload}%
-       \fi}%
-      {}%
-  \fi
-  \ifx\bbl@KVP@captions\@nil
-    \let\bbl@KVP@captions\bbl@KVP@import
-  \fi
-  % == 
-  \ifx\bbl@KVP@transforms\@nil\else
-    \bbl@replace\bbl@KVP@transforms{ }{,}%
-  \fi
-  % == Load ini ==
-  \ifcase\bbl@howloaded
-    \bbl@provide@new{#2}%
+\let\bbl@calendar\@empty
+\newcommand\BabelDateSpace{\nobreakspace}
+\newcommand\BabelDateDot{.\@}  % TODO. \let instead of repeating
+\newcommand\BabelDated[1]{{\number#1}}
+\newcommand\BabelDatedd[1]{{\ifnum#1<10 0\fi\number#1}}
+\newcommand\BabelDateM[1]{{\number#1}}
+\newcommand\BabelDateMM[1]{{\ifnum#1<10 0\fi\number#1}}
+\newcommand\BabelDateMMMM[1]{{%
+  \csname month\romannumeral#1\bbl@calendar name\endcsname}}%
+\newcommand\BabelDatey[1]{{\number#1}}%
+\newcommand\BabelDateyy[1]{{%
+  \ifnum#1<10 0\number#1 %
+  \else\ifnum#1<100 \number#1 %
+  \else\ifnum#1<1000 \expandafter\@gobble\number#1 %
+  \else\ifnum#1<10000 \expandafter\@gobbletwo\number#1 %
   \else
-    \bbl@ifblank{#1}%
-      {}%  With \bbl@load@basic below
-      {\bbl@provide@renew{#2}}%
-  \fi
-  % Post tasks
-  % ----------
-  % == subsequent calls after the first provide for a locale ==
-  \ifx\bbl@inidata\@empty\else
-    \bbl@extend@ini{#2}%
-  \fi
-  % == ensure captions ==
-  \ifx\bbl@KVP@captions\@nil\else
-    \bbl@ifunset{bbl@extracaps@#2}%
-      {\bbl@exp{\\\babelensure[exclude=\\\today]{#2}}}%
-      {\toks@\expandafter\expandafter\expandafter
-        {\csname bbl@extracaps@#2\endcsname}%
-       \bbl@exp{\\\babelensure[exclude=\\\today,include=\the\toks@}]{#2}}%
-    \bbl@ifunset{bbl@ensure@\languagename}%
-      {\bbl@exp{%
-        \\\DeclareRobustCommand\<bbl@ensure@\languagename>[1]{%
-          \\\foreignlanguage{\languagename}%
-          {####1}}}}%
-      {}%
-    \bbl@exp{%
-       \\\bbl@toglobal\<bbl@ensure@\languagename>%
-       \\\bbl@toglobal\<bbl@ensure@\languagename\space>}%
-  \fi
-  % ==
-  % At this point all parameters are defined if 'import'. Now we
-  % execute some code depending on them. But what about if nothing was
-  % imported? We just set the basic parameters, but still loading the
-  % whole ini file.
-  \bbl@load@basic{#2}%
-  % == script, language ==
-  % Override the values from ini or defines them
-  \ifx\bbl@KVP@script\@nil\else
-    \bbl@csarg\edef{sname@#2}{\bbl@KVP@script}%
-  \fi
-  \ifx\bbl@KVP@language\@nil\else
-    \bbl@csarg\edef{lname@#2}{\bbl@KVP@language}%
-  \fi
-   % == onchar ==
-  \ifx\bbl@KVP@onchar\@nil\else
-    \bbl@luahyphenate
-    \directlua{
-      if Babel.locale_mapped == nil then
-        Babel.locale_mapped = true
-        Babel.linebreaking.add_before(Babel.locale_map)
-        Babel.loc_to_scr = {}
-        Babel.chr_to_loc = Babel.chr_to_loc or {}
-      end}%
-    \bbl@xin@{ ids }{ \bbl@KVP@onchar\space}%
-    \ifin@
-      \ifx\bbl@starthyphens\@undefined % Needed if no explicit selection
-        \AddBabelHook{babel-onchar}{beforestart}{{\bbl@starthyphens}}%
-      \fi
-      \bbl@exp{\\\bbl@add\\\bbl@starthyphens
-        {\\\bbl@patterns@lua{\languagename}}}%
-      % TODO - error/warning if no script
-      \directlua{
-        if Babel.script_blocks['\bbl@cl{sbcp}'] then
-          Babel.loc_to_scr[\the\localeid] =
-            Babel.script_blocks['\bbl@cl{sbcp}']
-          Babel.locale_props[\the\localeid].lc = \the\localeid\space
-          Babel.locale_props[\the\localeid].lg = \the\@nameuse{l@\languagename}\space
-        end
-      }%
-    \fi
-    \bbl@xin@{ fonts }{ \bbl@KVP@onchar\space}%
-    \ifin@
-      \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
-      \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
+    \bbl@error
+      {Currently two-digit years are restricted to the\\
+       range 0-9999.}%
+      {There is little you can do. Sorry.}%
+  \fi\fi\fi\fi}}
+\newcommand\BabelDateyyyy[1]{{\number#1}} % TODO - add leading 0
+\def\bbl@replace@finish@iii#1{%
+  \bbl@exp{\def\\#1####1####2####3{\the\toks@}}}
+\def\bbl@TG@@date{%
+  \bbl@replace\bbl@toreplace{[ ]}{\BabelDateSpace{}}%
+  \bbl@replace\bbl@toreplace{[.]}{\BabelDateDot{}}%
+  \bbl@replace\bbl@toreplace{[d]}{\BabelDated{####3}}%
+  \bbl@replace\bbl@toreplace{[dd]}{\BabelDatedd{####3}}%
+  \bbl@replace\bbl@toreplace{[M]}{\BabelDateM{####2}}%
+  \bbl@replace\bbl@toreplace{[MM]}{\BabelDateMM{####2}}%
+  \bbl@replace\bbl@toreplace{[MMMM]}{\BabelDateMMMM{####2}}%
+  \bbl@replace\bbl@toreplace{[y]}{\BabelDatey{####1}}%
+  \bbl@replace\bbl@toreplace{[yy]}{\BabelDateyy{####1}}%
+  \bbl@replace\bbl@toreplace{[yyyy]}{\BabelDateyyyy{####1}}%
+  \bbl@replace\bbl@toreplace{[y|}{\bbl@datecntr[####1|}%
+  \bbl@replace\bbl@toreplace{[m|}{\bbl@datecntr[####2|}%
+  \bbl@replace\bbl@toreplace{[d|}{\bbl@datecntr[####3|}%
+  \bbl@replace@finish@iii\bbl@toreplace}
+\def\bbl@datecntr{\expandafter\bbl@xdatecntr\expandafter}
+\def\bbl@xdatecntr[#1|#2]{\localenumeral{#2}{#1}}
+%    \end{macrocode}
+%
+% \textbf{Transforms.}
+%
+%    \begin{macrocode}
+\let\bbl@release@transforms\@empty
+\@namedef{bbl@inikv@transforms.prehyphenation}{%
+  \bbl@transforms\babelprehyphenation}
+\@namedef{bbl@inikv@transforms.posthyphenation}{%
+  \bbl@transforms\babelposthyphenation}
+\def\bbl@transforms@aux#1#2#3,#4\relax{#1{#2}{#3}{#4}}
+\begingroup %  A hack. TODO. Don't require an specific order
+  \catcode`\%=12
+  \catcode`\&=14
+  \gdef\bbl@transforms#1#2#3{&%
+    \ifx\bbl@KVP@transforms\@nil\else
       \directlua{
-        if Babel.script_blocks['\bbl@cl{sbcp}'] then
-          Babel.loc_to_scr[\the\localeid] =
-            Babel.script_blocks['\bbl@cl{sbcp}']
-        end}%
-      \ifx\bbl@mapselect\@undefined  % TODO. almost the same as mapfont
-        \AtBeginDocument{%
-          \bbl@patchfont{{\bbl@mapselect}}%
-          {\selectfont}}%
-        \def\bbl@mapselect{%
-          \let\bbl@mapselect\relax
-          \edef\bbl@prefontid{\fontid\font}}%
-        \def\bbl@mapdir##1{%
-          {\def\languagename{##1}%
-           \let\bbl@ifrestoring\@firstoftwo % To avoid font warning
-           \bbl@switchfont
-           \directlua{
-             Babel.locale_props[\the\csname bbl@id@@##1\endcsname]%
-                     ['/\bbl@prefontid'] = \fontid\font\space}}}%
+         str = [==[#2]==]
+         str = str:gsub('%.%d+%.%d+$', '')
+         tex.print([[\def\string\babeltempa{]] .. str .. [[}]])
+      }&%
+      \bbl@xin@{,\babeltempa,}{,\bbl@KVP@transforms,}&%
+      \ifin@
+        \in@{.0$}{#2$}&%
+        \ifin@
+           \g@addto@macro\bbl@release@transforms{&%
+              \relax\bbl@transforms@aux#1{\languagename}{#3}}&%
+        \else
+           \g@addto@macro\bbl@release@transforms{, {#3}}&%
+        \fi
       \fi
-      \bbl@exp{\\\bbl@add\\\bbl@mapselect{\\\bbl@mapdir{\languagename}}}%
-    \fi
-    % TODO - catch non-valid values
-  \fi
-  % == mapfont ==
-  % For bidi texts, to switch the font based on direction
-  \ifx\bbl@KVP@mapfont\@nil\else
-    \bbl@ifsamestring{\bbl@KVP@mapfont}{direction}{}%
-      {\bbl@error{Option '\bbl@KVP@mapfont' unknown for\\%
-                  mapfont. Use 'direction'.%
-                 {See the manual for details.}}}%
-    \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
-    \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
-    \ifx\bbl@mapselect\@undefined % TODO. See onchar.
-      \AtBeginDocument{%
-        \bbl@patchfont{{\bbl@mapselect}}%
-        {\selectfont}}%
-      \def\bbl@mapselect{%
-        \let\bbl@mapselect\relax
-        \edef\bbl@prefontid{\fontid\font}}%
-      \def\bbl@mapdir##1{%
-        {\def\languagename{##1}%
-         \let\bbl@ifrestoring\@firstoftwo % avoid font warning
-         \bbl@switchfont
-         \directlua{Babel.fontmap
-           [\the\csname bbl@wdir@##1\endcsname]%
-           [\bbl@prefontid]=\fontid\font}}}%
-    \fi
-    \bbl@exp{\\\bbl@add\\\bbl@mapselect{\\\bbl@mapdir{\languagename}}}%
-  \fi
-  % == Line breaking: intraspace, intrapenalty ==
-  % For CJK, East Asian, Southeast Asian, if interspace in ini
-  \ifx\bbl@KVP@intraspace\@nil\else % We can override the ini or set
-    \bbl@csarg\edef{intsp@#2}{\bbl@KVP@intraspace}%
-  \fi
-  \bbl@provide@intraspace
-  % == Line breaking: CJK quotes ==
-  \ifcase\bbl@engine\or
-    \bbl@xin@{/c}{/\bbl@cl{lnbrk}}%
-    \ifin@
-      \bbl@ifunset{bbl@quote@\languagename}{}%
-        {\directlua{
-           Babel.locale_props[\the\localeid].cjk_quotes = {}
-           local cs = 'op'
-           for c in string.utfvalues(%
-               [[\csname bbl@quote@\languagename\endcsname]]) do
-             if Babel.cjk_characters[c].c == 'qu' then
-               Babel.locale_props[\the\localeid].cjk_quotes[c] = cs
-             end
-             cs = ( cs == 'op') and 'cl' or 'op'
-           end
-        }}%
-    \fi
-  \fi
-  % == Line breaking: justification ==
-  \ifx\bbl@KVP@justification\@nil\else
-     \let\bbl@KVP@linebreaking\bbl@KVP@justification
-  \fi
-  \ifx\bbl@KVP@linebreaking\@nil\else
-    \bbl@xin@{,\bbl@KVP@linebreaking,}{,elongated,kashida,cjk,unhyphenated,}%
-    \ifin@
-      \bbl@csarg\xdef
-        {lnbrk@\languagename}{\expandafter\@car\bbl@KVP@linebreaking\@nil}%
-    \fi
-  \fi
-  \bbl@xin@{/e}{/\bbl@cl{lnbrk}}%
-  \ifin@\else\bbl@xin@{/k}{/\bbl@cl{lnbrk}}\fi
-  \ifin@\bbl@arabicjust\fi
-  % == Line breaking: hyphenate.other.(locale|script) ==
-  \ifx\bbl@lbkflag\@empty
-    \bbl@ifunset{bbl@hyotl@\languagename}{}%
-      {\bbl@csarg\bbl@replace{hyotl@\languagename}{ }{,}%
-       \bbl@startcommands*{\languagename}{}%
-         \bbl@csarg\bbl@foreach{hyotl@\languagename}{%
-           \ifcase\bbl@engine
-             \ifnum##1<257
-               \SetHyphenMap{\BabelLower{##1}{##1}}%
-             \fi
-           \else
-             \SetHyphenMap{\BabelLower{##1}{##1}}%
-           \fi}%
-       \bbl@endcommands}%
-    \bbl@ifunset{bbl@hyots@\languagename}{}%
-      {\bbl@csarg\bbl@replace{hyots@\languagename}{ }{,}%
-       \bbl@csarg\bbl@foreach{hyots@\languagename}{%
-         \ifcase\bbl@engine
-           \ifnum##1<257
-             \global\lccode##1=##1\relax
+    \fi}
+\endgroup
+%    \end{macrocode}
+%
+% Language and Script values to be used when defining a font or
+% setting the direction are set with the following macros.
+%
+%    \begin{macrocode}
+\def\bbl@provide@lsys#1{%
+  \bbl@ifunset{bbl@lname@#1}%
+    {\bbl@load@info{#1}}%
+    {}%
+  \bbl@csarg\let{lsys@#1}\@empty
+  \bbl@ifunset{bbl@sname@#1}{\bbl@csarg\gdef{sname@#1}{Default}}{}%
+  \bbl@ifunset{bbl@sotf@#1}{\bbl@csarg\gdef{sotf@#1}{DFLT}}{}%
+  \bbl@csarg\bbl@add@list{lsys@#1}{Script=\bbl@cs{sname@#1}}%
+  \bbl@ifunset{bbl@lname@#1}{}%
+    {\bbl@csarg\bbl@add@list{lsys@#1}{Language=\bbl@cs{lname@#1}}}%
+  \ifcase\bbl@engine\or\or
+    \bbl@ifunset{bbl@prehc@#1}{}%
+      {\bbl@exp{\\\bbl@ifblank{\bbl@cs{prehc@#1}}}%
+        {}%
+        {\ifx\bbl@xenohyph\@undefined
+           \let\bbl@xenohyph\bbl@xenohyph@d
+           \ifx\AtBeginDocument\@notprerr
+             \expandafter\@secondoftwo  % to execute right now
            \fi
-         \else
-           \global\lccode##1=##1\relax
-         \fi}}%
-  \fi
-  % == Counters: maparabic ==
-  % Native digits, if provided in ini (TeX level, xe and lua)
-  \ifcase\bbl@engine\else
-    \bbl@ifunset{bbl@dgnat@\languagename}{}%
-      {\expandafter\ifx\csname bbl@dgnat@\languagename\endcsname\@empty\else
-        \expandafter\expandafter\expandafter
-        \bbl@setdigits\csname bbl@dgnat@\languagename\endcsname
-        \ifx\bbl@KVP@maparabic\@nil\else
-          \ifx\bbl@latinarabic\@undefined
-            \expandafter\let\expandafter\@arabic
-              \csname bbl@counter@\languagename\endcsname
-          \else    % ie, if layout=counters, which redefines \@arabic
-            \expandafter\let\expandafter\bbl@latinarabic
-              \csname bbl@counter@\languagename\endcsname
-          \fi
-        \fi
-      \fi}%
-  \fi
-  % == Counters: mapdigits ==
-  % Native digits (lua level).
-  \ifodd\bbl@engine
-    \ifx\bbl@KVP@mapdigits\@nil\else
-      \bbl@ifunset{bbl@dgnat@\languagename}{}%
-        {\RequirePackage{luatexbase}%
-         \bbl@activate@preotf
-         \directlua{
-           Babel = Babel or {}  %%% -> presets in luababel
-           Babel.digits_mapped = true
-           Babel.digits = Babel.digits or {}
-           Babel.digits[\the\localeid] =
-             table.pack(string.utfvalue('\bbl@cl{dgnat}'))
-           if not Babel.numbers then
-             function Babel.numbers(head)
-               local LOCALE = Babel.attr_locale
-               local GLYPH = node.id'glyph'
-               local inmath = false
-               for item in node.traverse(head) do
-                 if not inmath and item.id == GLYPH then
-                   local temp = node.get_attribute(item, LOCALE)
-                   if Babel.digits[temp] then
-                     local chr = item.char
-                     if chr > 47 and chr < 58 then
-                       item.char = Babel.digits[temp][chr-47]
-                     end
-                   end
-                 elseif item.id == node.id'math' then
-                   inmath = (item.subtype == 0)
-                 end
-               end
-               return head
-             end
-           end
-        }}%
-    \fi
-  \fi
-  % == Counters: alph, Alph ==
-  % What if extras<lang> contains a \babel@save\@alph? It won't be
-  % restored correctly when exiting the language, so we ignore 
-  % this change with the \bbl@alph@saved trick.
-  \ifx\bbl@KVP@alph\@nil\else
-    \bbl@extras@wrap{\\\bbl@alph@saved}%
-      {\let\bbl@alph@saved\@alph}%
-      {\let\@alph\bbl@alph@saved
-       \babel@save\@alph}%
-    \bbl@exp{%
-      \\\bbl@add\<extras\languagename>{%
-        \let\\\@alph\<bbl@cntr@\bbl@KVP@alph @\languagename>}}%
+           \AtBeginDocument{%
+             \bbl@patchfont{\bbl@xenohyph}%
+             \expandafter\selectlanguage\expandafter{\languagename}}%
+        \fi}}%
   \fi
-  \ifx\bbl@KVP@Alph\@nil\else
-    \bbl@extras@wrap{\\\bbl@Alph@saved}%
-      {\let\bbl@Alph@saved\@Alph}%
-      {\let\@Alph\bbl@Alph@saved
-       \babel@save\@Alph}%
+  \bbl@csarg\bbl@toglobal{lsys@#1}}
+\def\bbl@xenohyph@d{%
+  \bbl@ifset{bbl@prehc@\languagename}%
+    {\ifnum\hyphenchar\font=\defaulthyphenchar
+       \iffontchar\font\bbl@cl{prehc}\relax
+         \hyphenchar\font\bbl@cl{prehc}\relax
+       \else\iffontchar\font"200B
+         \hyphenchar\font"200B
+       \else
+         \bbl@warning
+           {Neither 0 nor ZERO WIDTH SPACE are available\\%
+            in the current font, and therefore the hyphen\\%
+            will be printed. Try changing the fontspec's\\%
+            'HyphenChar' to another value, but be aware\\%
+            this setting is not safe (see the manual)}%
+         \hyphenchar\font\defaulthyphenchar     
+       \fi\fi
+     \fi}%
+    {\hyphenchar\font\defaulthyphenchar}}
+  % \fi}
+%    \end{macrocode}
+%
+% The following |ini| reader ignores everything but the
+% |identification| section. It is called when a font is defined (ie,
+% when the language is first selected) to know which script/language
+% must be enabled. This means we must make sure a few characters are
+% not active. The |ini| is not read directly, but with a proxy |tex|
+% file named as the language (which means any code in it must be
+% skipped, too).
+%
+%    \begin{macrocode}
+\def\bbl@load@info#1{%
+  \def\BabelBeforeIni##1##2{%
+    \begingroup
+      \bbl@read@ini{##1}0%
+      \endinput          % babel- .tex may contain onlypreamble's
+    \endgroup}%            boxed, to avoid extra spaces:
+  {\bbl@input@texini{#1}}}
+%    \end{macrocode}
+%
+% A tool to define the macros for native digits from the list provided 
+% in the |ini| file. Somewhat convoluted because there are 10 digits, 
+% but only 9 arguments in \TeX. Non-digits characters are kept. The
+% first macro is the generic “localized” command.
+%
+%    \begin{macrocode}
+\def\bbl@setdigits#1#2#3#4#5{%
+  \bbl@exp{%
+    \def\<\languagename digits>####1{%       ie, \langdigits
+      \<bbl@digits@\languagename>####1\\\@nil}%
+    \let\<bbl@cntr@digits@\languagename>\<\languagename digits>%
+    \def\<\languagename counter>####1{%      ie, \langcounter
+      \\\expandafter\<bbl@counter@\languagename>%
+      \\\csname c@####1\endcsname}%
+    \def\<bbl@counter@\languagename>####1{% ie, \bbl@counter@lang
+      \\\expandafter\<bbl@digits@\languagename>%
+      \\\number####1\\\@nil}}%
+  \def\bbl@tempa##1##2##3##4##5{%
+    \bbl@exp{%    Wow, quite a lot of hashes! :-(
+      \def\<bbl@digits@\languagename>########1{%
+       \\\ifx########1\\\@nil              % ie, \bbl@digits@lang
+       \\\else
+         \\\ifx0########1#1%
+         \\\else\\\ifx1########1#2%
+         \\\else\\\ifx2########1#3%
+         \\\else\\\ifx3########1#4%
+         \\\else\\\ifx4########1#5%
+         \\\else\\\ifx5########1##1%
+         \\\else\\\ifx6########1##2%
+         \\\else\\\ifx7########1##3%
+         \\\else\\\ifx8########1##4%
+         \\\else\\\ifx9########1##5%
+         \\\else########1%
+         \\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi
+         \\\expandafter\<bbl@digits@\languagename>%
+       \\\fi}}}%
+  \bbl@tempa}
+%    \end{macrocode}
+%
+% Alphabetic counters must be converted from a space separated list to
+% an |\ifcase| structure.
+%
+%    \begin{macrocode}
+\def\bbl@buildifcase#1 {% Returns \bbl@tempa, requires \toks@={}
+  \ifx\\#1%             % \\ before, in case #1 is multiletter
     \bbl@exp{%
-      \\\bbl@add\<extras\languagename>{%
-        \let\\\@Alph\<bbl@cntr@\bbl@KVP@Alph @\languagename>}}%
+      \def\\\bbl@tempa####1{%
+        \<ifcase>####1\space\the\toks@\<else>\\\@ctrerr\<fi>}}%
+  \else
+    \toks@\expandafter{\the\toks@\or #1}%
+    \expandafter\bbl@buildifcase
+  \fi}
+%    \end{macrocode}
+%
+% The code for additive counters is somewhat tricky and it's based on
+% the fact the arguments just before |\@@| collects digits which have
+% been left ‘unused’ in previous arguments, the first of them being the
+% number of digits in the number to be converted. This explains the
+% reverse set |76543210|. Digits above 10000 are not handled yet. When
+% the key contains the subkey |.F.|, the number after is treated as an
+% special case, for a fixed form (see |babel-he.ini|, for example).
+%
+%    \begin{macrocode}
+\newcommand\localenumeral[2]{\bbl@cs{cntr@#1@\languagename}{#2}}
+\def\bbl@localecntr#1#2{\localenumeral{#2}{#1}}
+\newcommand\localecounter[2]{%
+  \expandafter\bbl@localecntr
+  \expandafter{\number\csname c@#2\endcsname}{#1}}
+\def\bbl@alphnumeral#1#2{%
+  \expandafter\bbl@alphnumeral@i\number#2 76543210\@@{#1}}
+\def\bbl@alphnumeral@i#1#2#3#4#5#6#7#8\@@#9{%
+  \ifcase\@car#8\@nil\or   % Currenty <10000, but prepared for bigger
+    \bbl@alphnumeral@ii{#9}000000#1\or
+    \bbl@alphnumeral@ii{#9}00000#1#2\or
+    \bbl@alphnumeral@ii{#9}0000#1#2#3\or
+    \bbl@alphnumeral@ii{#9}000#1#2#3#4\else
+    \bbl@alphnum@invalid{>9999}%
+  \fi}
+\def\bbl@alphnumeral@ii#1#2#3#4#5#6#7#8{%
+  \bbl@ifunset{bbl@cntr@#1.F.\number#5#6#7#8@\languagename}%
+    {\bbl@cs{cntr@#1.4@\languagename}#5%
+     \bbl@cs{cntr@#1.3@\languagename}#6%
+     \bbl@cs{cntr@#1.2@\languagename}#7%
+     \bbl@cs{cntr@#1.1@\languagename}#8%
+     \ifnum#6#7#8>\z@ % TODO. An ad hoc rule for Greek. Ugly.
+       \bbl@ifunset{bbl@cntr@#1.S.321@\languagename}{}%
+         {\bbl@cs{cntr@#1.S.321@\languagename}}%
+     \fi}%
+    {\bbl@cs{cntr@#1.F.\number#5#6#7#8@\languagename}}}
+\def\bbl@alphnum@invalid#1{%
+  \bbl@error{Alphabetic numeral too large (#1)}%
+    {Currently this is the limit.}}
+%    \end{macrocode}
+%
+% The information in the identification section can be useful, so the
+% following macro just exposes it with a user command.
+%
+%    \begin{macrocode}
+\newcommand\localeinfo[1]{%
+  \bbl@ifunset{bbl@\csname bbl@info@#1\endcsname @\languagename}%
+    {\bbl@error{I've found no info for the current locale.\\%
+                The corresponding ini file has not been loaded\\%
+                Perhaps it doesn't exist}%
+               {See the manual for details.}}%
+    {\bbl@cs{\csname bbl@info@#1\endcsname @\languagename}}}
+% \@namedef{bbl@info@name.locale}{lcname}
+\@namedef{bbl@info@tag.ini}{lini}
+\@namedef{bbl@info@name.english}{elname}
+\@namedef{bbl@info@name.opentype}{lname}
+\@namedef{bbl@info@tag.bcp47}{tbcp}
+\@namedef{bbl@info@language.tag.bcp47}{lbcp}
+\@namedef{bbl@info@tag.opentype}{lotf}
+\@namedef{bbl@info@script.name}{esname}
+\@namedef{bbl@info@script.name.opentype}{sname}
+\@namedef{bbl@info@script.tag.bcp47}{sbcp} 
+\@namedef{bbl@info@script.tag.opentype}{sotf} 
+\let\bbl@ensureinfo\@gobble
+\newcommand\BabelEnsureInfo{%
+  \ifx\InputIfFileExists\@undefined\else
+    \def\bbl@ensureinfo##1{%
+      \bbl@ifunset{bbl@lname@##1}{\bbl@load@info{##1}}{}}%
   \fi
-  % == require.babel in ini ==
-  % To load or reaload the babel-*.tex, if require.babel in ini
-  \ifx\bbl@beforestart\relax\else  % But not in doc aux or body
-    \bbl@ifunset{bbl@rqtex@\languagename}{}%
-      {\expandafter\ifx\csname bbl@rqtex@\languagename\endcsname\@empty\else
-         \let\BabelBeforeIni\@gobbletwo
-         \chardef\atcatcode=\catcode`\@
-         \catcode`\@=11\relax
-         \bbl@input@texini{\bbl@cs{rqtex@\languagename}}%
-         \catcode`\@=\atcatcode
-         \let\atcatcode\relax
-         \global\bbl@csarg\let{rqtex@\languagename}\relax
-       \fi}%
+  \bbl@foreach\bbl@loaded{{%
+    \def\languagename{##1}%
+    \bbl@ensureinfo{##1}}}}
+%    \end{macrocode}
+%
+% More general, but non-expandable, is |\getlocaleproperty|. To inspect
+% every possible loaded |ini|, we define |\LocaleForEach|, where
+% |\bbl@ini@loaded| is a comma-separated list of locales, built by
+% |\bbl@read@ini|. 
+%
+%    \begin{macrocode}   
+\newcommand\getlocaleproperty{%
+  \@ifstar\bbl@getproperty@s\bbl@getproperty@x}
+\def\bbl@getproperty@s#1#2#3{%
+  \let#1\relax
+  \def\bbl@elt##1##2##3{%
+    \bbl@ifsamestring{##1/##2}{#3}%
+      {\providecommand#1{##3}%
+       \def\bbl@elt####1####2####3{}}%
+      {}}%
+  \bbl@cs{inidata@#2}}%
+\def\bbl@getproperty@x#1#2#3{%
+  \bbl@getproperty@s{#1}{#2}{#3}%
+  \ifx#1\relax
+    \bbl@error
+      {Unknown key for locale '#2':\\%
+       #3\\%
+       \string#1 will be set to \relax}%
+      {Perhaps you misspelled it.}%
+  \fi}
+\let\bbl@ini@loaded\@empty
+\newcommand\LocaleForEach{\bbl@foreach\bbl@ini@loaded}
+%    \end{macrocode}
+%
+% \section{Adjusting the Babel bahavior}
+%
+% A generic high level inteface is provided to adjust some global
+% and general settings.
+%
+%    \begin{macrocode}
+\newcommand\babeladjust[1]{%  TODO. Error handling.
+  \bbl@forkv{#1}{%
+    \bbl@ifunset{bbl@ADJ@##1@##2}% 
+      {\bbl@cs{ADJ@##1}{##2}}%
+      {\bbl@cs{ADJ@##1@##2}}}}
+%
+\def\bbl@adjust@lua#1#2{%
+  \ifvmode
+    \ifnum\currentgrouplevel=\z@
+      \directlua{ Babel.#2 }%
+      \expandafter\expandafter\expandafter\@gobble
+    \fi
+  \fi      
+  {\bbl@error   % The error is gobbled if everything went ok.
+     {Currently, #1 related features can be adjusted only\\%
+      in the main vertical list.}%
+     {Maybe things change in the future, but this is what it is.}}}
+\@namedef{bbl@ADJ@bidi.mirroring@on}{%
+  \bbl@adjust@lua{bidi}{mirroring_enabled=true}}
+\@namedef{bbl@ADJ@bidi.mirroring@off}{%
+  \bbl@adjust@lua{bidi}{mirroring_enabled=false}}
+\@namedef{bbl@ADJ@bidi.text@on}{%
+  \bbl@adjust@lua{bidi}{bidi_enabled=true}}
+\@namedef{bbl@ADJ@bidi.text@off}{%
+  \bbl@adjust@lua{bidi}{bidi_enabled=false}}
+\@namedef{bbl@ADJ@bidi.mapdigits@on}{%
+  \bbl@adjust@lua{bidi}{digits_mapped=true}}
+\@namedef{bbl@ADJ@bidi.mapdigits@off}{%
+  \bbl@adjust@lua{bidi}{digits_mapped=false}}
+%
+\@namedef{bbl@ADJ@linebreak.sea@on}{%
+  \bbl@adjust@lua{linebreak}{sea_enabled=true}}
+\@namedef{bbl@ADJ@linebreak.sea@off}{%
+  \bbl@adjust@lua{linebreak}{sea_enabled=false}}
+\@namedef{bbl@ADJ@linebreak.cjk@on}{%
+  \bbl@adjust@lua{linebreak}{cjk_enabled=true}}
+\@namedef{bbl@ADJ@linebreak.cjk@off}{%
+  \bbl@adjust@lua{linebreak}{cjk_enabled=false}}
+\@namedef{bbl@ADJ@justify.arabic@on}{%
+  \bbl@adjust@lua{linebreak}{arabic.justify_enabled=true}}
+\@namedef{bbl@ADJ@justify.arabic@off}{%
+  \bbl@adjust@lua{linebreak}{arabic.justify_enabled=false}}
+%
+\def\bbl@adjust@layout#1{%
+  \ifvmode
+    #1%
+    \expandafter\@gobble
   \fi
-  % == frenchspacing ==
-  \ifcase\bbl@howloaded\in@true\else\in@false\fi
-  \ifin@\else\bbl@xin@{typography/frenchspacing}{\bbl@key@list}\fi
-  \ifin@
-    \bbl@extras@wrap{\\\bbl@pre@fs}%
-      {\bbl@pre@fs}%
-      {\bbl@post@fs}%
+  {\bbl@error   % The error is gobbled if everything went ok.
+     {Currently, layout related features can be adjusted only\\%
+      in vertical mode.}%
+     {Maybe things change in the future, but this is what it is.}}}
+\@namedef{bbl@ADJ@layout.tabular@on}{%
+  \bbl@adjust@layout{\let\@tabular\bbl@NL@@tabular}}
+\@namedef{bbl@ADJ@layout.tabular@off}{%
+  \bbl@adjust@layout{\let\@tabular\bbl@OL@@tabular}}
+\@namedef{bbl@ADJ@layout.lists@on}{%
+  \bbl@adjust@layout{\let\list\bbl@NL@list}}
+\@namedef{bbl@ADJ@layout.lists@off}{%
+  \bbl@adjust@layout{\let\list\bbl@OL@list}}
+\@namedef{bbl@ADJ@hyphenation.extra@on}{%
+  \bbl@activateposthyphen}
+%
+\@namedef{bbl@ADJ@autoload.bcp47@on}{%
+  \bbl@bcpallowedtrue}
+\@namedef{bbl@ADJ@autoload.bcp47@off}{%
+  \bbl@bcpallowedfalse}
+\@namedef{bbl@ADJ@autoload.bcp47.prefix}#1{%
+  \def\bbl@bcp@prefix{#1}}
+\def\bbl@bcp@prefix{bcp47-}
+\@namedef{bbl@ADJ@autoload.options}#1{%
+  \def\bbl@autoload@options{#1}}
+\let\bbl@autoload@bcpoptions\@empty
+\@namedef{bbl@ADJ@autoload.bcp47.options}#1{%
+  \def\bbl@autoload@bcpoptions{#1}}
+\newif\ifbbl@bcptoname
+\@namedef{bbl@ADJ@bcp47.toname@on}{%
+  \bbl@bcptonametrue
+  \BabelEnsureInfo}
+\@namedef{bbl@ADJ@bcp47.toname@off}{%
+  \bbl@bcptonamefalse}
+\@namedef{bbl@ADJ@prehyphenation.disable@nohyphenation}{%
+  \directlua{ Babel.ignore_pre_char = function(node)
+      return (node.lang == \the\csname l@nohyphenation\endcsname)
+    end }}
+\@namedef{bbl@ADJ@prehyphenation.disable@off}{%
+  \directlua{ Babel.ignore_pre_char = function(node)
+      return false
+    end }}
+\@namedef{bbl@ADJ@select.write@shift}{%
+  \let\bbl@restorelastskip\relax
+  \def\bbl@savelastskip{%
+    \let\bbl@restorelastskip\relax
+    \ifvmode
+      \ifdim\lastskip=\z@
+        \let\bbl@restorelastskip\nobreak
+      \else
+        \bbl@exp{%
+          \def\\\bbl@restorelastskip{%
+            \skip@=\the\lastskip
+            \\\nobreak \vskip-\skip@ \vskip\skip@}}%
+      \fi
+    \fi}}
+\@namedef{bbl@ADJ@select.write@keep}{%
+  \let\bbl@restorelastskip\relax
+  \let\bbl@savelastskip\relax}
+\@namedef{bbl@ADJ@select.write@omit}{%
+  \let\bbl@restorelastskip\relax
+  \def\bbl@savelastskip##1\bbl@restorelastskip{}}
+%    \end{macrocode}
+%
+% As the final task, load the code for lua. TODO: use babel name, override 
+%
+%    \begin{macrocode}
+\ifx\directlua\@undefined\else
+  \ifx\bbl@luapatterns\@undefined
+    \input luababel.def
   \fi
-  % == Release saved transforms ==
-  \bbl@release@transforms\relax % \relax closes the last item.
-  % == main ==
-  \ifx\bbl@KVP@main\@nil  % Restore only if not 'main'
-    \let\languagename\bbl@savelangname
-    \chardef\localeid\bbl@savelocaleid\relax
-  \fi}
+\fi
+%    \end{macrocode}
+%
+% Continue with \LaTeX{}.
+%
+%    \begin{macrocode}
+%</package|core>
+%<*package>
+%    \end{macrocode}
+%
+% \subsection{Cross referencing macros}
+%
+% The \LaTeX\ book states:
+% \begin{quote}
+%   The \emph{key} argument is any sequence of letters, digits, and
+%   punctuation symbols; upper- and lowercase letters are regarded as
+%   different.
+% \end{quote}
+% When the above quote should still be true when a document is
+% typeset in a language that has active characters, special care
+% has to be taken of the category codes of these characters when
+% they appear in an argument of the cross referencing macros.
+%
+% When a cross referencing command processes its argument, all
+% tokens in this argument should be character tokens with category
+% `letter' or `other'.
+%
+% The following package options control which macros are to be
+% redefined.
+%
+%    \begin{macrocode}
+%<<*More package options>>
+\DeclareOption{safe=none}{\let\bbl@opt@safe\@empty}
+\DeclareOption{safe=bib}{\def\bbl@opt@safe{B}}
+\DeclareOption{safe=ref}{\def\bbl@opt@safe{R}}
+%<</More package options>>
+%    \end{macrocode}
+%
+% \begin{macro}{\@newl@bel}
+%
+% First we open a new group to keep the changed setting of
+% |\protect| local and then we set the |@safe@actives| switch to
+% true to make sure that any shorthand that appears in any of the
+% arguments immediately expands to its non-active self.
+%
+%    \begin{macrocode}
+\bbl@trace{Cross referencing macros}
+\ifx\bbl@opt@safe\@empty\else
+  \def\@newl@bel#1#2#3{%
+   {\@safe@activestrue
+    \bbl@ifunset{#1@#2}%
+       \relax
+       {\gdef\@multiplelabels{%
+          \@latex@warning@no@line{There were multiply-defined labels}}%
+        \@latex@warning@no@line{Label `#2' multiply defined}}%
+    \global\@namedef{#1@#2}{#3}}}
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+%  \begin{macro}{\@testdef}
+%
+% An internal \LaTeX\ macro used to test if the labels that have
+% been written on the |.aux| file have changed.  It is called by
+% the |\enddocument| macro.
+%
+%    \begin{macrocode}
+  \CheckCommand*\@testdef[3]{%
+    \def\reserved@a{#3}%
+    \expandafter\ifx\csname#1@#2\endcsname\reserved@a
+    \else
+      \@tempswatrue
+    \fi}
+%    \end{macrocode}
+%
+% Now that we made sure that |\@testdef| still has the same definition
+% we can rewrite it. First we make the shorthands `safe'. Then we use
+% |\bbl@tempa| as an `alias' for the macro that contains the label
+% which is being checked. Then we define |\bbl@tempb| just as
+% |\@newl@bel| does it. When the label is defined we replace the
+% definition of |\bbl@tempa| by its meaning. If the label didn't
+% change, |\bbl@tempa| and |\bbl@tempb| should be identical macros.
+%
+%    \begin{macrocode}
+  \def\@testdef#1#2#3{%  TODO. With @samestring?
+    \@safe@activestrue
+    \expandafter\let\expandafter\bbl@tempa\csname #1@#2\endcsname
+    \def\bbl@tempb{#3}%
+    \@safe@activesfalse
+    \ifx\bbl@tempa\relax
+    \else
+      \edef\bbl@tempa{\expandafter\strip@prefix\meaning\bbl@tempa}%
+    \fi
+    \edef\bbl@tempb{\expandafter\strip@prefix\meaning\bbl@tempb}%
+    \ifx\bbl@tempa\bbl@tempb
+    \else
+      \@tempswatrue
+    \fi}
+\fi
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+% \begin{macro}{\ref}
+% \begin{macro}{\pageref}
+%
+% The same holds for the macro |\ref| that references a label and
+% |\pageref| to reference a page. We make them robust as well (if
+% they weren't already) to prevent problems if they should become
+% expanded at the wrong moment.
+%
+%    \begin{macrocode}
+\bbl@xin@{R}\bbl@opt@safe
+\ifin@
+  \bbl@redefinerobust\ref#1{%
+    \@safe@activestrue\org@ref{#1}\@safe@activesfalse}
+  \bbl@redefinerobust\pageref#1{%
+    \@safe@activestrue\org@pageref{#1}\@safe@activesfalse}
+\else
+  \let\org@ref\ref
+  \let\org@pageref\pageref
+\fi
+%    \end{macrocode}
+%
+%  \end{macro}
+%  \end{macro}
+%
+% \begin{macro}{\@citex}
+%
+% The macro used to cite from a bibliography, |\cite|, uses an
+% internal macro, |\@citex|.
+% It is this internal macro that picks up the argument(s),
+% so we redefine this internal macro and leave |\cite| alone. The
+% first argument is used for typesetting, so the shorthands need
+% only be deactivated in the second argument.
+%
+%    \begin{macrocode}
+\bbl@xin@{B}\bbl@opt@safe
+\ifin@
+  \bbl@redefine\@citex[#1]#2{%
+    \@safe@activestrue\edef\@tempa{#2}\@safe@activesfalse
+    \org@@citex[#1]{\@tempa}}
+%    \end{macrocode}
+%
+% Unfortunately, the packages \pkg{natbib} and \pkg{cite} need a
+% different definition of |\@citex|...
+% To begin with, \pkg{natbib} has a definition for |\@citex| with
+% \emph{three} arguments... We only know that a package is loaded
+% when |\begin{document}| is executed, so we need to postpone the
+% different redefinition.
+%
+%    \begin{macrocode}
+  \AtBeginDocument{%
+    \@ifpackageloaded{natbib}{%
+%    \end{macrocode}
+%
+% Notice that we use |\def| here instead of |\bbl@redefine| because
+% |\org@@citex| is already defined and we don't want to overwrite
+% that definition (it would result in parameter stack overflow
+% because of a circular definition).
+%
+% (Recent versions of \pkg{natbib} change dynamically |\@citex|, so PR4087
+% doesn't seem fixable in a simple way. Just load \pkg{natbib} before.)
+%
+%    \begin{macrocode}
+    \def\@citex[#1][#2]#3{%
+      \@safe@activestrue\edef\@tempa{#3}\@safe@activesfalse
+      \org@@citex[#1][#2]{\@tempa}}%
+    }{}}
+%    \end{macrocode}
+%
+% The package \pkg{cite} has a definition of |\@citex| where the
+% shorthands need to be turned off in both arguments.
+%
+%    \begin{macrocode}
+  \AtBeginDocument{%
+    \@ifpackageloaded{cite}{%
+      \def\@citex[#1]#2{%
+        \@safe@activestrue\org@@citex[#1]{#2}\@safe@activesfalse}%
+      }{}}
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+% \begin{macro}{\nocite}
+%
+% The macro |\nocite| which is used to instruct BiB\TeX\ to
+% extract uncited references from the database.
+%
+%    \begin{macrocode}
+  \bbl@redefine\nocite#1{%
+    \@safe@activestrue\org@nocite{#1}\@safe@activesfalse}
 %    \end{macrocode}
 %
-% Depending on whether or not the language exists (based on
-% |\date<language>|), we define two macros. Remember
-% |\bbl@startcommands| opens a group.
+%  \end{macro}
+%
+% \begin{macro}{\bibcite}
+%
+% The macro that is used in the |.aux| file to
+% define citation labels. When packages such as \pkg{natbib} or
+% \pkg{cite} are not loaded its second argument is used to typeset the
+% citation label. In that case, this second argument can contain
+% active characters but is used in an environment where
+% |\@safe@activestrue| is in effect. This switch needs to be reset
+% inside the |\hbox| which contains the citation label. In order to
+% determine during \file{.aux} file processing which definition of
+% |\bibcite| is needed we define |\bibcite| in such a way that it
+% redefines itself with the proper definition. We call
+% |\bbl@cite@choice| to select the proper definition for |\bibcite|.
+% This new definition is then activated.
 %
 %    \begin{macrocode}
-\def\bbl@provide@new#1{%
-  \@namedef{date#1}{}% marks lang exists - required by \StartBabelCommands
-  \@namedef{extras#1}{}%
-  \@namedef{noextras#1}{}%
-  \bbl@startcommands*{#1}{captions}%
-    \ifx\bbl@KVP@captions\@nil %      and also if import, implicit
-      \def\bbl@tempb##1{%             elt for \bbl@captionslist
-        \ifx##1\@empty\else
-          \bbl@exp{%
-            \\\SetString\\##1{%
-              \\\bbl@nocaption{\bbl@stripslash##1}{#1\bbl@stripslash##1}}}%
-          \expandafter\bbl@tempb
-        \fi}%
-      \expandafter\bbl@tempb\bbl@captionslist\@empty
-    \else
-      \ifx\bbl@initoload\relax
-        \bbl@read@ini{\bbl@KVP@captions}2%  % Here letters cat = 11
-      \else
-        \bbl@read@ini{\bbl@initoload}2%     % Same
-      \fi
-    \fi
-  \StartBabelCommands*{#1}{date}%
-    \ifx\bbl@KVP@import\@nil
-      \bbl@exp{%
-        \\\SetString\\\today{\\\bbl@nocaption{today}{#1today}}}%
-    \else
-      \bbl@savetoday
-      \bbl@savedate
-    \fi
-  \bbl@endcommands
-  \bbl@load@basic{#1}%
-  % == hyphenmins == (only if new)
-  \bbl@exp{%
-    \gdef\<#1hyphenmins>{%
-      {\bbl@ifunset{bbl@lfthm@#1}{2}{\bbl@cs{lfthm@#1}}}%
-      {\bbl@ifunset{bbl@rgthm@#1}{3}{\bbl@cs{rgthm@#1}}}}}%
-  % == hyphenrules (also in renew) == 
-  \bbl@provide@hyphens{#1}%
-  \ifx\bbl@KVP@main\@nil\else
-     \expandafter\main@language\expandafter{#1}%
-  \fi}
+  \bbl@redefine\bibcite{%
+    \bbl@cite@choice
+    \bibcite}
+%    \end{macrocode}
 %
-\def\bbl@provide@renew#1{%
-  \ifx\bbl@KVP@captions\@nil\else
-    \StartBabelCommands*{#1}{captions}%
-      \bbl@read@ini{\bbl@KVP@captions}2%   % Here all letters cat = 11
-    \EndBabelCommands
-  \fi
-  \ifx\bbl@KVP@import\@nil\else
-    \StartBabelCommands*{#1}{date}%
-      \bbl@savetoday
-      \bbl@savedate
-    \EndBabelCommands
-  \fi
-  % == hyphenrules (also in new) ==
-  \ifx\bbl@lbkflag\@empty
-    \bbl@provide@hyphens{#1}%
-  \fi}
+%  \end{macro}
+%
+% \begin{macro}{\bbl@bibcite}
+%
+% The macro |\bbl@bibcite| holds the definition of |\bibcite|
+% needed when neither \pkg{natbib} nor \pkg{cite} is loaded.
+%
+%    \begin{macrocode}
+  \def\bbl@bibcite#1#2{%
+    \org@bibcite{#1}{\@safe@activesfalse#2}}
 %    \end{macrocode}
 %
-% Load the basic parameters (ids, typography, counters, and a few
-% more), while captions and dates are left out. But it may happen some
-% data has been loaded before automatically, so we first discard the
-% saved values. (TODO. But preserving previous values would be useful.)
+%  \end{macro}
+%
+% \begin{macro}{\bbl@cite@choice}
+%
+% The macro |\bbl@cite@choice| determines which definition of
+% |\bibcite| is needed. First we give |\bibcite| its default
+% definition.
 %
 %    \begin{macrocode}
-\def\bbl@load@basic#1{%
-  \ifcase\bbl@howloaded\or\or
-    \ifcase\csname bbl@llevel@\languagename\endcsname
-      \bbl@csarg\let{lname@\languagename}\relax
-    \fi
-  \fi
-  \bbl@ifunset{bbl@lname@#1}% 
-    {\def\BabelBeforeIni##1##2{%
-       \begingroup
-         \let\bbl@ini@captions@aux\@gobbletwo
-         \def\bbl@inidate ####1.####2.####3.####4\relax ####5####6{}%
-         \bbl@read@ini{##1}1%
-         \ifx\bbl@initoload\relax\endinput\fi
-       \endgroup}%
-     \begingroup       % boxed, to avoid extra spaces:
-       \ifx\bbl@initoload\relax
-         \bbl@input@texini{#1}%
-       \else
-         \setbox\z@\hbox{\BabelBeforeIni{\bbl@initoload}{}}%
-       \fi
-     \endgroup}%
-    {}}
+  \def\bbl@cite@choice{%
+    \global\let\bibcite\bbl@bibcite
+    \@ifpackageloaded{natbib}{\global\let\bibcite\org@bibcite}{}%
+    \@ifpackageloaded{cite}{\global\let\bibcite\org@bibcite}{}%
+    \global\let\bbl@cite@choice\relax}
 %    \end{macrocode}
 %
-% The |hyphenrules| option is handled with an auxiliary macro.
+% When a document is run for the first time, no \file{.aux} file is
+% available, and |\bibcite| will not yet be properly defined. In
+% this case, this has to happen before the document starts.
 %
 %    \begin{macrocode}
-\def\bbl@provide@hyphens#1{%
-  \let\bbl@tempa\relax
-  \ifx\bbl@KVP@hyphenrules\@nil\else
-    \bbl@replace\bbl@KVP@hyphenrules{ }{,}%
-    \bbl@foreach\bbl@KVP@hyphenrules{%
-      \ifx\bbl@tempa\relax    %  if not yet found
-        \bbl@ifsamestring{##1}{+}%
-          {{\bbl@exp{\\\addlanguage\<l@##1>}}}%
-          {}%
-        \bbl@ifunset{l@##1}%
-          {}%
-          {\bbl@exp{\let\bbl@tempa\<l@##1>}}%
-      \fi}%
-  \fi
-  \ifx\bbl@tempa\relax %         if no opt or no language in opt found
-    \ifx\bbl@KVP@import\@nil
-      \ifx\bbl@initoload\relax\else
-        \bbl@exp{%               and hyphenrules is not empty
-          \\\bbl@ifblank{\bbl@cs{hyphr@#1}}%
-            {}%
-            {\let\\\bbl@tempa\<l@\bbl@cl{hyphr}>}}%
-      \fi 
-    \else % if importing
-      \bbl@exp{%                    and hyphenrules is not empty
-        \\\bbl@ifblank{\bbl@cs{hyphr@#1}}%
-          {}%
-          {\let\\\bbl@tempa\<l@\bbl@cl{hyphr}>}}%
-    \fi
-  \fi
-  \bbl@ifunset{bbl@tempa}%       ie, relax or undefined
-    {\bbl@ifunset{l@#1}%         no hyphenrules found - fallback
-       {\bbl@exp{\\\adddialect\<l@#1>\language}}%
-       {}}%                      so, l@<lang> is ok - nothing to do
-    {\bbl@exp{\\\adddialect\<l@#1>\bbl@tempa}}}% found in opt list or ini
+  \AtBeginDocument{\bbl@cite@choice}
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+% \begin{macro}{\@bibitem}
+%
+% One of the two internal \LaTeX\ macros called by |\bibitem|
+% that write the citation label on the |.aux| file.
+%
+%    \begin{macrocode}
+  \bbl@redefine\@bibitem#1{%
+    \@safe@activestrue\org@@bibitem{#1}\@safe@activesfalse}
+\else
+  \let\org@nocite\nocite
+  \let\org@@citex\@citex
+  \let\org@bibcite\bibcite
+  \let\org@@bibitem\@bibitem
+\fi
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+% \subsection{Marks}
+%
+% \begin{macro}{\markright}
+% Because the output routine is asynchronous, we must pass the
+% current language attribute to the head lines. To achieve this we
+% need to adapt the definition of |\markright| and |\markboth|
+% somewhat. However, headlines and footlines can contain text
+% outside marks; for that we must take some actions in the output
+% routine if the 'headfoot' options is used. 
+%
+% We need to make some redefinitions to the output routine
+% to avoid an endless loop and to correctly handle the page number
+% in bidi documents.
+%
+%    \begin{macrocode}
+\bbl@trace{Marks}
+\IfBabelLayout{sectioning}
+  {\ifx\bbl@opt@headfoot\@nnil
+     \g@addto@macro\@resetactivechars{%
+       \set@typeset@protect
+       \expandafter\select@language@x\expandafter{\bbl@main@language}%
+       \let\protect\noexpand
+       \ifcase\bbl@bidimode\else % Only with bidi. See also above
+         \edef\thepage{%
+           \noexpand\babelsublr{\unexpanded\expandafter{\thepage}}}%
+       \fi}%
+   \fi}
+  {\ifbbl@single\else
+     \bbl@ifunset{markright }\bbl@redefine\bbl@redefinerobust
+     \markright#1{%
+       \bbl@ifblank{#1}%
+         {\org@markright{}}%
+         {\toks@{#1}%
+          \bbl@exp{%
+            \\\org@markright{\\\protect\\\foreignlanguage{\languagename}%
+              {\\\protect\\\bbl@restore@actives\the\toks@}}}}}%
+%    \end{macrocode}
+%
+%  \end{macro}
+%
+%  \begin{macro}{\markboth}
+%  \begin{macro}{\@mkboth}
+%    The definition of |\markboth| is equivalent to that of
+%    |\markright|, except that we need two token registers. The
+%    documentclasses \cls{report} and \cls{book} define and set the
+%    headings for the page. While doing so they also store a copy of
+%    |\markboth| in |\@mkboth|. Therefore we need to check whether
+%    |\@mkboth| has already been set. If so we neeed to do that again
+%    with the new definition of |\markboth|. (As of Oct 2019, \LaTeX{}
+%    stores the definition in an intermediate macro, so it's not
+%    necessary anymore, but it's preserved for older versions.)
+%
+%    \begin{macrocode}
+     \ifx\@mkboth\markboth
+       \def\bbl@tempc{\let\@mkboth\markboth}
+     \else
+       \def\bbl@tempc{}
+     \fi
+     \bbl@ifunset{markboth }\bbl@redefine\bbl@redefinerobust
+     \markboth#1#2{%
+       \protected@edef\bbl@tempb##1{%
+         \protect\foreignlanguage
+         {\languagename}{\protect\bbl@restore@actives##1}}%
+       \bbl@ifblank{#1}%
+         {\toks@{}}%
+         {\toks@\expandafter{\bbl@tempb{#1}}}%
+       \bbl@ifblank{#2}%
+         {\@temptokena{}}%
+         {\@temptokena\expandafter{\bbl@tempb{#2}}}%
+       \bbl@exp{\\\org@markboth{\the\toks@}{\the\@temptokena}}}
+       \bbl@tempc
+     \fi}  % end ifbbl@single, end \IfBabelLayout
 %    \end{macrocode}
 %
-% The reader of |babel-...tex| files. We reset temporarily some
-% catcodes.
+%  \end{macro}
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@input@texini#1{%
-  \bbl@bsphack
-    \bbl@exp{%
-      \catcode`\\\%=14 \catcode`\\\\=0
-      \catcode`\\\{=1  \catcode`\\\}=2 
-      \lowercase{\\\InputIfFileExists{babel-#1.tex}{}{}}%
-      \catcode`\\\%=\the\catcode`\%\relax
-      \catcode`\\\\=\the\catcode`\\\relax
-      \catcode`\\\{=\the\catcode`\{\relax
-      \catcode`\\\}=\the\catcode`\}\relax}%
-  \bbl@esphack}
-%    \end{macrocode}
+% \subsection{Preventing clashes with other packages}
 %
-% The following macros read and store |ini| files (but don't process
-% them). For each line, there are 3 possible actions: ignore if starts
-% with |;|, switch section if starts with |[|, and store otherwise.
-% There are used in the first step of |\bbl@read@ini|.
+% \subsubsection{\pkg{ifthen}}
 %
-%    \begin{macrocode}
-\def\bbl@iniline#1\bbl@iniline{%
-  \@ifnextchar[\bbl@inisect{\@ifnextchar;\bbl@iniskip\bbl@inistore}#1\@@}% ]
-\def\bbl@inisect[#1]#2\@@{\def\bbl@section{#1}} 
-\def\bbl@iniskip#1\@@{}%      if starts with ;
-\def\bbl@inistore#1=#2\@@{%      full (default)
-  \bbl@trim@def\bbl@tempa{#1}%
-  \bbl@trim\toks@{#2}%
-  \bbl@xin@{;\bbl@section/\bbl@tempa;}{\bbl@key@list}%
-  \ifin@\else
-    \bbl@exp{%
-      \\\g@addto@macro\\\bbl@inidata{%
-        \\\bbl@elt{\bbl@section}{\bbl@tempa}{\the\toks@}}}%
-  \fi}
-\def\bbl@inistore@min#1=#2\@@{%  minimal (maybe set in \bbl@read@ini)
-  \bbl@trim@def\bbl@tempa{#1}%
-  \bbl@trim\toks@{#2}%
-  \bbl@xin@{.identification.}{.\bbl@section.}%
-  \ifin@
-    \bbl@exp{\\\g@addto@macro\\\bbl@inidata{%
-      \\\bbl@elt{identification}{\bbl@tempa}{\the\toks@}}}%
-  \fi}
-%    \end{macrocode}
+% \begin{macro}{\ifthenelse}
 %
-% Now, the ‘main loop’, which \textbf{**must be executed inside a
-% group**}. At this point, |\bbl@inidata| may contain data declared in
-% |\babelprovide|, with ‘slashed’ keys. There are 3 steps: first read
-% the ini file and store it; then traverse the stored values, and
-% process some groups if required (date, captions, labels, counters);
-% finally, ‘export’ some values by defining global macros
-% (identification, typography, characters, numbers). The second
-% argument is 0 when called to read the minimal data for fonts; with
-% |\babelprovide| it's either 1 or 2.
+% Sometimes a document writer wants to create a special effect
+% depending on the page a certain fragment of text appears on. This
+% can be achieved by the following piece of code:
+%\begin{verbatim}
+%    \ifthenelse{\isodd{\pageref{some:label}}}
+%               {code for odd pages}
+%               {code for even pages}
+%\end{verbatim}
+% In order for this to work the argument of |\isodd| needs to be
+% fully expandable. With the above redefinition of |\pageref| it is
+% not in the case of this example. To overcome that, we add some
+% code to the definition of |\ifthenelse| to make things work.
+%
+% We want to revert the definition of |\pageref| and |\ref| to
+% their original definition for the first argument of |\ifthenelse|,
+% so we first need to store their current meanings.
+%
+% Then we can set the |\@safe@actives| switch and call the original
+% |\ifthenelse|. In order to be able to use shorthands in the
+% second and third arguments of |\ifthenelse| the resetting of the
+% switch \emph{and} the definition of |\pageref| happens inside
+% those arguments. 
 %
 %    \begin{macrocode}
-\ifx\bbl@readstream\@undefined
-  \csname newread\endcsname\bbl@readstream
-\fi
-\def\bbl@read@ini#1#2{%
-  \global\let\bbl@extend@ini\@gobble
-  \openin\bbl@readstream=babel-#1.ini
-  \ifeof\bbl@readstream
-    \bbl@error
-      {There is no ini file for the requested language\\%
-       (#1). Perhaps you misspelled it or your installation\\%
-       is not complete.}%
-      {Fix the name or reinstall babel.}%
-  \else
-    % == Store ini data in \bbl@inidata ==
-    \catcode`\[=12 \catcode`\]=12 \catcode`\==12 \catcode`\&=12
-    \catcode`\;=12 \catcode`\|=12 \catcode`\%=14 \catcode`\-=12
-    \bbl@info{Importing
-                \ifcase#2font and identification \or basic \fi
-                 data for \languagename\\%
-              from babel-#1.ini. Reported}%
-    \ifnum#2=\z@
-      \global\let\bbl@inidata\@empty
-      \let\bbl@inistore\bbl@inistore@min    % Remember it's local
-    \fi
-    \def\bbl@section{identification}%
-    \bbl@exp{\\\bbl@inistore tag.ini=#1\\\@@}%
-    \bbl@inistore load.level=#2\@@
-    \loop
-    \if T\ifeof\bbl@readstream F\fi T\relax % Trick, because inside \loop
-      \endlinechar\m@ne
-      \read\bbl@readstream to \bbl@line
-      \endlinechar`\^^M
-      \ifx\bbl@line\@empty\else
-        \expandafter\bbl@iniline\bbl@line\bbl@iniline
-      \fi
-    \repeat
-    % == Process stored data ==
-    \bbl@csarg\xdef{lini@\languagename}{#1}%
-    \bbl@read@ini@aux
-    % == 'Export' data ==
-    \bbl@ini@exports{#2}%
-    \global\bbl@csarg\let{inidata@\languagename}\bbl@inidata
-    \global\let\bbl@inidata\@empty
-    \bbl@exp{\\\bbl@add@list\\\bbl@ini@loaded{\languagename}}%
-    \bbl@toglobal\bbl@ini@loaded
-  \fi}
-\def\bbl@read@ini@aux{%
-  \let\bbl@savestrings\@empty
-  \let\bbl@savetoday\@empty
-  \let\bbl@savedate\@empty
-  \def\bbl@elt##1##2##3{%
-    \def\bbl@section{##1}%
-    \in@{=date.}{=##1}% Find a better place
-    \ifin@
-      \bbl@ini@calendar{##1}%
-    \fi
-    \bbl@ifunset{bbl@inikv@##1}{}%
-      {\csname bbl@inikv@##1\endcsname{##2}{##3}}}%
-  \bbl@inidata}
+\bbl@trace{Preventing clashes with other packages}
+\bbl@xin@{R}\bbl@opt@safe
+\ifin@
+  \AtBeginDocument{%
+    \@ifpackageloaded{ifthen}{%
+      \bbl@redefine@long\ifthenelse#1#2#3{%
+        \let\bbl@temp@pref\pageref
+        \let\pageref\org@pageref
+        \let\bbl@temp@ref\ref
+        \let\ref\org@ref
+        \@safe@activestrue
+        \org@ifthenelse{#1}%
+          {\let\pageref\bbl@temp@pref
+           \let\ref\bbl@temp@ref
+           \@safe@activesfalse
+           #2}%
+          {\let\pageref\bbl@temp@pref
+           \let\ref\bbl@temp@ref
+           \@safe@activesfalse
+           #3}%
+        }%
+      }{}%
+    }
 %    \end{macrocode}
 %
-% A variant to be used when the ini file has been already loaded,
-% because it's not the first |\babelprovide| for this language.
+%  \end{macro}
+%
+% \subsubsection{\pkg{varioref}}
+%
+% \begin{macro}{\@@vpageref}
+% \begin{macro}{\vrefpagenum}
+% \begin{macro}{\Ref}
+%
+% When the package varioref is in use we need to modify its
+% internal command |\@@vpageref| in order to prevent problems when
+% an active character ends up in the argument of |\vref|. The same
+% needs to happen for |\vrefpagenum|.
 %
 %    \begin{macrocode}
-\def\bbl@extend@ini@aux#1{%
-  \bbl@startcommands*{#1}{captions}%
-    % Activate captions/... and modify exports
-    \bbl@csarg\def{inikv@captions.licr}##1##2{%
-      \setlocalecaption{#1}{##1}{##2}}%
-    \def\bbl@inikv@captions##1##2{%
-      \bbl@ini@captions@aux{##1}{##2}}%
-    \def\bbl@stringdef##1##2{\gdef##1{##2}}% 
-    \def\bbl@exportkey##1##2##3{%
-      \bbl@ifunset{bbl@@kv@##2}{}%
-        {\expandafter\ifx\csname bbl@@kv@##2\endcsname\@empty\else
-           \bbl@exp{\global\let\<bbl@##1@\languagename>\<bbl@@kv@##2>}%
-         \fi}}%
-    % As with \bbl@read@ini, but with some changes
-    \bbl@read@ini@aux
-    \bbl@ini@exports\tw@
-    % Update inidata@lang by pretending the ini is read.
-    \def\bbl@elt##1##2##3{%
-      \def\bbl@section{##1}%
-      \bbl@iniline##2=##3\bbl@iniline}%
-    \csname bbl@inidata@#1\endcsname
-    \global\bbl@csarg\let{inidata@#1}\bbl@inidata
-  \StartBabelCommands*{#1}{date}% And from the import stuff
-    \def\bbl@stringdef##1##2{\gdef##1{##2}}%
-    \bbl@savetoday
-    \bbl@savedate
-  \bbl@endcommands}
+  \AtBeginDocument{%
+    \@ifpackageloaded{varioref}{%
+      \bbl@redefine\@@vpageref#1[#2]#3{%
+        \@safe@activestrue
+        \org@@@vpageref{#1}[#2]{#3}%
+        \@safe@activesfalse}%
+      \bbl@redefine\vrefpagenum#1#2{%
+        \@safe@activestrue
+        \org@vrefpagenum{#1}{#2}%
+        \@safe@activesfalse}%
 %    \end{macrocode}
 %
-% A somewhat hackish tool to handle calendar sections. To be improved.
+% The package \pkg{varioref} defines |\Ref| to be a robust command
+% wich uppercases the first character of the reference text. In
+% order to be able to do that it needs to access the expandable form
+% of |\ref|. So we employ a little trick here. We redefine the
+% (internal) command \verb*|\Ref | to call |\org@ref| instead of
+% |\ref|. The disadvantage of this solution is that whenever the
+% definition of |\Ref| changes, this definition needs to be updated
+% as well.
 %
 %    \begin{macrocode}
-\def\bbl@ini@calendar#1{%
- \lowercase{\def\bbl@tempa{=#1=}}%
- \bbl@replace\bbl@tempa{=date.gregorian}{}%
- \bbl@replace\bbl@tempa{=date.}{}%
- \in@{.licr=}{#1=}%
- \ifin@
-   \ifcase\bbl@engine
-     \bbl@replace\bbl@tempa{.licr=}{}%
-   \else
-     \let\bbl@tempa\relax
-   \fi
- \fi
- \ifx\bbl@tempa\relax\else
-   \bbl@replace\bbl@tempa{=}{}%
-   \bbl@exp{%
-     \def\<bbl@inikv@#1>####1####2{% 
-       \\\bbl@inidate####1...\relax{####2}{\bbl@tempa}}}%
- \fi}
+      \expandafter\def\csname Ref \endcsname#1{%
+        \protected@edef\@tempa{\org@ref{#1}}\expandafter\MakeUppercase\@tempa}
+      }{}%
+    }
+\fi
 %    \end{macrocode}
 %
-% A key with a slash in |\babelprovide| replaces the value in the |ini|
-% file (which is ignored altogether). The mechanism is simple (but
-% suboptimal): add the data to the |ini| one (at this point the |ini|
-% file has not yet been read), and define a dummy macro. When the |ini|
-% file is read, just skip the corresponding key and reset the macro (in
-% |\bbl@inistore| above).
-% 
+%  \end{macro}
+%  \end{macro}
+%  \end{macro}
+%
+% \subsubsection{\pkg{hhline}}
+%
+%
+% \begin{macro}{\hhline}
+%
+% Delaying the activation of the shorthand characters has introduced
+% a problem with the \pkg{hhline} package. The reason is that it
+% uses the `:' character which is made active by the french support
+% in \babel. Therefore we need to \emph{reload} the package when
+% the `:' is an active character. Note that this happens
+% \emph{after} the category code of the @-sign has been changed to
+% other, so we need to temporarily change it to letter again.
 %
 %    \begin{macrocode}
-\def\bbl@renewinikey#1/#2\@@#3{%
-  \edef\bbl@tempa{\zap@space #1 \@empty}%   section
-  \edef\bbl@tempb{\zap@space #2 \@empty}%   key
-  \bbl@trim\toks@{#3}%                      value
-  \bbl@exp{%
-    \edef\\\bbl@key@list{\bbl@key@list \bbl@tempa/\bbl@tempb;}%
-    \\\g@addto@macro\\\bbl@inidata{%
-       \\\bbl@elt{\bbl@tempa}{\bbl@tempb}{\the\toks@}}}}%
+\AtEndOfPackage{%
+  \AtBeginDocument{%
+    \@ifpackageloaded{hhline}%
+      {\expandafter\ifx\csname normal@char\string:\endcsname\relax
+       \else
+         \makeatletter
+         \def\@currname{hhline}\input{hhline.sty}\makeatother
+       \fi}%
+      {}}}
 %    \end{macrocode}
 %
-% The previous assignments are local, so we need to export them. If
-% the value is empty, we can provide a default value.
+%  \end{macro}
+%
+% \begin{macro}{\substitutefontfamily}
+%
+% Deprecated. Use the tools provides by \LaTeX. The command
+% |\substitutefontfamily| creates an \file{.fd} file on the fly. The
+% first argument is an encoding mnemonic, the second and third
+% arguments are font family names.
 %
 %    \begin{macrocode}
-\def\bbl@exportkey#1#2#3{%
-  \bbl@ifunset{bbl@@kv@#2}%
-    {\bbl@csarg\gdef{#1@\languagename}{#3}}%
-    {\expandafter\ifx\csname bbl@@kv@#2\endcsname\@empty
-       \bbl@csarg\gdef{#1@\languagename}{#3}%
-     \else
-       \bbl@exp{\global\let\<bbl@#1@\languagename>\<bbl@@kv@#2>}%
-     \fi}}
+\def\substitutefontfamily#1#2#3{%
+  \lowercase{\immediate\openout15=#1#2.fd\relax}%
+  \immediate\write15{%
+    \string\ProvidesFile{#1#2.fd}%
+    [\the\year/\two@digits{\the\month}/\two@digits{\the\day}
+     \space generated font description file]^^J
+    \string\DeclareFontFamily{#1}{#2}{}^^J
+    \string\DeclareFontShape{#1}{#2}{m}{n}{<->ssub * #3/m/n}{}^^J
+    \string\DeclareFontShape{#1}{#2}{m}{it}{<->ssub * #3/m/it}{}^^J
+    \string\DeclareFontShape{#1}{#2}{m}{sl}{<->ssub * #3/m/sl}{}^^J
+    \string\DeclareFontShape{#1}{#2}{m}{sc}{<->ssub * #3/m/sc}{}^^J
+    \string\DeclareFontShape{#1}{#2}{b}{n}{<->ssub * #3/bx/n}{}^^J
+    \string\DeclareFontShape{#1}{#2}{b}{it}{<->ssub * #3/bx/it}{}^^J
+    \string\DeclareFontShape{#1}{#2}{b}{sl}{<->ssub * #3/bx/sl}{}^^J
+    \string\DeclareFontShape{#1}{#2}{b}{sc}{<->ssub * #3/bx/sc}{}^^J
+    }%
+  \closeout15
+  }
+\@onlypreamble\substitutefontfamily
 %    \end{macrocode}
 %
-% Key-value pairs are treated differently depending on the section in
-% the |ini| file. The following macros are the readers for
-% |identification| and |typography|. Note |\bbl@ini@exports|
-% is called always (via |\bbl@inisec|), while |\bbl@after@ini| must be
-% called explicitly after |\bbl@read@ini| if necessary.
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@iniwarning#1{%
-  \bbl@ifunset{bbl@@kv@identification.warning#1}{}%
-    {\bbl@warning{%
-       From babel-\bbl@cs{lini@\languagename}.ini:\\%
-       \bbl@cs{@kv@identification.warning#1}\\%
-       Reported }}}
+% \subsection{Encoding and fonts}
 %
-\let\bbl@release@transforms\@empty
+%  Because documents may use non-ASCII font encodings, we make sure
+%  that the logos of \TeX\ and \LaTeX\ always come out in the right
+%  encoding. There is a list of non-ASCII encodings. Requested
+%  encodings are currently stored in |\@fontenc@load@list|. If a
+%  non-ASCII has been loaded, we define versions of |\TeX| and |\LaTeX|
+%  for them using |\ensureascii|. The default ASCII encoding is set,
+%  too (in reverse order): the ``main'' encoding (when the document
+%  begins), the last loaded, or |OT1|.
 %
-\def\bbl@ini@exports#1{%
-  % Identification always exported
-  \bbl@iniwarning{}%
-  \ifcase\bbl@engine
-    \bbl@iniwarning{.pdflatex}%
-  \or
-    \bbl@iniwarning{.lualatex}%
-  \or
-    \bbl@iniwarning{.xelatex}%
-  \fi%
-  \bbl@exportkey{llevel}{identification.load.level}{}%
-  \bbl@exportkey{elname}{identification.name.english}{}%
-  \bbl@exp{\\\bbl@exportkey{lname}{identification.name.opentype}%
-    {\csname bbl@elname@\languagename\endcsname}}%
-  \bbl@exportkey{tbcp}{identification.tag.bcp47}{}%
-  \bbl@exportkey{lbcp}{identification.language.tag.bcp47}{}%
-  \bbl@exportkey{lotf}{identification.tag.opentype}{dflt}%
-  \bbl@exportkey{esname}{identification.script.name}{}%
-  \bbl@exp{\\\bbl@exportkey{sname}{identification.script.name.opentype}%
-    {\csname bbl@esname@\languagename\endcsname}}%
-  \bbl@exportkey{sbcp}{identification.script.tag.bcp47}{}%
-  \bbl@exportkey{sotf}{identification.script.tag.opentype}{DFLT}%
-  % Also maps bcp47 -> languagename
-  \ifbbl@bcptoname
-    \bbl@csarg\xdef{bcp@map@\bbl@cl{tbcp}}{\languagename}%
-  \fi
-  % Conditional
-  \ifnum#1>\z@         % 0 = only info, 1, 2 = basic, (re)new
-    \bbl@exportkey{lnbrk}{typography.linebreaking}{h}%
-    \bbl@exportkey{hyphr}{typography.hyphenrules}{}%
-    \bbl@exportkey{lfthm}{typography.lefthyphenmin}{2}%
-    \bbl@exportkey{rgthm}{typography.righthyphenmin}{3}%         
-    \bbl@exportkey{prehc}{typography.prehyphenchar}{}%
-    \bbl@exportkey{hyotl}{typography.hyphenate.other.locale}{}%
-    \bbl@exportkey{hyots}{typography.hyphenate.other.script}{}%
-    \bbl@exportkey{intsp}{typography.intraspace}{}%
-    \bbl@exportkey{frspc}{typography.frenchspacing}{u}%
-    \bbl@exportkey{chrng}{characters.ranges}{}%
-    \bbl@exportkey{quote}{characters.delimiters.quotes}{}%
-    \bbl@exportkey{dgnat}{numbers.digits.native}{}%
-    \ifnum#1=\tw@           % only (re)new
-      \bbl@exportkey{rqtex}{identification.require.babel}{}%
-      \bbl@toglobal\bbl@savetoday
-      \bbl@toglobal\bbl@savedate
-      \bbl@savestrings
+%  \begin{macro}{\ensureascii}
+%
+%    \begin{macrocode}
+\bbl@trace{Encoding and fonts}
+\newcommand\BabelNonASCII{LGR,X2,OT2,OT3,OT6,LHE,LWN,LMA,LMC,LMS,LMU}
+\newcommand\BabelNonText{TS1,T3,TS3}
+\let\org@TeX\TeX
+\let\org@LaTeX\LaTeX
+\let\ensureascii\@firstofone
+\AtBeginDocument{%
+  \def\@elt#1{,#1,}%
+  \edef\bbl@tempa{\expandafter\@gobbletwo\@fontenc@load@list}%
+  \let\@elt\relax
+  \let\bbl@tempb\@empty
+  \def\bbl@tempc{OT1}%
+  \bbl@foreach\BabelNonASCII{% LGR loaded in a non-standard way
+    \bbl@ifunset{T@#1}{}{\def\bbl@tempb{#1}}}%
+  \bbl@foreach\bbl@tempa{%
+    \bbl@xin@{#1}{\BabelNonASCII}%
+    \ifin@
+      \def\bbl@tempb{#1}% Store last non-ascii
+    \else\bbl@xin@{#1}{\BabelNonText}% Pass
+      \ifin@\else
+        \def\bbl@tempc{#1}% Store last ascii
+      \fi
+    \fi}%
+  \ifx\bbl@tempb\@empty\else
+    \bbl@xin@{,\cf@encoding,}{,\BabelNonASCII,\BabelNonText,}%
+    \ifin@\else
+      \edef\bbl@tempc{\cf@encoding}% The default if ascii wins
     \fi
+    \edef\ensureascii#1{%
+      {\noexpand\fontencoding{\bbl@tempc}\noexpand\selectfont#1}}%
+    \DeclareTextCommandDefault{\TeX}{\ensureascii{\org@TeX}}%
+    \DeclareTextCommandDefault{\LaTeX}{\ensureascii{\org@LaTeX}}%
   \fi}
 %    \end{macrocode}
 %
-% A shared handler for key=val lines to be stored in
-% |\bbl@@kv@<section>.<key>|.
+%  \end{macro}
+%
+%  Now comes the old deprecated stuff (with a little change in 3.9l,
+%  for \textsf{fontspec}).  The first thing we need to do is to
+%  determine, at |\begin{document}|, which latin fontencoding to use.
+%
+%  \begin{macro}{\latinencoding}
+%    When text is being typeset in an encoding other than `latin'
+%    (\texttt{OT1} or \texttt{T1}), it would be nice to still have
+%    Roman numerals come out in the Latin encoding.
+%    So we first assume that the current encoding at the end
+%    of processing the package is the Latin encoding.
 %
 %    \begin{macrocode}
-\def\bbl@inikv#1#2{%     key=value
-  \toks@{#2}%            This hides #'s from ini values
-  \bbl@csarg\edef{@kv@\bbl@section.#1}{\the\toks@}}
+\AtEndOfPackage{\edef\latinencoding{\cf@encoding}}
 %    \end{macrocode}
 %
-% By default, the following sections are just read. Actions are taken
-% later.
+%    But this might be overruled with a later loading of the package
+%    \pkg{fontenc}. Therefore we check at the execution of
+%    |\begin{document}| whether it was loaded with the \Lopt{T1}
+%    option. The normal way to do this (using |\@ifpackageloaded|) is
+%    disabled for this package. Now we have to revert to parsing the
+%    internal macro |\@filelist| which contains all the filenames
+%    loaded.
 %
 %    \begin{macrocode}
-\let\bbl@inikv@identification\bbl@inikv
-\let\bbl@inikv@typography\bbl@inikv
-\let\bbl@inikv@characters\bbl@inikv
-\let\bbl@inikv@numbers\bbl@inikv
+\AtBeginDocument{%
+  \@ifpackageloaded{fontspec}%
+    {\xdef\latinencoding{%
+       \ifx\UTFencname\@undefined
+         EU\ifcase\bbl@engine\or2\or1\fi
+       \else
+         \UTFencname
+       \fi}}%
+    {\gdef\latinencoding{OT1}%
+     \ifx\cf@encoding\bbl@t@one
+       \xdef\latinencoding{\bbl@t@one}%
+     \else
+       \def\@elt#1{,#1,}%
+       \edef\bbl@tempa{\expandafter\@gobbletwo\@fontenc@load@list}%
+       \let\@elt\relax
+       \bbl@xin@{,T1,}\bbl@tempa
+       \ifin@
+         \xdef\latinencoding{\bbl@t@one}%
+       \fi
+     \fi}}
 %    \end{macrocode}
 %
-% Additive numerals require an additional definition. When |.1| is
-% found, two macros are defined -- the basic one, without |.1| called
-% by |\localenumeral|, and another one preserving the trailing |.1| for
-% the ‘units’. 
+%  \end{macro}
 %
-%    \begin{macrocode}
-\def\bbl@inikv@counters#1#2{%
-  \bbl@ifsamestring{#1}{digits}%
-    {\bbl@error{The counter name 'digits' is reserved for mapping\\%
-                decimal digits}%
-               {Use another name.}}%
-    {}%
-  \def\bbl@tempc{#1}%
-  \bbl@trim@def{\bbl@tempb*}{#2}%
-  \in@{.1$}{#1$}%
-  \ifin@
-    \bbl@replace\bbl@tempc{.1}{}%
-    \bbl@csarg\protected@xdef{cntr@\bbl@tempc @\languagename}{%
-      \noexpand\bbl@alphnumeral{\bbl@tempc}}%
-  \fi
-  \in@{.F.}{#1}%
-  \ifin@\else\in@{.S.}{#1}\fi
-  \ifin@
-    \bbl@csarg\protected@xdef{cntr@#1@\languagename}{\bbl@tempb*}%
-  \else
-    \toks@{}% Required by \bbl@buildifcase, which returns \bbl@tempa
-    \expandafter\bbl@buildifcase\bbl@tempb* \\ % Space after \\
-    \bbl@csarg{\global\expandafter\let}{cntr@#1@\languagename}\bbl@tempa
-  \fi}
+%  \begin{macro}{\latintext}
+%    Then we can define the command |\latintext| which is a
+%    declarative switch to a latin font-encoding. Usage of this macro
+%    is deprecated.
+%
+%    \begin{macrocode}
+\DeclareRobustCommand{\latintext}{%
+  \fontencoding{\latinencoding}\selectfont
+  \def\encodingdefault{\latinencoding}}
 %    \end{macrocode}
 %
-% Now |captions| and |captions.licr|, depending on the engine. And
-% below also for dates. They rely on a few auxiliary macros. It is
-% expected the ini file provides the complete set in Unicode and LICR,
-% in that order.
+%  \end{macro}
+%
+%  \begin{macro}{\textlatin}
+%    This command takes an argument which is then typeset using the
+%    requested font encoding. In order to avoid many encoding switches
+%    it operates in a local scope.
 %
 %    \begin{macrocode}
-\ifcase\bbl@engine
-  \bbl@csarg\def{inikv@captions.licr}#1#2{%
-    \bbl@ini@captions@aux{#1}{#2}}
+\ifx\@undefined\DeclareTextFontCommand
+  \DeclareRobustCommand{\textlatin}[1]{\leavevmode{\latintext #1}}
 \else
-  \def\bbl@inikv@captions#1#2{%
-    \bbl@ini@captions@aux{#1}{#2}}
+  \DeclareTextFontCommand{\textlatin}{\latintext}
 \fi
 %    \end{macrocode}
 %
-% The auxiliary macro for captions define |\<caption>name|.
+% For several functions, we need to execute some code with
+% |\selectfont|. With \LaTeX\ 2021-06-01, there is a hook for this
+% purpose, but in older versions the \LaTeX{} command is patched (the
+% latter solution will be eventually removed).
 %
 %    \begin{macrocode}
-\def\bbl@ini@captions@template#1#2{% string language tempa=capt-name
-  \bbl@replace\bbl@tempa{.template}{}%
-  \def\bbl@toreplace{#1{}}%
-  \bbl@replace\bbl@toreplace{[ ]}{\nobreakspace{}}%
-  \bbl@replace\bbl@toreplace{[[}{\csname}%
-  \bbl@replace\bbl@toreplace{[}{\csname the}% 
-  \bbl@replace\bbl@toreplace{]]}{name\endcsname{}}%
-  \bbl@replace\bbl@toreplace{]}{\endcsname{}}% 
-  \bbl@xin@{,\bbl@tempa,}{,chapter,appendix,part,}%
-  \ifin@
-    \@nameuse{bbl@patch\bbl@tempa}%
-    \global\bbl@csarg\let{\bbl@tempa fmt@#2}\bbl@toreplace
-  \fi 
-  \bbl@xin@{,\bbl@tempa,}{,figure,table,}%
-  \ifin@
-    \toks@\expandafter{\bbl@toreplace}%
-    \bbl@exp{\gdef\<fnum@\bbl@tempa>{\the\toks@}}%
-  \fi}
-\def\bbl@ini@captions@aux#1#2{%
-  \bbl@trim@def\bbl@tempa{#1}%
-  \bbl@xin@{.template}{\bbl@tempa}%
-  \ifin@
-    \bbl@ini@captions@template{#2}\languagename
-  \else
-    \bbl@ifblank{#2}%
-      {\bbl@exp{%
-         \toks@{\\\bbl@nocaption{\bbl@tempa}{\languagename\bbl@tempa name}}}}%
-      {\bbl@trim\toks@{#2}}%
-    \bbl@exp{%
-      \\\bbl@add\\\bbl@savestrings{%
-        \\\SetString\<\bbl@tempa name>{\the\toks@}}}%
-    \toks@\expandafter{\bbl@captionslist}%
-    \bbl@exp{\\\in@{\<\bbl@tempa name>}{\the\toks@}}%
-    \ifin@\else
-      \bbl@exp{%
-        \\\bbl@add\<bbl@extracaps@\languagename>{\<\bbl@tempa name>}%
-        \\\bbl@toglobal\<bbl@extracaps@\languagename>}%
-    \fi
-  \fi}
+\bbl@ifformatlater{2021-06-01}%
+  {\def\bbl@patchfont#1{\AddToHook{selectfont}{#1}}}
+  {\def\bbl@patchfont#1{%
+     \expandafter\bbl@add\csname selectfont \endcsname{#1}%
+     \expandafter\bbl@toglobal\csname selectfont \endcsname}}
 %    \end{macrocode}
 %
-% \textbf{Labels.} Captions must contain just strings, no
-% format at all, so there is new group in ini files. 
-% 
-%    \begin{macrocode}
-\def\bbl@list@the{%
-  part,chapter,section,subsection,subsubsection,paragraph,%
-  subparagraph,enumi,enumii,enumiii,enumiv,equation,figure,%
-  table,page,footnote,mpfootnote,mpfn}
-\def\bbl@map@cnt#1{%  #1:roman,etc, // #2:enumi,etc
-  \bbl@ifunset{bbl@map@#1@\languagename}%
-    {\@nameuse{#1}}%
-    {\@nameuse{bbl@map@#1@\languagename}}}
-\def\bbl@inikv@labels#1#2{%
-  \in@{.map}{#1}%
-  \ifin@
-    \ifx\bbl@KVP@labels\@nil\else
-      \bbl@xin@{ map }{ \bbl@KVP@labels\space}%
-      \ifin@
-        \def\bbl@tempc{#1}%
-        \bbl@replace\bbl@tempc{.map}{}%
-        \in@{,#2,}{,arabic,roman,Roman,alph,Alph,fnsymbol,}%
-        \bbl@exp{%
-          \gdef\<bbl@map@\bbl@tempc @\languagename>%
-            {\ifin@\<#2>\else\\\localecounter{#2}\fi}}%
-        \bbl@foreach\bbl@list@the{%
-          \bbl@ifunset{the##1}{}%
-            {\bbl@exp{\let\\\bbl@tempd\<the##1>}%
-             \bbl@exp{%
-               \\\bbl@sreplace\<the##1>%
-                 {\<\bbl@tempc>{##1}}{\\\bbl@map@cnt{\bbl@tempc}{##1}}%
-               \\\bbl@sreplace\<the##1>%
-                 {\<\@empty @\bbl@tempc>\<c@##1>}{\\\bbl@map@cnt{\bbl@tempc}{##1}}}%
-             \expandafter\ifx\csname the##1\endcsname\bbl@tempd\else
-               \toks@\expandafter\expandafter\expandafter{%
-                 \csname the##1\endcsname}%
-               \expandafter\xdef\csname the##1\endcsname{{\the\toks@}}%
-             \fi}}%
-      \fi
-    \fi
-  %
-  \else
-    %
-    % The following code is still under study. You can test it and make
-    % suggestions. Eg, enumerate.2 = ([enumi]).([enumii]). It's
-    % language dependent.
-    \in@{enumerate.}{#1}%
-    \ifin@
-      \def\bbl@tempa{#1}%
-      \bbl@replace\bbl@tempa{enumerate.}{}%
-      \def\bbl@toreplace{#2}%
-      \bbl@replace\bbl@toreplace{[ ]}{\nobreakspace{}}%
-      \bbl@replace\bbl@toreplace{[}{\csname the}% 
-      \bbl@replace\bbl@toreplace{]}{\endcsname{}}% 
-      \toks@\expandafter{\bbl@toreplace}%
-      % TODO. Execute only once:
-      \bbl@exp{%
-        \\\bbl@add\<extras\languagename>{%
-          \\\babel@save\<labelenum\romannumeral\bbl@tempa>%
-          \def\<labelenum\romannumeral\bbl@tempa>{\the\toks@}}%
-        \\\bbl@toglobal\<extras\languagename>}%
-    \fi
-  \fi}
-%    \end{macrocode}
+% \end{macro}
 %
-% To show correctly some captions in a few languages, we need to patch
-% some internal macros, because the order is hardcoded. For example, in
-% Japanese the chapter number is surrounded by two string, while in
-% Hungarian is placed after. These replacement works in many classes,
-% but not all. Actually, the following lines are somewhat tentative.
+% \subsection{Basic bidi support}
 %
-%    \begin{macrocode}
-\def\bbl@chaptype{chapter}
-\ifx\@makechapterhead\@undefined
-  \let\bbl@patchchapter\relax
-\else\ifx\thechapter\@undefined
-  \let\bbl@patchchapter\relax
-\else\ifx\ps@headings\@undefined
-  \let\bbl@patchchapter\relax
-\else
-  \def\bbl@patchchapter{%
-    \global\let\bbl@patchchapter\relax
-    \bbl@add\appendix{\def\bbl@chaptype{appendix}}% Not harmful, I hope
-    \bbl@toglobal\appendix
-    \bbl@sreplace\ps@headings
-      {\@chapapp\ \thechapter}%
-      {\bbl@chapterformat}%  
-    \bbl@toglobal\ps@headings
-    \bbl@sreplace\chaptermark
-      {\@chapapp\ \thechapter}%
-      {\bbl@chapterformat}%  
-    \bbl@toglobal\chaptermark
-    \bbl@sreplace\@makechapterhead
-      {\@chapapp\space\thechapter}%
-      {\bbl@chapterformat}%
-    \bbl@toglobal\@makechapterhead
-    \gdef\bbl@chapterformat{%
-      \bbl@ifunset{bbl@\bbl@chaptype fmt@\languagename}%
-        {\@chapapp\space\thechapter}
-        {\@nameuse{bbl@\bbl@chaptype fmt@\languagename}}}}
-  \let\bbl@patchappendix\bbl@patchchapter
-\fi\fi\fi
-\ifx\@part\@undefined
-  \let\bbl@patchpart\relax
-\else
-  \def\bbl@patchpart{%
-    \global\let\bbl@patchpart\relax
-    \bbl@sreplace\@part
-      {\partname\nobreakspace\thepart}%
-      {\bbl@partformat}%
-    \bbl@toglobal\@part
-    \gdef\bbl@partformat{%
-      \bbl@ifunset{bbl@partfmt@\languagename}%
-        {\partname\nobreakspace\thepart}
-        {\@nameuse{bbl@partfmt@\languagename}}}}
-\fi
-%    \end{macrocode}
+% \textbf{Work in progress.} This code is currently placed here for
+% practical reasons. It will be moved to the correct place soon, I
+% hope.
 %
-% \textbf{Date.} TODO. Document
+% It is loosely based on |rlbabel.def|, but most of it has been
+% developed from scratch. This \babel{} module (by Johannes Braams and
+% Boris Lavva) has served the purpose of typesetting R documents for
+% two decades, and despite its flaws I think it is still a good starting
+% point (some parts have been copied here almost verbatim), partly
+% thanks to its simplicity. I've also looked at \textsc{arabi} (by
+% Youssef Jabri), which is compatible with \babel{}.
 %
-%    \begin{macrocode}
-% Arguments are _not_ protected.
-\let\bbl@calendar\@empty
-\DeclareRobustCommand\localedate[1][]{\bbl@localedate{#1}}
-\def\bbl@localedate#1#2#3#4{%
-  \begingroup
-    \ifx\@empty#1\@empty\else
-      \let\bbl@ld@calendar\@empty
-      \let\bbl@ld@variant\@empty
-      \edef\bbl@tempa{\zap@space#1 \@empty}%
-      \def\bbl@tempb##1=##2\@@{\@namedef{bbl@ld@##1}{##2}}%
-      \bbl@foreach\bbl@tempa{\bbl@tempb##1\@@}%
-      \edef\bbl@calendar{%
-        \bbl@ld@calendar
-        \ifx\bbl@ld@variant\@empty\else
-          .\bbl@ld@variant
-        \fi}%
-      \bbl@replace\bbl@calendar{gregorian}{}%
-    \fi
-    \bbl@cased
-      {\@nameuse{bbl@date@\languagename @\bbl@calendar}{#2}{#3}{#4}}%
-  \endgroup}
-% eg: 1=months, 2=wide, 3=1, 4=dummy, 5=value, 6=calendar
-\def\bbl@inidate#1.#2.#3.#4\relax#5#6{% TODO - ignore with 'captions'
-  \bbl@trim@def\bbl@tempa{#1.#2}%
-  \bbl@ifsamestring{\bbl@tempa}{months.wide}%      to savedate
-    {\bbl@trim@def\bbl@tempa{#3}%
-     \bbl@trim\toks@{#5}%
-     \@temptokena\expandafter{\bbl@savedate}%
-     \bbl@exp{%   Reverse order - in ini last wins
-       \def\\\bbl@savedate{%
-         \\\SetString\<month\romannumeral\bbl@tempa#6name>{\the\toks@}%
-         \the\@temptokena}}}%
-    {\bbl@ifsamestring{\bbl@tempa}{date.long}%     defined now
-      {\lowercase{\def\bbl@tempb{#6}}%
-       \bbl@trim@def\bbl@toreplace{#5}%
-       \bbl@TG@@date
-       \bbl@ifunset{bbl@date@\languagename @}%
-         {\bbl@exp{% TODO. Move to a better place.
-            \gdef\<\languagename date>{\\\protect\<\languagename date >}%
-            \gdef\<\languagename date >####1####2####3{%
-              \\\bbl@usedategrouptrue
-              \<bbl@ensure@\languagename>{%
-                \\\localedate{####1}{####2}{####3}}}%
-            \\\bbl@add\\\bbl@savetoday{%
-              \\\SetString\\\today{%
-                \<\languagename date>%
-                   {\\\the\year}{\\\the\month}{\\\the\day}}}}}%
-         {}%      
-       \global\bbl@csarg\let{date@\languagename @}\bbl@toreplace
-       \ifx\bbl@tempb\@empty\else
-         \global\bbl@csarg\let{date@\languagename @\bbl@tempb}\bbl@toreplace
-       \fi}%
-      {}}}
+% There are two ways of modifying macros to make them “bidi”, namely,
+% by patching the internal low-level macros (which is what I have done
+% with lists, columns, counters, tocs, much like |rlbabel| did), and
+% by introducing a “middle layer” just below the user interface
+% (sectioning, footnotes).
+%
+% \begin{itemize}
+% \item pdftex provides a minimal support for bidi text, and it
+%   must be done by hand. Vertical typesetting is not possible.
+% \item \xetex{} is somewhat better, thanks to its font engine
+%   (even if not always reliable) and a few additional tools. However,
+%   very little is done at the paragraph level. Another challenging
+%   problem is text direction does not honour \TeX{} grouping.
+% \item \luatex{} can provide the most complete solution, as we can
+%   manipulate almost freely the node list, the generated lines,
+%   and so on, but bidi text does not work out of the box and some
+%   development is necessary. It also provides tools to properly
+%   set left-to-right and right-to-left page layouts. As Lua\TeX-ja
+%   shows, vertical typesetting is possible, too.
+% \end{itemize}
+%
+%    \begin{macrocode}
+\bbl@trace{Loading basic (internal) bidi support}
+\ifodd\bbl@engine
+\else % TODO. Move to txtbabel
+  \ifnum\bbl@bidimode>100 \ifnum\bbl@bidimode<200
+    \bbl@error
+      {The bidi method 'basic' is available only in\\%
+       luatex. I'll continue with 'bidi=default', so\\%
+       expect wrong results}%
+      {See the manual for further details.}%
+    \let\bbl@beforeforeign\leavevmode
+    \AtEndOfPackage{%
+      \EnableBabelHook{babel-bidi}%
+      \bbl@xebidipar}
+  \fi\fi
+  \def\bbl@loadxebidi#1{%
+    \ifx\RTLfootnotetext\@undefined
+      \AtEndOfPackage{%
+        \EnableBabelHook{babel-bidi}%
+        \ifx\fontspec\@undefined
+          \bbl@loadfontspec % bidi needs fontspec
+        \fi
+        \usepackage#1{bidi}}%
+    \fi}
+  \ifnum\bbl@bidimode>200
+    \ifcase\expandafter\@gobbletwo\the\bbl@bidimode\or
+      \bbl@tentative{bidi=bidi}
+      \bbl@loadxebidi{}
+    \or
+      \bbl@loadxebidi{[rldocument]}
+    \or
+      \bbl@loadxebidi{}
+    \fi
+  \fi
+\fi
+% TODO? Separate:
+\ifnum\bbl@bidimode=\@ne
+  \let\bbl@beforeforeign\leavevmode
+  \ifodd\bbl@engine
+    \newattribute\bbl@attr@dir
+    \directlua{ Babel.attr_dir = luatexbase.registernumber'bbl@attr@dir' }
+    \bbl@exp{\output{\bodydir\pagedir\the\output}}
+  \fi
+  \AtEndOfPackage{%
+    \EnableBabelHook{babel-bidi}%
+    \ifodd\bbl@engine\else
+      \bbl@xebidipar
+    \fi}
+\fi
 %    \end{macrocode}
 %
-% \textbf{Dates} will require some macros for the basic formatting.
-% They may be redefined by language, so ``semi-public'' names (camel
-% case) are used. Oddly enough, the CLDR places particles like “de”
-% inconsistently in either in the date or in the month name. Note after
-% |\bbl@replace| |\toks@| contains the resulting string, which is used
-% by |\bbl@replace@finish@iii| (this implicit behavior doesn't seem a
-% good idea, but it’s efficient).
+% Now come the macros used to set the direction when a language is
+% switched. First the (mostly) common macros.
 %
 %    \begin{macrocode}
-\let\bbl@calendar\@empty
-\newcommand\BabelDateSpace{\nobreakspace}
-\newcommand\BabelDateDot{.\@}  % TODO. \let instead of repeating
-\newcommand\BabelDated[1]{{\number#1}}
-\newcommand\BabelDatedd[1]{{\ifnum#1<10 0\fi\number#1}}
-\newcommand\BabelDateM[1]{{\number#1}}
-\newcommand\BabelDateMM[1]{{\ifnum#1<10 0\fi\number#1}}
-\newcommand\BabelDateMMMM[1]{{%
-  \csname month\romannumeral#1\bbl@calendar name\endcsname}}%
-\newcommand\BabelDatey[1]{{\number#1}}%
-\newcommand\BabelDateyy[1]{{%
-  \ifnum#1<10 0\number#1 %
-  \else\ifnum#1<100 \number#1 %
-  \else\ifnum#1<1000 \expandafter\@gobble\number#1 %
-  \else\ifnum#1<10000 \expandafter\@gobbletwo\number#1 %
+\bbl@trace{Macros to switch the text direction}
+\def\bbl@alscripts{,Arabic,Syriac,Thaana,}
+\def\bbl@rscripts{% TODO. Base on codes ??
+  ,Imperial Aramaic,Avestan,Cypriot,Hatran,Hebrew,%
+  Old Hungarian,Old Hungarian,Lydian,Mandaean,Manichaean,%
+  Manichaean,Meroitic Cursive,Meroitic,Old North Arabian,%
+  Nabataean,N'Ko,Orkhon,Palmyrene,Inscriptional Pahlavi,%
+  Psalter Pahlavi,Phoenician,Inscriptional Parthian,Samaritan,%
+  Old South Arabian,}%
+\def\bbl@provide@dirs#1{%
+  \bbl@xin@{\csname bbl@sname@#1\endcsname}{\bbl@alscripts\bbl@rscripts}%
+  \ifin@
+    \global\bbl@csarg\chardef{wdir@#1}\@ne
+    \bbl@xin@{\csname bbl@sname@#1\endcsname}{\bbl@alscripts}%
+    \ifin@
+      \global\bbl@csarg\chardef{wdir@#1}\tw@  % useless in xetex
+    \fi
   \else
-    \bbl@error
-      {Currently two-digit years are restricted to the\\
-       range 0-9999.}%
-      {There is little you can do. Sorry.}%
-  \fi\fi\fi\fi}}
-\newcommand\BabelDateyyyy[1]{{\number#1}} % TODO - add leading 0
-\def\bbl@replace@finish@iii#1{%
-  \bbl@exp{\def\\#1####1####2####3{\the\toks@}}}
-\def\bbl@TG@@date{%
-  \bbl@replace\bbl@toreplace{[ ]}{\BabelDateSpace{}}%
-  \bbl@replace\bbl@toreplace{[.]}{\BabelDateDot{}}%
-  \bbl@replace\bbl@toreplace{[d]}{\BabelDated{####3}}%
-  \bbl@replace\bbl@toreplace{[dd]}{\BabelDatedd{####3}}%
-  \bbl@replace\bbl@toreplace{[M]}{\BabelDateM{####2}}%
-  \bbl@replace\bbl@toreplace{[MM]}{\BabelDateMM{####2}}%
-  \bbl@replace\bbl@toreplace{[MMMM]}{\BabelDateMMMM{####2}}%
-  \bbl@replace\bbl@toreplace{[y]}{\BabelDatey{####1}}%
-  \bbl@replace\bbl@toreplace{[yy]}{\BabelDateyy{####1}}%
-  \bbl@replace\bbl@toreplace{[yyyy]}{\BabelDateyyyy{####1}}%
-  \bbl@replace\bbl@toreplace{[y|}{\bbl@datecntr[####1|}%
-  \bbl@replace\bbl@toreplace{[m|}{\bbl@datecntr[####2|}%
-  \bbl@replace\bbl@toreplace{[d|}{\bbl@datecntr[####3|}%
-  \bbl@replace@finish@iii\bbl@toreplace}
-\def\bbl@datecntr{\expandafter\bbl@xdatecntr\expandafter}
-\def\bbl@xdatecntr[#1|#2]{\localenumeral{#2}{#1}}
+    \global\bbl@csarg\chardef{wdir@#1}\z@
+  \fi
+  \ifodd\bbl@engine
+    \bbl@csarg\ifcase{wdir@#1}%
+      \directlua{ Babel.locale_props[\the\localeid].textdir = 'l' }%
+    \or
+      \directlua{ Babel.locale_props[\the\localeid].textdir = 'r' }%
+    \or
+      \directlua{ Babel.locale_props[\the\localeid].textdir = 'al' }%
+    \fi
+  \fi}
+\def\bbl@switchdir{%
+  \bbl@ifunset{bbl@lsys@\languagename}{\bbl@provide@lsys{\languagename}}{}%
+  \bbl@ifunset{bbl@wdir@\languagename}{\bbl@provide@dirs{\languagename}}{}%
+  \bbl@exp{\\\bbl@setdirs\bbl@cl{wdir}}}
+\def\bbl@setdirs#1{% TODO - math
+  \ifcase\bbl@select@type % TODO - strictly, not the right test
+    \bbl@bodydir{#1}%
+    \bbl@pardir{#1}%
+  \fi
+  \bbl@textdir{#1}}
+% TODO. Only if \bbl@bidimode > 0?:
+\AddBabelHook{babel-bidi}{afterextras}{\bbl@switchdir}
+\DisableBabelHook{babel-bidi}
 %    \end{macrocode}
 %
-% \textbf{Transforms.}
+% Now the engine-dependent macros. TODO. Must be moved to the engine
+% files.
 %
-%    \begin{macrocode}
-\let\bbl@release@transforms\@empty
-\@namedef{bbl@inikv@transforms.prehyphenation}{%
-  \bbl@transforms\babelprehyphenation}
-\@namedef{bbl@inikv@transforms.posthyphenation}{%
-  \bbl@transforms\babelposthyphenation}
-\def\bbl@transforms@aux#1#2#3,#4\relax{#1{#2}{#3}{#4}}
-\begingroup
-  \catcode`\%=12
-  \catcode`\&=14
-  \gdef\bbl@transforms#1#2#3{&%
-    \ifx\bbl@KVP@transforms\@nil\else
-      \directlua{
-         str = [==[#2]==]
-         str = str:gsub('%.%d+%.%d+$', '')
-         tex.print([[\def\string\babeltempa{]] .. str .. [[}]])
-      }&%
-      \bbl@xin@{,\babeltempa,}{,\bbl@KVP@transforms,}&%
-      \ifin@
-        \in@{.0$}{#2$}&%
-        \ifin@
-           \g@addto@macro\bbl@release@transforms{&%
-              \relax\bbl@transforms@aux#1{\languagename}{#3}}&%
+%    \begin{macrocode} 
+\ifodd\bbl@engine  % luatex=1
+\else % pdftex=0, xetex=2
+  \newcount\bbl@dirlevel
+  \chardef\bbl@thetextdir\z@
+  \chardef\bbl@thepardir\z@
+  \def\bbl@textdir#1{%
+    \ifcase#1\relax
+       \chardef\bbl@thetextdir\z@
+       \bbl@textdir@i\beginL\endL
+     \else
+       \chardef\bbl@thetextdir\@ne
+       \bbl@textdir@i\beginR\endR
+    \fi}
+  \def\bbl@textdir@i#1#2{%
+    \ifhmode
+      \ifnum\currentgrouplevel>\z@
+        \ifnum\currentgrouplevel=\bbl@dirlevel
+          \bbl@error{Multiple bidi settings inside a group}%
+            {I'll insert a new group, but expect wrong results.}%
+          \bgroup\aftergroup#2\aftergroup\egroup
         \else
-           \g@addto@macro\bbl@release@transforms{, {#3}}&%
+          \ifcase\currentgrouptype\or % 0 bottom
+            \aftergroup#2% 1 simple {}
+          \or
+            \bgroup\aftergroup#2\aftergroup\egroup % 2 hbox
+          \or
+            \bgroup\aftergroup#2\aftergroup\egroup % 3 adj hbox
+          \or\or\or % vbox vtop align
+          \or
+            \bgroup\aftergroup#2\aftergroup\egroup % 7 noalign
+          \or\or\or\or\or\or % output math disc insert vcent mathchoice
+          \or
+            \aftergroup#2% 14 \begingroup
+          \else
+            \bgroup\aftergroup#2\aftergroup\egroup % 15 adj
+          \fi
         \fi
+        \bbl@dirlevel\currentgrouplevel
       \fi
+      #1%
     \fi}
-\endgroup
-%    \end{macrocode}
-%
-% Language and Script values to be used when defining a font or
-% setting the direction are set with the following macros.
-%
-%    \begin{macrocode}
-\def\bbl@provide@lsys#1{%
-  \bbl@ifunset{bbl@lname@#1}%
-    {\bbl@load@info{#1}}%
-    {}%
-  \bbl@csarg\let{lsys@#1}\@empty
-  \bbl@ifunset{bbl@sname@#1}{\bbl@csarg\gdef{sname@#1}{Default}}{}%
-  \bbl@ifunset{bbl@sotf@#1}{\bbl@csarg\gdef{sotf@#1}{DFLT}}{}%
-  \bbl@csarg\bbl@add@list{lsys@#1}{Script=\bbl@cs{sname@#1}}%
-  \bbl@ifunset{bbl@lname@#1}{}%
-    {\bbl@csarg\bbl@add@list{lsys@#1}{Language=\bbl@cs{lname@#1}}}%
-  \ifcase\bbl@engine\or\or
-    \bbl@ifunset{bbl@prehc@#1}{}%
-      {\bbl@exp{\\\bbl@ifblank{\bbl@cs{prehc@#1}}}%
-        {}%
-        {\ifx\bbl@xenohyph\@undefined
-           \let\bbl@xenohyph\bbl@xenohyph@d
-           \ifx\AtBeginDocument\@notprerr
-             \expandafter\@secondoftwo  % to execute right now
-           \fi
-           \AtBeginDocument{%
-             \bbl@patchfont{\bbl@xenohyph}%
-             \expandafter\selectlanguage\expandafter{\languagename}}%
-        \fi}}%
-  \fi
-  \bbl@csarg\bbl@toglobal{lsys@#1}}
-\def\bbl@xenohyph@d{%
-  \bbl@ifset{bbl@prehc@\languagename}%
-    {\ifnum\hyphenchar\font=\defaulthyphenchar
-       \iffontchar\font\bbl@cl{prehc}\relax
-         \hyphenchar\font\bbl@cl{prehc}\relax
-       \else\iffontchar\font"200B
-         \hyphenchar\font"200B
-       \else
-         \bbl@warning
-           {Neither 0 nor ZERO WIDTH SPACE are available\\%
-            in the current font, and therefore the hyphen\\%
-            will be printed. Try changing the fontspec's\\%
-            'HyphenChar' to another value, but be aware\\%
-            this setting is not safe (see the manual)}%
-         \hyphenchar\font\defaulthyphenchar     
-       \fi\fi
-     \fi}%
-    {\hyphenchar\font\defaulthyphenchar}}
-  % \fi}
+  \def\bbl@pardir#1{\chardef\bbl@thepardir#1\relax}
+  \let\bbl@bodydir\@gobble
+  \let\bbl@pagedir\@gobble
+  \def\bbl@dirparastext{\chardef\bbl@thepardir\bbl@thetextdir}
 %    \end{macrocode}
 %
-% The following |ini| reader ignores everything but the
-% |identification| section. It is called when a font is defined (ie,
-% when the language is first selected) to know which script/language
-% must be enabled. This means we must make sure a few characters are
-% not active. The |ini| is not read directly, but with a proxy |tex|
-% file named as the language (which means any code in it must be
-% skipped, too).
+% The following command is executed only if there is a right-to-left
+% script (once). It activates the |\everypar| hack for \xetex, to
+% properly handle the par direction. Note text and par dirs are
+% decoupled to some extent (although not completely).
 %
 %    \begin{macrocode}
-\def\bbl@load@info#1{%
-  \def\BabelBeforeIni##1##2{%
-    \begingroup
-      \bbl@read@ini{##1}0%
-      \endinput          % babel- .tex may contain onlypreamble's
-    \endgroup}%            boxed, to avoid extra spaces:
-  {\bbl@input@texini{#1}}}
+  \def\bbl@xebidipar{%
+    \let\bbl@xebidipar\relax
+    \TeXXeTstate\@ne
+    \def\bbl@xeeverypar{%
+      \ifcase\bbl@thepardir
+        \ifcase\bbl@thetextdir\else\beginR\fi
+      \else
+        {\setbox\z@\lastbox\beginR\box\z@}%
+      \fi}%
+    \let\bbl@severypar\everypar
+    \newtoks\everypar
+    \everypar=\bbl@severypar
+    \bbl@severypar{\bbl@xeeverypar\the\everypar}}
+  \ifnum\bbl@bidimode>200
+    \let\bbl@textdir@i\@gobbletwo
+    \let\bbl@xebidipar\@empty
+    \AddBabelHook{bidi}{foreign}{%
+      \def\bbl@tempa{\def\BabelText####1}%
+      \ifcase\bbl@thetextdir
+        \expandafter\bbl@tempa\expandafter{\BabelText{\LR{##1}}}%
+      \else
+        \expandafter\bbl@tempa\expandafter{\BabelText{\RL{##1}}}%
+      \fi}
+    \def\bbl@pardir#1{\ifcase#1\relax\setLR\else\setRL\fi}
+  \fi
+\fi
 %    \end{macrocode}
 %
-% A tool to define the macros for native digits from the list provided 
-% in the |ini| file. Somewhat convoluted because there are 10 digits, 
-% but only 9 arguments in \TeX. Non-digits characters are kept. The
-% first macro is the generic “localized” command.
+% A tool for weak L (mainly digits). We also disable warnings with
+% \textsf{hyperref}.
 %
 %    \begin{macrocode}
-\def\bbl@setdigits#1#2#3#4#5{%
-  \bbl@exp{%
-    \def\<\languagename digits>####1{%       ie, \langdigits
-      \<bbl@digits@\languagename>####1\\\@nil}%
-    \let\<bbl@cntr@digits@\languagename>\<\languagename digits>%
-    \def\<\languagename counter>####1{%      ie, \langcounter
-      \\\expandafter\<bbl@counter@\languagename>%
-      \\\csname c@####1\endcsname}%
-    \def\<bbl@counter@\languagename>####1{% ie, \bbl@counter@lang
-      \\\expandafter\<bbl@digits@\languagename>%
-      \\\number####1\\\@nil}}%
-  \def\bbl@tempa##1##2##3##4##5{%
-    \bbl@exp{%    Wow, quite a lot of hashes! :-(
-      \def\<bbl@digits@\languagename>########1{%
-       \\\ifx########1\\\@nil              % ie, \bbl@digits@lang
-       \\\else
-         \\\ifx0########1#1%
-         \\\else\\\ifx1########1#2%
-         \\\else\\\ifx2########1#3%
-         \\\else\\\ifx3########1#4%
-         \\\else\\\ifx4########1#5%
-         \\\else\\\ifx5########1##1%
-         \\\else\\\ifx6########1##2%
-         \\\else\\\ifx7########1##3%
-         \\\else\\\ifx8########1##4%
-         \\\else\\\ifx9########1##5%
-         \\\else########1%
-         \\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi\\\fi
-         \\\expandafter\<bbl@digits@\languagename>%
-       \\\fi}}}%
-  \bbl@tempa}
+\DeclareRobustCommand\babelsublr[1]{\leavevmode{\bbl@textdir\z@#1}}
+\AtBeginDocument{%
+  \ifx\pdfstringdefDisableCommands\@undefined\else
+    \ifx\pdfstringdefDisableCommands\relax\else
+      \pdfstringdefDisableCommands{\let\babelsublr\@firstofone}%
+    \fi
+  \fi}
 %    \end{macrocode}
 %
-% Alphabetic counters must be converted from a space separated list to
-% an |\ifcase| structure.
+% \subsection{Local Language Configuration}
+%
+% \begin{macro}{\loadlocalcfg}
+%
+% At some sites it may be necessary to add site-specific actions to
+% a language definition file. This can be done by creating a file
+% with the same name as the language definition file, but with the
+% extension \file{.cfg}. For instance the file \file{norsk.cfg}
+% will be loaded when the language definition file \file{norsk.ldf}
+% is loaded. 
+%
+% For plain-based formats we don't want to override the definition
+% of |\loadlocalcfg| from \file{plain.def}.
 %
 %    \begin{macrocode}
-\def\bbl@buildifcase#1 {% Returns \bbl@tempa, requires \toks@={}
-  \ifx\\#1%             % \\ before, in case #1 is multiletter
-    \bbl@exp{%
-      \def\\\bbl@tempa####1{%
-        \<ifcase>####1\space\the\toks@\<else>\\\@ctrerr\<fi>}}%
-  \else
-    \toks@\expandafter{\the\toks@\or #1}%
-    \expandafter\bbl@buildifcase
-  \fi}
-%    \end{macrocode}
+\bbl@trace{Local Language Configuration}
+\ifx\loadlocalcfg\@undefined
+  \@ifpackagewith{babel}{noconfigs}%
+    {\let\loadlocalcfg\@gobble}%
+    {\def\loadlocalcfg#1{%
+      \InputIfFileExists{#1.cfg}%
+        {\typeout{*************************************^^J%
+                       * Local config file #1.cfg used^^J%
+                       *}}%
+        \@empty}}
+\fi
+%    \end{macrocode}%
+%    \end{macro}
 %
-% The code for additive counters is somewhat tricky and it's based on
-% the fact the arguments just before |\@@| collects digits which have
-% been left ‘unused’ in previous arguments, the first of them being the
-% number of digits in the number to be converted. This explains the
-% reverse set |76543210|. Digits above 10000 are not handled yet. When
-% the key contains the subkey |.F.|, the number after is treated as an
-% special case, for a fixed form (see |babel-he.ini|, for example).
+% \subsection{Language options}
+%
+% Languages are loaded when processing the corresponding option
+% \textit{except} if a |main| language has been set. In such a
+% case, it is not loaded until all options has been processed.
+% The following macro inputs the ldf file and does some additional
+% checks (|\input| works, too, but possible errors are not catched).
 %
 %    \begin{macrocode}
-\newcommand\localenumeral[2]{\bbl@cs{cntr@#1@\languagename}{#2}}
-\def\bbl@localecntr#1#2{\localenumeral{#2}{#1}}
-\newcommand\localecounter[2]{%
-  \expandafter\bbl@localecntr
-  \expandafter{\number\csname c@#2\endcsname}{#1}}
-\def\bbl@alphnumeral#1#2{%
-  \expandafter\bbl@alphnumeral@i\number#2 76543210\@@{#1}}
-\def\bbl@alphnumeral@i#1#2#3#4#5#6#7#8\@@#9{%
-  \ifcase\@car#8\@nil\or   % Currenty <10000, but prepared for bigger
-    \bbl@alphnumeral@ii{#9}000000#1\or
-    \bbl@alphnumeral@ii{#9}00000#1#2\or
-    \bbl@alphnumeral@ii{#9}0000#1#2#3\or
-    \bbl@alphnumeral@ii{#9}000#1#2#3#4\else
-    \bbl@alphnum@invalid{>9999}%
-  \fi}
-\def\bbl@alphnumeral@ii#1#2#3#4#5#6#7#8{%
-  \bbl@ifunset{bbl@cntr@#1.F.\number#5#6#7#8@\languagename}%
-    {\bbl@cs{cntr@#1.4@\languagename}#5%
-     \bbl@cs{cntr@#1.3@\languagename}#6%
-     \bbl@cs{cntr@#1.2@\languagename}#7%
-     \bbl@cs{cntr@#1.1@\languagename}#8%
-     \ifnum#6#7#8>\z@ % TODO. An ad hoc rule for Greek. Ugly.
-       \bbl@ifunset{bbl@cntr@#1.S.321@\languagename}{}%
-         {\bbl@cs{cntr@#1.S.321@\languagename}}%
-     \fi}%
-    {\bbl@cs{cntr@#1.F.\number#5#6#7#8@\languagename}}}
-\def\bbl@alphnum@invalid#1{%
-  \bbl@error{Alphabetic numeral too large (#1)}%
-    {Currently this is the limit.}}
+\bbl@trace{Language options}
+\let\bbl@afterlang\relax
+\let\BabelModifiers\relax
+\let\bbl@loaded\@empty
+\def\bbl@load@language#1{%
+  \InputIfFileExists{#1.ldf}%
+    {\edef\bbl@loaded{\CurrentOption
+       \ifx\bbl@loaded\@empty\else,\bbl@loaded\fi}%
+     \expandafter\let\expandafter\bbl@afterlang
+        \csname\CurrentOption.ldf-h@@k\endcsname
+     \expandafter\let\expandafter\BabelModifiers
+        \csname bbl@mod@\CurrentOption\endcsname}%
+    {\bbl@error{%
+       Unknown option '\CurrentOption'. Either you misspelled it\\%
+       or the language definition file \CurrentOption.ldf was not found}{%
+       Valid options are, among others: shorthands=, KeepShorthandsActive,\\%
+       activeacute, activegrave, noconfigs, safe=, main=, math=\\%
+       headfoot=, strings=, config=, hyphenmap=, or a language name.}}}
 %    \end{macrocode}
 %
-% The information in the identification section can be useful, so the
-% following macro just exposes it with a user command.
+% Now, we set a few language options whose names are different from
+% |ldf| files. These declarations are preserved for backwards
+% compatibility, but they must be eventually removed. Use proxy files
+% instead.
 %
 %    \begin{macrocode}
-\newcommand\localeinfo[1]{%
-  \bbl@ifunset{bbl@\csname bbl@info@#1\endcsname @\languagename}%
-    {\bbl@error{I've found no info for the current locale.\\%
-                The corresponding ini file has not been loaded\\%
-                Perhaps it doesn't exist}%
-               {See the manual for details.}}%
-    {\bbl@cs{\csname bbl@info@#1\endcsname @\languagename}}}
-% \@namedef{bbl@info@name.locale}{lcname}
-\@namedef{bbl@info@tag.ini}{lini}
-\@namedef{bbl@info@name.english}{elname}
-\@namedef{bbl@info@name.opentype}{lname}
-\@namedef{bbl@info@tag.bcp47}{tbcp}
-\@namedef{bbl@info@language.tag.bcp47}{lbcp}
-\@namedef{bbl@info@tag.opentype}{lotf}
-\@namedef{bbl@info@script.name}{esname}
-\@namedef{bbl@info@script.name.opentype}{sname}
-\@namedef{bbl@info@script.tag.bcp47}{sbcp} 
-\@namedef{bbl@info@script.tag.opentype}{sotf} 
-\let\bbl@ensureinfo\@gobble
-\newcommand\BabelEnsureInfo{%
-  \ifx\InputIfFileExists\@undefined\else
-    \def\bbl@ensureinfo##1{%
-      \bbl@ifunset{bbl@lname@##1}{\bbl@load@info{##1}}{}}%
-  \fi
-  \bbl@foreach\bbl@loaded{{%
-    \def\languagename{##1}%
-    \bbl@ensureinfo{##1}}}}
-%    \end{macrocode}
+\def\bbl@try@load@lang#1#2#3{%
+  \IfFileExists{\CurrentOption.ldf}%
+    {\bbl@load@language{\CurrentOption}}%
+    {#1\bbl@load@language{#2}#3}}
 %
-% More general, but non-expandable, is |\getlocaleproperty|. To inspect
-% every possible loaded |ini|, we define |\LocaleForEach|, where
-% |\bbl@ini@loaded| is a comma-separated list of locales, built by
-% |\bbl@read@ini|. 
+\DeclareOption{hebrew}{%
+  \input{rlbabel.def}%
+  \bbl@load@language{hebrew}}
+\DeclareOption{hungarian}{\bbl@try@load@lang{}{magyar}{}}
+\DeclareOption{lowersorbian}{\bbl@try@load@lang{}{lsorbian}{}}
+\DeclareOption{nynorsk}{\bbl@try@load@lang{}{norsk}{}}
+\DeclareOption{polutonikogreek}{%
+  \bbl@try@load@lang{}{greek}{\languageattribute{greek}{polutoniko}}}
+\DeclareOption{russian}{\bbl@try@load@lang{}{russianb}{}}
+\DeclareOption{ukrainian}{\bbl@try@load@lang{}{ukraineb}{}}
+\DeclareOption{uppersorbian}{\bbl@try@load@lang{}{usorbian}{}}
+%    \end{macrocode}
 %
-%    \begin{macrocode}   
-\newcommand\getlocaleproperty{%
-  \@ifstar\bbl@getproperty@s\bbl@getproperty@x}
-\def\bbl@getproperty@s#1#2#3{%
-  \let#1\relax
-  \def\bbl@elt##1##2##3{%
-    \bbl@ifsamestring{##1/##2}{#3}%
-      {\providecommand#1{##3}%
-       \def\bbl@elt####1####2####3{}}%
+% Another way to extend the list of `known' options for \babel\ was
+% to create the file \file{bblopts.cfg} in which one can add option
+% declarations. However, this mechanism is deprecated -- if you
+% want an alternative name for a language, just create a new |.ldf|
+% file loading the actual one. You can also set the name
+% of the file with the package option |config=<name>|, which will
+% load |<name>.cfg| instead.
+%
+%    \begin{macrocode}
+\ifx\bbl@opt@config\@nnil
+  \@ifpackagewith{babel}{noconfigs}{}%
+    {\InputIfFileExists{bblopts.cfg}%
+      {\typeout{*************************************^^J%
+               * Local config file bblopts.cfg used^^J%
+               *}}%
       {}}%
-  \bbl@cs{inidata@#2}}%
-\def\bbl@getproperty@x#1#2#3{%
-  \bbl@getproperty@s{#1}{#2}{#3}%
-  \ifx#1\relax
-    \bbl@error
-      {Unknown key for locale '#2':\\%
-       #3\\%
-       \string#1 will be set to \relax}%
-      {Perhaps you misspelled it.}%
-  \fi}
-\let\bbl@ini@loaded\@empty
-\newcommand\LocaleForEach{\bbl@foreach\bbl@ini@loaded}
+\else
+  \InputIfFileExists{\bbl@opt@config.cfg}%
+    {\typeout{*************************************^^J%
+             * Local config file \bbl@opt@config.cfg used^^J%
+             *}}%
+    {\bbl@error{%
+       Local config file '\bbl@opt@config.cfg' not found}{%
+       Perhaps you misspelled it.}}%
+\fi
 %    \end{macrocode}
 %
-% \section{Adjusting the Babel bahavior}
+% Recognizing global options in packages not having a closed set of
+% them is not trivial, as for them to be processed they must be defined
+% explicitly. So, package options not yet taken into account and stored
+% in |bbl@language@opts| are assumed to be existing languages (note
+% this list also contains the language given with |main| as the last
+% element). If not declared above, the names of the option and the file
+% are the same. There are two steps -- first process option names and
+% collect the result, which then do the actual declarations.
 %
-% A generic high level inteface is provided to adjust some global
-% and general settings.
+% To allow multiple overlapping replacements, commas in
+% |\bbl@language@opts| are doubled.
 %
 %    \begin{macrocode}
-\newcommand\babeladjust[1]{%  TODO. Error handling.
-  \bbl@forkv{#1}{%
-    \bbl@ifunset{bbl@ADJ@##1@##2}% 
-      {\bbl@cs{ADJ@##1}{##2}}%
-      {\bbl@cs{ADJ@##1@##2}}}}
+\let\bbl@elt\relax
+\let\bbl@tempe\@empty
+\bbl@foreach\@classoptionslist{%
+  \bbl@xin@{,#1,$}{\bbl@language@opts$}% Match last
+  \ifin@\else
+    \bbl@xin@{,#1,}{\bbl@language@opts}% Match non-last
+    \ifin@
+      \bbl@replace\bbl@language@opts{,#1,}{,,}%
+      \edef\bbl@tempe{\bbl@tempe\bbl@elt{3}{#1}}%
+    \else
+      \babel@savecnt\z@ % Use as temp
+      \ifnum\bbl@iniflag<\thr@@ % Optimization: 3 = always ini
+        \IfFileExists{#1.ldf}{\advance\babel@savecnt\@ne}{}%
+      \fi
+      \ifnum\bbl@iniflag>\z@ % Optimization: 0 = always ldf
+        \IfFileExists{babel-#1.tex}{\advance\babel@savecnt\tw@}{}%
+      \fi
+      \ifnum\babel@savecnt>\z@
+        \edef\bbl@tempe{\bbl@tempe\bbl@elt{\the\babel@savecnt}{#1}}%
+      \fi
+    \fi
+  \fi}
 %
-\def\bbl@adjust@lua#1#2{%
-  \ifvmode
-    \ifnum\currentgrouplevel=\z@
-      \directlua{ Babel.#2 }%
-      \expandafter\expandafter\expandafter\@gobble
+\let\bbl@savemain\@empty
+\bbl@foreach\bbl@language@opts{%
+  \edef\bbl@tempe{\bbl@tempe\bbl@elt{3}{#1}}}
+\def\bbl@elt#1#2#3{%
+  \ifx#3\relax % if last
+    \bbl@ifunset{ds@#2}{}%
+      {\bbl@exp{\def\\\bbl@savemain{\\\DeclareOption{#2}{\[ds@#2]}}}}%
+    \bbl@add\bbl@savemain{\bbl@elt{#1}{#2}}% Save main
+    \DeclareOption{#2}{}% 
+  \else
+    \ifnum\bbl@iniflag<\tw@ % other as ldf
+      \ifodd#1\relax % Class: if ldf exists 1,3. Package: always 3
+        \bbl@ifunset{ds@#2}%
+         {\DeclareOption{#2}{\bbl@load@language{#2}}}%
+         {}%
+      \fi
+    \else % other as ini  
+      \ifnum#1>\@ne %  % Class: if ini exists 2,3. Package: always 3
+        \DeclareOption{#2}{%
+          \bbl@ldfinit
+          \babelprovide[import]{#2}%
+          \bbl@afterldf{}}%
+       \fi
     \fi
-  \fi      
-  {\bbl@error   % The error is gobbled if everything went ok.
-     {Currently, #1 related features can be adjusted only\\%
-      in the main vertical list.}%
-     {Maybe things change in the future, but this is what it is.}}}
-\@namedef{bbl@ADJ@bidi.mirroring@on}{%
-  \bbl@adjust@lua{bidi}{mirroring_enabled=true}}
-\@namedef{bbl@ADJ@bidi.mirroring@off}{%
-  \bbl@adjust@lua{bidi}{mirroring_enabled=false}}
-\@namedef{bbl@ADJ@bidi.text@on}{%
-  \bbl@adjust@lua{bidi}{bidi_enabled=true}}
-\@namedef{bbl@ADJ@bidi.text@off}{%
-  \bbl@adjust@lua{bidi}{bidi_enabled=false}}
-\@namedef{bbl@ADJ@bidi.mapdigits@on}{%
-  \bbl@adjust@lua{bidi}{digits_mapped=true}}
-\@namedef{bbl@ADJ@bidi.mapdigits@off}{%
-  \bbl@adjust@lua{bidi}{digits_mapped=false}}
+  \fi
+  #3}
+\bbl@tempe\relax % \relax catches last
+%    \end{macrocode}
 %
-\@namedef{bbl@ADJ@linebreak.sea@on}{%
-  \bbl@adjust@lua{linebreak}{sea_enabled=true}}
-\@namedef{bbl@ADJ@linebreak.sea@off}{%
-  \bbl@adjust@lua{linebreak}{sea_enabled=false}}
-\@namedef{bbl@ADJ@linebreak.cjk@on}{%
-  \bbl@adjust@lua{linebreak}{cjk_enabled=true}}
-\@namedef{bbl@ADJ@linebreak.cjk@off}{%
-  \bbl@adjust@lua{linebreak}{cjk_enabled=false}}
-\@namedef{bbl@ADJ@justify.arabic@on}{%
-  \bbl@adjust@lua{linebreak}{arabic.justify_enabled=true}}
-\@namedef{bbl@ADJ@justify.arabic@off}{%
-  \bbl@adjust@lua{linebreak}{arabic.justify_enabled=false}}
+% Now, we make sure an option is explicitly declared for any language
+% set as global option, by checking if an |ldf| exists. The previous
+% step was, in fact, somewhat redundant, but that way we minimize
+% accessing the file system just to see if the option could be a
+% language.
 %
-\def\bbl@adjust@layout#1{%
-  \ifvmode
-    #1%
-    \expandafter\@gobble
-  \fi
-  {\bbl@error   % The error is gobbled if everything went ok.
-     {Currently, layout related features can be adjusted only\\%
-      in vertical mode.}%
-     {Maybe things change in the future, but this is what it is.}}}
-\@namedef{bbl@ADJ@layout.tabular@on}{%
-  \bbl@adjust@layout{\let\@tabular\bbl@NL@@tabular}}
-\@namedef{bbl@ADJ@layout.tabular@off}{%
-  \bbl@adjust@layout{\let\@tabular\bbl@OL@@tabular}}
-\@namedef{bbl@ADJ@layout.lists@on}{%
-  \bbl@adjust@layout{\let\list\bbl@NL@list}}
-\@namedef{bbl@ADJ@layout.lists@off}{%
-  \bbl@adjust@layout{\let\list\bbl@OL@list}}
-\@namedef{bbl@ADJ@hyphenation.extra@on}{%
-  \bbl@activateposthyphen}
+%    If a main language has been set, store it for the third pass.
+% And we are done, because all options for this pass has been
+% declared. Those already processed in the first pass are just
+% ignored.
 %
-\@namedef{bbl@ADJ@autoload.bcp47@on}{%
-  \bbl@bcpallowedtrue}
-\@namedef{bbl@ADJ@autoload.bcp47@off}{%
-  \bbl@bcpallowedfalse}
-\@namedef{bbl@ADJ@autoload.bcp47.prefix}#1{%
-  \def\bbl@bcp@prefix{#1}}
-\def\bbl@bcp@prefix{bcp47-}
-\@namedef{bbl@ADJ@autoload.options}#1{%
-  \def\bbl@autoload@options{#1}}
-\let\bbl@autoload@bcpoptions\@empty
-\@namedef{bbl@ADJ@autoload.bcp47.options}#1{%
-  \def\bbl@autoload@bcpoptions{#1}}
-\newif\ifbbl@bcptoname
-\@namedef{bbl@ADJ@bcp47.toname@on}{%
-  \bbl@bcptonametrue
-  \BabelEnsureInfo}
-\@namedef{bbl@ADJ@bcp47.toname@off}{%
-  \bbl@bcptonamefalse}
-\@namedef{bbl@ADJ@prehyphenation.disable@nohyphenation}{%
-  \directlua{ Babel.ignore_pre_char = function(node)
-      return (node.lang == \the\csname l@nohyphenation\endcsname)
-    end }}
-\@namedef{bbl@ADJ@prehyphenation.disable@off}{%
-  \directlua{ Babel.ignore_pre_char = function(node)
-      return false
-    end }}
+% The options have to be processed in the order in which the user
+% specified them (except, of course, global options, which \LaTeX{}
+% processes before):
+%
+%    \begin{macrocode}
+\def\AfterBabelLanguage#1{%
+  \bbl@ifsamestring\CurrentOption{#1}{\global\bbl@add\bbl@afterlang}{}}
+\DeclareOption*{}
+\ProcessOptions*
 %    \end{macrocode}
 %
-% As the final task, load the code for lua. TODO: use babel name, override 
+% This finished the second pass. Now the third one begins, which
+% loads the main language set with the key |main|. A warning is
+% raised if the main language is not the same as the last named
+% one, or if the value of the key |main| is not a language. Then
+% execute directly the option (because it could be used only in
+% |main|). After loading all languages, we deactivate
+% |\AfterBabelLanguage|.
 %
 %    \begin{macrocode}
-\ifx\directlua\@undefined\else
-  \ifx\bbl@luapatterns\@undefined
-    \input luababel.def
+\bbl@trace{Option 'main'}
+\ifx\bbl@opt@main\@nnil
+  \edef\bbl@tempa{\@classoptionslist,\bbl@language@opts}
+  \let\bbl@tempc\@empty
+  \bbl@for\bbl@tempb\bbl@tempa{%
+    \bbl@xin@{,\bbl@tempb,}{,\bbl@loaded,}%
+    \ifin@\edef\bbl@tempc{\bbl@tempb}\fi}
+  \def\bbl@tempa#1,#2\@nnil{\def\bbl@tempb{#1}}
+  \expandafter\bbl@tempa\bbl@loaded,\@nnil
+  \ifx\bbl@tempb\bbl@tempc\else
+    \bbl@warning{%
+      Last declared language option is '\bbl@tempc',\\%
+      but the last processed one was '\bbl@tempb'.\\%
+      The main language can't be set as both a global\\%
+      and a package option. Use 'main=\bbl@tempc' as\\%
+      option. Reported}%
   \fi
 \fi
-%</core>
+\def\bbl@elt#1#2{% main
+  \ifodd\bbl@iniflag % as ini = 1(=), 3(*=)
+    \ifnum#1>\@ne %  % Class: if ini exists 2,3. Package: always 3
+      \def\CurrentOption{#2}% Directly, because luatexbase
+      \bbl@ldfinit
+      \babelprovide[\bbl@opt@provide,main,import]{#2}%
+      \bbl@afterldf{}%    
+      \DeclareOption{#2}{}%
+    \fi
+  \else % as ldf = 0(no), 2(+=)
+    \ifodd#1\relax % Class: if ldf exists 1,3. Package: always 3
+      \bbl@ifunset{ds@#2}%
+        {\DeclareOption{#2}{\bbl@load@language{#2}}}%
+        {}%
+      \ExecuteOptions{#2}%
+    \fi
+  \fi}
+\bbl@savemain
+\DeclareOption*{}%
+\ProcessOptions*
+\def\AfterBabelLanguage{%
+  \bbl@error
+    {Too late for \string\AfterBabelLanguage}%
+    {Languages have been loaded, so I can do nothing}}
+%    \end{macrocode}
+%      
+% In order to catch the case where the user forgot to specify a
+% language we check whether |\bbl@main@language|, has become
+% defined. If not, no language has been loaded and an error
+% message is displayed.
+%
+%    \begin{macrocode}
+\ifx\bbl@main@language\@undefined
+  \bbl@info{%
+    You haven't specified a language. I'll use 'nil'\\%
+    as the main language. Reported}
+    \bbl@load@language{nil}
+\fi
+%</package>
 %    \end{macrocode}
 %
+% \section{The kernel of Babel (\texttt{babel.def}, common)}
+%
+% The kernel of the \babel\ system is currently stored in
+% \file{babel.def}. The file \file{babel.def} contains most of the
+% code. The file \file{hyphen.cfg} is a file that can be loaded into
+% the format, which is necessary when you want to be able to switch
+% hyphenation patterns.
+%
+% Because plain \TeX\ users might want to use some of the features of
+% the \babel{} system too, care has to be taken that plain \TeX\ can
+% process the files. For this reason the current format will have to
+% be checked in a number of places. Some of the code below is common
+% to plain \TeX\ and \LaTeX, some of it is for the \LaTeX\ case only.
+%
+% Plain formats based on etex (etex, xetex, luatex) don't load
+% |hyphen.cfg| but |etex.src|, which follows a different naming
+% convention, so we need to define the babel names. It presumes
+% |language.def| exists and it is the same file used when formats were
+% created.
+%
 % A proxy file for switch.def
 %
 %    \begin{macrocode}
@@ -12891,7 +12779,7 @@ help from Bernd Raichle, for which I am grateful.
     \<keys_if_exist:nnF>{fontspec-opentype}{Language/\bbl@cl{lname}}%
       {\\\newfontlanguage{\bbl@cl{lname}}{\bbl@cl{lotf}}}%
     \\\renewfontfamily\\#4%
-      [\bbl@cs{lsys@\languagename},#2]}{#3}% ie \bbl@exp{..}{#3}
+      [\bbl@cl{lsys},#2]}{#3}% ie \bbl@exp{..}{#3}
   \begingroup
      #4%
      \xdef#1{\f@family}%     eg, \bbl@rmdflt@lang{FreeSerif(0)}
@@ -14635,6 +14523,7 @@ end
      {\ifx\tikz@atbegin@node\@undefined\else
         \ifx\AddToHook\@undefined\else % TODO. Still tentative.
           \AddToHook{env/pgfpicture/begin}{\bbl@pictsetdir\@ne}%
+          % \AddToHook{env/tikzpicture/begin}{\bbl@pictsetdir\z@}%
           \bbl@add\pgfinterruptpicture{\bbl@pictresetdir}%
         \fi
         \let\bbl@OL@pgfpicture\pgfpicture
@@ -22462,12 +22351,17 @@ Babel.cjk_breaks = {
 %
 % \subsection{Emulating some \LaTeX{} features}
 %
-% The following code duplicates or emulates parts of \LaTeXe\ that
-% are needed for \babel.
+% The file |babel.def| expects some definitions made in the \LaTeXe{}
+% style file. So, in Plain{} we must provide at least
+% some predefined values as well some tools to set them (even if not
+% all options are available). There are no package options, and
+% therefore and alternative mechanism is provided. For the moment,
+% only |\babeloptionstrings| and |\babeloptionmath| are provided,
+% which can be defined before loading \babel. |\BabelModifiers| can be
+% set too (but not sure it works).
 %
 %    \begin{macrocode}
 %<<*Emulate LaTeX>>
-  % == Code for plain ==
 \def\@empty{}
 \def\loadlocalcfg#1{%
   \openin0#1.cfg
@@ -22525,6 +22419,25 @@ Babel.cjk_breaks = {
   \ifx#2\@empty\else\expandafter\zap@space\fi
   #2}
 \let\bbl@trace\@gobble
+\def\bbl@error#1#2{%
+  \begingroup
+    \newlinechar=`\^^J
+    \def\\{^^J(babel) }%
+    \errhelp{#2}\errmessage{\\#1}%
+  \endgroup}
+\def\bbl@warning#1{%
+  \begingroup
+    \newlinechar=`\^^J
+    \def\\{^^J(babel) }%
+    \message{\\#1}%
+  \endgroup}
+\let\bbl@infowarn\bbl@warning
+\def\bbl@info#1{%
+  \begingroup
+    \newlinechar=`\^^J
+    \def\\{^^J}%
+    \wlog{#1}%
+  \endgroup}
 %    \end{macrocode}
 %
 %    \LaTeXe\ has the command |\@onlypreamble| which adds commands to
@@ -22879,7 +22792,7 @@ Babel.cjk_breaks = {
 \def\cf@encoding{OT1}
 %    \end{macrocode}
 %
-%    Currently we only use the \LaTeXe\ method for accents for those
+% Currently we only use the \LaTeXe\ method for accents for those
 %    that are known to be made active in \emph{some} language
 %    definition file.
 %
@@ -22903,20 +22816,47 @@ Babel.cjk_breaks = {
 \DeclareTextSymbol{\ss}{OT1}{25}
 %    \end{macrocode}
 %
-%    For a couple of languages we need the \LaTeX-control sequence
-%    |\scriptsize| to be available. Because plain \TeX\ doesn't have
-%    such a sofisticated font mechanism as \LaTeX\ has, we just |\let|
-%    it to |\sevenrm|.
+% For a couple of languages we need the \LaTeX-control sequence
+% |\scriptsize| to be available. Because plain \TeX\ doesn't have such
+% a sofisticated font mechanism as \LaTeX\ has, we just |\let| it to
+% |\sevenrm|.
 %
 %    \begin{macrocode}
 \ifx\scriptsize\@undefined
   \let\scriptsize\sevenrm
 \fi
-  % End of code for plain
+%    \end{macrocode}
+%
+%    And a few more “dummy” definitions.
+%
+%    \begin{macrocode}
+\def\languagename{english}%
+\let\bbl@opt@shorthands\@nnil
+\def\bbl@ifshorthand#1#2#3{#2}%
+\let\bbl@language@opts\@empty
+\ifx\babeloptionstrings\@undefined
+  \let\bbl@opt@strings\@nnil
+\else
+  \let\bbl@opt@strings\babeloptionstrings
+\fi
+\def\BabelStringsDefault{generic}
+\def\bbl@tempa{normal}
+\ifx\babeloptionmath\bbl@tempa
+  \def\bbl@mathnormal{\noexpand\textormath}
+\fi
+\def\AfterBabelLanguage#1#2{}
+\ifx\BabelModifiers\@undefined\let\BabelModifiers\relax\fi
+\let\bbl@afterlang\relax
+\def\bbl@opt@safe{BR}
+\ifx\@uclclist\@undefined\let\@uclclist\@empty\fi
+\ifx\bbl@trace\@undefined\def\bbl@trace#1{}\fi
+\expandafter\newif\csname ifbbl@single\endcsname
+\chardef\bbl@bidimode\z@
 %<</Emulate LaTeX>>
 %    \end{macrocode}
 %
 % A proxy file:
+%
 %    \begin{macrocode}
 %<*plain>
 \input babel.def
-- 
cgit v1.2.3

