The portfolio at leviek.dev is fully bilingual, serving the same content in both Spanish and English. Rather than relying on a third-party i18n library, the project uses Astro 6’s built-in internationalization routing system. Spanish is the default locale, served at the root pathDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Emmanuel-Mtz-777/My-Personal-Portfolio/llms.txt
Use this file to discover all available pages before exploring further.
/, and English is available at /en/. All UI text is stored in two JSON files — one per language — and components select the correct file at render time based on the current locale.
Astro i18n Configuration
The i18n routing is declared inastro.config.mjs:
- Serves the Spanish locale at
/(no path prefix, since"es"is thedefaultLocale) - Serves the English locale at
/en/(prefixed with the locale code) - Populates
Astro.currentLocalewith"es"or"en"on every page
Page Routes
The two locale entry points are separate Astro page files:| File | URL | Language |
|---|---|---|
src/pages/index.astro | / | Spanish (default) |
src/pages/en/index.astro | /en/ | English |
Hero, Experience, Projects, Stack, Education, AboutMe) — the language difference comes entirely from the content each component reads at build time.
Content File Structure
All UI strings are stored in JSON files undersrc/langs/:
| Key | Description |
|---|---|
hero | Greeting, role title, description, location, image alt text |
nav | Navigation link labels (Experience, Projects, Skills, etc.) |
experience | Section title and work history items |
projects | Section title and project entries (name, description, tech) |
stack | Section title and category labels for tech skills |
education | Degree entry (name, institution, date range) |
certifications | Section title and certification items (name, issuer, date) |
about | About Me section paragraphs with highlight keyword arrays |
Locale Detection in Components
Components detect the current locale usingAstro.currentLocale and import the correct translation object. Here is the pattern used in Header.astro and throughout all section components:
t.nav.projects returns "Proyectos" on the Spanish page and "Projects" on the English page.
Hero Section — Side-by-Side Example
Thehero key in both language files shows how the same content is expressed in each locale:
English (src/langs/en.json):
src/langs/es.json):
Language Switcher
TheHeader.astro component renders a pill-style language switcher that links directly between the two routes:
bg-white text-black and the inactive one with text-white/60, determined by comparing lang to "es" or "en".
Adding a New Locale
To add a third locale (for example, French at/fr/):
- Add
"fr"to thelocalesarray inastro.config.mjs: - Create
src/langs/fr.jsonwith all the same top-level keys asen.jsonandes.json. - Create
src/pages/fr/index.astromirroring the structure ofsrc/pages/en/index.astro. - Update the locale detection logic in each component to handle
lang === "fr". - Add the
/fr/link to the language switcher inHeader.astro.
Updating Existing Content Strings
To update a piece of UI text — for example, a project description or a nav label — open bothsrc/langs/es.json and src/langs/en.json and edit the corresponding key in each file. The change will be reflected at the next pnpm build or pnpm dev reload.
All UI text updates must be made in both language files (
es.json and en.json) to keep the Spanish and English versions in sync. A missing or stale key in one file will cause the affected component to display an undefined value.