Language‑Aware Discovery & Navigation
Navigation labels, links, and routes now derive strictly from the selected language; filenames and manifest language hints are advisory only.
Language‑Aware Discovery & Navigation
This document explains the new language-first behavior in the docs system. The sidebar and routes now reflect the user’s selected language, regardless of filename conventions or manifest language hints.
What changed
- ✅ WORKING: Intelligent cross-language linking system implemented
- Sidebar items and routes are generated using the currently selected language from
DocumentationService.currentLanguage - File exposure is controlled by the selected language, not by filename (e.g.,
.es.md) nor by manifestlanguagemetadata - Link generation prefixes
/es/only when Spanish is selected. English paths remain unprefixed - NEW: Frontmatter-based language switching with automatic equivalent page detection
- FIXED: Language switching now preserves page context instead of always redirecting to root
- Misplaced
.es.mdfiles underenglish/no longer leak Spanish titles into the English sidebar
How it works
🔄 Language Detection & Navigation
- Discovery builds a neutral list of files for the current language context and tags discovered items with that context
- When converting discovered items to navigation items, link paths are derived using the selected language:
- English:
/section/page - Spanish:
/es/section/page
- English:
- Dynamic route generation includes only routes that match the selected language context
🌐 Cross-Language Linking (NEW)
- Frontmatter Priority: When user switches languages, system first checks current page's frontmatter for
languageVersions - Intelligent Navigation: If equivalent page exists in target language, navigates directly to it
- Graceful Fallback: If frontmatter method fails, falls back to directory translation
- Final Fallback: If all methods fail, navigates to language root (
/getting-startedor/es/getting-started)
🔧 Technical Implementation
- HeaderActionsComponent: Handles language switching logic with frontmatter priority
- MarkdownService: Enhanced with full YAML parser for nested frontmatter objects
- Path Resolution: Intelligent file existence testing with content validation
- Error Handling: Robust fallback system prevents broken navigation
Key services involved
StructureSyncService- Selected language flows through
discoverStructure(language)and is applied when converting directories/files. - Link building uses the selected language to add the correct prefix.
- Selected language flows through
NavigationService- Reacts to language changes and reinitializes the discovered structure.
DynamicRoutesService- Generates routes only for the active language to avoid duplicates and cross-language leakage.
Authoring guidelines
- Prefer placing English files under
assets/docs/english/**and Spanish files underassets/docs/spanish/**. - You may keep translated files side-by-side (e.g.,
page.mdandpage.es.md). The selected language determines which appears. - Keep titles in each file's frontmatter in its own language; the system will not mix them between languages.
🚨 CRITICAL: Avoid Hardcoded Language Logic
❌ NEVER do this:
// BAD: Hardcoded language logic
const langPrefix = currentLang === 'es' ? '/es' : '';
const isSpanish = path.startsWith('/es/');
✅ ALWAYS do this:
// GOOD: Scalable language system
const languageUrlMap: { [key: string]: string } = {
'en': '',
'es': '/es',
'fr': '/fr',
'de': '/de',
'pt': '/pt',
'it': '/it',
'ja': '/ja',
'ko': '/ko',
'zh': '/zh'
};
const langPrefix = languageUrlMap[currentLang] || '';
// For detecting language from URL
const knownPrefixes = Object.values(languageUrlMap).filter(prefix => prefix);
let detectedLanguage = 'en';
for (const [lang, prefix] of Object.entries(languageUrlMap)) {
if (prefix && (path === prefix || path.startsWith(prefix + '/'))) {
detectedLanguage = lang;
break;
}
}
Why this matters:
- ✅ Future-proof: Easy to add new languages (French, German, etc.)
- ✅ Maintainable: Single source of truth for language mappings
- ✅ Consistent: Same pattern used across all services
- ✅ Scalable: No need to update multiple hardcoded checks
Migration notes
- No filename changes are required. The system is resilient to misplaced
.es.mdfiles. - If you want clean source organization, move Spanish files into
assets/docs/spanish/**and re-run the scanner.
🎉 Working Solution: Cross-Language Linking
📋 Implementation Example
To enable cross-language linking for any documentation page, add the following frontmatter to both language versions:
English File (apps/docs-angular/src/assets/docs/english/public/documentation/example-page.md):
---
title: Example Page
description: This is an example page
layout: guide
crossLanguageId: example-page
languageVersions:
en: documentation/example-page
es: documentacion/pagina-ejemplo
---
Spanish File (apps/docs-angular/src/assets/docs/spanish/public/documentacion/pagina-ejemplo.es.md):
---
title: Página de Ejemplo
description: Esta es una página de ejemplo
layout: guide
crossLanguageId: example-page
languageVersions:
en: documentation/example-page
es: documentacion/pagina-ejemplo
---
🔧 Key Requirements
- Identical
crossLanguageId: Both files must have the same identifier - Complete
languageVersions: Map all supported languages to their paths - No Language Prefixes: Paths should not include
/es/- the system adds this automatically - File Extensions: Spanish files use
.es.mdextension
✅ Verification
When working correctly, you should see these logs during language switching:
📄 Available frontmatter keys: (5) ['title', 'description', 'layout', 'crossLanguageId', 'languageVersions']
🎯 Frontmatter suggests target path: "documentation/example-page" → "/documentation/example-page"
🧪 Page existence test for "documentation/example-page" (en): ✅ EXISTS
✅ Found frontmatter-based equivalent: "documentacion/pagina-ejemplo" → "/documentation/example-page"
Troubleshooting
Language Display Issues
Sidebar shows the wrong language:
- Ensure URL reflects the desired language (Spanish pages are prefixed with
/es/). - Verify
DocumentationService.currentLanguage()reflects the selection.
- Ensure URL reflects the desired language (Spanish pages are prefixed with
Language dropdown shows current language instead of alternatives (Fixed):
- This was caused by UX Portal caching HTML content with
reusePortal: true - Fixed by setting
reusePortal: falseto ensure fresh content generation - Check console for language filtering logs to verify proper operation
- This was caused by UX Portal caching HTML content with
Content Loading Issues
404 errors during language switching (Fixed):
- Previously caused by malformed paths like
.es.mdor empty segments - Fixed with enhanced path validation and smart fallback strategies
- System now uses intelligent heuristics instead of expensive content existence checks
- Previously caused by malformed paths like
A page is missing:
- Run the scanner to refresh
docs-manifest.json. - Confirm the file has a
.mdextension and lives underenglish/orspanish/.
- Run the scanner to refresh
Performance Improvements
- Language switching is now faster due to smart fallback strategies
- Reduced 404 errors with path validation and content existence optimization
- Better user experience with immediate language state updates and UI consistency
See also
enhanced-docs-system.mdfor architecture and discovery pipelinenavigation.service.tsandstructure-sync.service.tsfor implementation details