%D \module
%D   [       file=lang-ini,
%D        version=1996.01.25,
%D          title=\CONTEXT\ Language Macros,
%D       subtitle=Initialization,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D Todo : --language=pl,en,nl : nl incs number of language

%D This module implements the (for the moment still simple)
%D multi||language support of \CONTEXT, which should not be
%D confused with the multi||lingual interface. This support
%D will be extended when needed.

\writestatus{loading}{Context Language Macros / Initialization}

\startmessages  dutch  library: linguals
  title: taal
      1: afbreekpatronen -- voor -- geladen (n=--,e=--,m=--)
      2: geen afbreekpatronen -- voor -- (n=--,e=--,m=--) (--,--)
      3: afbreekdefinities -- voor -- geladen (n=--,e=--,m=--)
      4: geen afbreekdefinities -- voor -- (n=--,e=--,m=--)
      5: afbreekpatronen voor -- niet geladen
      6: taal -- is niet gedefinieerd
      7: taal specifieke opties [--] introduceren een skip van --
      8: taal specifieke opties [--] naadloos toegevoegd
      9: taal -- is actief
     10: patronen --geladen
\stopmessages

\startmessages  english  library: linguals
  title: language
      1: patterns -- for -- loaded (n=--,e=--,m=--)
      2: no patterns -- for -- (n=--,e=--,m=--) (--,--)
      3: hyphenations -- for -- loaded (n=--,e=--,m=--)
      4: no hyphenations -- for -- (n=--,e=--,m=--)
      5: patterns for -- not loaded
      6: language -- is undefined
      7: language specific options [--] introduce a -- skip
      8: language specific options [--] seamless appended
      9: language -- is active
     10: patterns --loaded
\stopmessages

\startmessages  german  library: linguals
  title: Sprache
      1: Trennmuster -- fuer -- geladen (n=--,e=--,m=--)
      2: Keine Trennmuster -- fuer -- (n=--,e=--,m=--) (--,--)
      3: Trenndefinitionen -- fuer -- geladen (n=--,e=--,m=--)
      4: Keine Trenndefinitionen -- fuer -- (n=--,e=--,m=--)
      5: Trennmuster fuer -- nicht geladen
      6: Sprache -- ist undefiniert
      7: Sprachenspezifische Option [--] fuegt eine Luecke von -- ein
      8: Sprachenspezifische Option [--] nahtlos hinzugefuegt
      9: Sprache -- ist aktiv
     10: Trennmuster --geladen
\stopmessages

% TOM: 9 and 10

\startmessages  czech  library: linguals
  title: jazyky
      1: vzory -- pro -- nacteny (n=--,e=--,m=--)
      2: zadne vzory -- pro -- (n=--,e=--,m=--) (--,--)
      3: deleni slov -- pro -- nacteno (n=--,e=--,m=--)
      4: zadne deleni slov -- pro -- (n=--,e=--,m=--)
      5: vzory pro -- nenacteny
      6: jazyk -- neni definovan
      7: specificke volby jazyka [--] zavadeji -- (zavlecenou) mezeru
      8: specificke volby jazyka [--] bez mezer pripojeny
      9: language -- is active
     10: vzory --nacteny
\stopmessages

\startmessages  italian  library: linguals
  title: lingua
      1: schemi -- per -- caricati (n=--,e=--,m=--)
      2: niente schemi -- per -- (n=--,e=--,m=--) (--,--)
      3: sillabazione -- per -- caricata (n=--,e=--,m=--)
      4: niente sillabazione -- per -- (n=--,e=--,m=--)
      5: schemi per -- non caricati
      6: lingua -- non definita
      7: opzioni specifiche per la lingua [--] introducono un salto --
      8: opzioni specifiche per la lingua [--] aggiunte trasparentemente
      9: lingua -- attiva
     10: schemi -- caricati
\stopmessages

\startmessages  norwegian  library: linguals
  title: sprøk
      1: orddelingsmønster -- for -- er lest inn (n=--,e=--,m=--)
      2: ingen orddelingsmønster -- for -- (n=--,e=--,m=--) (--,--)
      3: orddelingsdefinisjon -- for -- er lest inn (n=--,e=--,m=--)
      4: ingen orddelingsdefinisjon -- for -- (n=--,e=--,m=--)
      5: orddelingsmønster for -- er ikke lest inn
      6: spràk -- er udefinert
      7: spràk spesifikk opsjon [--] introduserer et -- hopp
      8: spràk spesifikk opsjon [--] problemfritt tilføyd
      9: spràk -- er aktivt
     10: orddelingsmønster -- er lest inn
\stopmessages

\startmessages  romanian  library: linguals
  title: limbi
      1: sablonul -- pentru -- s-a incarcat (n=--,e=--,m=--)
      2: nu exista sabloane -- pentru -- (n=--,e=--,m=--) (--,--)
      3: despartirea in silabe -- pentru -- s-a incarcat (n=--,e=--,m=--)
      4: nu exista despartire in silabe -- pentru -- (n=--,e=--,m=--)
      5: sabloanele pentru -- nu sunt incarcate
      6: limba -- nu este definita
      7: optiunile specifice ale limbii [--] introduc un spatiu --
      8: optiunile specifice ale limbii [--] adaugate
      9: limba -- este activa
     10: sabloanele -- incarcate
\stopmessages

\startmessages  french  library: linguals
  title: langue
      1: les motifs -- pour -- sont chargés (n=--,e=--,m=--)
      2: pas de motifs -- pour -- (n=--,e=--,m=--) (--,--)
      3: hyphenations -- pour -- chargés (n=--,e=--,m=--)
      4: pas d'hyphenations -- pour -- (n=--,e=--,m=--)
      5: les motifs pour -- ne sont pas chargés
      6: langue -- non définie
      7: les options spécifiques de langue [--] introduisent un -- saut
      8: les options spécifiques de langue [--] sont ajoutés en douceur
      9: la langue -- est active
     10: motifs -- chargés
\stopmessages

\unprotect

\ifx\nonfrenchspacing\undefined \let\nonfrenchspacing\relax \fi
\ifx\frenchspacing   \undefined \let\frenchspacing   \relax \fi

%D When loading hyphenation patterns, \TEX\ assign a number to
%D each loaded table, starting with~0. Switching to a specific
%D table is done by assigning the relevant number to the
%D predefined \COUNTER\ \type{\language}. Unfortunately the
%D name of this command suits very well the name of the
%D language switching command we are to define, so let's save
%D this primitive under another name:

\let\normallanguage\language

%D We keep track of the last loaded patterns by means of a
%D pseudo \COUNTER. This just one of those situations in which
%D we don't want to spent a real one. Language zero has no
%D patterns, first of all because I like to start numbering
%D at one. It may come in handy for special purposes as well.

\normallanguage\zerocount \def\loadedlanguage{1}

%D Let's start with setting the lowercase code of quotes, so
%D that we get proper hyphenation in languages like Dutch,
%D French and Czech.

% elsewhere: \lccode`\'=`\'

% \def\showlccodes
%   {\currentlanguage:\space
%    \dostepwiserecurse{0}{255}{1}
%      {\ifnum\lccode\recurselevel>0
%         \char\recurselevel:\the\lccode\recurselevel\relax\space
%       \fi}
%    \endgraf}

% \de \hyphenatedword{Works''} \showlccodes
% \nl \hyphenatedword{Works''} \showlccodes
% \uk \hyphenatedword{Works''} \showlccodes

%D \macros
%D   {currentlanguage, setupcurrentlanguage}
%D
%D Instead of numbers,we are going to use symbolic names for
%D the languages. The current langage is saved in the macro
%D \type {\currentlanguage}. The setup macro is mainly used
%D for cosmetic purposes.
%D
%D \starttyping
%D \dorecurse{3}
%D   {\language[nl]
%D    \startmode[*en] english \stopmode
%D    \startmode[*nl] dutch   \stopmode
%D    \language[en]
%D    \startmode[*en] english \stopmode
%D    \startmode[*nl] dutch   \stopmode}
%D \stoptyping

\let\currentlanguage    \empty
\let\currentmainlanguage\empty

\def\setupcurrentlanguage[#1]{\setcurrentlanguage\currentmainlanguage{#1}}

\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
  {\doifsomething{#1}
     {\ifx\currentmainlanguage\empty\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
      \edef\currentmainlanguage{#1}%
      \setsystemmode{\systemmodeprefix\currentmainlanguage}}%
   \doifsomething{#2}
     {\ifx\currentlanguage\empty\else\resetsystemmode\currentlanguage\fi
      \edef\currentlanguage{#2}%
      \setsystemmode\currentlanguage}}

%D The internal macros will be defined later.

%D \macros
%D   {installlanguage}
%D
%D Hyphenation patterns can only be loaded when the format file
%D is prepared. The next macro takes care of this loading. A
%D language is specified with
%D
%D \showsetup{installlanguage}
%D
%D When \type {state} equals \type {start}, both patterns
%D and additional hyphenation specifications are loaded. These
%D files are seached for on the system path and are to be
%D named:
%D
%D \starttyping
%D \f!languageprefix-identifier.\f!patternsextension
%D \f!languageprefix-identifier.\f!hyhensextension
%D \stoptyping
%D
%D The \type{spacing} variable specifies how the spaces after
%D punctuation has to be handled. English is by tradition more
%D tolerant to inter||sentence spacing than other languages.
%D
%D This macro also defines \type {\identifier} as a shortcut
%D switch to the language. Furthermore the command defined as
%D being language specific, are executed. With
%D \type {default} we can default to another language
%D (patterns) at format generation time. This default language
%D is overruled when the appropriate patterns are loaded (some
%D implementations support run time addition of patterns to a
%D preloaded format).

\def\dodoinstalllanguage#1#2% #2 added
  {\doifundefined{#1}{\setvalue{#1}{\complexlanguage[#2]}}%
   \expanded{\noexpand\uppercase{\noexpand\edef\noexpand\ascii{#1}}}%
   \doifundefined\ascii{\setvalue\ascii{\complexlanguage[#2]}}}

%D \macros
%D   {preloadlanguages}
%D
%D We first try to load the files defined as file synonym
%D for \type {lang-*.pat} and \type {lang-*.hyp}. After that we
%D fall back on those files. The macro \type {\preloadpatterns}
%D reports which patterns are loaded and what hyphenmin
%D values are set.

\let\preloadedpatterns\empty
\let\preloadedpmessage\empty

\def\doshowpatterns#1#2#3#4% language number encoding mapping
  {#1->#3:#4->#2->\xxlanguageparameter{#1}\s!lefthyphenmin:\xxlanguageparameter{#1}\s!righthyphenmin\space}

\def\preloadlanguages
  {\doifsomething\preloadedpmessage{\showmessage\m!linguals{10}\preloadedpmessage}}

\fetchruntimecommand \showpatterns {\f!languageprefix\s!run}

\let\installedlanguages\empty

\def\doiflanguageelse#1{\doifdefinedelse{\??la#1\c!state}}

\def\doinstalllanguage[#1][#2]%
  {%\ConvertConstantAfter\doifinstringelse{=}{#2}
   \doifassignmentelse{#2}
     {\doiflanguageelse{#1}
        {\getparameters[\??la#1][#2]}
        {\setvalue{\l!prefix!#1}{#1}%
         \addtocommalist{#1}\installedlanguages
         \dodoinstalllanguage{#1}{#1}%
         \getparameters
           [\??la#1]
           [\c!state=\v!stop,
            \c!default=,
            \s!patterns=,
            \s!mapping=,
            \s!encoding=,
            \s!lefthyphenmin=\defaultlanguageparameter\s!lefthyphenmin,
            \s!righthyphenmin=\defaultlanguageparameter\s!righthyphenmin,
            #2]}%
      \doifvalue{\??la#1\c!default}{#1}{\letvalue{\??la#1\c!default}\empty}%
      % loop in deo: \doifvalue{\??la#1\s!patterns}{#1}{\letvalue{\??la#1\c!default}\empty}%
      \doifelsevalue{\??la#1\c!state}\v!start
        {\doifelsevaluenothing{\??la#1\s!patterns}
           {\edef\languagesuffix{#1}}
           {\edef\languagesuffix{\getvalue{\??la#1\s!patterns}}}%
         \doifundefinedelse{\??la\??la:\currentencoding:\currentmapping:\languagesuffix}
           {\doloadpatterns{#1}\languagesuffix}
           {\bgroup
            \edef\loadedlanguage{\getvalue{\??la\??la:\currentencoding:\currentmapping:\languagesuffix}}%
            \showmessage\m!linguals1{\languagesuffix,#1,\loadedlanguage,*,*}%
            \showmessage\m!linguals3{\languagesuffix,#1,\loadedlanguage,*,*}%
            \egroup}}
        {\showmessage\m!linguals5{#1}}}
     {\setvalue{\l!prefix!#1}{#2}%
      \dodoinstalllanguage{#1}{#2}}}

% ^^ \language[#1] gave unwanted side effect of loading language specifics

\def\installlanguage
  {\dodoubleargument\doinstalllanguage}

%D Handy

\def\preloadallpatterns
  {\gdef\preloadallpatterns##1{\installlanguage[##1][\c!state=\v!start]}%
   \processcommacommand[\installedlanguages]\preloadallpatterns
   \global\let\preloadallpatterns\relax}

%D When the second argument is a language identifier, a
%D synonym is created. This feature is present because we
%D used dutch mnemonics in the dutch version, but nowadays
%D conform a standard.

\let \patternencoding \s!default
\let \patternmapping  \s!default

\def\doloadpatterns#1#2%
  {\expanded{\getcommacommandsize[\getvalue{\??la#2\s!encoding}]}%
   \ifnum\commalistsize>0
    %\message{[nofpatterns #2: \commalistsize/\getvalue{\??la#2\s!encoding}]}%
     \dorecurse\commalistsize
       {\expanded{\getfromcommacommand[\getvalue{\??la#2\s!encoding}][\recurselevel]}%
        \let\patternencoding\commalistelement
        \expanded{\getfromcommacommand[\getvalue{\??la#2\s!mapping }][\recurselevel]}%
        \let\patternmapping \commalistelement
       %\message{[patterns: #1/#2/\patternencoding/\patternmapping]}%
        \dodoloadpatterns{#1}{#2}\patternencoding\patternmapping}%
   \else
    %\message{[patterns: #1/#2]}%
     \dodoloadpatterns{#1}{#2}{}{}%
   \fi}

\def\setuphyppatencoding
  {\pathypsettings
   \enableregime[utf]}

\beginXETEX
  \def\setuphyppatencoding{\pathypsettings}
\endXETEX

\beginMETATEX
  \def\setuphyppatencoding{\pathypsettings}
\endMETATEX

\def\dodoloadpatterns#1#2#3#4% beware, loaded language also incr
  {\normallanguage\loadedlanguage % when not really needed
   \bgroup
   \let\synchronizepatterns\relax % needed?
   \let\enabledmapping     \empty % needed?
   \doifelsenothing{#3}{\enableencoding[\s!default]}{\enableencoding[#3]}%
   \doifelsenothing{#4}{\enablemapping [\s!default]}{\enablemapping [#4]}%
   \setuphyppatencoding
   \ifundefined{\??la\??la:\currentencoding:\currentmapping:#2}%
     \let\doshowpatterns\relax
     \edef\alreadyloadedlanguage
       {\executeifdefined{\??la\??la:\currentencoding:\currentmapping:\truefilename{\f!languageprefix#2.\f!patternsextension}}\empty}%
     \edef\alreadyloadedlanguage
       {\executeifdefined{\??la\??la:\currentencoding:\currentmapping:\f!languageprefix#2.\f!patternsextension}\alreadyloadedlanguage}%
     \ifx\alreadyloadedlanguage\empty
       \letgvalue{\??la\??la:\currentencoding:\currentmapping:#2}\loadedlanguage
       \doifundefined{\??la\??la:\s!default:\s!default:#2}{\letgvalue{\??la\??la:\s!default:\s!default:#2}\loadedlanguage}% fall back
       \startpatternloading{\truefilename{\f!languageprefix#2.\f!patternsextension}}{#3}{#4}%
         \readsysfile{\truefilename{\f!languageprefix#2.\f!patternsextension}}
           {\setxvalue{\??la#1\s!patterns}{#2}%
            \setxvalue{\??la\??la:\currentencoding:\currentmapping:\truefilename{\f!languageprefix#2.\f!patternsextension}}{\number\loadedlanguage}%
            \xdef\preloadedpmessage{\preloadedpmessage\doshowpatterns{#2}{\number\normallanguage}{\currentencoding}{\currentmapping}}%
            \doglobal\addtocommalist{#2}\preloadedpatterns
            \showmessage\m!linguals1{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}
           {\showmessage\m!linguals2{#2,#1,\loadedlanguage,\currentencoding,\currentmapping,\f!languageprefix#2.\f!patternsextension,\truefilename{\f!languageprefix#2.\f!patternsextension}}}%
       \stoppatternloading
       \startpatternloading{\truefilename{\f!languageprefix#2.\f!hyphensextension}}{#3}{#4}%
         \readsysfile{\truefilename{\f!languageprefix#2.\f!hyphensextension}}
           {\showmessage\m!linguals3{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}
           {\showmessage\m!linguals4{#2,#1,\loadedlanguage,\currentencoding,\currentmapping}}%
       \stoppatternloading
       \doglobal\increment\loadedlanguage
       % \stopencoding
     \else % optimization, introduced 2004.08.24, while sorting out changes in tl
       \letgvalue{\??la\??la:\currentencoding:\currentmapping:#2}\alreadyloadedlanguage
       \doifundefined{\??la\??la:\s!default:\s!default:#2}{\letgvalue{\??la\??la:\s!default:\s!default:#2}\loadedlanguage}% fall back
       \setxvalue{\??la#1\s!patterns}{#2}%
       \xdef\preloadedpmessage{\preloadedpmessage\doshowpatterns{#2}{[\number\alreadyloadedlanguage]}{\currentencoding}{\currentmapping}}%
       \doglobal\addtocommalist{#2}\preloadedpatterns
       \showmessage\m!linguals1{#2,#1,[\alreadyloadedlanguage],\currentencoding,\currentmapping}%
     \fi
   \fi
   \egroup}

\def\doifpatternselse#1%
  {\expanded{\doifinsetelse{#1}{\preloadedpatterns}}}

%D Since we can only load patterns in ini\TeX, we nil the
%D loading before dumping (which saves a bit of memory, but
%D strangely enough not in the format).

\appendtoks
  \gdef\doloadpatterns{\doglobal\increment\loadedlanguage\gobbletwoarguments}%
  \globallet\dodoloadpatterns\gobblefourarguments
\to \everydump

%D \macros
%D   {setuplanguage}
%D
%D Quick and dirty, but useful:
%D
%D \showsetup{setuplanguage}
%D
%D Beware, this command can only be used when a language is installed.

\unprotected \def\setuplanguage
  {\dodoubleempty\dosetuplanguage}

\def\dosetuplanguage[#1][#2]% handy patch for testing
  {\ifsecondargument
     \getparameters[\??la#1][#2]%
     \doif{#1}\currentlanguage\docomplexlanguage
   \else
     \getparameters[\??la\currentlanguage][#1]%
     \docomplexlanguage
   \fi}

\setuplanguage
  [\s!default]
  [\s!lefthyphenmin=2,
   \s!righthyphenmin=2,
   \c!spacing=\v!packed,
   \c!midsentence=---,
   \c!leftsentence=---,
   \c!rightsentence=---,
   \c!leftsubsentence=---,
   \c!rightsubsentence=---,
   \c!leftquote=\upperleftsinglesixquote,
   \c!rightquote=\upperrightsingleninequote,
   \c!leftquotation=\upperleftdoublesixquote,
   \c!rightquotation=\upperrightdoubleninequote,
   \c!leftspeech=\languageparameter\c!leftquotation,
   \c!middlespeech=,
   \c!rightspeech=\languageparameter\c!rightquotation,
   \c!limittext=\unknown,
   \c!date={\v!year,\ ,\v!month,\ ,\v!day},
   \c!text=Ag]

% rather new, split and per language

\setuplanguage
  [\s!default]
  [\c!compoundhyphen=\compoundhyphen,
   \c!leftcompoundhyphen=\compoundhyphen,
   \c!rightcompoundhyphen=]

%D The values \type {leftsentence} and \type
%D {rightsentence} can be (and are) used to implement
%D automatic subsentence boundary glyphs, like in {\fr
%D |<|french guillemots|>|} or {\de |<|german guillemots|>|} or
%D {\nl |<|dutch dashes|>|} like situations. Furthermore \type
%D {leftquotation} and \type {leftquote} come into view
%D \quotation {when we quote} or \quote {quote} something.

%D \macros
%D  {currentdatespecification}
%D
%D Just to make things easy we can ask for the current date
%D specification by saying:

\def\currentdatespecification{\languageparameter\c!date}

%D This command is not meant for users.

%D Carefull reading of these macros shows that it's legal to
%D say
%D
%D \starttyping
%D \installlanguage [du] [de]
%D \stoptyping

%D \macros
%D   {language,mainlanguage}
%D
%D Switching to another language (actually another hyphenation
%D pattern) is done with:
%D
%D \starttyping
%D \language[identifier]
%D \stoptyping
%D
%D or with \type{\identifier}. Just to be compatible with
%D \PLAIN\ \TEX, we still support the original meaning, so
%D
%D \starttyping
%D \language=1
%D \stoptyping
%D
%D is a valid operation, where the relation between number
%D and language depends on the order in installing languages.
%D
%D \showsetup{language}
%D \showsetup{mainlanguage}
%D
%D Both commands take a predefined language identifier as
%D argument. We can use \type{\mainlanguage[identifier]} for
%D setting the (indeed) main language. This is the language
%D used for translating labels like {\em figure} and {\em
%D table}. The main language defaults to the current language.
%D
%D We take care of local as well as standardized language
%D switching (fr and fa, de and du, but nl and nl).

% new, encoding specific patterns

\ifx\synchronizepatterns\undefined \let\synchronizepatterns\relax \fi

\beginTEX

\def\dosetnormallanguage#1#2%
  {\@EA\ifx\csname\??la\??la#1#2\endcsname\relax
     \@EA\firstofoneargument
   \else\@EA\ifx\csname\??la\??la#1#2\endcsname\empty
     \@EAEAEA\firstofoneargument
   \else
     \donetrue
     \@EA\xdef\csname\??la\currentlanguage\s!patterns\endcsname{#2}%
     \normallanguage\csname\??la\??la#1#2\endcsname\relax % \relax is needed for lookahead problems
     \@EAEAEA\gobbleoneargument
   \fi\fi}

\endTEX

\beginETEX

\def\dosetnormallanguage#1#2%
  {\ifcsname\??la\??la#1#2\endcsname
     \edef\thenormallanguage{\csname\??la\??la#1#2\endcsname}%
     \ifx\thenormallanguage\empty
       \@EAEAEA\firstofoneargument
     \else
       \donetrue
       \@EA\xdef\csname\??la\currentlanguage\s!patterns\endcsname{#2}%
       \normallanguage\thenormallanguage\relax % \relax is needed for lookahead problems
       \@EAEAEA\gobbleoneargument
     \fi
   \else
     \@EA\firstofoneargument
   \fi}

\endETEX

\newevery \everylanguage               \relax
\newevery \everyresetlanguagespecifics \relax

\def\disablelanguagespecifics
  {\ignorecompoundcharacter}

% \def\setnormallanguage#1%
%   {\dosetnormallanguage{:\currentencoding:\currentmapping:}{#1}{%
%    \dosetnormallanguage{:\currentencoding:\s!default     :}{#1}{%
%    \dosetnormallanguage{:\s!default      :\currentmapping:}{#1}{%
%    \dosetnormallanguage{:\s!default      :\s!default     :}{#1}\empty}}}}
%
% assume #1 = \cs

\def\setnormallanguage#1%
  {\dosetnormallanguage{:\currentencoding:\currentmapping:}#1{%
   \dosetnormallanguage{:\currentencoding:\s!default     :}#1{%
   \dosetnormallanguage{:\s!default      :\currentmapping:}#1{%
   \dosetnormallanguage{:\s!default      :\s!default     :}#1\empty}}}}

\def\docomplexlanguage% assumes that \currentlanguage is set
  {\edef\currentdefaultlanguage{\defaultlanguage\currentlanguage}%
   % called quite often, so we use \csname
   % \def\synchronizepatterns{\setnormallanguage
   %   {\csname\??la\currentlanguage\s!patterns\endcsname}}% called often
   % of even better pre-expand in an ugly way:
   \@EA\def\@EA\synchronizepatterns\@EA{\@EA\setnormallanguage
     \csname\??la\currentlanguage\s!patterns\endcsname}%
   \donefalse
   \synchronizepatterns
   \ifdone\else
     \def\synchronizepatterns{\setnormallanguage\currentlanguage}%
     \synchronizepatterns
     \ifdone\else
       \ifx\currentdefaultlanguage\empty\else
         % \def\synchronizepatterns{\setnormallanguage
         %   {\csname\??la\currentdefaultlanguage\s!patterns\endcsname}}%
         \@EA\def\@EA\synchronizepatterns\@EA{\@EA\setnormallanguage
           \csname\??la\currentdefaultlanguage\s!patterns\endcsname}%
         \synchronizepatterns
         \ifdone\else
           \setnormallanguage\currentdefaultlanguage
           \synchronizepatterns
         \fi
       \fi
     \fi
   \fi
   \the\everylanguage
   \enablelanguagespecifics[\currentlanguage]%
   % strange, what is this doing here, dangerous for {il2,ec}
   %   \edef\languagemapping{\csname\??la\currentlanguage\s!mapping\endcsname}%
   %   \ifx\languagemapping\empty\else
   %     \fastenablemapping\languagemapping
   %   \fi
   \lefthyphenmin 0\languageparameter\s!lefthyphenmin
   \righthyphenmin0\languageparameter\s!righthyphenmin
   \relax
   % will be definable and move to core-spa !
   \doifelse{\languageparameter\c!spacing}\v!broad
     \nonfrenchspacing\frenchspacing}

\ifx\enablelanguagespecifics\undefined

  \def\enablelanguagespecifics[#1]{}

\fi

\beginETEX

\def\complexlanguage[#1]%
  {\edef\askedlanguage{#1}%
   \ifx\askedlanguage\empty \else
     \ifcsname\l!prefix!\askedlanguage\endcsname
       \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
       \ifx\currentlanguage\askedlanguage \else
         \setcurrentlanguage\currentmainlanguage\askedlanguage
         \docomplexlanguage
       \fi
     \else
       \showmessage\m!linguals6{#1}%
     \fi
   \fi}

\endETEX

\beginTEX

\def\complexlanguage[#1]%
  {\edef\askedlanguage{#1}%
   \ifx\askedlanguage\empty \else
     \@EA\ifx\csname\l!prefix!\askedlanguage\endcsname\relax
       \showmessage\m!linguals6{#1}%
     \else
       \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
       \ifx\currentlanguage\askedlanguage \else
         \setcurrentlanguage\currentmainlanguage\askedlanguage
         \docomplexlanguage
       \fi
     \fi
   \fi}

\endTEX

\let\simplelanguage\normallanguage

\definecomplexorsimple\language

\beginETEX

\def\mainlanguage[#1]%
  {\edef\askedlanguage{#1}%
   \ifx\askedlanguage\empty \else
     \ifcsname\l!prefix!\askedlanguage\endcsname
       \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
       \ifx\currentmainlanguage\askedlanguage \else
         \setcurrentlanguage\askedlanguage\askedlanguage
         \docomplexlanguage
       \fi
     \fi
   \fi}

\endETEX

\beginTEX

\def\mainlanguage[#1]%
  {\edef\askedlanguage{#1}%
   \ifx\askedlanguage\empty \else
     \@EA\ifx\csname\l!prefix!\askedlanguage\endcsname\relax\else
       \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
       \ifx\currentmainlanguage\askedlanguage \else
         \setcurrentlanguage\askedlanguage\askedlanguage
         \docomplexlanguage
       \fi
     \fi
   \fi}

\endTEX

%D \macros
%D   {defaultlanguage,languagedefault}
%D
%D The macro \type {\defaultlanguage{id}} expands into the
%D default language, when defined, while \type
%D {\languagedefault{id}\c!parameter} returns the default's
%D parameter.

\def\defaultlanguage#1%
  {\@EA\ifx\csname\??la#1\c!default\endcsname\empty
     #1%
   \else
     \@EA\defaultlanguage\csname\??la#1\c!default\endcsname
   \fi}

\def\languagedefault#1#2%
  {\csname\??la\defaultlanguage{#1}#2\endcsname}

% \def\languageparameter#1%
%   {\csname\??la\defaultlanguage\currentlanguage#1\endcsname}

\def\languageparameter % @EA = speedup
  {\@EA\dolanguageparameter\@EA{\defaultlanguage\currentlanguage}}

\def\specificlanguageparameter#1% @EA = speedup
  {\@EA\dospecificlanguageparameter\@EA{\defaultlanguage{#1}}{#1}}

\def\xxlanguageparameter#1% @EA = speedup
  {\@EA\dolanguageparameter\@EA{\defaultlanguage{#1}}}

\def\defaultlanguageparameter#1%
  {\csname\??la\s!default#1\endcsname}

\beginETEX

  \def\dolanguageparameter#1#2%
    {\csname\??la
       \ifcsname\??la\currentlanguage#2\endcsname
         \currentlanguage
       \else\ifcsname\??la#1#2\endcsname
         \@EA\ifx\csname\??la#1#2\endcsname\empty\s!default\else#1\fi
       \else
         \s!default
       \fi\fi
     #2\endcsname}

  \def\dospecificlanguageparameter#1#2#3%
    {\csname\??la
       \ifcsname\??la#2#3\endcsname
         \@EA\ifx\csname\??la#2#3\endcsname\empty\s!default\else#2\fi
       \else\ifcsname\??la#1#3\endcsname
         \@EA\ifx\csname\??la#1#3\endcsname\empty\s!default\else#1\fi
       \else
         \s!default
       \fi\fi
     #3\endcsname}

\endETEX

\beginTEX

  \def\dolanguageparameter#1#2%
    {\csname\??la
       \@EA\ifx\csname\??la\currentlanguage#2\endcsname\relax
         \@EA\ifx\csname\??la#1#2\endcsname\relax
           \s!default
         \else
           \@EA\ifx\csname\??la#1#2\endcsname\empty\s!default\else#1\fi
         \fi
       \else
         \currentlanguage
       \fi
     #2\endcsname}

  \def\dospecificlanguageparameter#1#2#3%
    {\csname\??la
       \@EA\ifx\csname\??la#2#3\endcsname\relax
         \@EA\ifx\csname\??la#1#3\endcsname\relax
           \s!default
         \else
           \@EA\ifx\csname\??la#1#3\endcsname\empty\s!default\else#1\fi
         \fi
       \else
         \@EA\ifx\csname\??la#2#3\endcsname\empty\s!default\else#2\fi
       \fi
     #3\endcsname}

\endTEX

% moved
%
% %D \macros
% %D   {leftguillemot,rightguillemot,leftsubguillemot,rightsubguillemot,
% %D    ...single...quote,...double...quote}
% %D
% %D We assign logical names to all kind of quote and sentence
% %D boundary characters.
% %D
% %D When using Computer Modern Roman, the next definitions
% %D looks a bit better than the default ligatures.
% %D
% %D \starttyping
% %D \def\lowerleftsingleninequote  {,}
% %D \def\lowerleftdoubleninequote  {,\kern-.1em,}
% %D \def\upperleftsingleninequote  {'}
% %D \def\upperleftdoubleninequote  {''\kern-.1em}
% %D \def\upperleftsinglesixquote   {`}
% %D \def\upperleftdoublesixquote   {`\kern-.1em`}
% %D
% %D \def\lowerrightsingleninequote {,}
% %D \def\lowerrightdoubleninequote {,\kern-.1em,}
% %D \def\upperrightsingleninequote {'}
% %D \def\upperrightdoubleninequote {''}
% %D \def\upperrightsinglesixquote  {`}
% %D \def\upperrightdoublesixquote  {\kern-.125em``}
% %D \stoptyping
% %D
% %D But in other fonts, these definitions can give problems, so
% %D we just say:
%
% \def\lowerleftsingleninequote  {,}
% \def\lowerleftdoubleninequote  {,,}
% \def\upperleftsingleninequote  {'}
% \def\upperleftdoubleninequote  {''}
% \def\upperleftsinglesixquote   {`}
% \def\upperleftdoublesixquote   {``}
%
% \def\lowerrightsingleninequote {,}
% \def\lowerrightdoubleninequote {,,}
% \def\upperrightsingleninequote {'}
% \def\upperrightdoubleninequote {''}
% \def\upperrightsinglesixquote  {`}
% \def\upperrightdoublesixquote  {``}
%
% %D Yes I know, they are ugly:
%
% \def\leftfakeguillemot
%   {\dontleavehmode\hbox{\raise.25ex\hbox{$\scriptscriptstyle\ll$}}}
%
% \def\rightfakeguillemot
%   {\hbox{\raise.25ex\hbox{$\scriptscriptstyle\gg$}}}
%
% \def\leftsubfakeguillemot
%   {\dontleavehmode\hbox{\raise.25ex\hbox{$\scriptscriptstyle<$}}}
%
% \def\rightsubfakeguillemot
%   {\hbox{\raise.25ex\hbox{$\scriptscriptstyle>$}}}

%D New (see nomarking and nolist):

\def\splitsequence#1#2%
  {\doifelse{#1}\v!no{#2}{\doifelse{#1}\v!yes{\languageparameter\c!limittext}{#1}}}

\def\splitsymbol#1%
  {\splitsequence{#1}{\languageparameter\c!limittext}}

%D Just like with subsentence boundary symbols, quotes
%D placement depends on the current language, therefore we show
%D the defaults here.
%D
%D \def\ShowLanguageValues [#1] [#2] #3 #4
%D   {\blank
%D    \startlinecorrection
%D    \vbox\bgroup
%D    \language[#1]%
%D    \setbox0=\hbox to \hsize{\hss\bf#2 subsentence symbol and quotes\hss}
%D    \dp0=0pt
%D    \box0
%D    \vskip.5em
%D    \hrule
%D    \vskip.5em
%D    \let\normalbar=|
%D    \hbox to \hsize
%D      {\hfil\quotation{#3 #4}\hfil\quote{#2}\hfil
%D       \let|=\normalbar\strut|<||<|#3|>|#4|>|\hfil}
%D    \vskip.5em
%D    \hrule
%D    \egroup
%D    \stoplinecorrection
%D    \blank}
%D
%D \ShowLanguageValues [af] [afrikaans]  afrikaanse ...
%D \ShowLanguageValues [ca] [catalan]    catalan ...
%D \ShowLanguageValues [cz] [czech]      tjechisch tex
%D \ShowLanguageValues [cz] [slovak]     slowaakse ...
%D \ShowLanguageValues [da] [danish]     deense ...
%D \ShowLanguageValues [de] [german]     duitse degelijkheid
%D \ShowLanguageValues [en] [english]    engelse humor
%D \ShowLanguageValues [fi] [finnish]    finse ...
%D \ShowLanguageValues [fr] [french]     franse slag
%D \ShowLanguageValues [it] [italian]    italiaanse ...
%D \ShowLanguageValues [la] [latin]      latijnse missen
%D \ShowLanguageValues [nl] [dutch]      nederlandse zuinigheid
%D \ShowLanguageValues [no] [norwegian]  noorse ...
%D \ShowLanguageValues [pl] [polish]     poolse ...
%D \ShowLanguageValues [pt] [portuguese] portugese ...
%D \ShowLanguageValues [es] [spanish]    spaans benauwd
%D \ShowLanguageValues [sv] [swedish]    zweedse ...
%D \ShowLanguageValues [tr] [turkish]    turks fruit

%D We support a lot of languages. These are specified and
%D loaded in separate files, according to their roots. Here
%D we only take care of (postponed) setting of the current
%D language.
%D
%D \unprotect
%D \placetable{The germanic languages (\type{lang-ger})}
%D \starttable[||||]
%D \HL
%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
%D \HL
%D \NC \s!nl        \NC dutch        \NC germanic  \NC\FR
%D \NC \s!en        \NC english      \NC germanic  \NC\MR
%D \NC \s!de        \NC german       \NC germanic  \NC\MR
%D \NC \s!da        \NC danish       \NC germanic  \NC\MR
%D \NC \s!sv        \NC swedish      \NC germanic  \NC\MR
%D \NC \s!af        \NC afrikaans    \NC germanic  \NC\MR
%D \NC \s!no        \NC norwegian    \NC germanic  \NC\LR
%D \HL
%D \stoptable
%D \protect
%D
%D \unprotect
%D \placetable{The italic languages (\type{lang-ita})}
%D \starttable[||||]
%D \HL
%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
%D \HL
%D \NC \s!fr        \NC french       \NC italic    \NC\FR
%D \NC \s!ca        \NC catalan      \NC italic    \NC\MR
%D \NC \s!es        \NC spanish      \NC italic    \NC\MR
%D \NC \s!it        \NC italian      \NC italic    \NC\MR
%D \NC \s!la        \NC latin        \NC italic    \NC\MR
%D \NC \s!pt        \NC portuguese   \NC italic    \NC\LR
%D \HL
%D \stoptable
%D \protect
%D
%D \unprotect
%D \placetable{The slavic languages (\type{lang-sla})}
%D \starttable[||||]
%D \HL
%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
%D \HL
%D \NC \s!pl        \NC polish       \NC slavic    \NC\FR
%D \NC \s!cz        \NC czech        \NC slavic    \NC\MR
%D \NC \s!sk        \NC slavik       \NC slavic    \NC\LR
%D \HL
%D \stoptable
%D \protect
%D \unprotect
%D
%D \placetable{The altaic languages (\type{lang-alt})}
%D \starttable[||||]
%D \HL
%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
%D \HL
%D \NC \s!tr        \NC turkish      \NC altaic    \NC\SR
%D \HL
%D \stoptable
%D
%D \placetable{The uralic languages (\type{lang-ura})}
%D \starttable[||||]
%D \HL
%D \NC \bf mnemonic \NC \bf language \NC \bf group \NC\SR
%D \HL
%D \NC \s!fi        \NC finnish      \NC uralic    \NC\SR
%D \HL
%D \stoptable
%D \protect

% \bgroup \normallanguage255 \patterns{} \egroup
% \def\nopatterns{\normallanguage255 }

\def\nopatterns{\normallanguage\minusone}

%D We default to the language belonging to the interface. This
%D is one of the few places outside the interface modules where
%D \type{\startinterface} is used.

\let\normaldoublequote ="
\let\normalforwardslash=/

%D We default to english:

\setupcurrentlanguage[\s!en]

\appendtoks\mainlanguage[\currentlanguage]\to\everyjob

\appendtoks\showmessage\m!linguals9\currentlanguage\to\everyjob

%D Brrr:

% \ifx\@@ladefault\undefined \let\@@ladefault\s!en \fi

\protect \endinput
