feat: i18n full support, responsive UI, multi-model AI config, and bug fixes

Major Features:
- Internationalization (i18n) with auto-detection for ES/EN/PT
- Mobile-first responsive design for Studio and Experience
- Multi-model AI configuration (llama3.2:3b, qwen3.5:9b, gpt-oss:latest)
- Course language configuration (auto-detect or fixed per course)

Backend Changes:
- shared/common: ModelType enum for intelligent model selection
- LMS: log_ai_usage function migration (fix chat tutor 500 error)
- LMS/CMS: course language config fields (language_setting, fixed_language)
- LMS: /courses/{id}/language-config endpoint for language detection

Frontend Changes:
- Experience: Enhanced i18n with browser language detection
- Experience: Audio recording with HTTPS check and error handling
- Studio: Memory game with unique pair IDs and debug logging
- Studio: Expanded translations (250+ keys for ES, EN, PT)
- Both: Language selector in headers (mobile responsive)

Documentation:
- AI_MODELS_CONFIG.md: Multi-model configuration guide
- RESPONSIVIDAD_GUIA.md: Mobile-first design patterns
- I18N_RESPONSIVIDAD_IMPLEMENTACION.md: Implementation details
- DEBUG_AUDIO_RECORDING.md: Audio troubleshooting guide
- DEBUG_MEMORY_GAME.md: Memory game debugging steps

Bug Fixes:
- Fix chat tutor 500 error (missing log_ai_usage function)
- Fix audio recording (HTTPS check, browser compatibility)
- Fix memory game pair IDs (unique ID generation)
- Fix HotspotBlock TypeScript errors

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-03-23 12:24:22 -03:00
parent 0598fc4865
commit 2ff06ee7ae
26 changed files with 2993 additions and 124 deletions
+445
View File
@@ -0,0 +1,445 @@
# Implementación de Internacionalización (i18n) y Responsividad
## Resumen de la Implementación
**Fecha**: 20 de Marzo, 2026
**Estado**: ✅ Completado
---
## 🌍 Internacionalización (i18n)
### Características Implementadas
1. **Detección Automática de Idioma**
- Detección del idioma del navegador al primer ingreso
- Soporte para múltiples idiomas del navegador (`navigator.languages`)
- Fallback a español si el idioma no está soportado
2. **Idiomas Soportados**
- 🇪🇸 Español (es)
- 🇬🇧 Inglés (en)
- 🇵🇹 Portugués (pt)
3. **Selector Manual de Idioma**
- Disponible en AppHeader (Experience) y Navbar (Studio)
- Persistencia en localStorage
- Cambio instantáneo sin recargar la página
4. **Configuración de Idioma por Curso**
- **Modo Automático**: Detecta el idioma del usuario
- **Modo Fijo**: Usa siempre el idioma configurado en el curso
- Ideal para cursos de idiomas (ej: curso de inglés siempre en inglés)
---
## 📱 Responsividad (Mobile-First)
### Breakpoints Utilizados
```
Mobile: < 640px (default)
sm: ≥ 640px
md: ≥ 768px
lg: ≥ 1024px
xl: ≥ 1280px
2xl: ≥ 1536px
```
### Componentes Responsivos
#### AppHeader (Experience)
**Mobile (< 768px):**
- Logo compacto
- Íconos de notificación y tema
- Botón de menú hamburguesa
- Sidebar deslizante con navegación completa
**Desktop (≥ 768px):**
- Logo completo
- Navegación horizontal visible
- Selector de idioma visible
- Perfil de usuario visible
#### Navbar (Studio)
**Mobile (< 768px):**
- Logo compacto
- Dropdowns colapsados
- Menú hamburguesa
- Sidebar deslizante
**Desktop (≥ 768px):**
- Logo completo
- Dropdowns visibles
- Información de usuario visible
---
## 🗂️ Archivos de Traducción
### Experience (web/experience/src/lib/locales/)
**Archivos:**
- `es.json` - Español (completo)
- `en.json` - Inglés (completo)
- `pt.json` - Portugués (completo)
**Categorías:**
- `common` - Textos comunes (loading, error, save, cancel)
- `nav` - Navegación (catalog, profile, signOut)
- `course` - Cursos (modules, lessons, progress)
- `lesson` - Lecciones (summary, transcription, complete)
- `auth` - Autenticación (login, register, password)
- `dashboard` - Dashboard (welcome, stats)
- `profile` - Perfil (edit, avatar, settings)
- `gamification` - Gamificación (level, xp, badges)
- `grading` - Calificaciones (grade, score, feedback)
- `quiz` - Cuestionarios (start, submit, attempts)
- `forum` - Foros (discussions, threads, replies)
- `payments` - Pagos (purchase, payment method)
- `accessibility` - Accesibilidad (contrast, text size)
- `language` - Idiomas (select, course, interface)
- `errors` - Errores (notFound, unauthorized)
- `dates` - Fechas (today, yesterday, daysAgo)
### Studio (web/studio/src/lib/locales/)
**Archivos:**
- `es.json` - Español (completo - administración)
- `en.json` - Inglés (básico - pendiente completar)
- `pt.json` - Portugués (básico - pendiente completar)
**Categorías Adicionales:**
- `course` - Gestión de cursos (create, edit, modules, lessons)
- `content` - Tipos de contenido (video, audio, quiz, code)
- `ai` - Funciones de IA (generate, model, tokens)
- `grading` - Sistema de calificación (categories, weights)
- `students` - Estudiantes (enrollments, progress)
- `analytics` - Analíticas (overview, retention)
- `settings` - Configuración (branding, integrations)
- `user` - Usuario (profile, preferences)
- `validation` - Validación de formularios
---
## 🗄️ Base de Datos
### Migración: Course Language Configuration
**Archivo:** `services/cms-service/migrations/20260320000002_add_course_language_config.sql`
**Campos Agregados a `courses`:**
```sql
language_setting VARCHAR(20) DEFAULT 'auto'
- 'auto': Detectar idioma del usuario
- 'fixed': Usar idioma fijo
fixed_language VARCHAR(5) DEFAULT NULL
- 'es': Español
- 'en': Inglés
- 'pt': Portugués
- NULL: Cuando language_setting es 'auto'
```
**Constraints:**
```sql
chk_language_setting: language_setting IN ('auto', 'fixed')
chk_fixed_language: fixed_language IS NULL OR fixed_language IN ('es', 'en', 'pt')
```
**Índice:**
```sql
idx_courses_language: (language_setting, fixed_language)
```
---
## 🔌 Backend API
### LMS Service (Port 3002)
**Endpoint: Course Language Config**
```http
GET /courses/{id}/language-config
Authorization: Bearer {token}
```
**Respuesta:**
```json
{
"language_setting": "auto",
"fixed_language": null
}
```
**Ejemplos de Uso:**
```javascript
// Curso en modo automático (usa idioma del usuario)
{
"language_setting": "auto",
"fixed_language": null
}
// Curso de inglés (siempre en inglés)
{
"language_setting": "fixed",
"fixed_language": "en"
}
// Curso de español (siempre en español)
{
"language_setting": "fixed",
"fixed_language": "es"
}
```
---
## ⚙️ Contextos y Hooks
### I18nContext (Experience y Studio)
**Funciones:**
```typescript
interface I18nContextType {
language: string;
setLanguage: (lang: string) => void;
t: (path: string) => string;
detectBrowserLanguage: () => string;
}
```
**Uso:**
```typescript
import { useTranslation } from '@/context/I18nContext';
function MyComponent() {
const { language, setLanguage, t } = useTranslation();
return (
<div>
<h1>{t('dashboard.welcome')}</h1>
<select
value={language}
onChange={(e) => setLanguage(e.target.value)}
>
<option value="es">ES</option>
<option value="en">EN</option>
<option value="pt">PT</option>
</select>
</div>
);
}
```
### useCourseLanguage Hook (Experience)
**Hook para idioma por curso:**
```typescript
import { useCourseLanguage } from '@/hooks/useCourseLanguage';
function CoursePage({ courseId }) {
const {
courseLanguage,
isFixedLanguage,
isLoading
} = useCourseLanguage(courseId);
if (isLoading) return <Loading />;
return (
<div>
<p>Idioma del curso: {courseLanguage}</p>
{isFixedLanguage() && (
<p>Este curso usa idioma fijo</p>
)}
</div>
);
}
```
**Funciones:**
- `courseLanguage`: Idioma actual del curso
- `isFixedLanguage()`: Boolean - ¿el curso tiene idioma fijo?
- `isLoading`: Boolean - ¿cargando configuración?
- `refreshConfig()`: Recargar configuración
### useCourseLanguageSwitcher Hook (Experience)
**Hook para cambiar idioma (solo si es permitido):**
```typescript
import { useCourseLanguageSwitcher } from '@/hooks/useCourseLanguage';
function LanguageSelector({ courseId }) {
const {
currentLanguage,
canChangeLanguage,
changeLanguage,
isFixed
} = useCourseLanguageSwitcher(courseId);
return (
<select
value={currentLanguage}
onChange={(e) => changeLanguage(e.target.value)}
disabled={!canChangeLanguage}
>
<option value="es">Español</option>
<option value="en">English</option>
<option value="pt">Português</option>
</select>
);
}
```
---
## 📋 Guía de Responsividad
**Archivo:** `RESPONSIVIDAD_GUIA.md`
### Principios Mobile-First
1. **Diseñar primero para móvil**
2. **Mejorar progresivamente para pantallas más grandes**
3. **Usar clases responsivas de Tailwind**
### Patrones Comunes
#### Grid de Cursos
```tsx
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
{courses.map(course => (
<CourseCard key={course.id} course={course} />
))}
</div>
```
#### Tablas Responsivas
```tsx
<div className="overflow-x-auto">
<table className="min-w-full">
{/* Tabla completa */}
</table>
</div>
```
#### Tipografía Fluida
```tsx
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold">
Título Responsivo
</h1>
```
#### Espaciado Responsivo
```tsx
<div className="px-4 md:px-6 lg:px-8 py-4 md:py-6 lg:py-8">
{/* Contenido */}
</div>
```
---
## 🧪 Pruebas
### Checklist de Responsividad
- [ ] Navegación funciona en mobile
- [ ] Menús desplegables accesibles
- [ ] Formularios usables en pantallas pequeñas
- [ ] Tablas con scroll horizontal
- [ ] Imágenes se escalan correctamente
- [ ] Texto legible sin zoom
- [ ] Botones táctiles (mínimo 44x44px)
- [ ] Sin overflow horizontal no intencional
### Dispositivos de Prueba (Chrome DevTools)
- iPhone SE (375x667)
- iPhone 12 Pro (390x844)
- iPad Air (820x1180)
- iPad Pro (1024x1366)
- Desktop (1920x1080)
---
## 🚀 Comandos Útiles
### Ver Logs de i18n
```bash
# Experience
docker logs openccb-experience-1 | grep -i "language\|i18n"
# Studio
docker logs openccb-studio-1 | grep -i "language\|i18n"
```
### Probar Detección de Idioma
```javascript
// Console del navegador
console.log(navigator.languages);
console.log(navigator.language);
localStorage.removeItem('experience_language');
location.reload();
```
### Ver Configuración de Curso
```bash
# SQL
SELECT id, title, language_setting, fixed_language
FROM courses
WHERE id = '{course-id}';
```
---
## 📝 Tareas Futuras (Opcionales)
1. **Completar traducciones de Studio**
- Agregar claves faltantes en `en.json` y `pt.json`
2. **Agregar más idiomas**
- Francés (fr)
- Alemán (de)
- Italiano (it)
3. **Traducción de contenido de cursos**
- Sistema de traducción de lecciones
- Contenido multi-idioma por lección
4. **Mejoras de accesibilidad**
- Aumentar contraste
- Texto de mayor tamaño
- Navegación por teclado
5. **Optimización de rendimiento**
- Lazy loading de traducciones
- Code splitting por idioma
---
## 📞 Referencias
- [Documentación de i18n](https://nextjs.org/docs/app/building-your-application/routing/internationalization)
- [Tailwind CSS Responsive Design](https://tailwindcss.com/docs/responsive-design)
- [MDN Internationalization](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization)
---
**Implementado por**: Equipo de Desarrollo OpenCCB
**Versión**: 1.0
**Última actualización**: 2026-03-20