feat(archive): import a studyset with everything in it and its progress

Your call (2026-10-11): an archive, imported from the Library's Import, to
bring a library from elsewhere as one's own, and later to restore backups
and move studysets between instances before federation.

An archive is a .zip: archive.json says its format; the studyset is laid
out as a release (ADR 0005, rule 3), so the release copier writes it, now
also unlinked from any publication (ReleaseCopier.write), its cards marked
"archive" as imported ones are, handing back each item's new id. A card may
name a dictionary entry instead of its payload: the import makes it from
the instance's dictionary as adding from it does, with today's entry,
examples and tags, and leaves out (counting) one the instance lacks; for
that, DictionaryEndpoint.entries gives entries by their ids, at most 1,000
at once. reviews.json lists reviews of the archive's cards; they go into
the person's review log once the cards are in, so every card's schedule
goes on from them.

The sheet says what the archive holds ("Japanese" holds: 12 studysets,
7,745 flashcards, 3 paths, 20,317 reviews), imports once confirmed, busy
meanwhile, and opens the studyset made. Not an archive, a newer format or
an unreadable one says so and imports nothing. No export into the format
yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-11 16:39:07 +02:00
commit ff31652a3a
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -198,6 +198,88 @@ class AppLocalizationsDe extends AppLocalizations {
String get libraryImportAnkiHint =>
'Wird ein eigenes Lernset, aus einer .apkg- oder .colpkg-Datei';
@override
String get libraryImportArchive => 'Halkyon-Archiv';
@override
String get libraryImportArchiveHint =>
'Ein Lernset mit allem darin und seinem Fortschritt, aus einer .zip-Datei';
@override
String get archiveFileType => 'Halkyon-Archiv';
@override
String get archiveImportTitle => 'Archiv importieren';
@override
String get archiveImportReading => 'Das Archiv wird gelesen …';
@override
String archiveImportHolds(String title) {
return '„$title“ enthält:';
}
@override
String archiveCountStudysets(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Lernsets',
one: '1 Lernset',
);
return '$_temp0';
}
@override
String archiveCountReviews(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Wiederholungen',
one: '1 Wiederholung',
);
return '$_temp0';
}
@override
String get archiveImportConfirm => 'Importieren';
@override
String archiveImported(String cards, String reviews) {
return 'Importiert: $cards und $reviews.';
}
@override
String archiveImportMissingEntries(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Wörter fehlen',
one: '1 Wort fehlt',
);
String _temp1 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: 'blieben',
one: 'blieb',
);
return '$_temp0 im Wörterbuch dieser Instanz und $_temp1 draußen.';
}
@override
String get archiveNotAnArchive => 'Diese Datei ist kein Halkyon-Archiv.';
@override
String get archiveNewerFormat =>
'Dieses Archiv stammt aus einer neueren Version der App. Aktualisiere die App, um es zu importieren.';
@override
String get archiveUnreadable => 'Dieses Archiv lässt sich nicht lesen.';
@override
String get archiveImportBrokeOff =>
'Der Import brach ab. Prüfe die Verbindung und versuche es noch einmal.';
@override
String get libraryRetry => 'Erneut versuchen';