feat: localize various UI texts and labels to Spanish across application pages and interactive components.
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user