5

I have a single LaTeX file from which I can output different PDFs in different languages. The system that I use right now works quite well but it is written in LaTeX3 and I found it very difficult to understand.
This is the code, the variable parts are given as “multiple arguments” to \lc:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[italian,french,english]{babel}

\ExplSyntaxOn

% the main command
\NewExpandableDocumentCommand{\lc}{m} % language choice
 {
  \fabbri_lc:n { #1 }
 }
% we can change the language mid document
\NewDocumentCommand{\setlclanguage}{m}
 {
  \fabbri_lc_set:n { #1 }
 }

% variables
\str_new:N \l_fabbri_lc_lang_str
\str_new:N \l_fabbri_lc_fallback_str

% internal functions
\cs_new:Nn \fabbri_lc:n
 {
  \str_case:VnF \l_fabbri_lc_lang_str
    { #1 }
    { \str_case:Vn \l_fabbri_lc_fallback_str { #1 } }
 }

\cs_new_protected:Nn \fabbri_lc_set:n
 {
  \str_set:Nn \l_fabbri_lc_lang_str { #1 }
  \fabbri_lc:n
   {
    {ita}{\selectlanguage{italian}}
    {fra}{\selectlanguage{french}}
    {eng}{\selectlanguage{english}}
   }
 }
\cs_generate_variant:Nn \fabbri_lc_set:n { e }


% setup
% set the default language based on \jobname of the form <name>-<lang>
\seq_set_split:NnV \l_tmpa_seq { - } \c_sys_jobname_str
\fabbri_lc_set:e { \seq_item:Nn \l_tmpa_seq { 2 } }

% set the fallback language
\str_set:Nn \l_fabbri_lc_fallback_str { eng } % choose the fallback language

\ExplSyntaxOff

\begin{document}

\section{\lc{
  {ita}{Titolo}
  {fra}{Titre}
  {eng}{Title}
}}

\lc{
 {ita}{Questo documento è in italiano}
 {fra}{Ce document est in français}
 {eng}{This document is in English}
}

% French is missing here
\lc{
  {ita}{Testo}
  {eng}{Text}
}

% change the default language
\setlclanguage{fra}

\section{\lc{
  {ita}{Titolo}
  {fra}{Titre}
  {eng}{Title}
}}

\lc{
 {ita}{Questo documento è in italiano}
 {fra}{Ce document est in français}
 {eng}{This document is in English}
}

% French is missing here
\lc{
  {ita}{Testo}
  {eng}{Text}
}

\end{document}

It is possible to select the language based on the job name. The main file is named fabbri.tex and the PDFs are created with pdflatex with these commands:

pdflatex -jobname=fabbri-ita fabbri
pdflatex -jobname=fabbri-eng fabbri

I got the code above from here.

I have recently updated my setup to use LuaLaTeX and I would like to:

  1. Change the code above from "inline" LaTeX3 to Lua code contained in a separate file.
  2. Change the language for the entire document so that the command \today print the date in the selected language.

Unfortunately, it seems to me that there is not much documentation on how to use Lua with LaTeX and I do not really know where to start.

4
  • 1
    Your question should be how to code this functionalities in LuaLaTeX.
    – projetmbc
    Nov 9, 2022 at 23:00
  • You are right, the title is not the best, but I think that now it is too late to change it. Nov 9, 2022 at 23:55
  • 2
    the expl3 language may look a bit daunting at the begin, but it is easier to handle than the various escaping rules and commands needed if you want to move between lua and tex. Before doing this switch better read the luacode documentation and some of the questions and answers here first. If you don't want to see the expl3 code in your preamble: simply put everything in a file language-selection-code.sty and then do \usepackage{language-selection-code}. Nov 10, 2022 at 8:46
  • Thank you for your comment, I will read more about the integration between LaTeX and Lua. For me the main advantage of Lua is that it is used as a scripting language in a lot of different programs. I did not know that I could move the expl3 code to a different file, thank you! Nov 10, 2022 at 9:45

2 Answers 2

6

I will not convert the full script for you but the following is hopefully sufficient to get you started.

To run Lua code from the LaTeX part of your document you can use the \directlua macro that has as argument the Lua code that you want to run. This can be a one-liner, but it can also be a call to a function that you have defined.

Defining functions can be done inside of a luacode environment, usually in the preamble.

To use the results of the Lua code in your document usually you add a tex.sprint() command in the code, which is a command that is specific for LuaLaTeX (i.e., it does not exist in regular Lua) which prints the argument in the document.

To pass an associative array to the Lua code you can use the regular Lua syntax for this kind of 'table' as it is called as the argument to \directlua.

Finally for \jobname there is a special variable tex.jobname available for use in the Lua code.

MWE:

\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function llc(langmap)
   local currlang = string.sub(tex.jobname, -3)
   tex.sprint(langmap[currlang])
end
\end{luacode}
\newcommand{\lc}[1]{\directlua{llc(#1)}}
\begin{document}
Jobname: \jobname

\lc{{ita="Questo documento è in italiano",
    fra="Ce document est in français",
    eng="This document is in English"}}
\end{document}

Result with lualatex -jobname=fabbri-fra yourfile.tex:

enter image description here

8
  • Thank you very much, this is very useful. Do you know how to do what I wrote in point 2? Nov 9, 2022 at 23:48
  • Basically, what I need is to call \selectlanguage{} from within Lua. Nov 10, 2022 at 0:06
  • 1
    You can use any LaTeX macro from Lua with tex.sprint, just make sure that you escape the backslash (for example tex.sprint("\\selectlanguage{french}"). You can use normal Lua string operations to construct this string by concatenating different parts, for example to get the language name from a Lua array. The basic principle is that tex.sprint inserts the argument in the code of the document at the current position, exactly the same as when you would have typed that code in the source yourself, including any LaTeX macros.
    – Marijn
    Nov 10, 2022 at 7:47
  • 1
    Can you try [[some t'ext]]?
    – projetmbc
    Nov 11, 2022 at 11:17
  • 2
    @AlbertoFabbri indeed using the raw string syntax as suggested by projectmbc should work. The issue itself is related to Babel shorthands that redefine the meaning of ". A quick solution is to turn them off, for example \usepackage[swedish,shorthands=off]{babel}.
    – Marijn
    Nov 11, 2022 at 12:42
5

There is no need to use expl3 nor lua script. Your intention can be realized using only TeX primitives:

\def\sdef#1{\expandafter\def\csname #1\endcsname}
\def\trycs#1#2{\ifcsname #1\endcsname \csname #1\endcsname \else #2\fi}
\def\readlanguage #1-#2;{\def\langmark{#2}}
\def\langmark{eng} % default language
%\expandafter\readlanguage \jobname;  % read \langmark from jobname

\sdef{sel:ita}{\selectlanguage{italian}\def\lcset{1}\sdef{use:ita}{1}}
\sdef{sel:fra}{\selectlanguage{french}\def\lcset{2}\sdef{use:fra}{2}}
\sdef{sel:eng}{\selectlanguage{english}\def\lcset{3}\sdef{use:eng}{3}}

\def\lc#1{\lcA#1{}{}}
\def\lcA#1#2{%
   \ifnum\lcset=\trycs{use:#1}{0} #2\fi
   \ifx&#1&\else \expandafter\lcA \fi
}

\trycs{sel:\langmark}{} % select a language given by \langmark

% test:
\lc{
 {ita}{Questo documento è in italiano}
 {fra}{Ce document est in français}
 {eng}{This document is in English}
}

There is default language eng defined at line 4. Remove comment character from the line 5 if you want to read \langmark from \jobname, i.e. when you are using -jobname file-fra file at your command line.

8
  • 4
    Honestly this seems even harder to understand than expl3 and it also does not change the language for the whole document. If I use \today it always prints the date in English. Nov 10, 2022 at 0:24
  • @AlbertoFabbri If you used \usepackage[italian,french,english]{babel} (as you mention in your example) then \today expand to the date in selected language. Moreover: you are working with TeX, so to understand the elementary TeX tools is usable (sometimes even necessary). Not all typesetting tasks can be done only by Lua. When you want to use LuaTeX at programmer level then you must understand TeX first. And when you understand TeX then my example cannot seem to you as "even harder to understand".
    – wipet
    Nov 10, 2022 at 4:54
  • 1
    I understand what you said, and it makes sense, but I have already spent a lot of time trying to understand TeX and it is sometimes hard to justify it considering that all its syntax and functioning is unique and does not apply to any other program as far as I know. Anyway, I am using babel and I tried to uncomment the code that reads the language from the jobname, but it does not change the language in which \today is printed. Nov 10, 2022 at 10:20
  • Furthermore, I got several warnings like this one from ChkTeX: You ought to not use primitive TeX in LaTeX code. Nov 10, 2022 at 10:21
  • I am not imagine what is doing in your computer. When I used babel then \today expands depending on the value of the \langmark macro. And I don't know what macro generates the warning about "not use primitive" but I'm interested in it. Can you be more precise?
    – wipet
    Nov 10, 2022 at 11:05

You must log in to answer this question.

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