wordeck/apps/web/src/lib/i18n/en.ts
Till JS a612ad05d6 feat(cards/new): typing, multiple-choice, audio-front im Erstellungs-UI
- Dropdown um 3 neue Types erweitert
- typing/multiple-choice: front + answer Felder (korrekte field-Namen)
- multiple-choice: optionaler distractor_pool (Fallback für kleine Decks)
- audio-front: audio_ref Text-Input + back Antworttext
- canSave + onSubmit korrekt pro Type
- i18n de + en vollständig

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:36:17 +02:00

256 lines
9.4 KiB
TypeScript

import type { TranslationNode } from './de.ts';
export const en: TranslationNode = {
app: {
name: 'Cards',
title_suffix: 'Cards',
},
nav: {
decks: 'Decks',
study: 'Study',
explore: 'Library',
import: 'Import',
stats: 'Stats',
login_dev: 'Login (dev)',
account: 'Account',
},
landing: {
welcome: 'Spaced-repetition flashcards.',
intro:
'Cardecky is the federated flashcard app of mana e.V. — FSRS scheduler, cloze cards, Anki import.',
cta_login: 'Login (dev)',
dev_user_prompt: 'User ID (dev):',
},
decks: {
title: 'Decks',
new: 'New deck',
empty: 'No decks yet.',
empty_cta: 'Create first deck',
loading: 'Loading…',
error: 'Error: {msg}',
card_count: '{n} cards',
card_count_one: '1 card',
card_count_more: '{n} more cards in the stack',
card_count_more_one: '1 more card in the stack',
due_count: '{n} due',
delete_confirm:
'Really delete deck "{name}"? All cards + review data will be lost.',
deleted: 'Deck "{name}" deleted',
delete_failed: 'Delete failed: {msg}',
},
deck_detail: {
back: '← Back to decks',
study_button: 'Study',
new_card: 'New card',
empty: 'No cards in this deck.',
empty_cta: 'Create first card →',
card_summary_due: '{cards} · {due} due',
card_delete_aria: 'Delete card',
card_delete_label: 'Delete',
card_delete_confirm: 'Really delete card? Reviews will be deleted with it.',
fan_aria: 'Fanned cards from stack "{name}"',
card_open: 'Open card — {type}',
},
deck_stack: {
aria_label: 'Stack "{name}" — {cards} cards, {due} due',
},
deck_new: {
title: 'New deck',
name_label: 'Name',
description_label: 'Description (optional)',
color_label: 'Color (optional)',
create: 'Create deck',
creating: 'Creating…',
cancel: 'Cancel',
create_failed: 'Create failed: {msg}',
},
card_new: {
title: 'New card',
back: '← Back',
deck_label: 'Deck',
type_label: 'Type',
type_basic: 'Basic (front → back)',
type_basic_reverse: 'Basic + Reverse (front ↔ back, 2 reviews)',
type_cloze: 'Cloze (fill-in-the-blank, 1 review per cluster)',
front_label: 'Front (Markdown)',
back_label: 'Back (Markdown)',
back_placeholder: 'Answer',
front_placeholder: '# Markdown is allowed\n**bold**, _italic_, `code`',
preview_label: 'Preview',
cloze_text_label: 'Text with blanks (Markdown)',
cloze_text_placeholder: 'The capital of {{c1::France}} is {{c2::Paris}}.',
cloze_help: '{{c1::Answer}} defines a blank. Each cluster ID (c1, c2, …) becomes its own review. Optional hint: {{c1::Answer::Hint}} — the hint replaces „…" in the prompt.',
cloze_no_clusters: 'At least one {{cN::…}} cluster is required.',
cloze_clusters_detected: '{n} clusters detected: c{ids} → {n} reviews.',
cloze_preview_label: 'Preview (c{first} masked)',
cloze_extra_label: 'Extra (optional)',
cloze_extra_placeholder: 'Additional context, shown below the answer.',
create: 'Create card',
creating: 'Saving…',
cancel: 'Cancel',
create_failed: 'Create failed: {msg}',
toast_basic: 'Card created',
toast_basic_reverse: '2 reviews initialized (front→back, back→front)',
toast_cloze: '{n} reviews initialized (1 per cluster)',
toast_image_occlusion: '{n} reviews initialized (1 per mask)',
type_image_occlusion: 'Image-Occlusion (image + N masks)',
type_typing: 'Typing (text input, fuzzy match)',
type_multiple_choice: 'Multiple-Choice (4 options, AI distractors)',
type_audio_front: 'Audio-Front (listen + answer)',
answer_label: 'Answer (Markdown)',
answer_placeholder: 'Correct answer',
distractor_pool_label: 'Distractor pool (optional)',
distractor_pool_placeholder: 'One entry per line — fallback when the deck is too small for AI distractors',
audio_ref_label: 'Audio reference (media_ref)',
audio_ref_placeholder: 'e.g. abc123.mp3',
back_audio_label: 'Answer text (Markdown)',
toast_typing: 'Typing card created',
toast_multiple_choice: 'Multiple-choice card created',
toast_audio_front: 'Audio-front card created',
decks_load_failed: 'Could not load decks: {msg}',
},
card_edit: {
title: 'Edit card',
back: '← Back to deck',
type_locked_help: 'The card type cannot be changed — the reviews table depends on it.',
save: 'Save',
saving: 'Saving…',
cancel: 'Cancel',
delete: 'Delete',
deleting: 'Deleting…',
delete_confirm: 'Really delete card? Reviews will be deleted with it.',
updated: 'Card updated',
save_failed: 'Save failed: {msg}',
delete_failed: 'Delete failed: {msg}',
deleted: 'Card deleted',
},
study: {
title: 'Study',
empty: 'No decks.',
none_due: 'Nothing due right now.',
study_now: 'Study now',
due_count: '{n} due',
},
study_session: {
back: '← Overview',
all_done: 'Done! All due cards reviewed.',
stats: 'Reviews: {reviewed} · Again: {again}',
reveal: 'Show answer',
reveal_hint: 'Space / Enter to reveal',
grade_again: 'Again',
grade_hard: 'Hard',
grade_good: 'Good',
grade_easy: 'Easy',
grade_hint: '1=Again · 2=Hard · 3=Good · 4=Easy',
loading: 'Loading…',
error: 'Error: {msg}',
manage_link: 'Manage cards →',
},
import: {
title: 'Import',
intro: 'Import decks and cards from an Anki file (.apkg or .colpkg). FSRS history is not carried over — all cards start as "new".',
what_works_title: 'What is imported',
what_works_decks: 'Decks (Anki hierarchy Foo::Bar becomes Foo / Bar).',
what_works_basic: 'Basic + Basic-Reverse: front/back directly.',
what_works_cloze: 'Cloze: {{c1::…}} is created with sub-index per cluster.',
what_works_media: 'Images + audio (embedded as Markdown / <audio> tag).',
what_skipped_title: 'What is not imported',
what_skipped_media: '— (Images + audio are imported since Sprint 9k, see above)',
what_skipped_history: 'FSRS learning history (Anki reviews are deliberately reset).',
what_skipped_addons: 'Add-on specific card types (image-occlusion etc.).',
anki_label: 'Import from Anki',
dropzone: '📦 Drop .apkg file here or click',
dropzone_hint: 'Basic, Basic + Reverse, Cloze · Images + audio are imported too (limit 25 MB per file).',
parsing: 'Reading {file}…',
preview_found: 'Found in',
preview_decks_one: '1 deck',
preview_decks: '{n} decks',
preview_cards_one: '1 card',
preview_cards: '{n} cards',
preview_breakdown: '({basic} basic, {basic_reverse} basic-reverse, {cloze} cloze)',
preview_media: '{n} media files will be uploaded',
preview_skipped: '{n} skipped (unknown type)',
preview_warnings: 'Notes ({n})',
cancel: 'Cancel',
import_now: 'Import',
stage_media: 'Uploading media · {current} / {total}',
stage_decks: 'Creating decks · {current} / {total}',
stage_cards: 'Importing cards · {current} / {total}',
stage_done: 'Done.',
done_summary_one: '✓ {cards} cards in 1 deck.',
done_summary: '✓ {cards} cards in {decks} decks.',
done_dupes: '{n} duplicates skipped (same content already exists).',
done_media: '{uploaded} media uploaded, {failed} failed.',
done_failures: '{n} errors',
done_more: 'Another file',
error_label: 'Error: {msg}',
retry: 'Try again',
},
inbox_banner: {
label: '📥 Inbox',
count_one: '1 incoming card from other apps',
count: '{n} incoming cards from other apps',
cta: '— sort →',
},
account: {
title: 'Account',
user_id_label: 'User ID',
logout: 'Sign out',
phase2_hint:
'Phase 2 note: identity is currently a dev stub (sessionStorage). With auth federation, this switches to a mana-auth login against auth.mana.how.',
export_title: 'Data export',
export_intro:
'Download all your Cards data as JSON — decks, cards, reviews, study sessions, tags, media refs, import jobs. GDPR Art. 15/20.',
export_button: 'Export data',
export_loading: 'Loading…',
export_done: 'Export downloaded: {decks} decks, {cards} cards, {reviews} reviews.',
export_failed: 'Export failed: {msg}',
delete_title: 'Delete account',
delete_intro:
'Irreversibly deletes all your Cards data. GDPR Art. 17. Other mana apps (Memoro, Who, …) keep their data independently — if you want to delete there too, do it there or use the Verein-wide GDPR collective request via mana-admin.',
delete_button: 'Delete all Cards data',
delete_loading: 'Deleting…',
delete_confirm:
'ALL your Cards data will be deleted irreversibly. Type DELETE to confirm.',
delete_confirm_word: 'DELETE',
delete_done: 'Deleted: {decks} decks, {imports} import jobs.',
delete_failed: 'Delete failed: {msg}',
},
stats: {
title: 'Stats',
generated_at: 'As of {date}',
decks: 'Decks',
cards: 'Cards',
reviews: 'Reviews',
due_now: 'Due now',
days_title: 'Active days',
streak: 'Streak: {n} days · last 7 days: {total} reviews',
streak_one: 'Streak: 1 day · last 7 days: {total} reviews',
fsrs_title: 'FSRS status',
fsrs_intro: 'Distribution of your card reviews across FSRS states.',
fsrs_new: 'New',
fsrs_learning: 'Learning',
fsrs_review: 'Review',
fsrs_relearning: 'Relearning',
loading: 'Loading…',
error: 'Error: {msg}',
},
common: {
empty: '(empty)',
skip_to_content: 'Skip to content',
main_nav: 'Main navigation',
notifications: 'Notifications',
language_switcher: 'Switch language',
},
image_occlusion: {
image_label: 'Choose image',
uploading: 'Uploading image…',
not_an_image: 'File is not an image.',
canvas_aria: 'Image canvas — drag to create masks',
draw_hint: 'Drag a rectangle on the image to create a mask.',
label_placeholder: 'Label (optional)',
delete_mask: 'Delete mask',
no_image_selected: 'Choose an image first.',
no_masks: 'Create at least one mask.',
},
};