Overview
Vitaes supports creating resumes in multiple languages, each with localized example data to help you get started quickly. The application interface is also fully internationalized, adapting to your preferred language.
Supported Languages
Vitaes currently supports seven languages:
English (en) Default language with Kendall Roy example data
Spanish (es) Íñigo Montoya example data
French (fr) Arsène Lupin example data
German (de) King Schultz example data
Japanese (ja) Gol D. Roger example data
Portuguese (pt) Agostinho Carrara example data
Chinese (zh) Sun Tzu example data
Language Selection
You can select a language in two contexts:
1. When Creating a Resume
When creating a new resume, you choose the language for the initial example data:
export const appRouter = {
createResume: protectedProcedure
. input (
z . object ({
name: z . string (),
language: z . enum ( Object . keys ( exampleResumes ) as [ string , ... string []]),
template: TemplateSchema . optional (),
}),
)
. handler ( async ({ context , input }) => {
const { name , language , template = 'awesome' } = input
const exampleResume =
exampleResumes [ language as keyof typeof exampleResumes ]
const initialData = {
... exampleResume ,
config: {
... exampleResume . config ,
template ,
},
}
const currentUser = context . session . user
const [ createdResume ] = await db
. insert ( resume )
. values ({
id: uuidv7 (),
name ,
userEmail: currentUser . email ,
data: initialData ,
slug: uniqueSlug ( currentUser . email , name ),
})
. returning ()
return createdResume
}),
}
The language you select determines which example data is used to pre-populate your new resume. You can edit all content freely after creation.
2. UI Language Selection
The application interface language can be changed independently:
import { LanguageSelector } from './language-selector'
< LanguageSelector />
The UI language affects:
Button labels
Form field names
Dialog messages
Validation errors
Navigation items
Example Data Structure
Each language has a complete resume example with culturally appropriate content:
export const exampleResumes = {
en: kendallRoyNew ,
es: inigoMontoyaNew ,
fr: arseneLupinNew ,
de: kingSchultzNew ,
ja: golDRogerNew ,
pt: agostinhoCarraraResume ,
zh: sunTzuNew ,
}
Spanish Example Data (es)
export const inigoMontoyaNew : IResume = {
config: {
themeColor: 'awesome-emerald' ,
headerAlign: 'left' ,
sectionColorHighlight: true ,
fontSize: 9 ,
pageSize: 'A4' ,
// ...
},
personalInfo: {
firstName: 'Íñigo' ,
lastName: 'Montoya' ,
position: 'Maestro de Esgrima' ,
address: 'Toledo, España' ,
quote: 'La dedicación y la práctica perfeccionan cualquier arte.' ,
socials: [
{
id: 'phone' ,
platform: 'mobile' ,
value: '+34-91-123-4567' ,
},
{
id: 'email' ,
platform: 'email' ,
value: '[email protected] ' ,
},
],
},
sections: [
{
id: 'summary' ,
title: 'Resumen' ,
type: 'text' ,
content:
'Maestro de esgrima con más de 20 años de experiencia en la enseñanza y práctica de artes marciales históricas.' ,
},
{
id: 'experience' ,
title: 'Experiencia Laboral' ,
type: 'timeline' ,
entries: [
{
id: 'fencing-academy' ,
position: 'Director y Maestro Principal' ,
title: 'Academia de Esgrima Montoya' ,
location: 'Toledo, España' ,
date: '2015-01-01 — present' ,
items: [
'Formación de más de 200 estudiantes en esgrima histórica.' ,
'Preparación de campeones nacionales e internacionales.' ,
],
},
],
},
{
id: 'languages' ,
title: 'Idiomas' ,
type: 'taxonomy' ,
categories: [
{
id: 'spanish' ,
type: 'Español' ,
items: [ 'Nativo' ],
},
{
id: 'english' ,
type: 'Inglés' ,
items: [ 'Avanzado' ],
},
],
},
],
}
Example Data Files
Example data is stored in separate files for maintainability:
packages/types/src/example-data/
├── en.ts # English - Kendall Roy (business executive)
├── es.ts # Spanish - Íñigo Montoya (fencing master)
├── fr.ts # French - Arsène Lupin (gentleman thief)
├── de.ts # German - King Schultz (bounty hunter)
├── ja.ts # Japanese - Gol D. Roger (pirate king)
├── pt.ts # Portuguese - Agostinho Carrara (various roles)
└── zh.ts # Chinese - Sun Tzu (military strategist)
Each file exports a complete IResume object with:
Personal information in the target language
Multiple sections demonstrating different section types
Culturally appropriate content and formatting
Proper date formats for the language/region
Localization Features
Section Titles
Section titles are localized in example data:
Summary
Work Experience
Education
Skills
Resumen
Experiencia Laboral
Educación
Habilidades
Résumé
Expérience Professionnelle
Formation
Compétences
Date formats follow regional conventions:
// English/International
date : '2018-01-01 — present'
// Spanish
date : '2015-01-01 — presente'
// French
date : '2015-01-01 — présent'
Phone numbers, addresses, and other location-specific data use appropriate formats:
// Spanish example
address : 'Toledo, España' ,
value : '+34-91-123-4567' ,
// French example
address : 'Paris, France' ,
value : '+33-1-42-86-82-00' ,
UI Internationalization
The application interface uses Paraglide for internationalization:
import { m } from '@/paraglide/messages'
// Usage in components
< DialogTitle >{m [ 'dialogs.createResume.title' ] ()} </ DialogTitle >
< Button >{m [ 'editor.download' ] ()} </ Button >
< span >{m [ 'editor.saving' ] ()} </ span >
Message Examples
// English
m [ 'editor.personalInfo' ]() // "Personal Info"
m [ 'editor.sections' ]() // "Sections"
m [ 'editor.saving' ]() // "Saving..."
// Spanish
m [ 'editor.personalInfo' ]() // "Información Personal"
m [ 'editor.sections' ]() // "Secciones"
m [ 'editor.saving' ]() // "Guardando..."
Creating Multilingual Resumes
You can create resumes in multiple languages:
Create a resume in your first language (e.g., English)
Duplicate the resume from your dashboard
Edit the content to translate all sections
Rename to indicate the language (e.g., “Resume - English” and “Resume - Spanish”)
Each resume is independent. You’ll need to manually translate and maintain content across different language versions.
Best Practices
Choose the right example data
Select the language that matches your target audience when creating a new resume. The example data provides a good starting point with appropriate formatting and structure.
When creating multilingual versions of your resume, ensure all information is accurately translated and culturally appropriate.
Follow the date format conventions for your target region (ISO format works universally).
Localize contact information
Include international phone number prefixes and use address formats appropriate for the target country.
Consider cultural differences
Different regions have different resume conventions (e.g., including photos, personal information, length expectations). Research these before finalizing your resume.
Language Selector Component
The language selector in the header allows users to switch UI languages:
import { LanguageSelector } from '@/components/language-selector'
< BuilderHeader >
< LanguageSelector />
</ BuilderHeader >
This changes:
All UI text and labels
Form validation messages
Date formatting in the interface
Number formatting
Changing the UI language doesn’t affect your resume content - only the interface. Your resume content remains in whatever language you’ve written it in.
Adding New Languages
To add support for a new language:
Create a new example data file in packages/types/src/example-data/
Export a complete IResume object with localized content
Add the new language to the exampleResumes object in resume.ts
Add UI translations to the Paraglide message files
Update the language selector to include the new option
Example structure:
// packages/types/src/example-data/it.ts
import type { IResume } from '../resume'
export const italianExample : IResume = {
config: { /* ... */ },
personalInfo: {
firstName: 'Marco' ,
lastName: 'Rossi' ,
position: 'Sviluppatore Software' ,
address: 'Roma, Italia' ,
// ...
},
sections: [
{
id: 'summary' ,
title: 'Riepilogo' ,
type: 'text' ,
content: '...' ,
},
// ...
],
}
Then update the exports:
export const exampleResumes = {
en: kendallRoyNew ,
es: inigoMontoyaNew ,
fr: arseneLupinNew ,
de: kingSchultzNew ,
ja: golDRogerNew ,
pt: agostinhoCarraraResume ,
zh: sunTzuNew ,
it: italianExample , // New language
}