Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/iwinser117/react-portafolio/llms.txt

Use this file to discover all available pages before exploring further.

Hector Portfolio is fully bilingual. Every user-facing string is stored in translation files and resolved at runtime through i18next and its React binding react-i18next. Visitors can switch between Spanish and English at any time via the Settings panel, and their choice is remembered across sessions.

Libraries

PackageRole
i18nextCore internationalisation framework
react-i18nextReact hooks and components that wrap i18next

Configuration — src/locales/i18nConfig.js

The config file bootstraps i18next once on application start. It imports both JSON translation bundles, registers them as resources, and reads the user’s saved language from localStorage — falling back to Spanish ('es') if nothing is stored.
// src/locales/i18nConfig.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import es from './es.json';
import en from './en.json';

const resources = {
  es: { translation: es },
  en: { translation: en },
};

i18n
  .use(initReactI18next)
  .init({
    resources,
    lng: localStorage.getItem('language') || 'es', // persisted preference
    fallbackLng: 'es',                              // fallback if key is missing
    interpolation: {
      escapeValue: false, // React already escapes output
    },
  });

export default i18n;
OptionValueMeaning
lnglocalStorage.getItem('language') || 'es'Active language at startup
fallbackLng'es'Used when a key is missing in the active language
escapeValuefalseDisables double-escaping (React handles XSS)

Translation Files

Both files live in src/locales/ and share the same namespace structure. They use a single flat translation namespace (set in i18nConfig.js) whose top-level keys logically group strings by section.

Top-level namespaces

KeyDescription
navNavigation link labels
bannerHero section — title, description, social links
aboutAbout section — greeting, name, descriptions
skillsSkills section — title and technology descriptions
projectsProjects page — titles, search, labels
contactContact form — labels, placeholders, messages
settingsSettings modal — theme and language option labels
AsideSidebar — contact me link

projects namespace (full structure)

"projects": {
  "pageTitle": "My Projects",
  "pageDescription": "Explore my portfolio of modern and functional web applications",
  "allProjects": "All Projects",
  "projectsOf": "Projects of",
  "search": "Search projects...",
  "noResults": "No projects found",
  "tryOther": "Try other search terms or categories",
  "featured": "Featured Projects",
  "project": "project",
  "projects": "projects"
}

Using Translations in a Component

Call useTranslation() to obtain the t function, then pass the dot-separated key path as a string. The function returns the string for the currently active language.
import { useTranslation } from 'react-i18next';

const Nav = () => {
  const { t } = useTranslation();
  return <span>{t('nav.home')}</span>; // renders "Home" or "Inicio"
};
You can also destructure i18n from useTranslation() when you need the current language code or the changeLanguage method: const { t, i18n } = useTranslation();

Switching Language at Runtime

SettingsModal calls i18n.changeLanguage() and immediately persists the selection to localStorage so that the choice survives a full page reload (the config file reads this value on init).
// src/buttons/SettingsModal.jsx
const handleLanguageChange = (lang) => {
  i18n.changeLanguage(lang);           // updates all mounted components instantly
  localStorage.setItem('language', lang); // persisted across page reloads
};

// Called when the user clicks the language buttons:
handleLanguageChange('en'); // switch to English
handleLanguageChange('es'); // switch to Spanish
The UI highlights the active language button by comparing i18n.language against the button’s locale code.

Adding a New Translation Key

1

Add the key to en.json

Open src/locales/en.json and add your new key under the appropriate top-level namespace (or create a new one).
"contact": {
  ...
  "yourNewKey": "Your English text here"
}
2

Add the key to es.json

Open src/locales/es.json and add the matching Spanish translation under the same namespace path.
"contact": {
  ...
  "yourNewKey": "Tu texto en español aquí"
}
3

Use the key in your component

Import useTranslation and call t() with the dot-path to your new key.
import { useTranslation } from 'react-i18next';

const MyComponent = () => {
  const { t } = useTranslation();
  return <p>{t('contact.yourNewKey')}</p>;
};
Because fallbackLng is set to 'es', a key that exists in es.json but is missing from en.json will still render the Spanish string rather than the raw key. Always add keys to both files to avoid unintended language bleed.

Build docs developers (and LLMs) love