Pedro Tiago Martins

# CV in several languages with LaTeX

May 15, 2021

Having a CV in English is basically a given in academia, but if you are in an environment where other languages are used (quite likely), you might need to maintain a CV in a different language as well.

This got me thinking: what if I could generate CVs in LaTeX in several languages from a single source, guaranteeing that they always have the exact same information and are always up-to-date?

I had two requirements to make it worth it:

1. list of publications and talks would have to be automatically generated (from a .bib file)
2. anything that can be localized should be localized, namely:
• the references themselves (tiny details that change from one language to another)
• dates
• place names

With these two requirements, most of the CV should be taken care of (academic CVs are indeed mostly publications and talks, places and dates). Here’s my attempt. I’ll go through the different snippets that accomplish each of the things I’m going for, but there is also a minimal working example at the end.

## Automatically generated reference lists

I wanted to generate references automatically, but have control over what shows up and where. So I used biblatex with the biber backend, but instead of generating an actual list of references, I used the fullcite command to get “full” in-text citations. I put them in a numbered list, since this way I can also label and refer to them by number if need be.

...

\usepackage[backend=biber,style=numeric,]{biblatex}

...

\begin{enumerate}
\item \fullcite{paper1}
\item \label{projectpaper} \fullcite{paper2}
\end{enumerate}

...

I completed project blabla (results published in paper \ref{projectpaper}).


This gives me:

1. Some Author and Jane Doe. “Some paper”. In: Journal of Stuff 2 (2021), pp. 1–10. doi: 10.1110/j.stuff.123
2. Author, S. “Some other paper”. Journal of things 4 (2020)

I completed project blabla (results published in paper 2).

What about talks? They are bit different. What entry type to use? And dates for talks are usually more specific than just a year…

Well, it turns out that biblatex handles all kinds of dates really nicely, including date ranges (it follows the ISO 8601 standard), and that there are a couple of entry types that can do the job. I settled on the unpublished type.1 Talks in my .bib file look like this:

@unpublished{talk1,
author = {Author, Some},
title = {That talk},
note = {That event},
location = {London, UK},
date = {2018-10-3/2018-10-9}
}


When you cite it:

\begin{enumerate}
\item \fullcite{talk1}
\end{enumerate}


you get:

1. Author, S. “That talk”. That event. London, UK, Oct. 3-9, 2015

Notice that date range. It knows that the start and end dates share a month, and it formats the date range accordingly. Great for our purposes. The date will be as specific as you want it to be.

Notice also that I used the numeric style. Full citations in this style display the date at the end of the line, which is nice for talks, but you might want to experiment with other styles.

Remember you can also change the formatting of different fields in specific entry types. For example, you can suppress the quotation marks in titles that the numeric style uses by declaring a field format that just outputs the title, by saying in the preamble:

\DeclareFieldFormat[article,inproceedings,incollection,thesis,unpublished]{title}{#1}


There is one other thing that is common in publication lists in CVs that you might want to do: highlight your name. biblatex offers functionality for this. You can add a field AUTHOR+an and highlight the corresponding author:

@article{paper1,
author = {Author, Some and Doe, Jane},
AUTHOR+an = {1=highlight},
title = {Some paper},
journal = {Journal of Stuff},
volume = {2},
pages = {1--10},
date = {2021},
doi = {10.1110/j.stuff.123}
}


and in your cv.tex preamble redefine that annotation to be, for example, bold:

\renewcommand*{\mkbibnamegiven}[1]{%
\ifitemannotation{highlight}
{\textbf{#1}}
{#1}}


This will give you:

Some Author and Jane Doe. “Some paper”. In: Journal of Stuff 2 (2021), pp. 1–10. doi: 10.1110/j.stuff.123

And it will work regardless of the style you choose.

So that’s our publications and talks taken care of.

### Dates in general

But this got me thinking: what about other dates, that have nothing to do with talks and publications? Wouldn’t it be nice if I could type them in the biblatex way, for consistency? There are a couple of packages for formatting dates, such as isodate and datetime2, but they have problems (one has poor localization and the other does not deal with date ranges).

So I checked, and eventually I asked, and eventually got the answer.2 The answer is to actually use biblatex.

The idea is that a dates.bib file is generated on the fly with any dates you enclose in a newly created \dates command, which also cites them, and they are therefore handled the biblatex way:

\addbibresource{dates.bib} % generated/updated on the fly
\newwrite\mydates
\newcounter{datecnt}
\NewDocumentCommand\dates {m}
{%
\stepcounter{datecnt}%
\immediate\write\mydates{@misc{date\thedatecnt,date={#1}}}%
\citedate{date\thedatecnt}%
}
\AtBeginDocument{\immediate\openout\mydates=dates.bib}
\AtEndDocument{\immediate\closeout\mydates}


If I use the \dates command in the text with a biblatex style date, I get what I need:

command output
\dates{2018} 2018
\dates{2018-07} July 2018
\dates{2018-07-02} July 2, 2018
\dates{2018-07-02/2018-07-04} July 2-4, 2018
\dates{2018-07-02/2018-08-03} July 2–Aug. 3, 2018
\dates{2018-07-02/2019-08-03} July 2, 2018–Aug. 3, 2019

These should cover most use cases (you can check the biblatex documentation for more).

## Multi-language

So far, so good, but the main thing is to get CVs in different languages. The first step towards this is to use the babel package, and load the languages we want (say, English and Portuguese):3

\usepackage[english,portuges]{babel}


But we still need:

• a way to switch between the languages for the right output to be created.
• a way to mark the text as being in one language or the other
• a way to ignore the text that’s not in the language we want

First, we create conditionals for the languages, and then set the values accordingly. Here, we activate the “English” switch:

\newif\ifen
\newif\ifpt

\entrue % english enabled
%\pttrue % portuguese disabled


And then we define the commands for marking up the text.

We say: if our English “switch” is on (basically, if \entrue), select english as the language for this piece of text. Same for portuges. If a switch is off, the corresponding text will not even be printed (since outputting it in the first place is dependent on the switch for that language being on):

\newcommand{\langen}[1]{
\ifen\selectlanguage{english}#1\fi}
\newcommand{\langpt}[1]{
\ifpt\selectlanguage{portuges}#1\fi}


This means that with this:

\langen{Text in English}\langpt{Texto em português}


The output, for \entrue, will be:

Text in English

If we comment out \entrue and uncomment \pttrue, we get:

Texto em português

So now we can basically translate whatever we want. I can say:

\dates{2021-07-02} - \langen{PhD in things}\langpt{Doutoramento em coisas}


And depending on what option is uncommented we get either:

Jul. 2, 2021 – PhD in things

or

2 de jul. de 2021 - Doutoramento em coisas

Dates, references, and other text are taken care of. Great! But most likely some things will be repeated over and over again, and maybe some shortcuts would be nice. We can define a sort of dictionary. Let’s say the same institution is mentioned a lot. We have degrees from there, we’ve given talks there, etc. We can have a new command whose definition is the multiple translations for that institution:

\newcommand{\uresearch}{\langen{University of Research}\langpt{Universidade de Investigação}}


And now we can say:

\dates{2021-07-02} - \langen{PhD in things}\langpt{Doutoramento em coisas}\\
\uresearch


And get:

Jul. 2, 2021 – PhD in things
University of Research

or

2 de jul. de 2021 - Doutoramento em coisas

We might even create a separate file with all our “dictionary entries” (let’s call it dictionary.tex):

\newcommand{\uresearch}{\langen{University of Research}\langpt{Universidade de Investigação}}
\newcommand{\ny}{\langen{New York}\langpt{Nova Iorque}}
\newcommand{\usa}{\langen{USA}\langpt{EUA}}


and then input it in our cv.tex with \input{dictionary.tex}. This will keep our source file cleaner.

Now, here’s a cool thing: you can actually use these dictionary macros in your .bib file. So, let’s say this “University of Research” is in New York, and you gave a talk there. You can have a .bib entry like this:

@unpublished{nytalk,
author = {Author, Some},
title = {That talk},
location = {\uresearch, \ny, \usa},
date = {2021-05-23}
}


Notice the macros in the location field.

And just by citing it the way we did before:

\item \fullcite{nytalk}


We get:

Some Author. “That talk”. University of Research, New York, USA, May 23, 2021

or

Some Author. “That talk”. Universidade de Investigação, Nova Iorque, EUA, 23 de mai. de 2021

Basically, since you have to translate things at least once anyway, you might as well put them in the dictionary. It will ensure re-usability, consistency, and a cleaner source. And you will be able to use them in your .bib file. Place names taken care of!

Other things can also be put in the dictionary. Here’s another example. In our dictionary.tex file:

\newcommand{\poster}{\langen{poster}\langpt{póster}}


In our source:

\begin{enumerate}
\item \fullcite{nytalk} (\poster)
\end{enumerate}


Output for each language:

1. Some Author. That talk. University of Research, New York, USA, May 23, 2021 (poster)
1. Some Author. That talk. Universidade de Investigação, Nova Iorque, EUA, 23 de mai. de 2021 (póster)

And that’s pretty much it. We update our CV, and we have an up-to-date version in both languages ready to go.

This can of course be done for several more languages, and for documents other than CVs. It could be that there are other ways to do this, but the method described here works.

## Bonus: compiling the right language(s) automatically

But there is one last thing. We can generate either CV (or both) without having to switch languages in the preamble, and name the resulting .pdf files accordingly. A makefile can do the trick.4

We want to:

• select the language automatically by declaring the correct “language switch”
• generate a .pdf with an unambiguous name (say, cv_pt.pdf for Portuguese)
• be able to compile all cvs at once, but also just the one of our choosing

A good way to compile latex documents is using latexmk, since it also takes care of bibliographies and cross-references (if you used, say, pdflatex, you would have to run it once, then run biber, then run pdflatex once or twice more; latexmk runs everything the correct number of times). We can craft a latexmk command that can do what we need.

The name of the .pdf file can be defined with the -jobname option. The conditionals and values for language switching can be passed as LaTeX commands (in quotes) as part of a -pdflatex option. This means that you must remove the language conditionals and values from cv.tex (basically, the lines above \documentclass{article}), otherwise this won’t work. Here’s our makefile:

all: pt en

SOURCES:    cv.tex \
refs.bib \
dictionary.tex

pt: $(SOURCES) latexmk -jobname=cv_pt -pdf -pdflatex='pdflatex %O -interaction=nonstopmode -synctex=1 "\newif\ifen\newif\ifpt\pttrue\input{%S}"' cv en:$(SOURCES)
latexmk -jobname=cv_en -pdf -pdflatex='pdflatex %O -interaction=nonstopmode -synctex=1 "\newif\ifen\newif\ifpt\entrue\input{%S}"' cv

clean:
rm -f *{aux,bbl,bcf,blg,fdb_latexmk,fls,log,xml,gz}


If you run:

make


Both cvs will be generated (cv_pt.pdf and cv_en.pdf).

If you run:

make pt


Only cv_pt.pdf gets generated. Same goes for make en and cv_en.pdf.

Finally, if you run

make clean


All auxiliary files generated by LaTeX will be removed.

## Minimal working example

You can copy and paste, or download a .zip file with everything you need: cv_mwe.zip

A source file cv.tex:

\newif\ifen
\newif\ifpt
\entrue % English enabled
%\pttrue % Portuguese disabled

%% -- comment out all lines above if using makefile -- %%

\documentclass{article}
\usepackage[english,portuges]{babel}
\usepackage{csquotes} % recommended when using babel

%language markup commands
\newcommand{\langen}[1]{%
\ifen\selectlanguage{english}#1\fi}
\newcommand{\langpt}[1]{%
\ifpt\selectlanguage{portuges}#1\fi}

%refs
\usepackage[backend=biber,style=numeric,]{biblatex}

%dates
\addbibresource{dates.bib} % generated/updated on the fly
\newwrite\mydates
\newcounter{datecnt}
\NewDocumentCommand\dates {m}
{%
\stepcounter{datecnt}%
\immediate\write\mydates{@misc{date\thedatecnt,date={#1}}}%
\citedate{date\thedatecnt}%
}
\AtBeginDocument{\immediate\openout\mydates=dates.bib}
\AtEndDocument{\immediate\closeout\mydates}

\title{Curriculum Vitae}
\author{Some Author}
\date{}
\input{dictionary.tex}
\begin{document}
\maketitle
\langen{\section{Education}}\langpt{\section{Formação}}
\dates{2021-07-02} - \langen{PhD in things}\langpt{Doutoramento em coisas}\\
\uresearch

\langen{\section{Publications}}\langpt{\section{Publicações}}
\begin{enumerate}
\item \fullcite{paper1}
\end{enumerate}

\langen{\section{Talks}}\langpt{\section{Comunicações}}
\begin{enumerate}
\item \fullcite{nytalk}
\end{enumerate}

\end{document}


A refs.bib file:

@article{paper1,
author = {Author, Some and Doe, Jane},
title = {Some paper},
journal = {Journal of Stuff},
volume = {2},
pages = {1--10},
date = {2021},
doi = {10.1110/j.stuff.123}
}

@unpublished{nytalk,
author = {Author, Some},
title = {That talk},
note = {That conference},
location = {\uresearch, \ny, \usa},
date = {2021-05-23}
}


A dictionary file dictionary.tex (optional):

\newcommand{\uresearch}{\langen{University of Research}\langpt{Universidade de Investigação}}
\newcommand{\ny}{\langen{New York}\langpt{Nova Iorque}}
\newcommand{\usa}{\langen{USA}\langpt{EUA}}


This will get you:

Curriculum Vitae

Some Author

1. Education
Jul. 2, 2021 – PhD in things
University of Research

2. Publications
1. Some Author and Jane Doe. “Some paper”. Journal of Stuff 2, pp. 1-10. 2021 doi: 10.1110/j.stuff.123

3. Talks
1. Some Author. “That talk”. University of Research, New York, USA, May 23, 2021

and if you switch off English and switch on Portuguese:

%\entrue % english disabled
\pttrue % portuguese enabled


you’ll get:

Curriculum Vitae

Some Author

1. Formação
2 de jul. de 2021 – Doutoramento em coisas

2. Publicações
1. Some Author e Jane Doe. “Some paper”. Journal of Stuff 2, pp. 1-10. 2021 doi: 10.1110/j.stuff.123

3. Comunicações
1. Some Author. “That talk”. Universidade de Investigação, Nova Iorque, EUA, 23 de mai. de 2021

## Notes

1. The idea of choosing the unpublished type for talks as well as using \fullcite instead of generating a reference list (neither had ever crossed my mind) came from Brian Buccola’s CV

2. Thanks to Ulrike Fischer for her answer on TeX Stack Exchange

3. I am not quite sure why the babel option for Portuguese is portuges, and not the expected portuguese. At first I thought that maybe babel limited the number of characters used for option names, but this is not the case.

4. Thanks to Alejandro Andirkó for the suggestion to use a makefile (and also for general comments and suggestions on this post). I was originally going to use a shell function, but this makes more sense.