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:
.bib
file)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.
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}
\addbibresource{refs.bib}
...
\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:
- Some Author and Jane Doe. “Some paper”. In: Journal of Stuff 2 (2021), pp. 1–10. doi: 10.1110/j.stuff.123
- 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:
- 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.
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).
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:
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
Universidade de Investigação
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:
- Some Author. That talk. University of Research, New York, USA, May 23, 2021 (poster)
- 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.
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:
.pdf
with an unambiguous name (say, cv_pt.pdf
for Portuguese)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.
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}
\addbibresource{refs.bib}
%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
Education
Jul. 2, 2021 – PhD in things
University of ResearchPublications
1. Some Author and Jane Doe. “Some paper”. Journal of Stuff 2, pp. 1-10. 2021 doi: 10.1110/j.stuff.123Talks
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
Formação
2 de jul. de 2021 – Doutoramento em coisas
Universidade de InvestigaçãoPublicações
1. Some Author e Jane Doe. “Some paper”. Journal of Stuff 2, pp. 1-10. 2021 doi: 10.1110/j.stuff.123Comunicações
1. Some Author. “That talk”. Universidade de Investigação, Nova Iorque, EUA, 23 de mai. de 2021
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. ↩
Thanks to Ulrike Fischer for her answer on TeX Stack Exchange. ↩
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. ↩
Thanks to Alejandro Andirkó for the suggestion to use a makefile
(and also for general comments and suggestions on this post). ↩