feat: localize various UI texts and labels to Spanish across application pages and interactive components.

This commit is contained in:
2026-01-16 23:25:36 -03:00
parent 2cfd1f204b
commit ffbef17396
19 changed files with 178 additions and 181 deletions
@@ -11,7 +11,7 @@ export default function DescriptionPlayer({ id, title, content }: DescriptionPla
<div className="space-y-8" id={id}>
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Overview"}
{title || "Resumen"}
</h3>
</div>
@@ -46,7 +46,7 @@ export default function FillInTheBlanksPlayer({ id, title, content, allowRetry =
<div className="space-y-8" id={id}>
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Fill in the Blanks"}
{title || "Rellena los Espacios en Blanco"}
</h3>
</div>
@@ -84,7 +84,7 @@ export default function FillInTheBlanksPlayer({ id, title, content, allowRetry =
onClick={() => setSubmitted(true)}
className="btn-premium w-full py-5 font-black text-xs uppercase tracking-[0.2em] shadow-xl shadow-blue-500/20"
>
Validate Answers
Validar Respuestas
</button>
)}
@@ -93,7 +93,7 @@ export default function FillInTheBlanksPlayer({ id, title, content, allowRetry =
onClick={handleReset}
className="w-full py-5 glass text-blue-400 font-black text-xs uppercase tracking-[0.2em] hover:bg-white/5 transition-all rounded-3xl border-white/5"
>
Try Again
Intentar de Nuevo
</button>
)}
</>
@@ -41,13 +41,13 @@ export default function MatchingPlayer({ id, title, pairs, allowRetry = true }:
<div className="space-y-8" id={id}>
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Concept Matching"}
{title || "Emparejamiento de Conceptos"}
</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 p-8 glass border-white/5 rounded-3xl relative">
<div className="space-y-4">
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Term</label>
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Término</label>
{(pairs || []).map((pair, i) => (
<button
key={i}
@@ -63,7 +63,7 @@ export default function MatchingPlayer({ id, title, pairs, allowRetry = true }:
</div>
<div className="space-y-4">
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Definition</label>
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Definición</label>
{shuffledRight.map((item, i) => {
const matchedLeftIdx = Object.keys(matches).find(k => matches[parseInt(k)] === item.originalIdx);
const isCorrect = submitted && matchedLeftIdx !== undefined && parseInt(matchedLeftIdx) === item.originalIdx;
@@ -98,7 +98,7 @@ export default function MatchingPlayer({ id, title, pairs, allowRetry = true }:
onClick={() => setSubmitted(true)}
className="btn-premium w-full py-5 font-black text-xs uppercase tracking-[0.2em] shadow-xl shadow-blue-500/20"
>
Validate Matching
Validar Emparejamiento
</button>
)}
{submitted && (
@@ -106,7 +106,7 @@ export default function MatchingPlayer({ id, title, pairs, allowRetry = true }:
onClick={handleReset}
className="w-full py-5 glass text-blue-400 font-black text-xs uppercase tracking-[0.2em] hover:bg-white/5 transition-all rounded-2xl border-white/5"
>
Try Again
Intentar de Nuevo
</button>
)}
</div>
@@ -59,15 +59,15 @@ export default function MediaPlayer({ id, title, url, media_type, config, initia
if (locked) {
return (
<div className="space-y-4" id={id}>
<h3 className="text-xs font-black uppercase tracking-widest text-gray-400">{title || "Multimedia Content"}</h3>
<h3 className="text-xs font-black uppercase tracking-widest text-gray-400">{title || "Contenido Multimedia"}</h3>
<div className="glass-card aspect-video flex flex-col items-center justify-center gap-6 border-red-500/20 bg-red-500/5">
<div className="w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center text-red-500">
<Lock size={32} />
</div>
<div className="text-center">
<p className="text-xl font-bold text-white mb-2">Content Locked</p>
<p className="text-xl font-bold text-white mb-2">Contenido Bloqueado</p>
<p className="text-sm text-gray-500 max-w-xs uppercase tracking-widest font-black">
You have reached the limit of {maxPlays} plays for this content.
Has alcanzado el límite de {maxPlays} reproducciones para este contenido.
</p>
</div>
</div>
@@ -89,10 +89,10 @@ export default function MediaPlayer({ id, title, url, media_type, config, initia
return (
<div className="space-y-6" id={id}>
<div className="flex items-center justify-between">
<h3 className="text-xs font-black uppercase tracking-widest text-gray-400">{title || "Multimedia Content"}</h3>
<h3 className="text-xs font-black uppercase tracking-widest text-gray-400">{title || "Contenido Multimedia"}</h3>
{maxPlays > 0 && (
<span className="text-[10px] font-bold uppercase tracking-widest px-3 py-1 rounded-full bg-white/5 border border-white/5 text-gray-500">
{playCount} / {maxPlays} PLAYS
{playCount} / {maxPlays} REPRODUCCIONES
</span>
)}
</div>
@@ -134,7 +134,7 @@ export default function MediaPlayer({ id, title, url, media_type, config, initia
{maxPlays > 0 && playCount > 0 && (
<div className="flex items-center gap-2 text-[10px] font-bold uppercase tracking-widest text-orange-500/70 p-4 rounded-xl bg-orange-500/5 border border-orange-500/10">
<AlertCircle size={14} />
<span>Watch carefully. Content will lock after {maxPlays} plays.</span>
<span>Presta atención. El contenido se bloqueará después de {maxPlays} reproducciones.</span>
</div>
)}
</div>
@@ -37,14 +37,14 @@ export default function OrderingPlayer({ id, title, items, allowRetry = true }:
<div className="space-y-8" id={id}>
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Sequence Ordering"}
{title || "Ordenamiento de Secuencia"}
</h3>
</div>
<div className="space-y-8 p-8 glass border-white/5 rounded-3xl">
<div className="grid grid-cols-1 md:grid-cols-2 gap-12">
<div className="space-y-4">
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Available Items</label>
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Elementos Disponibles</label>
<div className="flex flex-wrap gap-3">
{shuffledItems.map((item, i) => {
const isPicked = userOrder.includes(item.originalIdx);
@@ -65,9 +65,9 @@ export default function OrderingPlayer({ id, title, items, allowRetry = true }:
</div>
<div className="space-y-4">
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Your Sequence</label>
<label className="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-4 block">Tu Secuencia</label>
<div className="space-y-3">
{userOrder.length === 0 && <p className="text-xs text-gray-600 italic py-4">Click items to build the sequence...</p>}
{userOrder.length === 0 && <p className="text-xs text-gray-600 italic py-4">Haz clic en los elementos para construir la secuencia...</p>}
{userOrder.map((idx, i) => {
const isItemCorrect = submitted && idx === i;
const isItemWrong = submitted && idx !== i;
@@ -100,7 +100,7 @@ export default function OrderingPlayer({ id, title, items, allowRetry = true }:
onClick={() => setSubmitted(true)}
className="btn-premium w-full py-5 font-black text-xs uppercase tracking-[0.2em] shadow-xl shadow-blue-500/20"
>
Validate Sequence
Validar Secuencia
</button>
)}
{submitted && (
@@ -108,7 +108,7 @@ export default function OrderingPlayer({ id, title, items, allowRetry = true }:
onClick={handleReset}
className="w-full py-5 glass text-blue-400 font-black text-xs uppercase tracking-[0.2em] hover:bg-white/5 transition-all rounded-2xl border-white/5"
>
Try Again
Intentar de Nuevo
</button>
)}
</div>
@@ -65,11 +65,11 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max
<div className="space-y-8 notranslate" id={id} translate="no">
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Knowledge Check"}
{title || "Verificación de Conocimientos"}
</h3>
{maxAttempts > 0 && (
<span className="text-[10px] font-bold uppercase tracking-widest px-3 py-1 rounded-full bg-white/5 border border-white/5 text-gray-500">
Attempt {attempts} / {maxAttempts}
Intento {attempts} / {maxAttempts}
</span>
)}
</div>
@@ -106,7 +106,7 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max
<span>{opt}</span>
{submitted && isActuallyCorrect && <span></span>}
{submitted && isWrongSelection && <span></span>}
{submitted && missedCorrect && <span className="text-[10px] uppercase font-black tracking-tighter">Correct Answer</span>}
{submitted && missedCorrect && <span className="text-[10px] uppercase font-black tracking-tighter">Respuesta Correcta</span>}
</div>
</button>
);
@@ -123,7 +123,7 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max
disabled={maxAttempts > 0 && attempts >= maxAttempts}
className={`btn-premium w-full py-5 font-black text-xs uppercase tracking-[0.2em] shadow-xl shadow-blue-500/20 ${maxAttempts > 0 && attempts >= maxAttempts ? 'opacity-50 cursor-not-allowed' : ''}`}
>
{maxAttempts > 0 && attempts >= maxAttempts ? 'Max Attempts Reached' : 'Validate Answers'}
{maxAttempts > 0 && attempts >= maxAttempts ? 'Máximo de Intentos Alcanzado' : 'Validar Respuestas'}
</button>
)}
{submitted && (
@@ -136,7 +136,7 @@ export default function QuizPlayer({ id, title, quizData, allowRetry = true, max
disabled={maxAttempts > 0 && attempts >= maxAttempts}
className={`w-full py-5 glass text-blue-400 font-black text-xs uppercase tracking-[0.2em] hover:bg-white/5 transition-all rounded-3xl border-white/5 ${maxAttempts > 0 && attempts >= maxAttempts ? 'opacity-50 cursor-not-allowed' : ''}`}
>
{maxAttempts > 0 && attempts >= maxAttempts ? 'Max Attempts Reached' : 'Try Again'}
{maxAttempts > 0 && attempts >= maxAttempts ? 'Máximo de Intentos Alcanzado' : 'Intentar de Nuevo'}
</button>
)}
</>
@@ -25,12 +25,12 @@ export default function ShortAnswerPlayer({ id, title, prompt, correctAnswers, a
<div className="space-y-8" id={id}>
<div className="space-y-2">
<h3 className="text-xl font-bold border-l-4 border-blue-500 pl-4 py-1 tracking-tight text-white uppercase tracking-widest text-[10px]">
{title || "Short Answer"}
{title || "Respuesta Corta"}
</h3>
</div>
<div className="p-8 glass border-white/5 rounded-3xl space-y-8">
<p className="text-xl font-bold text-gray-100">{prompt || "Please enter your answer below:"}</p>
<p className="text-xl font-bold text-gray-100">{prompt || "Por favor, introduce tu respuesta a continuación:"}</p>
<div className="space-y-4">
<input
@@ -42,12 +42,12 @@ export default function ShortAnswerPlayer({ id, title, prompt, correctAnswers, a
? (isCorrect ? "border-green-500 bg-green-500/10 text-green-400" : "border-red-500 bg-red-500/10 text-red-100")
: "border-white/10 focus:border-blue-500 text-white"
}`}
placeholder="Type your answer..."
placeholder="Escribe tu respuesta..."
/>
{submitted && !isCorrect && (
<div className="p-4 bg-orange-500/10 border border-orange-500/20 rounded-xl animate-in fade-in duration-500">
<p className="text-[10px] text-orange-400 uppercase font-black tracking-widest">Suggested Answer(s):</p>
<p className="text-[10px] text-orange-400 uppercase font-black tracking-widest">Respuesta(s) Sugerida(s):</p>
<p className="text-sm text-gray-400 mt-1">{(correctAnswers || [])[0]}</p>
</div>
)}
@@ -61,7 +61,7 @@ export default function ShortAnswerPlayer({ id, title, prompt, correctAnswers, a
disabled={!userAnswer.trim()}
className="btn-premium w-full py-5 font-black text-xs uppercase tracking-[0.2em] shadow-xl shadow-blue-500/20 disabled:opacity-50 disabled:grayscale"
>
Submit Answer
Enviar Respuesta
</button>
)}
@@ -70,7 +70,7 @@ export default function ShortAnswerPlayer({ id, title, prompt, correctAnswers, a
onClick={handleReset}
className="w-full py-5 glass text-blue-400 font-black text-xs uppercase tracking-[0.2em] hover:bg-white/5 transition-all rounded-3xl border-white/5"
>
Try Again
Intentar de Nuevo
</button>
)}
</>