[Tex/LaTex] IfLanguageName versus iflanguage

babellanguages

The babel package recommends using the command IfLanguageName of the iflang package to test for a language.
It is explained that the command iflanguage is too coarse, because it is only based on the hyphenation pattern.

But if for example, we would like to test if the current language is one of the four English, USEnglish, usenglish or american, do we have to do four tests for each one of these languages?

Is there any test for language families, for example one for the English language family that includes British, American and other variants?

Best Answer

Package babel knows more than four languages of the family English:

\DeclareOption{american}{\bbl@load@language{english}}
\DeclareOption{australian}{\bbl@load@language{english}}
\DeclareOption{british}{\bbl@load@language{english}}
\DeclareOption{canadian}{\bbl@load@language{english}}
\DeclareOption{newzealand}{\bbl@load@language{english}}
\DeclareOption{UKenglish}{\bbl@load@language{english}}
\DeclareOption{USenglish}{\bbl@load@language{english}}

And babel knows lots of hyphenation patterns (macro \l@<language>), from english.ldf

\ifx\l@english\@undefined
  \ifx\l@UKenglish\@undefined
    \ifx\l@british\@undefined
      \ifx\l@american\@undefined
        \ifx\l@USenglish\@undefined
          \ifx\l@canadian\@undefined
            \ifx\l@australian\@undefined
              \ifx\l@newzealand\@undefined

A detection of an English language would have to test either eight language names or eight hyphenation patterns.

Non-expandable \IfLangEnglish

The following example defines \IfLangEnglish using LaTeX's \in@ to check if an argument can be found in a list:

\documentclass{article}
\usepackage[USenglish,british,canadian,australian,ngerman]{babel}

\makeatletter
\newcommand*{\LanguageEnglishList}{%
  ,american,australian,british,canadian,english,newzealand,UKenglish,USenglish,%
}
\@onelevel@sanitize\LanguageEnglishList
\DeclareRobustCommand*{\IfLangEnglish}{%
  \let\@LanguageName@\languagename
  \@onelevel@sanitize\@LanguageName@
  \edef\@next{%
    \noexpand\in@{,\@LanguageName@,}{\LanguageEnglishList}%
  }\@next
  \ifin@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\begin{document}
  \def\test#1/#2 {%
    \par \textbf{\IfLangEnglish{yes}{no}} (#1/\textbf{#2})\par
  }%
  \test start document/ngerman
  \foreignlanguage{USenglish}{%
    \test foreignlanguage/USenglish
  }
  \begin{otherlanguage}{british}
    \test otherlanguage/british
  \end{otherlanguage}
  \begin{otherlanguage*}{canadian}
    \test otherlanguage*/canadian
  \end{otherlanguage*}
  \selectlanguage{australian}
  \test selectlanguage/australian
  \selectlanguage{ngerman}
  \test selectlanguage/ngerman
\end{document}

The categories of the letters inside \languagename can be 11 (letter) or 12 (other) or even a mixup (e.g. first character has 12, the others 11). Therefore \@onelevel@sanitize normalizes the characters to category 12 for the comparison.

Result:

Result

Expandable \IfLangEnglish

The former \IfLangEnglish is not fully expandable because of assignments and definitions.

Therefore I would use the following definition for \IfLangEnglish based on the expandable \IfLanguageName of package iflang:

\documentclass{article}
\usepackage[USenglish,british,canadian,australian,ngerman]{babel}

\usepackage{iflang}

\makeatletter
\newcommand*{\IfLangEnglish}{%
  % The order can be optimized by putting more often used names first.
  \IfLanguageName{american}\@firstoftwo{%
  \IfLanguageName{australian}\@firstoftwo{%
  \IfLanguageName{british}\@firstoftwo{%
  \IfLanguageName{canadian}\@firstoftwo{%
  \IfLanguageName{english}\@firstoftwo{%
  \IfLanguageName{newzealand}\@firstoftwo{%
  \IfLanguageName{UKenglish}\@firstoftwo{%
  \IfLanguageName{USenglish}\@firstoftwo\@secondoftwo}}}}}}}%
}
\makeatother

\begin{document}
  \def\test#1/#2 {%
    \par
    \csname if\IfLangEnglish{true}{false}\endcsname
      \textbf{yes}
    \else
      \textbf{no}
    \fi
    (#1/\textbf{#2})\par
  }%
  \test start document/ngerman
  \foreignlanguage{USenglish}{%
    \test foreignlanguage/USenglish
  }
  \begin{otherlanguage}{british}
    \test otherlanguage/british 
  \end{otherlanguage}
  \begin{otherlanguage*}{canadian}
    \test otherlanguage*/canadian 
  \end{otherlanguage*}
  \selectlanguage{australian}
  \test selectlanguage/australian
  \selectlanguage{ngerman}
  \test selectlanguage/ngerman
\end{document}

Result

Package iflang 2014/04/29 v1.7

The new version of iflang is available here until it hits CTAN. (The .dtx file is embedded as PDF attachment, run it through plain TeX to get the unpacked package file.)

The new version provides test commands for language families:

\IfLanguageFamilyEnglish{<yes>}{<no>}

The implementation is based on the expandable \IfLangEnglish macro.

See the documentation for the supported language families and their included languages.