23

How can I make my package aware of the language choosen with babel or polyglossia, so that some auto-generated strings can be generated in respect to the current language?

As an example, I have a macro \my@string that shall expand to “Caption” in english text, “Überschrift” in german text, or “titre” in french ones.

4

1 Answer 1

23

There are several possibilities. I'll present four different ways. The first two use directly or indirectly the macros \captions<lang> or \extras<lang> which are provided both by babel and polyglossia. babel says the following about those two:

  • \captions<lang> : The macro \captions<lang> defines the macros that hold the texts to replace the original hard-wired texts.
  • \extras<lang> : The macro \extras<lang> contains all the extra definitions needed for a specific language. This macro [...] is a hook – you can add things to it, but it must not be used directly.

the babel manual uses \extras<lang> for examples of user defined definitions for the language <lang>. The main difference to \captions<lang> from a user perspective is that \extras<lang> is set later. So if both define the same macro for a language the definition in \extras<lang> »wins«.

\addto\captions<...>

You can check if babel or polyglossia have been loaded and if they are add the translations to \captions<lang> or \extras<lang>:

\newcommand*\mytitle{Title}
\@ifpackageloaded{babel}
  {\addto\captionsngerman{\def\mytitle{Titel}}}
  {
    \@ifpackageloaded{polyglossia}
      {\addto\captionsngerman{\def\mytitle{Titel}}}
      {}
  }

This could be wrapped up in a more convenient conditional, of course, in order not to have to duplicate code.

This is an expandable solution which means that \mytitle can also be used in PDF bookmarks or other places where this is useful.

A possible drawback: with this solution you have to provide translations for each »dialect«. For example if you set \addto\captionsngerman but a user chooses the language german he won't see the translation.

\RequirePackage{filecontents}
\begin{filecontents*}{mypackage.sty}
\ProvidesPackage{mypackage}[2014/07/27 v0.0 my new package]

\newcommand*\iflanguagepackage[1]{%
  \@ifpackageloaded{babel}
    {#1}
    {%
      \@ifpackageloaded{polyglossia}
        {#1}
        {}%
    }%
}

\newcommand*\mytitle{Title}
\iflanguagepackage{%
  \addto\captionsenglish{\def\mytitle{Title}}%
  \addto\captionsngerman{\def\mytitle{Titel}}%
  \addto\captionsfrench{\def\mytitle{Titre}}%
}
\end{filecontents*}

\documentclass{article}
\usepackage[english,french,ngerman]{babel}
\usepackage{mypackage}
\begin{document}

\mytitle

\selectlanguage{french}
\mytitle

\selectlanguage{english}
\mytitle

\end{document}

scrbase

The KOMA-Script classes or more precisely the KOMA-Script support package scrbase provides \providecaptionname. With this macro you don't have to check for the language packages. Otherwise it is pretty much the same:

\newcommand*\mytitle{Title}
\providecaptionname{ngerman}\mytitle{Titel}

It has the same advantages and drawbacks as the first solution (expandability, dialects, ...).

\RequirePackage{filecontents}
\begin{filecontents*}{mypackage.sty}
\ProvidesPackage{mypackage}[2014/07/27 v0.0 my new package]
\RequirePackage{scrbase}

\newcommand*\mytitle{Title}
\providecaptionname{english}\mytitle{Title}
\providecaptionname{ngerman}\mytitle{Titel}
\providecaptionname{french}\mytitle{Titre}

\end{filecontents*}

\documentclass{article}
\usepackage[english,french,ngerman]{babel}
\usepackage{mypackage}
\begin{document}

\mytitle

\selectlanguage{french}
\mytitle

\selectlanguage{english}
\mytitle

\end{document}

It has advantages over the pure babel/polyglossia way, though: for one thing the first argument of \providecaptionname can be a comma separated list of languages so it is more convenient to provide translations for dialects or language aliases. Also there are a number of related commands that allow finer control:

  • \defcaptionname{<list of languages>}{<macro>}{<translation>}: define the translation no matter what. (Like \def)
  • \providecaptionname{<list of languages>}{<macro>}{<translation>}: define a caption name for a language in <list of languages> if there isn't one, yet. (Like \providecommand)
  • \newcaptionname{<list of languages>}{<macro>}{<translation>}: define a caption name for a language in <list of languages> if there isn't one, yet, throw an error otherwise. (like \newcommand)
  • \renewcaptionname{<list of languages>}{<macro>}{<translation>}: renew an existing caption name for a language in <list of languages>. If there isn't one, yet, throw an error. (like \renewcommand)

Those commands decide themselves if it is better to add the translations to \captions<lang> or \extras<lang> except if you use their starred variants which will always use \extras<lang>. With v3.12 those macros defer the definitions at begin document.

translator

The translator package (part of beamer) is a more general solution.

The beamer manual says this:

The translator package is a LaTeX package that provides a flexible mechanism for translating individual words into different languages. For example, it can be used to translate a word like “figure” into, say, the German word “Abbildung”. Such a translation mechanism is useful when the author of some package would like to localize the package such that texts are correctly translated into the language preferred by the user. The translator package is not intended to be used to automatically translate more than a few words.

You may wonder whether the translator package is really necessary since there is the (very nice) babel package available for LaTeX. This package already provides translations for words like “figure”. Unfortunately, the architecture of the babel package was designed in such a way that there is no way of adding translations of new words to the (very short) list of translations directly built into babel.

Although we know now this is not entirely true the translator package is nevertheless a very useful generalization. The basic usage is as follows:

\newcommand*\mytitle{\translate{mypackage-title}}
\newtranslation[to=English]{mypackage-title}{Title}
\newtranslation[to=German]{mypackage-title}{Titel}

With it you also don't have to check for babel or polyglossia yourself. However, for the translating to work correctly the translator package needs to get the used language as package option which means a user should use the language as global option:

\documentclass[german]{article}
\usepackage{mypackage}

So a package using it should probably tell users about this. On the plus side: \newtranslation[to=German] works for german and ngerman automatically. If a language is used where no translation is given the English translation is used as fallback.

On the minus side: \translate is not expandable which might or might not cause trouble (e.g. when used in a \section and hyperref is used for PDF bookmarks).

One other possible advantage: it comes with dictionaries which already provide quite a number of translations.

Besides \newtranslation translator provides a number of similar commands:

  • \deftranslation[to=<lang>]{<string>}{<translation>} : provide a new translation to <string> for language <lang> no matter what. (like \def)
  • \newtranslation[to=<lang>]{<string>}{<translation>} : provide a new translation to <string> for language <lang>. Throw an error if it already exists. (like \newcommand)
  • \providetranslation[to=<lang>]{<string>}{<translation>} : provide a new translation to <string> for language <lang> if it doesn't exist, yet. (like \providecommand)
  • \renewtranslation[to=<lang>]{<string>}{<translation>} : renew an existing translation to <string> for language <lang>. Throw an error if it doesn't exist, yet. (like \renewcommand)
\RequirePackage{filecontents}
\begin{filecontents*}{mypackage.sty}
\ProvidesPackage{mypackage}[2014/07/27 v0.0 my new package]
\RequirePackage{translator}

\newcommand*\mytitle{\translate{mypackage-title}}
\newtranslation[to=English]{mypackage-title}{Title}
\newtranslation[to=German]{mypackage-title}{Titel}
\newtranslation[to=French]{mypackage-title}{Titre}

\end{filecontents*}

\documentclass[english,french,ngerman]{article}
\usepackage{babel}
\usepackage{mypackage}
\begin{document}

\mytitle

\selectlanguage{french}
\mytitle

\selectlanguage{english}
\mytitle

\end{document}

translations

You might also want to have a look at the translations package.

It's usage is very similar to translator. It has a few advantages, though:

  • its \GetTranslation is expandable
  • the chosen language is recognized also if not given as global option
  • it knows the concept of dialects

From the manual:

This package provides means for package authors to have an easy interface for internationalization of their packages. The functionality of this package is in many parts also covered by the package translator (part of the beamer bundle). Internationalization is also possible with babel and it’s \addto\captions<language> mechanism or KOMA-Script's \providecaptionname and similar commands. However, I believe that translations is more flexible than all of these. Unlike translator it detects the used (babel or polyglossia) language itself and provides expandable retrieving of the translated key. translations also provides support for language dialects which means package authors can for example distinguish between British, Australian, Canadian and US English.

translations provides a number of macros for defining and retrieving translated strings. Most of the times

  • \DeclareTranslationFallback{<string>}{<translation>} ,
  • \DeclareTranslation{<language>}{<string>}{<translation>} and
  • \GetTranslation{<string>}

will suffice, though.

There are also

  • \NewTranslation{<language>}{<string>}{<translation>} ,
  • \ProvideTranslation{<language>}{<string>}{<translation>} and
  • \RenewTranslation{<language>}{<string>}{<translation>}

with the same consequences as mentioned for scrbase's and translator's macros.

Each string should at least have a »fallback translation« which is used whenever no language package is present or the user has chosen a language for which no translation has been provided.

Like the translator package translations also knows dictionaries and already provides a number of translations.

\RequirePackage{filecontents}
\begin{filecontents*}{mypackage.sty}
\ProvidesPackage{mypackage}[2014/07/27 v0.0 my new package]
\RequirePackage{translations}

\newcommand*\mytitle{\GetTranslation{mypackage-title}}

% translations for `mypackage-title':
\DeclareTranslationFallback {mypackage-title}{Title}
\DeclareTranslation{English}{mypackage-title}{Title}
\DeclareTranslation{French} {mypackage-title}{Titre}
\DeclareTranslation{German} {mypackage-title}{Titel}

\end{filecontents*}

\documentclass{article}
\usepackage[english,french,ngerman]{babel}
\usepackage{mypackage}
\begin{document}

\mytitle

\selectlanguage{french}
\mytitle

\selectlanguage{english}
\mytitle

\end{document}

All complete examples give

enter image description here

8
  • Thank you, translations seems to do it job very well since it does not depend on global options or koma-stuff (even if I primarily use KOMA, there might be persons or institutions who/which decline to use it, as my university does)
    – NobbZ
    Commented Jul 27, 2014 at 15:07
  • I use translations quite a lot in my packages myself. However, since it's easy to load scrbase independently (as I've shown in the example above) none of the four solutions depend on a KOMA class!
    – cgnieder
    Commented Jul 27, 2014 at 15:12
  • But it depends on scrbase, which is forbidden at my university as part of KOMA-script. I really don't know why, and I won't start a discussion about that topic, many have tried before and all have lost.
    – NobbZ
    Commented Jul 27, 2014 at 16:46
  • In that case you can't use translations either since it loads the KOMA package scrlfile. Does that mean you have to check \listfiles every time in order to make sure that no KOMA package has been loaded? I can't believe that!
    – cgnieder
    Commented Jul 27, 2014 at 16:51
  • There are quite a number of KOMA packages that could be loaded by other packages, too: scrbase, scrlfile, scrrfile, tocbasic, scrhack ...
    – cgnieder
    Commented Jul 27, 2014 at 16:59

You must log in to answer this question.

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