# Directus Integration - Migration Guide ## 🎯 Overview This portfolio now has a **hybrid i18n system**: - ✅ **JSON Files** (Primary) → All translations work from `messages/*.json` files - ✅ **Directus CMS** (Optional) → Can override translations dynamically without rebuilds **Important**: Directus is **optional**. The app works perfectly fine without it using JSON fallbacks. ## 📁 New File Structure ### Core Infrastructure - `lib/directus.ts` - REST Client for Directus (uses `de-DE`, `en-US` locale codes) - `lib/i18n-loader.ts` - Loads texts with Fallback Chain - `lib/translations-loader.ts` - Batch loader for all sections (cleaned up to match actual usage) - `types/translations.ts` - TypeScript types for all translation objects (fixed to match components) ### Components All component wrappers properly load and pass translations to client components. ## 🔄 How It Works ### Without Directus (Default) ``` Component → useTranslations("nav") → JSON File (messages/en.json) ``` ### With Directus (Optional) ``` Server Component → getNavTranslations(locale) → Try Directus API (de-DE/en-US) → If not found: JSON File (de/en) → Props to Client Component ``` ## 🗄️ Directus Setup (Optional) Only set this up if you want to edit translations through a CMS without rebuilding the app. ### 1. Environment Variables Add to `.env.local`: ```bash DIRECTUS_URL=https://cms.example.com DIRECTUS_STATIC_TOKEN=your_token_here ``` **If these are not set**, the system will skip Directus and use JSON files only. ### 2. Collection: `messages` Create a `messages` collection in Directus with these fields: - `key` (String, required) - e.g., "nav.home" - `translations` (Translations) - Directus native translations feature - Configure languages: `en-US` and `de-DE` **Note**: Keys use dot notation (`nav.home`) but locales use dashes (`en-US`, `de-DE`). ### 3. Permissions Grant **Public** role read access to `messages` collection. ## 📝 Translation Keys See `docs/LOCALE_SYSTEM.md` for the complete list of translation keys and their structure. All keys are organized hierarchically: - `nav.*` - Navigation items - `home.hero.*` - Hero section - `home.about.*` - About section - `home.projects.*` - Projects section - `home.contact.*` - Contact form and info - `footer.*` - Footer content - `consent.*` - Privacy consent banner ## 🎨 Rich Text Content For longer content that needs formatting (bold, italic, lists), use the `content_pages` collection: ### Collection: `content_pages` (Optional) Fields: - `slug` (String, unique) - e.g., "home-hero" - `locale` (String) - `en` or `de` - `title` (String) - `content` (Rich Text or Long Text) Examples: - `home-hero` - Hero section description - `home-about` - About section content - `home-contact` - Contact intro text Components fetch these via `/api/content/page` and render using `RichTextClient`. ## 🔍 Fallback Chain For every translation key, the system searches in this order: 1. **Directus** (if configured) in requested locale (e.g., `de-DE`) 2. **Directus** in English fallback (e.g., `en-US`) 3. **JSON file** in requested locale (e.g., `messages/de.json`) 4. **JSON file** in English (e.g., `messages/en.json`) 5. **Key itself** as last resort (e.g., returns `"nav.home"`) ## ✅ What Was Fixed Previous issues that have been resolved: 1. ✅ **Type mismatches** - All translation types now match actual component usage 2. ✅ **Unused fields** - Removed translation keys that were never used (like `hero.greeting`, `hero.name`) 3. ✅ **Wrong structure** - Fixed `AboutTranslations` structure (removed fake `interests` nesting) 4. ✅ **Missing keys** - Aligned loaders with JSON files and actual component requirements 5. ✅ **Confusing comments** - Removed misleading comments in `translations-loader.ts` ## 🎯 Best Practices 1. **Always maintain JSON files** - Even if using Directus, keep JSON files as fallback 2. **Use types** - TypeScript types ensure correct usage 3. **Test without Directus** - App should work perfectly without CMS configured 4. **Rich text for formatting** - Use `content_pages` for content that needs bold/italic/lists 5. **JSON for UI labels** - Use JSON/messages for short UI strings like buttons and labels ## 🐛 Troubleshooting ### Directus not configured **This is normal!** The app works fine. All translations come from JSON files. ### Want to use Directus? 1. Set up `DIRECTUS_URL` and `DIRECTUS_STATIC_TOKEN` 2. Create `messages` collection 3. Add your translations 4. They will override JSON values ### Translation not showing? Check in this order: 1. Does key exist in `messages/en.json`? 2. Is the key spelled correctly? 3. Is component using correct namespace? ## 📚 Further Reading - **Complete locale documentation**: `docs/LOCALE_SYSTEM.md` - **Directus setup checklist**: `DIRECTUS_CHECKLIST.md` - **Operations guide**: `docs/OPERATIONS.md`