6

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?

1
  • 2
    \IfLanguagePatterns{english} returns true when the current language is english, USenglish and american (as specified in the option to babel). Also \iflanguage{english} does, but the test is less reliable in some circumstances.
    – egreg
    Commented Apr 29, 2014 at 10:40

2 Answers 2

10

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.

11
  • Thank you. As things stand, I should create an iflangfamily package that adapts your IfLangEnglish command to the other language families listed in section 1.1 of the babel manual.
    – Enno
    Commented Apr 29, 2014 at 13:19
  • Is it possible that for example IfLanguageName{american} returns false if only usepackage[american]{babel} is in the preamble? The IfLangEnglish command only works as expected over here if babel is loaded with the english or british option.
    – Enno
    Commented Apr 29, 2014 at 14:45
  • @user3528522: Please clarify the problem. Commented Apr 29, 2014 at 15:05
  • If you do one test at a time, by a minimal working example only containing \documentclass{article} \usepackage[american]{babel} and the IfLangEnglish command before begin{document}, then apparently IfLangEnglish does not return true.
    – Enno
    Commented Apr 29, 2014 at 16:00
  • 1
    @HeikoOberdiek The current version of iflang (2018/01/21 v1.7) has no support for language families any more?
    – mhchem
    Commented Jun 8, 2019 at 21:25
5

The translations package offers the (expandable)

\ifcurrentbaselanguage{<lang>}{<true>}{<false>}

test where <lang> is the name of what translations calls a base language. »English« is one of them. Other languages are dialects or aliases as far as translations is concerned. \ifcurrentbaselanguage{english}{<true>}{<false>} puts the <true> branch in the input stream as long as the current babel language is either english or an alias (English) or a dialect (british, ...) or an alias of a dialect (UKenglish, ...)

All the tests in the following example print yes except for the first one where the current language is ngerman:

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

\usepackage{translations}

\begin{document}

% ngerman
\ifcurrentbaselanguage{English}{yes}{no}

\begin{otherlanguage}{british}
  \ifcurrentbaselanguage{English}{yes}{no}
\end{otherlanguage}

\begin{otherlanguage*}{canadian}
  \ifcurrentbaselanguage{English}{yes}{no}
\end{otherlanguage*}

\selectlanguage{australian}
\ifcurrentbaselanguage{English}{yes}{no}

\selectlanguage{american}
\ifcurrentbaselanguage{English}{yes}{no}

\selectlanguage{newzealand}
\ifcurrentbaselanguage{English}{yes}{no}

\selectlanguage{USenglish}
\ifcurrentbaselanguage{English}{yes}{no}

\selectlanguage{UKenglish}
\ifcurrentbaselanguage{English}{yes}{no}

% this shows that the test is expandable:
\edef\foo{\ifcurrentbaselanguage{English}{yes}{no}}
\show\foo
% > \foo=macro:
% ->yes.
% l.32 \show\foo

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .