5bf6013460
Progressive lesson streaming via onSegment callback (fixes SSE for non-English users — locale was shadowed in lesson-reader useEffect). Adds: BullMQ workers, Redis stream buffer, token budget enforcement, Langfuse tracing, golden-eval runner, Playwright e2e scaffolding, lesson depth/locale/preferences schema, mastery map UI, admin panel (blueprints/users/reports/quality/misconceptions), image queries, source citations, view transitions, reading animations, i18n (next-intl), PDF export, surprise endpoint, and 402 passing unit tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
586 lines
19 KiB
JSON
586 lines
19 KiB
JSON
{
|
||
"lesson": {
|
||
"ariaLesson": "Lesson",
|
||
"ariaProgress": "Lesson progress",
|
||
"reading": "Reading",
|
||
"segments": "{count, plural, one {# segment} other {# segments}}",
|
||
"segmentLocked": "Complete the previous checkpoint to continue.",
|
||
"checkpoint": {
|
||
"predict": "Predict",
|
||
"explain": "Explain",
|
||
"solve": "Solve",
|
||
"placeholder": "Write your answer here…",
|
||
"checking": "Checking…",
|
||
"submitted": "Submitted",
|
||
"confidenceLegend": "Before you submit — how sure are you?",
|
||
"notSure": "Not sure",
|
||
"thinkSo": "Think so",
|
||
"confident": "Confident",
|
||
"notSureAria": "Not sure about my answer",
|
||
"thinkSoAria": "I think my answer is right",
|
||
"confidentAria": "I am confident in my answer"
|
||
},
|
||
"print": "Export PDF",
|
||
"considering": "Considering…",
|
||
"empty": "This lesson has no segments yet. Check back shortly — content is still being prepared.",
|
||
"outline": {
|
||
"intro": "What you'll explore",
|
||
"preparing": "Generating your lesson…",
|
||
"streaming": "Writing your lesson…",
|
||
"streamingLabel": "Lesson content loading"
|
||
},
|
||
"tangent": {
|
||
"placeholder": "Curious about something?",
|
||
"ariaInput": "Curiosity question",
|
||
"ariaAsk": "Ask",
|
||
"considering": "Looking into it…"
|
||
},
|
||
"journeyProgress": "Lesson {current} of {total}",
|
||
"complete": {
|
||
"ariaLabel": "Lesson complete",
|
||
"heading": "Lesson complete.",
|
||
"saved": "Progress saved.",
|
||
"saving": "Saving…",
|
||
"markComplete": "Mark complete",
|
||
"nextLesson": "Next lesson →",
|
||
"deepen": "Go deeper →",
|
||
"journeyDone": "Journey complete.",
|
||
"journeyDoneNote": "You've finished all lessons in this journey."
|
||
}
|
||
},
|
||
"review": {
|
||
"title": "Daily Review",
|
||
"aria": "Daily review session",
|
||
"loading": "Loading your review…",
|
||
"empty": "Nothing due for review. Check back tomorrow.",
|
||
"progress": "{current} of {total}",
|
||
"considering": "Considering…",
|
||
"next": "Next →",
|
||
"finish": "Finish",
|
||
"complete": {
|
||
"heading": "Session complete",
|
||
"reviewed": "{count, plural, one {# concept reviewed} other {# concepts reviewed}}",
|
||
"netDelta": "Net mastery: {delta}",
|
||
"nothingDue": "You're all caught up.",
|
||
"backHome": "Back to learning"
|
||
},
|
||
"delta": {
|
||
"up": "↑ {pct}%",
|
||
"down": "↓ {pct}%",
|
||
"same": "unchanged"
|
||
},
|
||
"emptyUntil": "All caught up. Your next review is on {date}.",
|
||
"emptyNoHistory": "No reviews yet. Complete a lesson to start building your review queue."
|
||
},
|
||
"nav": {
|
||
"learn": "Learn",
|
||
"review": "Review",
|
||
"mastery": "Mastery",
|
||
"map": "Map",
|
||
"signIn": "Sign in",
|
||
"signOut": "Sign out",
|
||
"profile": "Profile",
|
||
"admin": "Admin"
|
||
},
|
||
"home": {
|
||
"eyebrow": "Curiosity-led mastery",
|
||
"title": "What do you want to understand?",
|
||
"lede": "Tell us what you're curious about.",
|
||
"fieldLabel": "Your learning intent",
|
||
"placeholder": "e.g. how vaccines work",
|
||
"examplesLabel": "Or try one of these",
|
||
"submit": "Start learning",
|
||
"submitting": "Finding your lesson…",
|
||
"error": "Something went wrong. Try again.",
|
||
"examples": [
|
||
"Why ice is slippery",
|
||
"How a gyroscope stays upright",
|
||
"Why the sky is blue",
|
||
"What temperature really is",
|
||
"How noise-cancelling headphones work",
|
||
"Why light speed is a limit",
|
||
"How lasers work",
|
||
"Why magnets attract",
|
||
"What causes friction",
|
||
"How a microwave heats food",
|
||
"Why glass is transparent",
|
||
"How superconductors work",
|
||
"What quantum entanglement is",
|
||
"Why mirrors flip left and right",
|
||
"How sound travels",
|
||
"What makes a rainbow",
|
||
"Why hot air rises",
|
||
"How a nuclear reactor works",
|
||
"What dark matter might be",
|
||
"Why time slows near light speed",
|
||
"How black holes form",
|
||
"Why the moon causes tides",
|
||
"What a neutron star is",
|
||
"How stars make elements",
|
||
"Why Mars is red",
|
||
"How rockets reach orbit",
|
||
"What the Big Bang was",
|
||
"Why Pluto isn't a planet",
|
||
"How GPS uses relativity",
|
||
"What causes solar eclipses",
|
||
"How telescopes see the past",
|
||
"Why galaxies spiral",
|
||
"What a light-year measures",
|
||
"How the sun produces energy",
|
||
"Why space is cold but sunlight burns",
|
||
"What causes the seasons",
|
||
"How comets get their tails",
|
||
"Why the universe is expanding",
|
||
"What exoplanets are",
|
||
"How auroras form",
|
||
"How vaccines work",
|
||
"Why onions make you cry",
|
||
"How memory is stored",
|
||
"Why we dream",
|
||
"How muscles grow",
|
||
"What causes aging",
|
||
"How antibiotics kill bacteria",
|
||
"Why we get fevers",
|
||
"How the immune system learns",
|
||
"What DNA actually does",
|
||
"How nerves send signals",
|
||
"Why we yawn",
|
||
"How the heart keeps rhythm",
|
||
"What gut bacteria do",
|
||
"How wounds heal",
|
||
"Why we need sleep",
|
||
"How eyes detect color",
|
||
"What causes allergies",
|
||
"How cells divide",
|
||
"Why exercise builds endurance",
|
||
"Why soap cleans",
|
||
"How batteries store energy",
|
||
"What makes something acidic",
|
||
"How glass is made",
|
||
"Why metals conduct electricity",
|
||
"How fireworks get their colors",
|
||
"What rust really is",
|
||
"How catalysts speed reactions",
|
||
"Why oil and water don't mix",
|
||
"How plastic is made",
|
||
"What pH measures",
|
||
"How fermentation works",
|
||
"Why diamonds are hard",
|
||
"How soap bubbles form",
|
||
"What makes chili peppers hot",
|
||
"How dry ice works",
|
||
"Why bread rises",
|
||
"How perfume spreads",
|
||
"What alloys are",
|
||
"How carbon dating works",
|
||
"TCP congestion control",
|
||
"How encryption keeps secrets",
|
||
"What a database index does",
|
||
"How neural networks learn",
|
||
"Why passwords get hashed",
|
||
"How the internet routes data",
|
||
"What a compiler does",
|
||
"How GPS finds your location",
|
||
"Why computers use binary",
|
||
"How a CPU executes code",
|
||
"What caching really solves",
|
||
"How Wi-Fi carries data",
|
||
"What blockchain actually is",
|
||
"How search engines rank pages",
|
||
"Why RAM is faster than disk",
|
||
"How image compression works",
|
||
"What an API is",
|
||
"How public-key crypto works",
|
||
"Why software has bugs",
|
||
"How machine translation works",
|
||
"Why prime numbers matter",
|
||
"What calculus measures",
|
||
"How probability works",
|
||
"Why pi is everywhere",
|
||
"What infinity really means",
|
||
"What a derivative tells you",
|
||
"Why zero was revolutionary",
|
||
"How statistics can mislead",
|
||
"What exponential growth means",
|
||
"Why some problems are unsolvable",
|
||
"How compound interest grows",
|
||
"What a logarithm is",
|
||
"Why the bell curve appears",
|
||
"How fractals are made",
|
||
"What Bayes' theorem does",
|
||
"Why we can't divide by zero",
|
||
"How GPS triangulates position",
|
||
"What a matrix represents",
|
||
"Why randomness is hard",
|
||
"How central banks set rates",
|
||
"What causes inflation",
|
||
"How stock markets work",
|
||
"Why money has value",
|
||
"What a recession is",
|
||
"How taxes shape behavior",
|
||
"Why prices rise and fall",
|
||
"What supply and demand means",
|
||
"How insurance spreads risk",
|
||
"Why trade benefits both sides",
|
||
"What GDP measures",
|
||
"How credit scores work",
|
||
"Why bubbles form and burst",
|
||
"How exchange rates move",
|
||
"Why monopolies are risky",
|
||
"What a bond is",
|
||
"How venture capital works",
|
||
"Why diversification matters",
|
||
"What game theory explains",
|
||
"How the printing press changed Europe",
|
||
"Why empires collapse",
|
||
"How writing was invented",
|
||
"What caused the Industrial Revolution",
|
||
"Why the Roman Empire fell",
|
||
"How money replaced barter",
|
||
"What sparked the Renaissance",
|
||
"How democracy began",
|
||
"Why the Silk Road mattered",
|
||
"What the Enlightenment changed",
|
||
"How plagues reshaped society",
|
||
"Why borders are where they are",
|
||
"How language families spread",
|
||
"What caused the Cold War",
|
||
"How cities first formed",
|
||
"Why revolutions happen",
|
||
"How navigation opened the world",
|
||
"What feudalism really was",
|
||
"How the calendar was set",
|
||
"Why some civilizations vanished",
|
||
"How earthquakes happen",
|
||
"Why volcanoes erupt",
|
||
"What causes weather",
|
||
"How mountains form",
|
||
"Why the ocean is salty",
|
||
"How rivers shape land",
|
||
"What drives ocean currents",
|
||
"Why deserts form where they do",
|
||
"How fossils are made",
|
||
"How clouds form rain",
|
||
"Why the climate is changing",
|
||
"How coral reefs grow",
|
||
"What plate tectonics explains",
|
||
"How caves form",
|
||
"Why leaves change color",
|
||
"How lightning forms",
|
||
"What soil is made of",
|
||
"How glaciers move",
|
||
"Why some places get monsoons",
|
||
"Why we procrastinate",
|
||
"How habits form",
|
||
"Why music moves us",
|
||
"How we learn languages",
|
||
"What makes things go viral",
|
||
"Why optical illusions fool us",
|
||
"How memory tricks work",
|
||
"Why we feel déjà vu",
|
||
"How persuasion works",
|
||
"What makes a melody catchy",
|
||
"Why crowds behave irrationally",
|
||
"How accents develop",
|
||
"Why we see faces everywhere",
|
||
"How the placebo effect works",
|
||
"Why deadlines boost focus",
|
||
"How color affects mood",
|
||
"Why stories stick with us",
|
||
"How bilingual brains switch",
|
||
"Why we forget names",
|
||
"How attention actually works"
|
||
],
|
||
"spark": "Spark something",
|
||
"sparking": "Finding something…",
|
||
"or": "or",
|
||
"depthLabel": "Lesson depth",
|
||
"depth": {
|
||
"quick": "Quick",
|
||
"quickMeta": "~5 min",
|
||
"standard": "Standard",
|
||
"standardMeta": "~10 min",
|
||
"deep": "Deep",
|
||
"deepMeta": "~20 min"
|
||
},
|
||
"modeLabel": "Format",
|
||
"mode": {
|
||
"practice": "Practice",
|
||
"read": "Just read"
|
||
},
|
||
"continue": {
|
||
"heading": "Continue learning",
|
||
"lessonProgress": "Lesson {position} of {total}",
|
||
"resume": "Resume →"
|
||
},
|
||
"dueReviews": "{count} due for review →"
|
||
},
|
||
"auth": {
|
||
"login": {
|
||
"title": "Sign in",
|
||
"email": "Email",
|
||
"password": "Password",
|
||
"submit": "Sign in",
|
||
"submitting": "Signing in…",
|
||
"error": "Invalid email or password.",
|
||
"forgotPassword": "Forgot password?",
|
||
"noAccount": "No account?",
|
||
"register": "Register",
|
||
"resetSuccess": "Password updated. Sign in with your new password.",
|
||
"or": "or",
|
||
"continueWithGoogle": "Continue with Google",
|
||
"continueWithGitHub": "Continue with GitHub",
|
||
"continueWith": "Continue with {provider}"
|
||
},
|
||
"register": {
|
||
"title": "Create account",
|
||
"name": "Name",
|
||
"email": "Email",
|
||
"password": "Password",
|
||
"confirmPassword": "Confirm password",
|
||
"passwordMismatch": "Passwords do not match.",
|
||
"submit": "Create account",
|
||
"submitting": "Creating account…",
|
||
"signInFailed": "Account created but sign-in failed. Try signing in manually.",
|
||
"hasAccount": "Already have an account?",
|
||
"signIn": "Sign in"
|
||
},
|
||
"forgotPassword": {
|
||
"title": "Reset password",
|
||
"email": "Email",
|
||
"submit": "Send reset link",
|
||
"submitting": "Sending…",
|
||
"sentTitle": "Check your inbox",
|
||
"sentBody": "If an account exists for that email, we sent a reset link. It expires in 1 hour.",
|
||
"backToSignIn": "Back to sign in",
|
||
"error": "Something went wrong. Try again."
|
||
},
|
||
"resetPassword": {
|
||
"title": "Set new password",
|
||
"newPassword": "New password",
|
||
"confirmPassword": "Confirm password",
|
||
"passwordMismatch": "Passwords do not match.",
|
||
"submit": "Set password",
|
||
"submitting": "Saving…",
|
||
"error": "Failed to reset password.",
|
||
"invalidLink": "Invalid reset link.",
|
||
"requestNew": "Request a new one"
|
||
},
|
||
"acceptInvite": {
|
||
"title": "Accept your invitation",
|
||
"subtitle": "Set up your account to get started.",
|
||
"email": "Email",
|
||
"name": "Your name",
|
||
"password": "Password",
|
||
"confirmPassword": "Confirm password",
|
||
"passwordMismatch": "Passwords do not match.",
|
||
"submit": "Create account",
|
||
"submitting": "Creating…",
|
||
"error": "Could not accept this invite.",
|
||
"invalidLink": "This invite link is invalid, expired, or already used.",
|
||
"goToLogin": "Go to sign in"
|
||
},
|
||
"verifyEmail": {
|
||
"title": "Verify your email",
|
||
"body": "We sent a verification link to your email address. Click it to activate your account.",
|
||
"subtext": "Didn't receive it? Check your spam folder."
|
||
},
|
||
"error": {
|
||
"title": "Authentication error",
|
||
"default": "Something went wrong during sign in.",
|
||
"Configuration": "Server configuration error. Contact support.",
|
||
"AccessDenied": "Access denied.",
|
||
"Verification": "The verification link has expired or already been used.",
|
||
"backToSignIn": "Back to sign in"
|
||
}
|
||
},
|
||
"settings": {
|
||
"title": "Settings",
|
||
"profile": {
|
||
"title": "Profile",
|
||
"name": "Display name",
|
||
"save": "Save",
|
||
"saving": "Saving…",
|
||
"saved": "Saved.",
|
||
"saveFailed": "Failed to save."
|
||
},
|
||
"language": {
|
||
"title": "Language",
|
||
"label": "Interface language",
|
||
"description": "Choose the language used throughout the app.",
|
||
"en": "English",
|
||
"fr": "Français"
|
||
},
|
||
"security": {
|
||
"title": "Security",
|
||
"currentPassword": "Current password",
|
||
"newPassword": "New password",
|
||
"confirmPassword": "Confirm new password",
|
||
"changePassword": "Change password",
|
||
"changing": "Changing…",
|
||
"changed": "Password changed.",
|
||
"failed": "Failed.",
|
||
"oauthNote": "Password change is not available for accounts using social sign-in.",
|
||
"linked": "Linked via: {providers}",
|
||
"passwordMismatch": "New passwords do not match."
|
||
},
|
||
"appearance": {
|
||
"title": "Appearance",
|
||
"theme": {
|
||
"label": "Theme",
|
||
"system": "System",
|
||
"light": "Light",
|
||
"dark": "Dark"
|
||
}
|
||
},
|
||
"danger": {
|
||
"title": "Danger zone",
|
||
"deleteAccount": "Delete account",
|
||
"deleteConfirm": "Delete my account",
|
||
"deleteWarning": "This will permanently delete your account and all your learning data. This cannot be undone.",
|
||
"deleting": "Deleting…"
|
||
},
|
||
"learning": {
|
||
"title": "Learning",
|
||
"description": "Shape how lessons are written for you.",
|
||
"ageGroup": {
|
||
"label": "Who is learning?",
|
||
"child": "Child (8–12)",
|
||
"teen": "Teen (13–17)",
|
||
"adult": "Adult"
|
||
},
|
||
"difficulty": {
|
||
"label": "Default difficulty",
|
||
"1": "Beginner",
|
||
"2": "Intermediate",
|
||
"3": "Advanced"
|
||
},
|
||
"depth": {
|
||
"label": "Default lesson length",
|
||
"quick": "Quick (~5 min)",
|
||
"standard": "Standard (~10 min)",
|
||
"deep": "Deep (~20 min)"
|
||
},
|
||
"hint": {
|
||
"label": "About you (optional)",
|
||
"placeholder": "e.g. I'm a nurse, I like analogies with cooking…",
|
||
"description": "A short note helps tailor explanations to your background."
|
||
},
|
||
"save": "Save",
|
||
"saving": "Saving…",
|
||
"saved": "Saved.",
|
||
"saveFailed": "Failed to save."
|
||
},
|
||
"notifications": {
|
||
"title": "Notifications",
|
||
"description": "Control how Curio contacts you.",
|
||
"emailDigest": "Send me a daily email when reviews are due"
|
||
}
|
||
},
|
||
"onboarding": {
|
||
"title": "Welcome to Curio",
|
||
"subtitle": "Let's set up your learning profile. You can always change this later.",
|
||
"ageGroup": {
|
||
"label": "Who is learning?",
|
||
"child": "Child (8–12)",
|
||
"teen": "Teen (13–17)",
|
||
"adult": "Adult"
|
||
},
|
||
"difficulty": {
|
||
"label": "How familiar are you with most topics?",
|
||
"1": "Beginner — build from first principles",
|
||
"2": "Intermediate — assume basic familiarity",
|
||
"3": "Advanced — go deep, explore edge cases"
|
||
},
|
||
"depth": {
|
||
"label": "Preferred lesson length",
|
||
"quick": "Quick (~5 min)",
|
||
"standard": "Standard (~10 min)",
|
||
"deep": "Deep (~20 min)"
|
||
},
|
||
"hint": {
|
||
"label": "Tell us a bit about yourself (optional)",
|
||
"placeholder": "e.g. I'm a nurse, I like analogies with cooking…",
|
||
"description": "Helps tailor explanations to your background."
|
||
},
|
||
"submit": "Get started",
|
||
"submitting": "Saving…",
|
||
"skip": "Skip for now"
|
||
},
|
||
"masteryMap": {
|
||
"title": "Mastery Map",
|
||
"loading": "Loading…",
|
||
"empty": "No mastery data yet.",
|
||
"emptyLink": "Start learning",
|
||
"due": "due",
|
||
"dueZone": {
|
||
"heading": "Due for review",
|
||
"startReview": "Start review →",
|
||
"none": "Nothing due right now."
|
||
},
|
||
"overview": {
|
||
"mastered": "Mastered",
|
||
"learning": "Learning",
|
||
"needsWork": "Needs work",
|
||
"progress": "{mastered} of {total} concepts mastered"
|
||
},
|
||
"status": {
|
||
"mastered": "Mastered",
|
||
"learning": "Learning",
|
||
"needsWork": "Needs work",
|
||
"notStarted": "Not started"
|
||
},
|
||
"filter": {
|
||
"all": "All",
|
||
"due": "Due",
|
||
"needsWork": "Needs work"
|
||
},
|
||
"remove": "Remove",
|
||
"removeBlueprint": "Remove {title} from mastery map"
|
||
},
|
||
"profile": {
|
||
"title": "Your profile",
|
||
"masteryTitle": "Mastery overview",
|
||
"noMastery": "No mastery data yet. Start learning to see progress here."
|
||
},
|
||
"grade": {
|
||
"verdict": {
|
||
"mastered": "Understood",
|
||
"partial": "Partial",
|
||
"misconception": "Misconception",
|
||
"uncertain": "Unclear"
|
||
},
|
||
"calibration": {
|
||
"confidentFailed": "You rated yourself confident — worth pausing on what tripped you.",
|
||
"unsurePassed": "You rated yourself unsure, but your answer was solid. Trust your understanding."
|
||
},
|
||
"referenceHeading": "Full answer",
|
||
"ariaFeedback": "Tutor feedback",
|
||
"ariaCalibration": "Calibration note",
|
||
"socratic": {
|
||
"ariaLabel": "Socratic follow-up",
|
||
"placeholder": "Go ahead…",
|
||
"ariaInput": "Follow-up answer",
|
||
"submit": "Reply",
|
||
"considering": "Considering…"
|
||
},
|
||
"reexplain": {
|
||
"loading": "Preparing another explanation…",
|
||
"trigger": "Try another explanation →"
|
||
},
|
||
"retry": "Try again →",
|
||
"report": {
|
||
"toggle": "Flag an issue",
|
||
"ariaLabel": "Report an issue",
|
||
"thanks": "Thanks — we'll look into it.",
|
||
"reasonGradeWrong": "Grade seems wrong",
|
||
"reasonContentError": "Content error",
|
||
"reasonOther": "Other",
|
||
"notesPlaceholder": "Optional details…",
|
||
"ariaReason": "Reason",
|
||
"ariaDetails": "Details",
|
||
"submit": "Send",
|
||
"cancel": "Cancel"
|
||
}
|
||
}
|
||
} |