From a0bc01ea501cf20ad992d480abbb7230b5656131 Mon Sep 17 00:00:00 2001 From: neon <18559658+neonsolstice@users.noreply.github.com> Date: Fri, 31 Jul 2026 21:45:06 +0000 Subject: [PATCH] fix(client): remove Hungarian and Korean locales Both catalogs held nothing but English fallback values, so selecting either language produced a fully English interface that reads as broken rather than untranslated. Crowdin Translate covers only 24 languages and includes neither, so neither locale had any machine translation route, and no human translations existed yet. Drop them from the shared locale list, the Crowdin export configuration, the pull request allowlist, the catalogs, and the tests, leaving fifteen target languages. Remove both from the Crowdin project as well, after confirming each export was byte-identical to the English source so no translation work was discarded. Re-adding either is cheap once a translation route exists, whether that is a machine translation engine that supports them or a volunteer translator. Give the locale tests the same fallback semantics the application runs with. Production always loads the English catalog and points `fallbackLocale` at it, so a key a target catalog does not carry renders English. The test instances omitted both, which resolves a missing key to its own name, and several assertions compared a translated label against the English one without checking that the language actually translates that key. Both patterns pass only while every catalog is complete, and would fail confusingly the first time a language lags behind a new key. Delete the Crowdin service branch automatically once its pull request closes or merges. Crowdin appends every export to the same branch and never rebases it, so a branch that outlives its pull request keeps its original merge base and each later export diverges further from main until every catalog conflicts. Deleting it forces Crowdin to recreate the branch from the current main. Ref #576 --- .github/workflows/crowdin-branch-cleanup.yml | 33 + .../components/DashboardSettingsSheet.spec.ts | 44 +- .../__tests__/useDashboardLabels.spec.ts | 30 +- client/src/i18n/icu.spec.ts | 78 +- client/src/locales/hu.json | 6909 ----------------- client/src/locales/ko.json | 6909 ----------------- client/src/stores/__tests__/locale.spec.ts | 2 - crowdin.yml | 2 - docs/LOCALIZATION.md | 8 +- packages/types/src/locale.ts | 25 +- scripts/classify-crowdin-pr.sh | 2 - 11 files changed, 114 insertions(+), 13928 deletions(-) create mode 100644 .github/workflows/crowdin-branch-cleanup.yml delete mode 100644 client/src/locales/hu.json delete mode 100644 client/src/locales/ko.json diff --git a/.github/workflows/crowdin-branch-cleanup.yml b/.github/workflows/crowdin-branch-cleanup.yml new file mode 100644 index 000000000..fdda5e9c8 --- /dev/null +++ b/.github/workflows/crowdin-branch-cleanup.yml @@ -0,0 +1,33 @@ +name: Crowdin Branch Cleanup + +on: + pull_request: + types: [closed] + +permissions: + contents: write + +jobs: + delete-service-branch: + # Crowdin appends every export to the same service branch and never rebases it. + # A branch that outlives its pull request keeps its original merge base, so each + # later export diverges further from main and eventually conflicts on every + # catalog. Deleting it forces Crowdin to recreate it from the current main. + # This runs on close as well as merge, because Crowdin reuses the branch either way. + if: github.event.pull_request.head.ref == 'l10n_main' && github.event.pull_request.head.repo.full_name == github.repository + name: Delete l10n_main + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Delete the Crowdin service branch + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + BRANCH: l10n_main + run: | + if gh api "repos/$REPO/git/refs/heads/$BRANCH" >/dev/null 2>&1; then + gh api -X DELETE "repos/$REPO/git/refs/heads/$BRANCH" + echo "Deleted $BRANCH; Crowdin will recreate it from main on the next export." + else + echo "$BRANCH is already absent; nothing to delete." + fi diff --git a/client/src/features/dashboard/components/DashboardSettingsSheet.spec.ts b/client/src/features/dashboard/components/DashboardSettingsSheet.spec.ts index b43e311aa..fa77ce032 100644 --- a/client/src/features/dashboard/components/DashboardSettingsSheet.spec.ts +++ b/client/src/features/dashboard/components/DashboardSettingsSheet.spec.ts @@ -7,6 +7,13 @@ import { setI18nLocale } from '@/i18n' import en from '@/locales/en.json' import pt from '@/locales/pt.json' +// Production falls back to English for any key a target catalog has not translated, +// so these are the labels Portuguese actually renders. Reading pt directly would +// assert `undefined` against rendered English the first time Portuguese lags +// behind a new dashboard key. +const PT_WIDGET_NAMES = { ...en.dashboard.settings.widgetNames, ...pt.dashboard.settings.widgetNames } +const PT_SHELF_NAMES = { ...en.dashboard.settings.shelfNames, ...pt.dashboard.settings.shelfNames } + type UseSmartScopesMock = () => { smartScopes: Ref fetchSmartScopes: () => void @@ -113,7 +120,7 @@ describe('DashboardSettingsSheet', () => { await setI18nLocale('pt') await nextTick() - expect(shelfOptionLabels(wrapper).sort()).toEqual(Object.values(pt.dashboard.settings.shelfNames).sort()) + expect(shelfOptionLabels(wrapper).sort()).toEqual(Object.values(PT_SHELF_NAMES).sort()) }) it('renders every widget name from the catalog rather than a hardcoded map', async () => { @@ -146,20 +153,27 @@ describe('DashboardSettingsSheet', () => { const labels = widgetRowLabels(wrapper) expect(labels).toEqual([ - pt.dashboard.settings.widgetNames.readingStreak, - pt.dashboard.settings.widgetNames.currentlyReading, - pt.dashboard.settings.widgetNames.readingGoal, - pt.dashboard.settings.widgetNames.readingDna, - pt.dashboard.settings.widgetNames.monthlyChallenge, - pt.dashboard.settings.widgetNames.highlightOfTheDay, - pt.dashboard.settings.widgetNames.neglectedGems, - pt.dashboard.settings.widgetNames.readingRhythm, - pt.dashboard.settings.widgetNames.diversityScore, - pt.dashboard.settings.widgetNames.libraryOverview, - pt.dashboard.settings.widgetNames.yearProjection, - pt.dashboard.settings.widgetNames.longWait, + PT_WIDGET_NAMES.readingStreak, + PT_WIDGET_NAMES.currentlyReading, + PT_WIDGET_NAMES.readingGoal, + PT_WIDGET_NAMES.readingDna, + PT_WIDGET_NAMES.monthlyChallenge, + PT_WIDGET_NAMES.highlightOfTheDay, + PT_WIDGET_NAMES.neglectedGems, + PT_WIDGET_NAMES.readingRhythm, + PT_WIDGET_NAMES.diversityScore, + PT_WIDGET_NAMES.libraryOverview, + PT_WIDGET_NAMES.yearProjection, + PT_WIDGET_NAMES.longWait, ]) - expect(labels).not.toContain(en.dashboard.settings.widgetNames.readingStreak) - expect(labels).not.toContain(en.dashboard.settings.widgetNames.currentlyReading) + + // Only meaningful for names Portuguese actually translates. A name that falls + // back to English renders the English label legitimately, so asserting its + // absence would fail for a reason that is not a bug. + const englishNamesPortugueseReplaces = (['readingStreak', 'currentlyReading'] as const) + .filter((key) => PT_WIDGET_NAMES[key] !== en.dashboard.settings.widgetNames[key]) + .map((key) => en.dashboard.settings.widgetNames[key]) + + expect(labels.filter((label) => englishNamesPortugueseReplaces.includes(label))).toEqual([]) }) }) diff --git a/client/src/features/dashboard/composables/__tests__/useDashboardLabels.spec.ts b/client/src/features/dashboard/composables/__tests__/useDashboardLabels.spec.ts index aa01791b7..549055341 100644 --- a/client/src/features/dashboard/composables/__tests__/useDashboardLabels.spec.ts +++ b/client/src/features/dashboard/composables/__tests__/useDashboardLabels.spec.ts @@ -24,9 +24,16 @@ function mountComposable(): ReturnType { type CatalogNames = { widgetNames: Record; shelfNames: Record } +// Production falls back to English for any key a target catalog has not translated, +// so the expected label is the Portuguese one where it exists and English otherwise. +// Reading pt directly would assert `undefined` against rendered English the first +// time Portuguese lags behind a new dashboard key. const CATALOGS: Record<'en' | 'pt', CatalogNames> = { en: en.dashboard.settings, - pt: pt.dashboard.settings, + pt: { + widgetNames: { ...en.dashboard.settings.widgetNames, ...pt.dashboard.settings.widgetNames }, + shelfNames: { ...en.dashboard.settings.shelfNames, ...pt.dashboard.settings.shelfNames }, + }, } // Mirrors the kebab-case type to camel-case message key mapping the composable owns. @@ -46,6 +53,13 @@ const WIDGET_KEY_BY_TYPE: Record = { 'long-wait': 'longWait', } +// A widget whose Portuguese name genuinely differs from English. Assertions that a +// translated label is not the English one only hold for such a widget: a name that +// falls back to English renders the English string for a legitimate reason. +const PT_TRANSLATED_WIDGET = (Object.keys(WIDGET_KEY_BY_TYPE) as WidgetType[]).find( + (type) => CATALOGS.pt.widgetNames[WIDGET_KEY_BY_TYPE[type]] !== CATALOGS.en.widgetNames[WIDGET_KEY_BY_TYPE[type]], +) + const SHELF_KEY_BY_TYPE: Record = { 'recently-added': 'recentlyAdded', 'continue-reading': 'continueReading', @@ -107,19 +121,23 @@ describe('useDashboardLabels', () => { const key = WIDGET_KEY_BY_TYPE[type] expect(widgetName(type), `widget name for ${type}`).toBe(CATALOGS.pt.widgetNames[key]) } - expect(widgetName('reading-streak')).not.toBe(CATALOGS.en.widgetNames.readingStreak) - expect(widgetName('currently-reading')).not.toBe(CATALOGS.en.widgetNames.currentlyReading) + expect(PT_TRANSLATED_WIDGET, 'Portuguese should translate at least one widget name').toBeDefined() + const translatedKey = WIDGET_KEY_BY_TYPE[PT_TRANSLATED_WIDGET!] + expect(widgetName(PT_TRANSLATED_WIDGET!)).not.toBe(CATALOGS.en.widgetNames[translatedKey]) }) it('re-resolves when the locale changes back', async () => { const { widgetName } = mountComposable() + expect(PT_TRANSLATED_WIDGET, 'Portuguese should translate at least one widget name').toBeDefined() + const type = PT_TRANSLATED_WIDGET! + await setI18nLocale('pt') - const translated = widgetName('reading-streak') + const translated = widgetName(type) await setI18nLocale('en') - expect(translated).not.toBe(widgetName('reading-streak')) - expect(widgetName('reading-streak')).toBe(CATALOGS.en.widgetNames.readingStreak) + expect(translated).not.toBe(widgetName(type)) + expect(widgetName(type)).toBe(CATALOGS.en.widgetNames[WIDGET_KEY_BY_TYPE[type]]) }) }) diff --git a/client/src/i18n/icu.spec.ts b/client/src/i18n/icu.spec.ts index 21ce29b87..fc32fc2a3 100644 --- a/client/src/i18n/icu.spec.ts +++ b/client/src/i18n/icu.spec.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from 'vitest' import { createI18n } from 'vue-i18n' +import type { Locale } from '@bookorbit/types' import cs from '@/locales/cs.json' import da from '@/locales/da.json' import de from '@/locales/de.json' @@ -7,9 +8,7 @@ import en from '@/locales/en.json' import fi from '@/locales/fi.json' import spanish from '@/locales/es.json' import french from '@/locales/fr.json' -import hu from '@/locales/hu.json' import italian from '@/locales/it.json' -import ko from '@/locales/ko.json' import nl from '@/locales/nl.json' import polish from '@/locales/pl.json' import pt from '@/locales/pt.json' @@ -35,6 +34,19 @@ function messageValues(message: string, count: number): Record [name, name === 'count' ? count : 2])) } +// Mirrors the production setup in `@/i18n`, where the English catalog is always +// loaded and `fallbackLocale` points at it. Without that, a key absent from a +// target catalog resolves to the key name rather than English, so a catalog +// carrying only translated keys would fail these tests instead of falling back +// the way the running application does. +function createCatalogI18n(locale: Locale, catalog: typeof en) { + const messages: Record = { + en: compileIcuCatalog(en, 'en'), + [locale]: compileIcuCatalog(catalog, locale), + } + return createI18n({ legacy: false, locale, fallbackLocale: 'en', messages }) +} + describe('ICU message compilation', () => { it('detects ICU plurals without treating ordinary interpolation as ICU', () => { expect(isIcuPluralMessage('{count, plural, one {One book} other {# books}}')).toBe(true) @@ -92,12 +104,7 @@ describe('ICU message compilation', () => { ['pt', pt, [0, 1, 2, 1_234]], ['sl', sl, [0, 1, 2, 3, 5, 1_234]], ] as const)('isolates the styled count in both dialogs for %s', (locale, catalog, counts) => { - const messages = compileIcuCatalog(catalog, locale) - const testI18n = createI18n({ - legacy: false, - locale, - messages: { [locale]: messages }, - }) + const testI18n = createCatalogI18n(locale, catalog) for (const key of ['tools.bulkRename.confirmDialog.body', 'tools.entityManager.bulkDeleteModal.confirm']) { for (const count of counts) { @@ -141,16 +148,8 @@ describe('ICU message compilation', () => { }) it('renders reviewed Italian and Polish count messages with the correct grammar', () => { - const italianI18n = createI18n({ - legacy: false, - locale: 'it', - messages: { it: compileIcuCatalog(italian, 'it') }, - }) - const polishI18n = createI18n({ - legacy: false, - locale: 'pl', - messages: { pl: compileIcuCatalog(polish, 'pl') }, - }) + const italianI18n = createCatalogI18n('it', italian) + const polishI18n = createCatalogI18n('pl', polish) expect(italianI18n.global.t('settings.appearance.icons.selectedCount', { count: 1 })).toBe('1 icona selezionata') expect(italianI18n.global.t('settings.appearance.icons.selectedCount', { count: 2 })).toBe('2 icone selezionate') @@ -186,11 +185,7 @@ describe('ICU message compilation', () => { }) it('preserves spacing around collection names in reviewed Italian messages', () => { - const testI18n = createI18n({ - legacy: false, - locale: 'it', - messages: { it: compileIcuCatalog(italian, 'it') }, - }) + const testI18n = createCatalogI18n('it', italian) expect(testI18n.global.t('collection.addToSheet.createdAndAdded', { count: 2, name: 'Preferiti' })).toBe('Creata "Preferiti" e aggiunti 2 libri') expect(testI18n.global.t('collection.addToSheet.addedToCollection', { count: 2, name: 'Preferiti' })).toBe('Aggiunti 2 libri a "Preferiti"') @@ -212,12 +207,7 @@ describe('ICU message compilation', () => { ['pt', pt, [0, 1, 1_000_000], ['Sem grupos duplicados', 'Um grupo duplicado', '1.000.000 grupos duplicados']], ['sl', sl, [0, 1, 2, 3, 5], ['No duplicate groups', 'One duplicate group', '2 duplicate groups', '3 duplicate groups', '5 duplicate groups']], ] as const)('renders migrated Book Duplicates messages for %s', (locale, catalog, counts, expectedGroups) => { - const messages = compileIcuCatalog(catalog, locale) - const testI18n = createI18n({ - legacy: false, - locale, - messages: { [locale]: messages }, - }) + const testI18n = createCatalogI18n(locale, catalog) expect(counts.map((count) => testI18n.global.t('tools.bookDuplicates.groupsFound', { count }))).toEqual(expectedGroups) @@ -245,12 +235,7 @@ describe('ICU message compilation', () => { ['pt', pt, [1, 1_000_000], ['1 falha', '1.000.000 falhas']], ['sl', sl, [1, 2, 3, 5], ['1 napaka', '2 napaki', '3 napak', '5 napak']], ] as const)('renders migrated Kobo activity plurals for %s', (locale, catalog, counts, expected) => { - const messages = compileIcuCatalog(catalog, locale) - const testI18n = createI18n({ - legacy: false, - locale, - messages: { [locale]: messages }, - }) + const testI18n = createCatalogI18n(locale, catalog) expect(counts.map((count) => testI18n.global.t('settings.reader.kobo.activity.failureCount', { count }))).toEqual(expected) }) @@ -276,23 +261,13 @@ describe('ICU message compilation', () => { ['0 datotek pripravljenih', '1 datoteka pripravljena', '2 datoteki pripravljeni', '3 datoteke pripravljene', '5 datotek pripravljenih'], ], ] as const)('renders migrated finalize-dialog counts for %s', (locale, catalog, counts, expected) => { - const messages = compileIcuCatalog(catalog, locale) - const testI18n = createI18n({ - legacy: false, - locale, - messages: { [locale]: messages }, - }) + const testI18n = createCatalogI18n(locale, catalog) expect(counts.map((count) => testI18n.global.t('bookDock.finalizeDialog.readyCount', { count }))).toEqual(expected) }) it('uses the reviewed Slovenian zero/one/other mappings in the finalize dialog', () => { - const messages = compileIcuCatalog(sl, 'sl') - const testI18n = createI18n({ - legacy: false, - locale: 'sl', - messages: { sl: messages }, - }) + const testI18n = createCatalogI18n('sl', sl) expect(testI18n.global.t('bookDock.finalizeDialog.title', { count: 0 })).toBe('Zaključi brez datotek') expect(testI18n.global.t('bookDock.finalizeDialog.title', { count: 1 })).toBe('Zaključi 1 datoteko') @@ -308,10 +283,8 @@ describe('ICU message compilation', () => { ['de', de, [0, 1, 2]], ['es', spanish, [0, 1, 2, 1_000_000]], ['fi', fi, [0, 1, 2]], - ['hu', hu, [0, 1, 2]], ['fr', french, [0, 1, 2, 1_000_000]], ['it', italian, [0, 1, 2, 1_000_000]], - ['ko', ko, [0, 1, 2]], ['nl', nl, [0, 1, 2]], // Polish reserves `other` for fractions, exactly as Czech does. ['pl', polish, [0, 1, 2, 5, 1.5, 1_000_000]], @@ -323,12 +296,7 @@ describe('ICU message compilation', () => { ['uk', uk, [0, 1, 2, 5, 1.5]], ['zh', zh, [0, 1, 2]], ] as const)('formats every ICU message for all relevant plural categories in %s', (locale, catalog, counts) => { - const messages = compileIcuCatalog(catalog, locale) - const testI18n = createI18n({ - legacy: false, - locale, - messages: { [locale]: messages }, - }) + const testI18n = createCatalogI18n(locale, catalog) for (const [key, message] of flattenMessages(catalog)) { if (!isIcuPluralMessage(message)) continue diff --git a/client/src/locales/hu.json b/client/src/locales/hu.json deleted file mode 100644 index 9cc1ebb8c..000000000 --- a/client/src/locales/hu.json +++ /dev/null @@ -1,6909 +0,0 @@ -{ - "common": { - "resetSortAria": "Reset sort to default", - "save": "Save", - "cancel": "Cancel", - "delete": "Delete", - "edit": "Edit", - "close": "Close", - "confirm": "Confirm", - "loading": "Loading...", - "search": "Search", - "back": "Back", - "next": "Next", - "previous": "Previous", - "retry": "Retry", - "yes": "Yes", - "no": "No" - }, - "settings": { - "privacySharing": { - "title": "Privacy & Sharing", - "subtitle": "Control whether administrators can see an identifiable summary of your reading activity.", - "levelLegend": "Reading insights sharing level", - "current": "Current setting", - "levels": { - "private": { - "title": "Private", - "description": "Only you can see your reading statistics." - }, - "summary": { - "title": "Share summary", - "description": "Share aggregate habits without book titles, authors, series, or narrators." - }, - "detailed": { - "title": "Share detailed insights", - "description": "Also share recent and top books, authors, series, genres, and narrators." - } - }, - "fields": { - "frequency": "Reading frequency and active days", - "completion": "Aggregate books started and completed", - "formats": "Format distribution", - "genres": "Broad genre distribution", - "trend": "Aggregate reading trend", - "books": "Current, recent, and most-read book titles", - "authors": "Top authors", - "series": "Top series", - "narrators": "Top narrators" - }, - "confirm": { - "shareTitle": "Enable {level}?", - "shareDescription": "Administrators with permission will be able to see the following information.", - "stopTitle": "Stop sharing reading insights?", - "stopDescription": "Administrator access will be blocked immediately. Existing access records remain in your history.", - "recordedNotice": "Each administrator profile view is recorded and appears in your access history." - }, - "preview": { - "title": "Preview your shared profile", - "description": "See the information currently available to authorized administrators.", - "action": "Load preview", - "readingTime": "Reading time", - "activeDays": "Active days", - "started": "Books started", - "completed": "Books completed", - "topBooks": "Top books" - }, - "history": { - "title": "Profile access history", - "description": "Recent administrator views of your shared reading profile.", - "empty": "No administrator has viewed your shared reading profile.", - "paginationLabel": "Profile access history pages" - }, - "durationMinutes": "{count, plural, one {# minute} other {# minutes}}", - "durationHours": "{count, plural, one {# hour} other {# hours}}", - "unknownTitle": "Untitled book", - "errors": { - "load": "Failed to load sharing settings.", - "save": "Failed to update sharing settings.", - "preview": "Failed to load the shared-profile preview." - } - }, - "appearance": { - "language": { - "title": "Language", - "description": "Choose the language used across the interface.", - "label": "Interface language", - "loadError": "Failed to load the selected language", - "saveError": "Failed to save language preference" - }, - "pageTitle": "Display", - "pageSubtitle": "Control themes, covers, layout, and how your library is presented.", - "mobileSummary": "Theme: {theme} • Accent: {accent} • Background: {background}", - "themeMode": { - "light": "Light", - "dark": "Dark", - "system": "System" - }, - "theme": { - "title": "Theme", - "colorScheme": { - "label": "Color scheme", - "hint": "Light or dark interface" - }, - "accents": { - "grey": "Grey", - "scarlet": "Scarlet", - "vermilion": "Vermilion", - "rose": "Rose", - "copper": "Copper", - "orange": "Orange", - "chartreuse": "Chartreuse", - "marigold": "Marigold", - "wasabi": "Wasabi", - "amber": "Amber", - "malachite": "Malachite", - "yellow": "Yellow", - "viridian": "Viridian", - "turquoise": "Turquoise", - "lime": "Lime", - "green": "Green", - "acid-green": "Acid Green", - "emerald": "Emerald", - "teal": "Teal", - "electric-blue": "Electric Blue", - "cyan": "Cyan", - "jade": "Jade", - "ultramarine": "Ultramarine", - "iris": "Iris", - "purple": "Purple", - "blue": "Blue", - "indigo": "Indigo", - "violet": "Violet", - "amethyst": "Amethyst", - "fuchsia": "Fuchsia", - "raspberry": "Raspberry", - "pink": "Pink", - "white": "White", - "rosewater": "Rosewater", - "salmon": "Salmon", - "coral": "Coral", - "sand": "Sand", - "peach": "Peach", - "pear": "Pear", - "flax": "Flax", - "sprout": "Sprout", - "butter": "Butter", - "aloe": "Aloe", - "lemon": "Lemon", - "foam": "Foam", - "aqua": "Aqua", - "celadon": "Celadon", - "sage": "Sage", - "pistachio": "Pistachio", - "mint": "Mint", - "seafoam": "Seafoam", - "baby-blue": "Baby Blue", - "powder": "Powder", - "sea-glass": "Sea Glass", - "bluebell": "Bluebell", - "cornflower": "Cornflower", - "thistle": "Thistle", - "periwinkle": "Periwinkle", - "wisteria": "Wisteria", - "lavender": "Lavender", - "mauve": "Mauve", - "orchid": "Orchid", - "rose-quartz": "Rose Quartz", - "blush": "Blush" - }, - "accentColor": { - "label": "Accent color", - "hint": "Controls highlights and interactive elements" - }, - "cornerRadius": { - "label": "Corner radius", - "hint": "Roundness of cards and UI elements" - }, - "surfaceBrightness": { - "label": "Surface brightness", - "hint": "Lighten dark mode surfaces", - "reset": "Reset" - }, - "libraryBackground": { - "title": "Library Background", - "pattern": { - "label": "Background pattern", - "hint": "Pattern shown behind the book grid" - } - }, - "backgroundGroups": { - "fundamental": "Fundamental", - "structural": "Structural", - "ambient": "Ambient", - "refractive": "Refractive" - } - }, - "storage": { - "title": "Where to save appearance preferences", - "active": "Active", - "notAvailable": "Not available", - "device": { - "title": "This device only", - "description": "Preferences stay in your browser. Best if you want a different look on different devices." - }, - "account": { - "title": "My account", - "description": "Preferences are saved to your account. Best if you want the same appearance on every device." - }, - "toasts": { - "synced": "Preferences will now be synced", - "local": "Preferences will stay on this device" - }, - "errors": { - "demoRestricted": "Demo-restricted account cannot change theme storage mode", - "update": "Failed to update storage mode", - "generic": "An error occurred while updating storage mode" - } - }, - "bookCovers": { - "title": "Book Covers", - "displayMode": { - "title": "Cover display mode", - "hint": "Controls how real covers fit inside book slots when aspect ratios differ", - "blurredFit": { - "label": "Blurred fit", - "hint": "Show the full cover with a blurred fill behind it" - }, - "fillCrop": { - "label": "Fill card", - "hint": "Fill the entire slot by cropping edges when aspect ratios differ" - }, - "naturalBottom": { - "label": "Natural bottom", - "hint": "Keep the original cover ratio and anchor the cover to the bottom" - } - }, - "spine": { - "title": "Book spine overlay", - "hint": "Adds a stylized spine and gloss effect to cover cards", - "off": { - "label": "Off", - "hint": "No spine/gloss effect on covers" - }, - "subtle": { - "label": "Subtle", - "hint": "Light spine and sheen, closer to the default look" - }, - "strong": { - "label": "Strong", - "hint": "More pronounced spine and gloss treatment" - } - }, - "showSpineOnComics": { - "label": "Show spine on comics", - "hint": "Apply the spine and gloss effect to comic covers (cbz, cbr, cb7)" - }, - "shadow": { - "title": "Cover shadow strength", - "hint": "Controls depth under covers across grid, list, table, and dashboard thumbnails", - "default": { - "label": "Default", - "hint": "Current elevation and depth" - }, - "strong": { - "label": "Strong", - "hint": "Heavier shelf-like drop shadow under covers" - } - }, - "overlays": { - "title": "Card overlays", - "hint": "Choose metadata shown directly on book cover cards", - "progressBar": { - "label": "Progress bar", - "hint": "Thin colored line along the bottom edge" - }, - "format": { - "label": "File format", - "hint": "Color-coded EPUB, PDF, CBZ badge at bottom-right" - }, - "rating": { - "label": "Rating", - "hint": "Star rating indicator at bottom-left" - }, - "readStatus": { - "label": "Read status", - "hint": "Color icon showing the current reading status at top-left" - }, - "seriesPosition": { - "label": "Series number", - "hint": "Badge showing the book position in its series at top-right (e.g. #3, #1.5)" - }, - "lockStatus": { - "label": "Lock status", - "hint": "Metadata lock icon at top-right - orange when locked, green when unlocked" - } - } - }, - "layout": { - "coverSize": "Cover size", - "gridSpacing": "Grid spacing", - "gridLayout": { - "title": "Library Grid Layout" - }, - "coverSizeBehavior": { - "label": "Cover size behavior", - "hint": "Control whether portrait/square sizes and grid spacing are shared across all views or kept per-view", - "perViewHint": "Per-view mode: adjust cover size and spacing from each view's Display panel.", - "syncAll": "Sync all views", - "perView": "Per-view sizes" - }, - "portraitCoverSize": { - "label": "Portrait cover size", - "hint": "Used for portrait libraries and views" - }, - "squareCoverSize": { - "label": "Square cover size", - "hint": "Used for square libraries and views" - }, - "portraitGridSpacing": { - "label": "Portrait grid spacing", - "hint": "Gap between portrait covers" - }, - "squareGridSpacing": { - "label": "Square grid spacing", - "hint": "Gap between square covers" - }, - "cardInfoMode": { - "label": "Card info mode", - "hint": "Where to show book title and author on grid cards", - "onHover": "On hover", - "belowCover": "Below cover", - "off": "Off" - }, - "primaryCardLabel": { - "label": "Primary card label", - "hint": "Text shown below each book cover (first line)" - }, - "secondaryCardLabel": { - "label": "Secondary card label", - "hint": "Additional text below the primary label (second line)" - }, - "labelField": { - "hidden": "Hidden", - "bookTitle": "Book title", - "seriesTitle": "Series title", - "seriesTitlePosition": "Series title + position", - "author": "Author" - }, - "seriesDisplay": { - "title": "Series Display", - "collapsedCover": { - "label": "Collapsed series cover", - "hint": "Choose which cover to show when series are collapsed in the book grid" - }, - "stack": "Stack", - "mosaic": "Mosaic", - "first": "First", - "latest": "Latest", - "firstUnread": "First Unread" - }, - "authorGrid": { - "title": "Author Grid", - "coverSize": { - "label": "Cover size", - "hint": "Width of author covers in the grid" - }, - "coverShape": { - "label": "Cover shape", - "hint": "Shape of author covers in the grid" - }, - "circle": "Circle", - "square": "Square" - }, - "listTableViews": { - "title": "List and Table Views" - }, - "zebraStriping": { - "label": "Zebra striping", - "hint": "Alternate row background colors for easier scanning" - } - }, - "behavior": { - "title": "Library Behavior", - "thumbnailClicks": { - "label": "Thumbnail clicks", - "hint": "Choose what happens when opening a book from grid and list views", - "readFirst": "Read first", - "readFirstHint": "Open the reader when a readable file exists", - "openDetails": "Open details", - "openDetailsHint": "Go to the book details page from grid and list thumbnails" - }, - "filterPreview": { - "label": "Show filter preview by default", - "hint": "Expand the active filter and sort summary when opening a smartScope" - }, - "collapseSeries": { - "label": "Collapse series by default", - "hint": "Group books in the same series into a single card in library and collection views" - } - }, - "icons": { - "title": "Custom Icons", - "uploadIcons": "Upload icons", - "uploadedCount": "{count, plural, =0 {no icons uploaded} one {# icon uploaded} other {# icons uploaded}}", - "searchPlaceholder": "Search icons", - "sort": { - "newest": "Newest", - "name": "Name" - }, - "selectedCount": "{count, plural, one {# selected} other {# selected}}", - "clear": "Clear", - "deleteSelected": "Delete selected", - "loading": "Loading icons...", - "emptySearch": "No icons match your search.", - "emptyNoIcons": "No custom icons uploaded yet.", - "namePlaceholder": "Name", - "checkingUsage": "Checking usage...", - "usedBy": "Used by {count}", - "notUsedYet": "Not used yet", - "rename": "Rename", - "replace": "Replace", - "usage": { - "libraries": "{count, plural, =0 {no libraries} one {# library} other {# libraries}}", - "collections": "{count, plural, =0 {no collections} one {# collection} other {# collections}}", - "smartScopes": "{count, plural, =0 {no smart scopes} one {# smart scope} other {# smart scopes}}" - }, - "confirm": { - "deleteOne": "Delete \"{name}\"? Existing uses will fall back to their default icon.", - "deleteMany": "{count, plural, =0 {Delete no icons?} one {Delete # icon? Existing uses will fall back to their default icon.} other {Delete # icons? Existing uses will fall back to their default icon.}}" - }, - "toasts": { - "saved": "Icon saved", - "updated": "Icon updated", - "deleted": "Icon deleted", - "bulkDeleted": "{count, plural, =0 {Deleted no icons} one {Deleted # icon} other {Deleted # icons}}", - "bulkDeletePartial": "Deleted {deleted}, {failed} failed" - }, - "errors": { - "load": "Failed to load icons", - "save": "Failed to save icon", - "replace": "Failed to replace icon", - "delete": "Failed to delete icon", - "bulkDelete": "Failed to delete icons" - } - }, - "tabs": { - "theme": "Theme", - "book-covers": "Book Covers", - "icons": "Icons", - "layout": "Layout", - "behavior": "Behavior" - } - }, - "account": { - "title": "Account", - "subtitle": "Manage your personal profile settings.", - "subtitleAll": "Manage your profile and notification preferences.", - "tabs": { - "profile": "Profile", - "privacy": "Privacy & Sharing", - "notifications": "Notifications", - "restrictions": "Restrictions" - }, - "demoRestricted": { - "cannotEdit": "Demo-restricted account cannot edit account settings", - "notice": "Demo-restricted account: editing profile, password, avatar, and linked identities is disabled." - }, - "feedback": { - "unsavedChanges": "Unsaved changes", - "discard": "Discard" - }, - "profile": { - "securityHeading": "Profile & Security", - "username": "Username", - "fullName": "Full name", - "email": "Email", - "emailHint": "Contact an administrator to change your email address.", - "save": "Save profile", - "saving": "Saving...", - "changePassword": "Change password", - "accountType": "Account type:", - "accountTypeOidc": "OIDC / SSO", - "accountTypeShared": "Shared", - "accountTypeLocal": "Local", - "nameRequired": "Name is required", - "updateFailed": "Failed to update profile", - "updated": "Profile updated", - "usernameHint": "Your username cannot be changed.", - "passwordHint": "Change the password you use to sign in.", - "passwordHintOidc": "Your password is managed by your identity provider.", - "passwordHintShared": "Shared accounts sign in through a magic link and have no password." - }, - "readingPreferences": { - "title": "Reading Preferences", - "timezoneHint": "Timezone is used for time-sensitive achievements like Early Bird and All-nighter.", - "timezone": "Timezone", - "save": "Save preferences", - "enableAchievements": "Enable achievements", - "enableAchievementsHint": "Track achievement progress and show achievement-related interface. Manage achievement notifications separately in Notifications.", - "achievementsEnabled": "Achievements enabled", - "achievementsDisabled": "Achievements disabled", - "achievementsSaveFailed": "Failed to update the achievement preference" - }, - "preferences": { - "saveFailed": "Failed to save preferences", - "saved": "Preferences saved" - }, - "avatar": { - "title": "Profile Picture", - "unknownUser": "Unknown user", - "formatHint": "PNG/JPEG/WEBP up to {size} MB", - "upload": "Upload picture", - "replace": "Replace picture", - "uploading": "Uploading...", - "remove": "Remove picture", - "removing": "Removing...", - "updated": "Profile picture updated", - "uploadFailed": "Failed to upload profile picture", - "removed": "Profile picture removed", - "removeFailed": "Failed to remove profile picture", - "removeConfirm": { - "title": "Remove profile picture?", - "description": "Your avatar will be removed and replaced with initials.", - "confirm": "Remove" - } - }, - "connectedAccounts": { - "title": "Connected Accounts", - "unlink": "Unlink", - "unlinking": "Unlinking...", - "linkAdditional": "Link additional providers:", - "linkProvider": "Link {provider}", - "redirecting": "Redirecting...", - "noneConfigured": "No OIDC providers are configured. Ask an administrator to set up SSO.", - "linkStateFailed": "Failed to generate link state", - "startLinkFailed": "Failed to start OIDC link", - "unlinkFailed": "Failed to unlink", - "unlinked": "Identity unlinked", - "unlinkIdentityFailed": "Failed to unlink identity", - "unlinkDialog": { - "title": "Unlink {provider} identity?", - "description": "Enter your password to confirm. You will no longer be able to sign in with this provider.", - "currentPassword": "Current password" - }, - "description": "Sign in with an external identity provider linked to this account.", - "unlinkAria": "Unlink {provider}" - }, - "tour": { - "title": "Guided Tour", - "description": "Replay the walkthrough that highlights key features of the app.", - "action": "Take the tour again" - }, - "restrictions": { - "none": { - "title": "No content restrictions", - "description": "Your account has full access to all content within your assigned libraries." - }, - "banner": "Your account has content restrictions applied by an administrator. Some books may not be visible to you.", - "allowedTags": { - "title": "Allowed tags", - "description": "Only books that have at least one of these tags are shown to you." - }, - "blockedTags": { - "title": "Blocked tags", - "description": "Books with any of these tags are hidden from you." - }, - "allowedGenres": { - "title": "Allowed genres", - "description": "Only books that have at least one of these genres are shown to you." - }, - "blockedGenres": { - "title": "Blocked genres", - "description": "Books with any of these genres are hidden from you." - } - }, - "groups": { - "profile": "Profile", - "preferences": "Preferences", - "security": "Security & access" - } - }, - "magicLinks": { - "title": "Magic Links", - "subtitle": "Create shareable login links for shared accounts.", - "createLink": "Create link", - "noSharedAccounts": "No shared accounts found", - "noSharedAccountsHint": "Create a shared account from the {usersPage} first to generate magic links.", - "activeLinks": "Active links", - "inactiveLinks": "Inactive links", - "paused": "Paused", - "deletedUser": "Deleted user", - "expiredPrefix": "Expired ", - "never": "No recorded activity", - "noExpiry": "No expiry", - "expired": "Expired", - "expiresOn": "Expires {date}", - "revokedOn": "Revoked {date}", - "expiredOn": "Expired {date}", - "usesCount": "{count, plural, =0 {no uses} one {one use} other {# uses}}", - "copied": "Copied!", - "copyLink": "Copy link", - "pause": "Pause", - "resume": "Resume", - "revoke": "Revoke", - "revoking": "Revoking...", - "emptyState": "No magic links created yet. Click \"{action}\" to generate a shareable login URL.", - "columns": { - "label": "Label", - "account": "Account", - "createdBy": "Created by", - "expires": "Expires", - "uses": "Uses", - "created": "Created", - "status": "Status", - "totalUses": "Total uses", - "actions": "Actions" - }, - "createDialog": { - "title": "Create magic link", - "description": "Generate a shareable login URL for a shared account.", - "sharedAccount": "Shared account", - "selectAccount": "Select a shared account", - "label": "Label", - "labelPlaceholder": "e.g. Demo link for conference", - "expiresAt": "Expires at", - "optional": "(optional)", - "create": "Create", - "creating": "Creating..." - }, - "revokeDialog": { - "title": "Revoke magic link?", - "description": "This will immediately invalidate the link and terminate all active sessions for the linked account." - }, - "errors": { - "create": "Failed to create", - "copy": "Failed to copy magic link", - "update": "Failed to update magic link", - "revoke": "Failed to revoke" - }, - "usersPage": "Users page", - "emptyTitle": "No magic links created yet", - "emptyHint": "Click \"{action}\" to generate a shareable login URL.", - "noActiveTitle": "No active magic links", - "noActiveHint": "All generated magic links for this page have expired or been revoked.", - "copyLinkAria": "Copy the link for {label}", - "pauseAria": "Pause {label}", - "resumeAria": "Resume {label}", - "revokeAria": "Revoke {label}", - "lastUsedLabel": "Last used {date}" - }, - "oidc": { - "title": "OIDC / SSO", - "subtitle": "Manage OpenID Connect providers for single sign-on.", - "providers": "Providers", - "addProvider": "Add Provider", - "editProvider": "Edit Provider", - "configureNew": "Configure a new OIDC provider.", - "editing": "Editing {slug}", - "enabled": "Enabled", - "disabled": "Disabled", - "empty": { - "title": "No providers yet", - "description": "Add an OIDC provider to enable single sign-on for your users." - }, - "form": { - "status": "Status", - "enableProvider": "Enable provider", - "enableProviderHint": "Show this provider on the login page.", - "identity": "Provider Identity", - "slug": "Slug", - "slugHint": "Unique identifier (lowercase, hyphens). Cannot be changed later.", - "displayName": "Display Name", - "displayNameHint": "Shown on the login button.", - "iconUrl": "Icon URL", - "iconUrlHint": "Optional logo shown next to the login button.", - "iconPreviewAlt": "icon preview", - "connection": "Connection", - "issuerUri": "Issuer URI", - "issuerUriHint": "The provider's base URL.", - "test": "Test", - "testing": "Testing...", - "clientId": "Client ID", - "clientSecret": "Client Secret", - "clientSecretPlaceholder": "Leave blank to keep existing", - "scopes": "Scopes", - "claimMapping": "Claim Mapping", - "previewClaims": "Preview claims", - "redirecting": "Redirecting...", - "mappedClaims": "Mapped claims", - "rawClaims": "Raw claims", - "usernameClaim": "Username claim", - "nameClaim": "Name claim", - "emailClaim": "Email claim", - "groupsClaim": "Groups claim", - "autoProvisioning": "Auto-Provisioning", - "autoProvisionUsers": "Auto-provision users", - "autoProvisionUsersHint": "Create accounts on first OIDC login if user does not exist.", - "allowLocalLinking": "Allow local account linking", - "allowLocalLinkingHint": "Link OIDC identity to an existing local account by username match.", - "defaultPermissions": "Default permissions", - "defaultPermissionsHint": "Permissions granted to new users on first OIDC login.", - "createProvider": "Create Provider", - "saveChanges": "Save Changes", - "saving": "Saving...", - "deleteProvider": "Delete Provider", - "deleting": "Deleting..." - }, - "test": { - "connected": "Connected - {issuer}", - "connectionFailed": "Connection failed", - "hide": "Hide", - "details": "Details", - "supported": "supported", - "notSupported": "not supported" - }, - "groupMappings": { - "title": "Group Mappings", - "description": "Map OIDC group claims to BookOrbit permissions. Synced on every login.", - "noPermission": "No permission", - "empty": "No group mappings configured.", - "addMapping": "Add mapping", - "claimPlaceholder": "OIDC group claim (e.g. admins)", - "add": "Add", - "adding": "Adding..." - }, - "toasts": { - "providerCreated": "Provider created", - "providerSaved": "Provider saved", - "providerDeleted": "Provider deleted", - "mappingAdded": "Group mapping added", - "mappingRemoved": "Group mapping removed" - }, - "errors": { - "loadProvider": "Failed to load provider", - "createProvider": "Failed to create provider", - "save": "Failed to save", - "delete": "Failed to delete", - "deleteProvider": "Failed to delete provider", - "requestFailed": "Request failed", - "previewState": "Failed to generate preview state", - "startPreview": "Failed to start preview", - "addMapping": "Failed to add mapping", - "removeMapping": "Failed to remove group mapping" - } - }, - "admin": { - "title": "Admin", - "subtitle": "Manage users and authentication settings.", - "system": { - "title": "System", - "subtitle": "File organization, ingestion, and maintenance settings." - }, - "maintenance": { - "title": "Maintenance", - "subtitle": "Manage background tasks, system indices, and maintenance operations.", - "importGroup": "Import", - "recommendationsGroup": "Recommendations", - "achievementsGroup": "Achievements", - "updatesGroup": "Updates", - "importFromBooklore": "Import from Booklore", - "bookloreImportConfigured": "Booklore import configured", - "migrationRunning": "Migration running", - "migrationCompleted": "Migration completed", - "migrationFailed": "Migration failed", - "importDescription": "One-time import of books, metadata, and reading progress from a previous Booklore installation.", - "configuredDescription": "Source: {name}. No migration run yet - continue setup to run the import.", - "runningDescription": "Stage: {stage} - started {started}", - "completedDescription": "From {name} - completed {date}", - "migrationErrorGeneric": "An error occurred during migration.", - "stageInitializing": "initializing", - "recently": "recently", - "getStarted": "Get Started", - "continueSetup": "Continue Setup", - "viewDetails": "View Details", - "refreshRecommendationIndex": "Refresh recommendation index", - "refreshRecommendationHint": "Update the recommendations engine with your latest library changes. This process runs in the background.", - "booksQueuedForProcessing": "{count, plural, =0 {no books queued for processing} one {# book queued for processing} other {# books queued for processing}}", - "run": "Run", - "running": "Running...", - "backfillAchievements": "Backfill achievements", - "backfillAchievementsHint": "Re-evaluate achievements across all users.", - "backfillResult": "Processed {users} users; granted {awards} awards.", - "runBackfill": "Run Backfill", - "checkForUpdates": "Check for updates", - "checkForUpdatesHint": "Automatically check GitHub for a new release on startup and show an indicator in the sidebar when one is available.", - "updateChecksEnabled": "Update checks enabled", - "updateChecksDisabled": "Update checks disabled", - "updateSettingFailed": "Failed to update setting", - "booksQueuedForEmbedding": "{count, plural, =0 {no books queued for embedding} one {# book queued for embedding} other {# books queued for embedding}}", - "failed": "Failed", - "unknownError": "Unknown error", - "rebuildEmbeddingsFailed": "Failed to rebuild embeddings: {error}", - "achievementBackfillConfirm": "Run achievement backfill for all achievements across all users? This may take a while.", - "achievementBackfillComplete": "Achievement backfill complete: {count} awards granted", - "backfillRunFailed": "Failed to run backfill", - "achievementBackfillFailed": "Failed to run achievement backfill: {error}", - "uploadsGroup": "Uploads", - "maxUploadSize": "Maximum upload file size limit", - "maxUploadSizeHint": "Configure the maximum size limit for file uploads across the system.", - "save": "Save", - "uploadSizeInvalid": "Upload size limit must be greater than 0", - "uploadSizeUpdated": "Upload size limit updated" - }, - "migration": { - "title": "Migration", - "subtitle": "One-time Booklore import: connect source, map users, dry-run, start migration, and export a report.", - "progress": "Progress", - "stepSourceConnection": "Source Connection", - "stepUserPathMapping": "User & Path Mapping", - "stepDryRun": "Dry-Run", - "stepDryRunTitle": "Dry Run", - "stepRunMigration": "Run Migration", - "stepReport": "Report", - "stepReportTitle": "Migration Report", - "subtitleSource": "Configure the database connection to your source Booklore instance.", - "subtitleMappings": "Map source users to target users and translate file paths.", - "subtitleDryRun": "Preview what will be imported before running the live migration.", - "subtitleRun": "Start the live import and monitor its progress.", - "subtitleReport": "Review what was imported and export a detailed report.", - "continueToMappings": "Continue to Mappings", - "continueToDryRun": "Continue to Dry Run", - "continueToMigration": "Continue to Migration", - "viewReport": "View Report", - "badgeValidated": "Validated", - "badgeSaved": "Saved", - "badgeUpToDate": "Up to date", - "badgeCompleted": "Completed", - "badgeRunning": "Running", - "badgeFailed": "Failed", - "mediaPathRequired": "Required for migrating book covers.", - "mediaPathAbsolute": "Use an absolute path (for example: /books). Relative paths are not supported.", - "mediaPathConfigured": "Cover import path configured. Use Test Connection to verify access and Booklore images folder structure.", - "issueSaveSource": "Save source connection settings", - "issueValidateSource": "Validate source connection", - "issueSaveMappings": "Save user and path mappings", - "issueSavePathMappings": "Save path mappings to validate them", - "issueFreshDryRun": "Run a fresh dry-run", - "issueResolveDuplicates": "Resolve duplicate target book matches in the dry-run", - "issueWaitActiveRun": "Wait for active run to finish", - "sourceRecordId": "Source record ID #{id}", - "byAuthorWithId": "by {author} (ID: {id})", - "filePathWithId": "{path} (ID: {id})", - "bookloreSourceId": "Booklore source ID: {id}", - "libraryBookNum": "Library book #{id}", - "errorInitialize": "Failed to initialize migration settings", - "errorLoadSourceTypes": "Failed to load supported migration source types", - "errorLoadTargetUsers": "Failed to load target users", - "errorLoadLibraryFolders": "Failed to load target library folders", - "noSourceUsersReturned": "No source users were returned", - "userMappingSuggestionsLoaded": "User mapping suggestions loaded", - "errorLoadSuggestions": "Failed to load user mapping suggestions", - "requiredFields": "Host, user, database, and source name are required", - "connectionTestPassedWithWarnings": "Connection test passed with warnings", - "connectionTestPassedWithCount": "Connection test passed with {count} warning(s). First: {first}", - "connectionTestPassed": "Connection test passed", - "connectionOkMissingTables": "Connection ok, but {count} required table(s) are missing", - "cannotTestMediaPathActiveRun": "Cannot test media path while a run is active", - "mediaRootPathRequiredCover": "Media Root Path is required for cover import.", - "useAbsolutePath": "Use an absolute path (for example: /books).", - "mediaPathVerified": "Media path verified.", - "mediaPathValidReadable": "Media path is valid and readable", - "mediaPathValidationFailed": "Media path validation failed.", - "connectionFailedBeforeMediaPath": "Connection test failed before media path validation could complete.", - "cannotModifySourceActiveRun": "Cannot modify source while a run is active", - "sourceSavedValidatedWarnings": "Source saved and validated with {count} warning(s)", - "sourceSavedValidated": "Source saved and validated", - "errorSaveValidateSource": "Failed to save or validate source", - "cannotSaveMappingsActiveRun": "Cannot save mappings while a run is active", - "saveSourceFirst": "Save source first", - "mapAtLeastOneUser": "Map at least one source user to a target user", - "mapEveryUser": "Map every source user before saving", - "pathValidationFailedProfileSaved": "Path validation failed, but profile will still be saved", - "mappingsSaved": "Mappings saved", - "errorSaveMappings": "Failed to save mappings", - "cannotRunDryRunActiveRun": "Cannot run dry-run while a run is active", - "saveMappingsFirst": "Save mappings first", - "dryRunCompleted": "Dry-run completed: {matched} matched, {unresolved} unresolved", - "dryRunFailed": "Dry-run failed", - "selectSourceForAllGroups": "Select a source book for all {count} duplicate groups", - "duplicatesResolved": "Duplicate matches resolved", - "errorResolveDuplicates": "Failed to resolve duplicates", - "preflightNotReady": "Migration preflight not ready", - "runDryRunFirst": "Run dry-run first", - "runStarted": "Migration run started", - "errorStartMigration": "Failed to start migration", - "runCancelled": "Migration run cancelled", - "errorCancelMigration": "Failed to cancel migration", - "runRetried": "Migration run retried - resuming from last completed stage", - "errorRetryMigration": "Failed to retry migration", - "errorLoadRunProgress": "Failed to load run progress", - "startMigrationFirst": "Start migration first", - "reportRefreshed": "Run report refreshed", - "errorLoadReport": "Failed to load run report", - "reportExported": "Report exported as {format}", - "errorExportReport": "Failed to export migration report", - "reasonNoTitleAuthorMatch": "No matching book found by title or author", - "reasonNoFilePathMatch": "File path did not match any book in this library", - "reasonNoFileHashMatch": "File hash did not match any book in this library", - "reasonNoIsbnMatch": "ISBN did not match any book in this library", - "reasonInsufficientSourceData": "Not enough metadata to attempt matching", - "reasonAmbiguousIsbnMatch": "Multiple books matched the same ISBN", - "reasonAmbiguousFileHashMatch": "Multiple books matched the same file hash", - "reasonAmbiguousFilePathMatch": "Multiple books matched the same file path", - "reasonAmbiguousTitleAuthorMatch": "Multiple books matched the same title and author", - "reasonUnknown": "Could not determine reason", - "strategyIsbn": "Matched by ISBN", - "strategyFileHash": "Matched by file hash", - "strategyPathMapping": "Matched by mapped file path", - "strategyTitleAuthor": "Matched by title and author", - "strategyUnavailable": "Match strategy unavailable", - "userPreviewCounts": "{statuses} statuses, {progress} progress entries, {bookmarks} bookmarks, {annotations} annotations, {collections} collection entries", - "connErrorUnreachable": "Could not reach the database server. Check the host and port.", - "connErrorAuth": "Authentication failed. Check the username and password.", - "connErrorUnknownDatabase": "Database not found. Check the database name.", - "connErrorTimeout": "Connection timed out. Check host and firewall settings.", - "connErrorGeneric": "Connection test failed", - "sourceType": "Source Type", - "sourceName": "Source Name", - "host": "Host", - "port": "Port", - "user": "User", - "password": "Password", - "passwordSavedPlaceholder": "Saved - leave unchanged", - "passwordEmptyPlaceholder": "No password set", - "database": "Database", - "mediaRootPath": "Media Root Path", - "pathOk": "Path OK", - "pathIssue": "Path Issue", - "testPath": "Test Path", - "useTls": "Use TLS/SSL", - "testConnection": "Test Connection", - "saveAndValidate": "Save & Validate", - "sourceValidatedWithWarnings": "Source validated with warnings", - "lastValidationSnapshot": "Last validation snapshot", - "sourceVersion": "Source version: {version}", - "unknown": "Unknown", - "missingRequiredTables": "Missing required tables: {tables}", - "suggestionsAutoLoad": "User suggestions load automatically after source validation.", - "refresh": "Refresh", - "sourceUser": "Source User", - "targetUser": "Target User", - "noSourceUsersLoaded": "No source users loaded yet.", - "noActiveTargetUsers": "No active target users found. Create or re-enable a BookOrbit user before mapping.", - "pathPrefixMappings": "Path Prefix Mappings", - "addMapping": "Add Mapping", - "pathMappingsHelp1": "Path mappings translate source file paths to target paths so books can be matched by file location. For example, if your Booklore library stored files under", - "pathMappingsHelp2": "and the same files now live under", - "pathMappingsHelp3": ", add that mapping here. Books are also matched by ISBN, file hash, and title/author regardless of path mappings - path mapping is only one of four strategies and does not limit which source books are included in the migration.", - "noPrefixesFound": "No prefixes found - validate source first", - "selectSourcePrefix": "Select source prefix...", - "selectTargetFolder": "Select target folder...", - "remove": "Remove", - "pathValidation": "Path validation", - "pathValidationMapped": "{mapped} of {total} source books have a mapped path", - "pathValidationUnmatched": "{count} mapped paths not found on disk - those books will fall back to ISBN / title matching", - "pathValidationAllMatched": "All {count} mapped paths found on disk", - "saveMappings": "Save Mappings", - "runDryRun": "Run Dry-Run", - "matched": "Matched:", - "unresolved": "Unresolved:", - "duplicateMatches": "Duplicate matches:", - "unresolvedSummary": "Unresolved summary", - "resolveDuplicateMatches": "Resolve duplicate target matches", - "resolveDuplicateHint": "For each target book, choose one source book to keep. Recommended choices are preselected when there is a single strongest match.", - "remainingGroups": "Remaining groups:", - "ofCount": "of {count}", - "targetBookNum": "Target book #{id}", - "recommended": "Recommended", - "resolveDuplicatesButton": "{count, plural, =0 {Resolve # duplicate} one {Resolve # duplicate} other {Resolve # duplicates}}", - "preflightChecks": "Preflight checks", - "allChecksPassed": "All checks passed - ready to migrate", - "checkSourceValidated": "Source validated", - "checkSaveValidateSource": "Save and validate source connection", - "checkValidateSource": "Validate source connection", - "checkMappingsSaved": "Mappings saved", - "checkSaveMappings": "Save user and path mappings", - "checkPathMappingsValidated": "Path mappings validated", - "checkSavePathMappings": "Save path mappings to validate them", - "checkDryRunUpToDate": "Dry-run is up to date", - "checkFreshDryRun": "Run a fresh dry-run", - "startConfirmPrompt": "This will start the live migration. Are you sure?", - "confirmStart": "Confirm Start", - "startMigration": "Start Migration", - "cancelRun": "Cancel Run", - "refreshStatus": "Refresh Status", - "statusPollingStopped": "Status polling stopped due to an error.", - "retry": "Retry", - "stageLabel": "Stage: {stage}", - "stageInitializing": "initializing", - "endedLabel": "Ended {date}", - "stageCompleted": "Completed", - "stageInit": "Initializing", - "stageSharedOverlays": "Importing metadata", - "stageBookCovers": "Importing covers", - "stageUserState": "Importing user data", - "noRunYet": "No migration run yet. Complete the steps above to start.", - "runNum": "Run #{id}", - "notStarted": "Not started", - "reloadReport": "Reload Report", - "loadFullReport": "Load Full Report", - "exportJson": "Export JSON", - "exportCsv": "Export CSV", - "migrationFailed": "Migration failed", - "retryFromLastStage": "Retry from last completed stage", - "booksCard": "Books", - "metadataOverlaysApplied": "Metadata overlays applied", - "authorMappingsReplaced": "Author mappings replaced", - "narratorMappingsReplaced": "Narrator mappings replaced", - "genreMappingsReplaced": "Genre mappings replaced", - "tagMappingsReplaced": "Tag mappings replaced", - "coversImported": "Covers imported", - "coverImportSkipped": "Cover import was skipped - media root path is not configured on the source", - "couldNotMatch": "Could not match", - "userDataCard": "User Data", - "readingStatuses": "Reading statuses", - "readingProgressEntries": "Reading progress entries", - "audiobookProgressEntries": "Audiobook progress entries", - "bookmarksLabel": "Bookmarks", - "annotationsLabel": "Annotations", - "collectionEntries": "Collection entries", - "loadFullReportHint": "Click \"Load Full Report\" to include the dry-run match summary in the exported report.", - "completedNoIssues": "Migration completed with no unresolved books or failures.", - "matchedBooksHeading": "Matched books ({count})", - "matchedBooksHint": "These dry-run matches were used to decide which library books received imported data.", - "sourceBookFallback": "Source book {id}", - "libraryBookFallback": "Library book {id}", - "unresolvedBooksHeading": "Unresolved books ({count})", - "unresolvedBooksHint": "These books exist in the source but could not be matched to any book in your library.", - "mappedUsersHeading": "Mapped users ({count})", - "mappedUsersHint": "Per-user totals come from the dry-run preview cached with the migration plan.", - "coverImportsFailed": "{count} cover import(s) failed. Detailed failure rows are not stored.", - "backToSetup": "Back to Setup" - }, - "libraries": { - "title": "Libraries", - "subtitle": "Manage your media libraries and trigger content scans.", - "scanAll": "Scan All", - "scanning": "Scanning...", - "addLibrary": "Add Library", - "scan": "Scan", - "editLibrary": "Edit library", - "refreshCovers": "Refresh covers", - "syncMetadataToFiles": "Sync metadata to files", - "deleteLibrary": "Delete library", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "addedDate": "Added {date}", - "fileMode": "File mode", - "folderMode": "Folder mode", - "folderCount": "{count, plural, =0 {no folders} one {# folder} other {# folders}}", - "watching": "Watching", - "fileWrite": "File write", - "fileRename": "File rename", - "emptyTitle": "No libraries yet", - "emptyHint": "Add a library to start organizing your books.", - "addFirstLibrary": "Add your first library", - "deleteConfirmTitle": "Delete \"{name}\"?", - "deleteConfirmBody": "This will permanently remove all books, metadata, reading progress, bookmarks, and annotations in this library. This cannot be undone.", - "deleteConfirmTypeName": "Type the library name to confirm:", - "deleting": "Deleting...", - "deleteLibraryButton": "Delete Library", - "syncConfirmTitle": "Sync metadata to files?", - "syncConfirmBodyPrefix": "This will overwrite the metadata inside every supported file in", - "syncConfirmBodySuffix": "directly on disk. This cannot be undone.", - "syncFiles": "Sync files", - "metadataSynced": "Metadata synced to files for \"{name}\"", - "fileWriteNotEnabled": "Metadata file write is not enabled for this library. Enable it in the library settings.", - "fileSyncFailed": "File sync failed for \"{name}\"", - "scanStarted": "Scan started for \"{name}\"", - "scanStartFailed": "Failed to start scan for \"{name}\"", - "refreshCoversFailed": "Failed to refresh covers for \"{name}\"", - "scanStartedAll": "Scan started for all libraries", - "librariesFailedToStart": "{count, plural, =0 {no libraries failed to start} one {# library failed to start} other {# libraries failed to start}}", - "scansStartFailed": "Failed to start scans", - "libraryCreated": "Library \"{name}\" created", - "libraryUpdated": "Library \"{name}\" updated", - "libraryDeleted": "\"{name}\" deleted", - "deleteFailed": "Failed to delete library", - "scanningProgress": "Scanning {pct}% ({processed}/{total})", - "scanDone": "Done - {added} added, {updated} updated", - "scanFailedWithError": "Failed: {error}", - "scanFailed": "Scan failed", - "refreshingCovers": "Refreshing covers {pct}% ({processed}/{total})", - "coversRefreshed": "Covers refreshed ({count} processed)" - }, - "authorEnrichment": { - "configuration": "Configuration", - "saving": "Saving...", - "running": "Running...", - "runEligibleShort": "Run eligible", - "runAllShort": "Run all", - "enableTitle": "Enable auto author enrichment", - "enableHint": "Automatically fetch author biographies and profile photos when books are added or updated.", - "updateStrategyTitle": "Update strategy", - "updateStrategyHint": "What to do when an author already has a biography or photo.", - "writeModeMissingOnly": "Only fill missing data (recommended)", - "writeModeAlwaysRefetch": "Always refresh existing data", - "triggerOnImportTitle": "Trigger on import", - "triggerOnImportHint": "Queue authors for enrichment when books are first added to a library.", - "eligibilityTitle": "Eligibility conditions", - "eligibilityHint": "An author is eligible if it matches any enabled condition.", - "neverEnrichedTitle": "Never enriched", - "neverEnrichedHint": "Enrich authors that have never had a successful enrichment.", - "missingBioTitle": "Missing bio", - "missingBioHint": "Enrich if the author has no biography.", - "missingPhotoTitle": "Missing photo", - "missingPhotoHint": "Enrich if the author has no profile photo.", - "runForEligibleAuthors": "Run for eligible authors", - "eligibleCount": "~{count} eligible", - "runForAllAuthors": "Run for all authors", - "saved": "Author enrichment settings saved", - "saveFailed": "Failed to save author enrichment settings", - "noEligibleAuthors": "No eligible authors found", - "noAuthorsToEnrich": "No authors to enrich", - "queueFailed": "Failed to queue author backfill" - }, - "scoreWeights": { - "groupLabel": "Score Weights", - "assignHintPrefix": "Assign a weight to each field. Total weight:", - "areYouSure": "Are you sure?", - "resetToDefaultsButton": "Reset to defaults", - "recalculateAll": "Recalculate all", - "confirmReset": "Confirm reset", - "reset": "Reset", - "recalculate": "Recalculate", - "subtotal": "subtotal: {count}", - "savedRecalculating": "Score weights saved. Recalculating library scores...", - "saveFailed": "Failed to save score weights", - "recalcStarted": "Score recalculation started in the background", - "recalcFailed": "Recalculation failed", - "resetToDefaults": "Weights reset to defaults. Save to apply." - }, - "tabs": { - "users": "Users", - "account-activity": "Account Activity", - "magic-links": "Magic Links", - "oidc": "OIDC / SSO" - } - }, - "common": { - "nav": { - "libraries": "Libraries", - "display": "Display", - "reader": "Reader", - "metadata": "Metadata", - "email": "Email", - "opds": "OPDS", - "kobo": "Kobo", - "koreader": "KOReader", - "hardcover": "Hardcover", - "admin": "Admin", - "system": "System", - "account": "Account" - } - }, - "metadata": { - "title": "Metadata", - "noPermission": "You do not have permission to manage metadata settings.", - "fields": { - "title": "Title", - "subtitle": "Subtitle", - "description": "Description", - "cover": "Cover", - "authors": "Authors", - "publisher": "Publisher", - "publishedYear": "Published year", - "language": "Language", - "pageCount": "Page count", - "communityRating": "Community rating", - "seriesName": "Series name", - "seriesIndex": "Series index", - "genres": "Genres", - "narrators": "Narrators", - "duration": "Duration", - "abridged": "Abridged" - }, - "mergeStrategy": { - "fillMissing": { - "label": "Fill missing", - "description": "Only write if field is currently empty" - }, - "overwriteIfProvided": { - "label": "Overwrite if provided", - "description": "Write if provider returned a value" - }, - "overwrite": { - "label": "Always overwrite", - "description": "Always replace existing value" - } - }, - "autoFetch": { - "globalSettings": "Global Settings", - "perLibraryOverrides": "Per-Library Overrides", - "saving": "Saving...", - "running": "Running...", - "runNow": "Run now", - "runForEligible": "Run for eligible books", - "enable": { - "label": "Enable auto-fetch", - "hint": "Automatically fetch metadata for eligible books." - }, - "triggerOnImport": { - "label": "Trigger on import", - "hint": "Queue eligible books when they are first added to a library." - }, - "status": { - "inQueuePaused": "{count} in queue - paused", - "remaining": "{count} remaining", - "eligible": "~{count} eligible" - }, - "trigger": { - "queued": "{count, plural, one {Queued # book} other {Queued # books}}", - "noneFound": "No eligible books found" - }, - "lastRun": { - "justNow": "just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "yesterday": "yesterday", - "daysAgo": "{count, plural, one {# day ago} other {# days ago}}", - "label": "Last run: {when}", - "labelQueued": "Last run: {when} - queued {count} books", - "labelNoneEligible": "Last run: {when} - no eligible books" - }, - "conditions": { - "title": "Eligibility conditions", - "hint": "A book is eligible if it matches any enabled condition.", - "noneEnabled": "No conditions enabled", - "neverFetched": { - "label": "Never fetched", - "hint": "Fetch books that have never had a metadata fetch attempt.", - "summary": "Never fetched" - }, - "scoreThreshold": { - "label": "Low metadata score", - "hint": "Fetch if the metadata score is below a threshold.", - "scoreBelow": "Score below", - "summary": "Score < {threshold}" - }, - "missingFields": { - "label": "Missing fields", - "hint": "Fetch if any of the selected fields are empty.", - "summary": "{count, plural, one {Missing # field} other {Missing # fields}}" - } - }, - "library": { - "inheritingGlobal": "Inheriting global defaults", - "inheritFromGlobal": "Inherit from global", - "usingGlobalDefaults": "Using global defaults.", - "saveOverride": "Save override" - } - }, - "providers": { - "availableSources": "Available Sources", - "saveChanges": "Save Changes", - "test": "Test", - "testing": "Testing...", - "enabled": "Enabled", - "retryIn": "Retry in {duration}", - "runTestBeforeEnabling": "Run Test before enabling", - "hardcoverEnableHint": "Run Test with the current token to unlock the enable switch.", - "badge": { - "setupRequired": "Setup Required", - "throttled": "Throttled", - "ready": "Ready" - }, - "fields": { - "apiKey": "API Key", - "region": "Region", - "cookie": "Cookie", - "coverResolution": "Cover Resolution", - "country": "Country", - "language": "Language", - "ttbKey": "TTB Key" - }, - "helpers": { - "googleApiKey": "Google Books API key from Google Cloud." - }, - "hints": { - "google": "Broad coverage from Google's book index. Google Books now requires an API key before this provider can be enabled.", - "amazon": "Session cookie is recommended. Paste cookie value only (no \"Cookie:\").", - "goodreads": "The largest reading community on the web. No setup required.", - "hardcover": "A modern alternative to Goodreads. Token from hardcover.app/account/api. \"Bearer \" prefix is optional.", - "openLibrary": "The Internet Archive's free book catalog. No setup required.", - "itunes": "Apple's digital book catalog. Choose whether to fetch high or standard resolution covers.", - "kobo": "Scrapes Kobo's public book pages. Country and language must match Kobo URL paths; bot protection can block requests.", - "audible": "Pulls audiobook metadata from Audible. No additional setup is required.", - "audnexus": "Community-driven audiobook metadata. No setup required.", - "comicvine": "Comic book metadata from ComicVine. A free API key is required from comicvine.gamespot.com.", - "ranobedb": "Japanese light novel metadata from RanobeDB. No setup required.", - "lubimyczytac": "Polish book catalog (lubimyczytac.pl). Scrapes public book pages. No setup required.", - "aladin": "Korean book metadata from Aladin (알라딘). A TTB Key from aladin.co.kr is required." - }, - "blocked": { - "google": "Google Books requires an API key before it can be enabled", - "hardcover": "Hardcover requires an API key before it can be enabled", - "hardcoverTest": "Hardcover token must pass Test before it can be enabled", - "comicvine": "ComicVine requires an API key before it can be enabled", - "aladin": "Aladin requires a TTB Key before it can be enabled" - } - }, - "fieldRules": { - "clearAllProviders": "Clear All Providers", - "clearAll": "Clear All", - "resetToDefault": "Reset to Default", - "reset": "Reset", - "dragProvidersHint": "Drag providers from here onto any field to add them", - "dragProviderHere": "drag a provider here", - "howItWorks": { - "title": "How Field Rules Work", - "priorityOrder": { - "title": "Priority Order", - "body": "Drag providers in the list to reorder them. The top-most provider that returns a result will be the primary source for that field." - }, - "mergeStrategy": { - "title": "Merge Strategy", - "fillMissingTerm": "Fill missing:", - "fillMissingBody": "Only write if current value is empty.", - "overwriteTerm": "Overwrite:", - "overwriteBody": "Replace whenever a provider has data." - } - }, - "libraryOverrides": { - "title": "Library Overrides", - "hint": "Expand a library to customize individual fields. Fields not overridden inherit global defaults." - }, - "global": { - "title": "Global Defaults", - "hint": "Default rules applied to every library. Override per-library below.", - "saveDefaults": "Save Defaults", - "clearAllConfirm": "Remove all active providers from every field? This will be saved immediately and cannot be undone.", - "resetConfirm": "Reset all global field rules to system defaults? This will overwrite your current configuration." - }, - "advanced": { - "title": "Advanced Fetch Behavior", - "combineGenres": { - "label": "Combine genres from all selected providers", - "hint": "Collect and deduplicate genres from every provider assigned to the Genres field, rather than stopping at the first result." - }, - "storeProviderIds": { - "label": "Store provider IDs on books", - "hint": "When fetching metadata, save the returned provider IDs (ISBN, ASIN, Goodreads ID, etc.) on the book record for more accurate future lookups." - } - }, - "library": { - "primary": "Primary:", - "overrideCount": "{count, plural, one {# Override} other {# Overrides}}", - "unsavedSuffix": "(unsaved)", - "unsavedChanges": "Unsaved changes", - "globalDefaults": "Global Defaults", - "overriding": "Overriding: {fields}", - "inheritingAll": "Inheriting all global metadata rules", - "subHint": "Fields not overridden inherit global defaults.", - "resetTooltip": "Remove all overrides and inherit global defaults", - "clearAllConfirm": "Remove all active providers from every field in \"{library}\"?", - "resetConfirm": "Reset \"{library}\" to global defaults? All library overrides will be removed." - }, - "groups": { - "core": "Core", - "contributors": "Contributors", - "publication": "Publication", - "series": "Series", - "classification": "Classification", - "audiobook": "Audiobook" - }, - "groupSummary": { - "base": "{fields} fields · {enabled} enabled", - "withOverrides": "{base} · {overrides} overrides" - }, - "table": { - "field": "Field", - "activeProviders": "Active Providers (ordered by priority)", - "mergeStrategy": "Merge Strategy", - "status": "Status" - }, - "field": { - "noProviders": "Enabled but has no providers", - "empty": "Empty", - "config": "Config", - "custom": "Custom", - "default": "Default", - "resetToDefault": "Reset to default" - }, - "reservoir": { - "disabled": "{provider} - disabled", - "notConfigured": "{provider} - not configured", - "dragToAssign": "Drag to assign {provider} to a field" - }, - "sheet": { - "subtitle": "Tap providers to assign, use arrows to reorder", - "enableField": "Enable this field during refresh", - "providers": "Providers", - "statusDisabled": "disabled", - "statusNotConfigured": "not configured", - "done": "Done" - } - }, - "genreBlocklist": { - "heading": "Global Genre Exclusions", - "hint": "Exact genre values in this list are stripped from provider results before metadata is written.", - "saving": "Saving", - "genreValueLabel": "Genre value", - "addPlaceholder": "Add a genre value, for example Audiobook", - "duplicate": "This genre is already blocked.", - "add": "Add", - "filterPlaceholder": "Filter blocklist", - "entryCount": "{count, plural, one {# entry} other {# entries}}", - "filteredCount": "{shown} of {total}", - "noFilterMatch": "No blocked genres match the current filter.", - "emptyTitle": "No blocked genres", - "emptyHint": "Add exact values such as Audiobook or Adult to keep them out of fetched metadata.", - "removeLabel": "Remove {genre}" - }, - "customFields": { - "label": "Label", - "labelPlaceholder": "e.g. Original Title", - "labelTooLong": "Label must be 255 characters or fewer", - "labelDuplicate": "A field with this label already exists", - "type": "Type", - "usage": "{count, plural, one {Used by # book} other {Used by # books}}", - "newField": { - "title": "New Field", - "hint": "Define a custom metadata field and choose which libraries use it." - }, - "previewToggle": "Preview how this field appears when editing a book", - "untitledField": "Untitled field", - "addField": "Add field", - "fields": "Fields", - "fieldsHint": "Drag to reorder, edit labels, toggle libraries, or archive fields you no longer need.", - "searchPlaceholder": "Search fields", - "searchAriaLabel": "Search custom fields", - "emptyTitle": "No custom fields yet", - "emptyHint": "Use the form above to define your first custom metadata field.", - "noMatchTitle": "No fields match \"{query}\"", - "noMatchHint": "Try a different label, key, or type.", - "clearSearchToReorder": "Clear search to reorder", - "dragToReorder": "Drag to reorder", - "dragToReorderField": "Drag to reorder field", - "unsaved": "Unsaved", - "archive": "Archive", - "archivedFields": "Archived Fields", - "archivedSummary": "{count, plural, one {# archived field - restore or permanently delete.} other {# archived fields - restore or permanently delete.}}", - "archivedAt": "Archived {when}", - "restore": "Restore", - "deleteForever": "Delete forever", - "deleteDialog": { - "title": "Permanently delete field", - "bodyBefore": "This will permanently delete", - "bodyMiddle": "and remove its stored values from", - "bodyAfter": ". This cannot be undone.", - "confirmBefore": "Type", - "confirmAfter": "to confirm", - "confirmPlaceholder": "Type the field label to confirm" - }, - "preview": "Preview", - "sampleValue": "Sample value", - "enabledLibraries": "Enabled Libraries", - "countOf": "{selected} of {total}", - "selectAll": "Select all", - "clear": "Clear", - "noLibraries": "No libraries available yet.", - "allLibraries": "All libraries" - }, - "tabs": { - "providers": "Providers", - "field-rules": "Field Rules", - "custom-fields": "Custom Fields", - "genre-blocklist": "Genre Blocklist", - "score": "Score", - "auto-fetch": "Books", - "authors": "Authors" - }, - "tabTitles": { - "providers": "Providers", - "field-rules": "Field-Level Rules", - "custom-fields": "Custom Metadata", - "genre-blocklist": "Genre Blocklist", - "score": "Confidence Score", - "auto-fetch": "Book Auto-Fetch", - "authors": "Author Auto-Fetch" - }, - "tabSubtitles": { - "providers": "Enable external metadata sources and configure their credentials.", - "field-rules": "Control which provider supplies each metadata field and how values are merged across your libraries.", - "custom-fields": "Define custom metadata fields and choose which libraries use them.", - "genre-blocklist": "Prevent unwanted provider genre values from being written to books.", - "score": "Assign weights to metadata fields to calculate how much to trust fetched results.", - "auto-fetch": "Automatically fetch covers, descriptions, and other details when new books are added to your library.", - "authors": "Automatically fetch biographies and profile photos when new authors appear in your library." - } - }, - "reader": { - "resetToDefaults": "Reset to defaults", - "all": { - "title": "Reader", - "subtitle": "Configure defaults for all reading modes in one place." - }, - "general": { - "title": "Reading", - "subtitle": "General behavior that applies across all reader types.", - "storageLabel": "Where to save reader preferences", - "deviceOnly": "This device only", - "deviceOnlyHint": "Preferences stay in your browser. Best if you always read on this device, or want different settings per device.", - "myAccount": "My account", - "myAccountHint": "Preferences are saved to your account. Best if you log in from multiple devices and want a consistent experience everywhere.", - "active": "Active", - "notAvailable": "Not available", - "demoCannotChangeStorage": "Demo-restricted account cannot change reader storage mode", - "preferencesSynced": "Preferences will now be synced", - "preferencesLocal": "Preferences will stay on this device", - "storageUpdateFailed": "Failed to update storage mode", - "storageUpdateError": "An error occurred while updating storage mode" - }, - "ebook": { - "title": "eBook Reader", - "subtitle": "Default settings applied when opening EPUB, MOBI, FB2, and TXT files.", - "newBooks": "New Books", - "applySettings": "Apply my settings to new books", - "applySettingsHint": "When off, new books open with the publisher's own fonts and layout. Your settings only apply once you change something in-reader.", - "layout": "Layout", - "readingFlow": "Reading flow", - "readingFlowHint": "Paginated flips pages; scrolled flows continuously", - "paginated": "Paginated", - "scrolled": "Scrolled", - "fixedLayoutSpread": "Fixed-layout page spreads", - "fixedLayoutSpreadHint": "Default for manga, comics, and image-based EPUBs", - "bookDefault": "Book default", - "singlePage": "Single page", - "columns": "Columns", - "columnsHint": "Number of text columns per page", - "theme": "Theme", - "darkMode": "Dark mode", - "darkModeHint": "Use the dark variant of the selected theme", - "typography": "Typography", - "font": "Font", - "fontHint": "Typeface used for body text", - "builtInFonts": "Built-in fonts", - "yourFonts": "Your Fonts", - "fontSize": "Font size", - "fontSizeHint": "Base text size in pixels", - "lineHeight": "Line height", - "lineHeightHint": "Vertical spacing between lines", - "justify": "Justify text", - "justifyHint": "Align text to both margins", - "hyphenation": "Hyphenation", - "hyphenationHint": "Automatically break long words with hyphens", - "advanced": "Advanced", - "maxContentWidth": "Max content width", - "maxContentWidthHint": "Maximum width of the text area in pixels", - "columnGap": "Column gap", - "columnGapHint": "Horizontal padding on each side of the text area" - }, - "pdf": { - "title": "PDF Reader", - "subtitle": "Default settings applied when opening PDF files.", - "layout": "Layout", - "scrollMode": "Scroll mode", - "scrollModeHint": "Page flips one at a time; continuous scrolls through all pages", - "page": "Page", - "scrolled": "Scrolled", - "pageSpread": "Page spread", - "pageSpreadHint": "Which page number starts on the right in two-page view", - "spreadNone": "None", - "spreadOdd": "Odd", - "spreadEven": "Even", - "zoom": "Zoom", - "defaultFit": "Default fit", - "defaultFitHint": "How pages are scaled when a PDF is opened", - "fitPage": "Fit Page", - "fitWidth": "Fit Width", - "custom": "Custom", - "zoomLevel": "Zoom level", - "zoomLevelHint": "Scale factor for custom zoom mode" - }, - "comics": { - "title": "Comics Reader", - "subtitle": "Default settings applied when opening CBZ, CBR, and CB7 files.", - "view": "View", - "readingMode": "Reading mode", - "readingModeHint": "How pages are navigated - use \"Infinite (no gaps)\" for webtoons", - "paginated": "Paginated", - "infiniteSpaced": "Infinite (spaced)", - "infiniteNoGaps": "Infinite (no gaps)", - "pageView": "Page view", - "pageViewHint": "Show one or two pages side by side", - "single": "Single", - "twoPage": "Two-page", - "fitMode": "Fit mode", - "fitModeHint": "How pages are scaled to fit the screen", - "fitPage": "Page", - "fitWidth": "Width", - "fitHeight": "Height", - "fitActual": "Actual", - "readingDirection": "Reading direction", - "readingDirectionHint": "Left-to-right for western comics; right-to-left for manga", - "ltr": "L to R", - "rtl": "R to L", - "spreadAlignment": "Spread alignment", - "spreadAlignmentHint": "Shift pairing by one page after the cover for off-by-one scans", - "alignmentNormal": "Normal", - "alignmentShifted": "Shifted", - "spreadGap": "Spread gap", - "spreadGapHint": "Space between pages in two-page view", - "spreadGapValue": "{value}px", - "widePageHandling": "Wide-page handling", - "widePageHandlingHint": "Auto shows wide scans alone in two-page paginated mode", - "widePageAuto": "Auto", - "widePageDisable": "Disable", - "forceTwoPage": "Force two-page on small screens", - "forceTwoPageHint": "Bypass mobile auto-fallback when paginated two-page mode is selected", - "off": "Off", - "on": "On", - "display": "Display", - "backgroundColor": "Background color", - "backgroundColorHint": "Canvas color behind pages", - "bgBlack": "Black", - "bgGray": "Gray", - "bgWhite": "White" - }, - "audio": { - "title": "Audiobook Player", - "subtitle": "Default settings applied when playing M4B, MP3, and other audio formats.", - "playback": "Playback", - "playbackSpeed": "Default playback speed", - "playbackSpeedHint": "Speed multiplier applied when opening a new audiobook", - "volume": "Default volume", - "volumeHint": "Initial volume level (0 to 100%)", - "skipControls": "Skip controls", - "skipBack": "Skip back duration", - "skipBackHint": "Seconds rewound on skip-back press", - "skipForward": "Skip forward duration", - "skipForwardHint": "Seconds advanced on skip-forward press" - }, - "fonts": { - "title": "Fonts", - "subtitle": "Upload custom fonts for use in the eBook reader.", - "uploadFonts": "Upload Fonts", - "notAvailableDemo": "Not available for demo accounts", - "uploading": "Uploading...", - "dropFilesHere": "Drop files here", - "dragFontsPrefix": "Drag font files here, or", - "browse": "browse", - "fileTypesHint": "TTF, OTF, WOFF, WOFF2 - max 10 MB each", - "yourFonts": "Your Fonts", - "fontsUsed": "{count} / {max} used", - "noFontsYet": "No fonts uploaded yet", - "noFontsHint": "Drag a font file above to get started.", - "fileCount": "{count, plural, =0 {no files} one {# file} other {# files}}", - "pangram": "The quick brown fox jumps over the lazy dog", - "renameFamily": "Rename family", - "deleteFamily": "Delete family", - "editVariant": "Edit weight/style", - "deleteVariant": "Delete variant", - "styleNormal": "Normal", - "styleItalic": "Italic", - "weightThin": "Thin", - "weightExtraLight": "Extra Light", - "weightLight": "Light", - "weightRegular": "Regular", - "weightMedium": "Medium", - "weightSemiBold": "Semi Bold", - "weightBold": "Bold", - "weightExtraBold": "Extra Bold", - "weightBlack": "Black", - "renameFamilyFailed": "Failed to rename font family", - "renamedTo": "Renamed to \"{name}\"", - "updateVariantFailed": "Failed to update font variant", - "deleteFontFailed": "Failed to delete font", - "deleteFamilyFailed": "Failed to delete font family", - "demoCannotManage": "Demo-restricted account cannot manage fonts", - "fileAdded": "\"{name}\" added", - "uploadFailed": "Upload failed" - }, - "bookDock": { - "title": "Book Dock", - "subtitle": "Configure how files are processed when they enter Book Dock.", - "dropFolder": "Drop folder", - "containerPath": "Container path", - "containerPathHint": "Copy or move book files into this folder and they will be automatically picked up and processed by Book Dock. Subdirectories are supported.", - "changePathPrefix": "To change this path, set", - "changePathMiddle": "in your", - "changePathSuffix": "file.", - "metadata": "Metadata", - "autoFetch": "Auto-fetch metadata from providers", - "autoFetchHint": "Automatically fetch metadata from configured providers (Google Books, iTunes, Open Library, etc.) after a file is added to Book Dock.", - "autoFinalize": "Auto-finalize", - "enableAutoFinalize": "Enable auto-finalize", - "enableAutoFinalizeHint": "Files with a metadata confidence score at or above the threshold will be finalized automatically.", - "confidenceThreshold": "Confidence threshold: {value}%", - "thresholdIgnored": "(ignored in Embedded only mode)", - "destinationLibrary": "Destination library", - "selectLibrary": "Select a library...", - "metadataMode": "Metadata mode", - "metadataModeSafeMerge": "Safe merge (recommended)", - "metadataModeFetchedOnly": "Fetched only", - "metadataModeEmbeddedOnly": "Embedded only", - "destinationFolder": "Destination folder", - "selectFolder": "Select a folder...", - "saveSettingFailed": "Failed to save setting", - "updateSettingFailed": "Failed to update setting", - "autoFetchEnabled": "Auto-fetch enabled", - "autoFetchDisabled": "Auto-fetch disabled", - "autoFinalizeEnabled": "Auto-finalize enabled", - "autoFinalizeDisabled": "Auto-finalize disabled", - "destinationLibraryUpdated": "Destination library updated", - "destinationFolderUpdated": "Destination folder updated", - "confidenceThresholdUpdated": "Confidence threshold updated", - "metadataModeUpdated": "Metadata mode updated" - }, - "fileNaming": { - "title": "File Naming", - "subtitle": "Control how files are organized on disk when uploaded and how they are named when downloaded using placeholder tokens.", - "copy": "Copy", - "previewLabel": "Preview:", - "globalDefaults": "Global Defaults", - "crossPlatform": "Cross-platform path sanitization", - "crossPlatformHint": "Make generated file and folder names safe on Windows by replacing invalid characters and reserved names, and removing trailing dots and spaces. Disable only for Linux-only setups that intentionally keep those characters.", - "fileAsBookDefault": "File as Book default", - "fileAsBookDefaultHint": "Upload pattern for libraries using File as Book mode. Each file is one book.", - "folderAsBookDefault": "Folder as Book default", - "folderAsBookDefaultHint": "Upload pattern for libraries using Folder as Book mode. Each book must be in its own folder.", - "downloadPattern": "Download Pattern", - "downloadPatternHint": "Suggested filenames for single-file downloads and files inside export ZIPs.", - "libraryOverrides": "Library Overrides", - "noLibraries": "No libraries configured. Create one in Library settings to set custom naming patterns.", - "badgeCustom": "Custom", - "badgeDefault": "Default", - "orgFolderAsBook": "Folder as Book", - "orgFileAsBook": "File as Book", - "resetToDefault": "Reset to default", - "tokens": "Tokens", - "clickTokenHint": "Click any token to copy it to your clipboard.", - "copyValue": "Copy {value}", - "modifiers": "Modifiers", - "modifiersExplain": "Append a modifier inside a token to transform its value:", - "modFirst": "First value only", - "modSort": "Last, First format", - "modInitial": "First letter only", - "modFixed2": "Two decimal places", - "folderOnlyPrefix": "End a pattern with", - "folderOnlySuffix": "to specify a folder only. The original filename will be preserved inside it.", - "conditionalLogic": "Conditional Logic", - "conditionalPart1": "Wrap in", - "conditionalPart2": "to skip a segment when its token is empty. Use", - "conditionalPart3": "for a default value.", - "examples": "Examples", - "exCalibre": "Calibre-style default", - "exSeriesReader": "Series reader", - "exCleanDownload": "Clean download filename", - "exAlphabetical": "Alphabetical grouping with series", - "exSeriesFallback": "Series or Standalone fallback", - "exOptionalSubtitle": "Download with optional subtitle", - "exMultilingual": "Multilingual library", - "exPublisher": "Publisher-organized", - "exStacked": "Stacked optional folders", - "exFolderDrop": "Folder-drop with sort name", - "caseWithYear": "with year", - "caseNoYear": "no year", - "caseInSeries": "in series", - "caseStandalone": "standalone", - "caseNoSeries": "no series", - "caseFull": "full", - "caseMinimal": "minimal", - "caseWithLanguage": "with language", - "caseNoLanguage": "no language", - "caseWithPublisher": "with publisher", - "caseNoPublisher": "no publisher", - "caseAllSet": "all set", - "copiedToClipboard": "{value} copied to clipboard", - "copyTokenFailed": "Failed to copy token", - "patternCopied": "Pattern copied to clipboard", - "copyPatternFailed": "Failed to copy pattern", - "labelCopied": "{label} copied to clipboard", - "copyLabelFailed": "Failed to copy {label}", - "patternHelp": "Pattern help", - "patternHelpDescription": "Tokens, modifiers and ready-made patterns you can copy into any field.", - "copyPreview": "Copy {label}", - "copyExample": "Copy the {label} pattern", - "invalidCharacters": "Pattern contains invalid characters", - "fileAsBookSaved": "File as Book default saved", - "folderAsBookSaved": "Folder as Book default saved", - "downloadPatternSaved": "Download pattern saved", - "savePatternFailed": "Failed to save pattern", - "saveDownloadPatternFailed": "Failed to save download pattern", - "crossPlatformEnabled": "Cross-platform path sanitization enabled", - "crossPlatformDisabled": "Cross-platform path sanitization disabled", - "crossPlatformSaveFailed": "Failed to save cross-platform path sanitization", - "librarySaved": "Pattern saved for {name}", - "librarySaveFailed": "Failed to save library pattern", - "saveLibraryPattern": "Save pattern for {name}", - "resetLibraryPattern": "Reset {name} to the default pattern", - "tokenTitle": "Book title", - "tokenSubtitle": "Book subtitle", - "tokenAuthors": "Author(s), comma-separated", - "tokenYear": "Publication year", - "tokenSeries": "Series name", - "tokenSeriesIndex": "Series index (zero-padded)", - "tokenPublisher": "Publisher", - "tokenIsbn": "ISBN-13", - "tokenLanguage": "Language", - "tokenOriginalFilename": "Original filename (without extension)", - "tokenExtension": "File extension (without dot)", - "patternHelpIntro": "Patterns use tokens like {titleToken} and {authorsToken}, plus modifiers and optional segments.", - "browseTokensAndExamples": "Browse tokens and examples" - }, - "kobo": { - "title": "Kobo Sync", - "subtitle": "Pair your Kobo device to sync your library.", - "copy": "Copy", - "never": "Never", - "justNow": "Just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "daysAgo": "{count}d ago", - "loadFailed": "Failed to load", - "devicePaired": "Device paired successfully", - "devicePairedHint": "You're ready to set up your Kobo. Follow the instructions below.", - "syncUrl": "Sync URL", - "urlNotShownAgain": "This URL will not be shown again. Keep it private.", - "registeredDevices": "Registered Devices", - "addDevice": "Add device", - "deviceName": "Device name", - "deviceNamePlaceholder": "e.g. My Kobo Libra", - "creating": "Creating...", - "createDevice": "Create device", - "createDeviceFailed": "Failed to create device", - "deviceRegistered": "Device \"{name}\" registered", - "noDevicesYet": "No devices yet", - "noDevicesHint": "Add a device to start syncing your books to your Kobo.", - "lastSync": "Last sync: {time}", - "renameDevice": "Rename device", - "revokeAccess": "Revoke access", - "deviceRenamed": "Device renamed", - "renameDeviceFailed": "Failed to rename device", - "revokeConfirm": "Revoke access for \"{name}\"? The device will not be able to sync until re-paired.", - "accessRevoked": "Access revoked for \"{name}\"", - "revokeFailed": "Failed to revoke access", - "syncUrlCopied": "Sync URL copied to clipboard", - "syncUrlCopyFailed": "Failed to copy sync URL", - "syncPreferences": "Sync Preferences", - "twoWaySync": "Two-way progress sync", - "twoWaySyncHint": "Sync reading position between BookOrbit and Kobo. Requires KEPUB delivery for precise locations and reliable page restore.", - "syncHighlights": "Sync BookOrbit highlights to Kobo", - "syncHighlightsHint": "Send highlights made in BookOrbit or KOReader to your Kobo. Kobo highlights are imported into BookOrbit even when this is off. Linked annotations sync edits and deletes both ways. Requires KEPUB delivery; the book on Kobo must be the KEPUB downloaded from BookOrbit.", - "convertKepub": "Convert to KEPUB", - "convertKepubHint": "Send eligible EPUBs as KEPUB. This stays on when progress sync or BookOrbit-to-Kobo highlights are enabled. On the next Kobo sync, affected books are offered again as KEPUB downloads; remove any old EPUB copy if Kobo keeps opening it.", - "forceHyphenation": "Force hyphenation", - "forceHyphenationHint": "Ensures consistent text justification. This will regenerate cached KEPUBs.", - "progressThresholds": "Progress Thresholds", - "progressThresholdsHint": "Define when Kobo reading progress updates your library status.", - "markAsReading": "Mark as Reading", - "markAsReadingHint": "Minimum percentage to move a book to \"Reading\".", - "markAsFinished": "Mark as Finished", - "markAsFinishedHint": "Percentage threshold to mark a book as \"Finished\".", - "kepubLimit": "KEPUB conversion limit", - "kepubLimitHint": "Books above this limit are sent as regular EPUBs, so BookOrbit will not sync their reader position back to Kobo.", - "changesMustBeSaved": "Changes must be saved to take effect.", - "saving": "Saving...", - "saveSyncSettings": "Save Sync Settings", - "thresholdOrderError": "Reading threshold must be less than finished threshold", - "saveSettingsFailed": "Failed to save settings", - "settingsSaved": "Kobo sync settings saved", - "saveFailed": "Failed to save", - "activity": { - "waitingForActivity": "Waiting for activity", - "needsAttention": "Needs attention", - "syncHealthy": "Sync healthy", - "never": "Never", - "none": "None", - "unknown": "Unknown", - "failureCount": "{count, plural, one {# failure} other {# failures}}", - "noActivityRecorded": "No Kobo sync activity has been recorded.", - "lastSuccess": "Last success {time}", - "lastFailure": "Last failure {time}", - "noFailedActivity": "No failed Kobo activity in recent history.", - "noActivityYet": "No Kobo activity yet.", - "event": { - "librarySync": "Library checked for updates", - "bookDownload": "Book downloaded", - "progressUpdate": "Reading position updated", - "annotationsPull": "Highlights sent to Kobo", - "annotationsPush": "Highlights received from Kobo" - }, - "outcome": { - "failed": "Failed", - "noUpdates": "No updates", - "noChanges": "No changes", - "pending": "Pending", - "completed": "Completed", - "downloaded": "Downloaded", - "updated": "Updated", - "sent": "Sent", - "imported": "Imported" - }, - "failure": { - "librarySync": "Library check did not complete", - "bookDownload": "Download did not complete", - "progressUpdate": "Reading position did not update", - "annotationsPull": "Highlights were not sent", - "annotationsPush": "Highlights were not imported" - }, - "chip": { - "morePending": "More pending", - "noUpdatesPending": "No updates pending", - "bookCount": "{count, plural, one {# book} other {# books}}", - "deletedAnnotations": "{count} deleted annotations", - "deviceAlreadyCurrent": "Device already current", - "freshHighlightData": "Fresh highlight data", - "created": "{count} created", - "updated": "{count} updated", - "deleted": "{count} deleted", - "unchanged": "{count} unchanged" - }, - "readingPositionSyncedTitle": "Reading position synced: {title}", - "readingPositionSynced": "Reading position synced", - "labelWithTitle": "{label}: {title}", - "updateCount": "{count, plural, one {# update} other {# updates}}", - "directionToKobo": "BookOrbit -> Kobo", - "directionToBookOrbit": "Kobo -> BookOrbit", - "twoWaySyncEnabled": "Two-way sync enabled", - "deviceProgressSaved": "Device progress saved", - "summary": { - "noLibraryUpdatesPending": "No library updates are pending for this device", - "libraryUpdatesPrepared": "{count, plural, one {# library update prepared for the device} other {# library updates prepared for the device}}", - "bookDownloadedBy": "{title} was downloaded by {device}", - "booksDownloaded": "{count, plural, one {# book downloaded} other {# books downloaded}}", - "progressUpdatesSyncedFor": "{count, plural, one {# progress update synced for {title}} other {# progress updates synced for {title}}}", - "progressUpdatesSynced": "{count, plural, one {# progress update synced} other {# progress updates synced}}", - "newReadingPositionFor": "Kobo reported a new reading position for {title}", - "newReadingPosition": "Kobo reported a new reading position", - "noHighlightChangesNeededFor": "No highlight changes needed for {title}", - "noHighlightChangesNeeded": "No highlight changes needed", - "highlightsSentToKoboFor": "{count, plural, one {# highlight sent to Kobo for {title}} other {# highlights sent to Kobo for {title}}}", - "highlightsSentToKobo": "{count, plural, one {# highlight sent to Kobo} other {# highlights sent to Kobo}}", - "noKoboHighlightChangesFor": "No Kobo highlight changes for {title}", - "noKoboHighlightChanges": "No Kobo highlight changes", - "highlightsImportedFromKoboFor": "{count, plural, one {# highlight imported from Kobo for {title}} other {# highlights imported from Kobo for {title}}}", - "highlightsImportedFromKobo": "{count, plural, one {# highlight imported from Kobo} other {# highlights imported from Kobo}}" - }, - "timeRange": "{from} to {to}", - "eventsGrouped": "{count, plural, one {# event grouped} other {# events grouped}}", - "removedDevice": "Removed device", - "loadMoreFailed": "Failed to load more history", - "historyRefreshed": "Kobo sync history refreshed", - "refreshFailed": "Failed to refresh history", - "recentActivity": "Recent Kobo Activity", - "filterAll": "All", - "filterFailures": "Failures", - "refresh": "Refresh", - "loadingActivity": "Loading Kobo activity...", - "noActivityHint": "Recent sync activity will appear after a paired Kobo contacts BookOrbit.", - "error": "Error", - "loading": "Loading...", - "loadMore": "Load more activity" - }, - "howBooksSynced": { - "title": "How books are synced", - "body": "To send books to your Kobo device, you must enable {syncToKobo} on the collections containing those books. Open any collection from the sidebar, click the Edit icon, and toggle {syncToKobo}. Books that are not part of an enabled collection will not sync." - }, - "nextSteps": { - "title": "Next Steps", - "step1": "1. Configure your Kobo device to sync with the Sync URL above.", - "step2": "2. In BookOrbit, go to any collection from the sidebar, click the Edit icon, and enable {syncToKobo}. Only books inside sync-enabled collections will download to your device." - }, - "syncToKobo": "Sync to Kobo", - "tabs": { - "syncSettings": "Sync Settings", - "activityLog": "Activity Log" - } - }, - "koreader": { - "title": "KOReader Sync", - "subtitle": "Browse your BookOrbit catalog in KOReader and sync progress, reading activity, highlights, and annotation changes.", - "tabs": { - "sync": "Sync Settings", - "fileNaming": "File Naming" - }, - "fileNaming": { - "accountTitle": "Account default KOReader pattern", - "accountDescription": "Sets the default relative folder and filename used by BookOrbit plugin downloads for your KOReader account. Device-specific rules can override it below.", - "defaultPattern": "Default book path pattern", - "accountHelp": "Your account default for KOReader plugin downloads unless a device has a custom rule.", - "accountHint": "Used by your KOReader devices that do not have a custom override.", - "preview": "Preview", - "saveAccount": "Save account default", - "deviceTitle": "KOReader device overrides", - "deviceDescription": "Customize any combination of default, series, and standalone paths. Empty device-specific rows inherit the device default, which itself can inherit the account default KOReader pattern.", - "noDevices": "Devices appear here after they sync with BookOrbit.", - "customOrganization": "Custom organization", - "usingAccountDefault": "Using account default", - "deviceDefaultHelp": "Fallback for this device. Leave it equal to the account default to inherit future changes automatically.", - "seriesBooks": "Books in a series", - "seriesHelp": "Optional path used only for books with series metadata. Leave empty to use this device's default path pattern.", - "standaloneBooks": "Books without a series", - "standaloneHelp": "Optional path used only for books without series metadata. Leave empty to use this device's default path pattern.", - "inheritPlaceholder": "Leave empty to use this device's default pattern", - "useAccount": "Use account default", - "saveOverride": "Save override", - "loadFailed": "Failed to load file organization settings", - "accountRequired": "Enter a default book path pattern before saving.", - "accountSaved": "Account default KOReader pattern saved", - "accountSaveFailed": "Failed to save file organization settings", - "deviceUsesAccount": "Device now uses the account default KOReader pattern", - "deviceSaved": "Device organization override saved", - "deviceSaveFailed": "Failed to save device override", - "deviceResetFailed": "Failed to reset device override" - }, - "loadingSettings": "Loading KOReader settings...", - "loadFailed": "Failed to load KOReader settings", - "never": "Never", - "justNow": "Just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "daysAgo": "{count}d ago", - "unknown": "Unknown", - "updateAvailable": "Update available", - "upToDate": "Up to date", - "versionUnknown": "Version unknown", - "latestPlugin": "Latest plugin: v{version}", - "latestPluginUnavailable": "Latest plugin unavailable", - "notConfigured": "KOReader sync is not configured", - "notConfiguredHint": "Create one set of sync credentials, then use them with the BookOrbit KOReader plugin for browsing, downloads, progress, reading events, highlights, and deletes.", - "createCredentials": "Create credentials", - "createFormTitle": "Create KOReader Sync Credentials", - "createFormHint": "These credentials authenticate your KOReader devices with BookOrbit.", - "username": "Username", - "usernamePlaceholder": "e.g. myreader", - "password": "Password", - "passwordPlaceholder": "Min 6 characters", - "creating": "Creating...", - "create": "Create", - "credentialsCreated": "KOReader sync credentials created", - "createCredentialsFailed": "Failed to create credentials", - "status": "KOReader Status", - "refresh": "Refresh", - "progressSync": "Progress sync", - "progressSyncHint": "Allow KOReader devices to sync progress, reading activity, highlights, and annotation deletes with BookOrbit.", - "lastSync": "Last sync", - "syncedBooks": "Synced books", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "devices": "Devices", - "deviceCount": "{count, plural, =0 {no devices} one {# device} other {# devices}}", - "credentialsCreatedLabel": "Credentials created", - "setup": "Setup", - "pluginServerUrl": "Plugin server URL", - "copied": "Copied", - "copyUrl": "Copy URL", - "preconfiguredPlugin": "Preconfigured BookOrbit plugin", - "preconfiguredPluginHintPrefix": "Download a zip with the server URL and your sync login already configured. The plugin includes catalog browsing and sync. Copy the folder to", - "preconfiguredPluginHintSuffix": "and restart KOReader.", - "latestPluginNote": "{label}. Device updates run from the BookOrbit menu in KOReader.", - "preparing": "Preparing...", - "downloadPlugin": "Download Plugin", - "noDevicesSynced": "No devices have synced yet", - "noDevicesSyncedHint": "Install the BookOrbit plugin for full sync, or configure KOReader's stock progress sync for progress-only updates.", - "lastSyncLabel": "Last sync:", - "lastBookLabel": "Last book:", - "noneYet": "None yet", - "pluginActivity": "Plugin Activity", - "noPluginActivity": "No plugin activity has been reported yet.", - "lastFullSync": "Last full sync: {time}", - "latestPluginSuffix": "- latest plugin v{version}", - "matchedBooks": "Matched books", - "readingEvents": "Reading events", - "highlights": "Highlights", - "syncedTotals": "Synced totals", - "trashedHighlights": "Trashed highlights", - "pendingDeletes": "{count, plural, =0 {no deleted highlights awaiting KOReader plugin acknowledgement.} one {# deleted highlight awaiting KOReader plugin acknowledgement.} other {# deleted highlights awaiting KOReader plugin acknowledgement.}}", - "failedPositions": "{count, plural, =0 {no highlight positions need attention.} one {# highlight position needs attention.} other {# highlight positions need attention.}}", - "setupGuide": "Setup Guide", - "setupSteps": "KOReader setup steps", - "setupStepsHint": "Use the BookOrbit plugin for catalog browsing, downloads, progress, reading events, and highlights. Use the stock plugin for progress only.", - "pluginGuideTitle": "BookOrbit plugin", - "pluginStep1": "Download the preconfigured plugin above.", - "pluginStep2Prefix": "Unzip it and copy", - "pluginStep2Middle": "to", - "pluginStep2Suffix": "on your device.", - "pluginStep3": "Restart KOReader. The server and login are configured automatically.", - "pluginStep4Prefix": "Open", - "pluginStep4Suffix": "to search, download, and link books to sync.", - "stockGuideTitle": "Stock progress sync plugin", - "stockStep1Prefix": "On your KOReader device, go to", - "stockStep1Suffix": ".", - "stockStep2": "Set the custom sync server to the URL shown above.", - "stockStep3": "Enter the username and password you created, then tap Login.", - "locationNote": "BookOrbit saves KOReader-compatible EPUB locations from the web reader. Restore should land close to the same position, though exact line placement can vary by reader and EPUB layout.", - "dangerZone": "Danger Zone", - "deleteCredentials": "Delete KOReader credentials", - "deleteCredentialsHint": "Remove sync credentials and disconnect all devices. Progress data will be retained.", - "credentialsDeleted": "KOReader credentials deleted", - "deleteCredentialsFailed": "Failed to delete credentials", - "deleteConfirmTitle": "Delete KOReader credentials?", - "deleteConfirmBody": "This will remove your sync credentials and disconnect all KOReader devices. Existing progress data will be kept.", - "syncEnabled": "KOReader sync enabled", - "syncDisabled": "KOReader sync disabled", - "toggleSyncFailed": "Failed to toggle sync", - "syncUrlCopied": "Sync URL copied to clipboard", - "syncUrlCopyFailed": "Failed to copy sync URL", - "statusRefreshed": "Sync status refreshed", - "refreshFailed": "Failed to refresh", - "pluginDownloaded": "Plugin downloaded. Copy bookorbit.koplugin from the zip to koreader/plugins/ on your device.", - "pluginDownloadFailed": "Failed to download the plugin", - "hashLinks": { - "unmatchedTitle": "Unmatched KOReader Books", - "unmatchedBooks": "Unmatched books", - "manualTitle": "Manual KOReader Links", - "refresh": "Refresh", - "link": "Link", - "change": "Change", - "unlink": "Unlink", - "hash": "Hash:", - "lastOpened": "Last opened:", - "firstSeen": "First seen:", - "lastSeen": "Last seen:", - "linked": "Linked:", - "updated": "Updated:", - "linkedTo": "Linked to {title}", - "loadingUnmatched": "Loading unmatched books...", - "loadingManual": "Loading manual hash links...", - "noUnmatched": "No unmatched KOReader books.", - "noManual": "No manual KOReader links.", - "pageOf": "Page {page} of {total}", - "showingRange": "Showing {start}-{end} of {total}", - "unknownFile": "Unknown KOReader file {hash}", - "unknownAuthor": "Unknown author", - "noTitleOrAuthor": "No title or author reported", - "bookNumber": "BookOrbit book #{id}", - "toast": { - "unmatchedRefreshed": "Unmatched books refreshed", - "unmatchedRefreshFailed": "Failed to refresh unmatched books", - "manualRefreshed": "Manual hash links refreshed", - "manualRefreshFailed": "Failed to refresh manual hash links", - "bookLinked": "Book linked", - "linkUpdated": "Link updated", - "linkFailed": "Failed to link book", - "linkRemoved": "Link removed", - "unlinkFailed": "Failed to unlink book", - "unmatchedDismissed": "Unmatched book dismissed", - "dismissFailed": "Failed to dismiss unmatched book", - "allDismissed": "{count, plural, =0 {Dismissed no unmatched books} one {Dismissed # unmatched book} other {Dismissed # unmatched books}}", - "dismissAllFailed": "Failed to dismiss all unmatched books" - }, - "modal": { - "linkTitle": "Link KOReader book", - "changeTitle": "Change KOReader link", - "bookOrbitBook": "BookOrbit book", - "searchPlaceholder": "Search your BookOrbit library", - "minChars": "Enter at least 2 characters.", - "searching": "Searching...", - "noBooksFound": "No books found.", - "untitledBook": "Untitled book", - "selected": "Selected", - "select": "Select", - "loadMore": "Load more", - "confirmTitle": "Confirm KOReader link", - "koreader": "KOReader", - "bookOrbit": "BookOrbit", - "bookId": "Book ID: {id}", - "syncedStatsNote": "Already synced stats will stay on their current BookOrbit book.", - "chooseDifferent": "Choose different", - "saving": "Saving...", - "confirmLink": "Confirm link", - "unlinkTitle": "Unlink KOReader book?", - "unlinkBody": "Future syncs for this hash will stop resolving to {title} until it is linked again. Already synced stats will stay on their current BookOrbit book.", - "unlinking": "Unlinking..." - }, - "dismiss": "Dismiss", - "dismissAll": "Dismiss all", - "dismissing": "Dismissing...", - "unlinking": "Unlinking...", - "unlinkConfirmTitle": "Unlink KOReader book?", - "unlinkConfirmBody": "Future syncs for this hash will stop resolving to {title} until it is linked again. Already synced stats will stay on their current BookOrbit book.", - "dismissConfirmTitle": "Dismiss {title}?", - "dismissConfirmBody": "This removes it from your unmatched books list. If any device reports this hash again, it will reappear as a new entry.", - "dismissAllConfirmTitle": "{count, plural, =0 {no unmatched books} one {Dismiss all # unmatched book?} other {Dismiss all # unmatched books?}}", - "dismissAllConfirmBody": "This clears your entire unmatched books list, not just the current page. If any device reports one of these hashes again, it will reappear as a new entry.", - "changeLinkTitle": "Change KOReader link", - "linkBookTitle": "Link KOReader book", - "bookOrbitBook": "BookOrbit book", - "searchLibraryPlaceholder": "Search your BookOrbit library", - "enterMinChars": "Enter at least 2 characters.", - "searching": "Searching...", - "noBooksFound": "No books found.", - "untitledBook": "Untitled book", - "selected": "Selected", - "select": "Select", - "loadMore": "Load more", - "loadingMore": "Loading...", - "confirmLinkTitle": "Confirm KOReader link", - "bookId": "Book ID: {id}", - "syncedStatsNote": "Already synced stats will stay on their current BookOrbit book.", - "chooseDifferent": "Choose different", - "saving": "Saving...", - "confirmLink": "Confirm link" - }, - "remove": "Remove", - "removing": "Removing...", - "unmatchedBooks": "Unmatched books", - "deviceRemoved": "Device removed", - "removeDeviceFailed": "Failed to remove device", - "removeDeviceConfirmTitle": "Remove {device}?", - "removeDeviceConfirmBody": "This permanently deletes this device's synced progress, reading activity, and any unmatched-book entries no longer reported by another device. If the device syncs again later, it will reappear as a new entry." - }, - "opds": { - "title": "OPDS", - "subtitle": "Connect OPDS-compatible reading apps like KOReader or Thorium Reader to your library.", - "copy": "Copy", - "loadFailed": "Failed to load", - "server": "Server", - "catalogServer": "OPDS Catalog Server", - "catalogServerHint": "Allow OPDS clients to browse and download books", - "endpoint": "Endpoint", - "accounts": "OPDS Accounts", - "add": "Add", - "addAccount": "Add account", - "username": "Username", - "usernameLabel": "Username", - "usernamePlaceholder": "e.g. koreader", - "password": "Password", - "passwordPlaceholder": "Min 8 characters", - "defaultSort": "Default Sort", - "sortLabel": "Sort", - "creating": "Creating...", - "create": "Create", - "noAccounts": "No OPDS accounts yet. Create one to start using OPDS clients.", - "hideDetails": "Hide details", - "showDetails": "Show details", - "copyUsername": "Copy username", - "notes": "OPDS Notes", - "notesBody": "Use OPDS accounts in reader apps. Keep credentials private and rotate passwords if shared accidentally.", - "deleteConfirmTitle": "Delete OPDS account?", - "deleteConfirmBody": "Delete \"{username}\". This action cannot be undone.", - "sortRecent": "Recently Added", - "sortTitleAsc": "Title (A-Z)", - "sortTitleDesc": "Title (Z-A)", - "sortAuthorAsc": "Author (A-Z)", - "sortAuthorDesc": "Author (Z-A)", - "sortSeriesAsc": "Series (A-Z)", - "sortSeriesDesc": "Series (Z-A)", - "serverEnabled": "OPDS server enabled", - "serverDisabled": "OPDS server disabled", - "updateSettingsFailed": "Failed to update OPDS settings", - "urlCopied": "OPDS URL copied to clipboard", - "urlCopyFailed": "Failed to copy OPDS URL", - "createUserFailed": "Failed to create OPDS user", - "userCreated": "OPDS user \"{username}\" created", - "sortOrderUpdated": "Sort order updated for \"{username}\"", - "updateSortFailed": "Failed to update sort order", - "userDeleted": "OPDS user \"{username}\" deleted", - "deleteUserFailed": "Failed to delete OPDS user", - "labelCopied": "{label} copied", - "copyLabelFailed": "Failed to copy {label}" - }, - "tabs": { - "general": "General", - "ebook": "eBook", - "pdf": "PDF", - "comics": "Comics", - "audio": "Audiobook", - "fonts": "Fonts" - } - }, - "system": { - "tabs": { - "file-naming": "File Naming", - "book-dock": "Book Dock", - "maintenance": "Maintenance", - "audit-log": "Audit Log" - } - } - }, - "achievements": { - "title": "Achievements", - "tiersCount": "{earned} / {total} tiers", - "loadFailed": "Failed to load achievements", - "tryAgain": "Try again", - "noMatchFilter": "No achievements match this filter", - "secretAchievement": "Secret Achievement", - "earnedOn": "Earned {date}", - "whileReading": "While reading “{title}”", - "tierProgress": "Tier {earned} of {total}", - "progressToNext": "{current} / {threshold} to {name}", - "rarity": { - "common": "Common", - "rare": "Rare", - "epic": "Epic", - "legendary": "Legendary" - }, - "filter": { - "all": "All", - "earned": "Earned ({count})", - "inProgress": "In Progress ({count})", - "locked": "Locked ({count})" - } - }, - "adminFeature": { - "accountActivity": { - "title": "Account Activity", - "subtitle": "Review account authentication activity without exposing reading history.", - "privacyNotice": "This page reports sign-ins and authentication refreshes only. It does not use reading history, book progress, or library activity.", - "privacyLabel": "About account activity privacy", - "never": "Never", - "openInsightsFor": "Open shared reading insights for {name}", - "permissionLabel": "View user activity", - "states": { - "recent": "Recently active", - "dormant": "Dormant", - "never": "No recorded activity", - "disabled": "Disabled" - }, - "filters": { - "search": "Search accounts", - "searchPlaceholder": "Search name or username", - "state": "Activity state", - "allStates": "All activity states", - "provisioning": "Authentication method", - "allMethods": "All authentication methods", - "sort": "Sort accounts", - "mostRecent": "Most recently active", - "leastRecent": "Least recently active", - "lastLogin": "Most recent login", - "newest": "Newest accounts", - "oldest": "Oldest accounts", - "name": "Name", - "apply": "Apply", - "clear": "Clear" - }, - "methods": { - "local": "Local", - "manual": "Administrator-created", - "oidc": "OIDC / SSO", - "shared": "Shared magic link" - }, - "columns": { - "user": "User", - "state": "Account state", - "lastLogin": "Last login", - "lastAuthenticated": "Last authenticated", - "created": "Created", - "readingInsights": "Reading insights" - }, - "sharing": { - "private": "Not shared", - "summary": "Summary shared", - "detailed": "Detailed shared" - }, - "empty": { - "title": "No accounts found", - "description": "Try changing or clearing the current filters." - }, - "pagination": { - "label": "Account activity pages", - "page": "Page {page} of {totalPages}" - }, - "errors": { - "load": "Failed to load account activity." - } - }, - "sharedInsights": { - "title": "Shared reading insights", - "subtitle": "Reading information this user voluntarily chose to share.", - "auditNotice": "Access to this profile is recorded and visible to the user.", - "period": "Reporting period", - "periodDays": "Last {count} days", - "durationMinutes": "{count, plural, one {# minute} other {# minutes}}", - "durationHours": "{count, plural, one {# hour} other {# hours}}", - "metrics": { - "sessions": "Sessions", - "readingTime": "Reading time", - "activeDays": "Active days", - "started": "Books started", - "completed": "Books completed" - }, - "trend": "Daily reading trend", - "emptyTitle": "No reading activity in this period", - "noData": "No recorded reading data for this period.", - "sourceNames": { - "web": "Web reader", - "koreader": "KOReader", - "manual": "Manual", - "kobo": "Kobo", - "unknown": "Unknown" - }, - "formats": "Formats", - "genres": "Genres", - "broadGenres": { - "science_fiction": "Science fiction", - "fantasy": "Fantasy", - "mystery_thriller": "Mystery & thriller", - "romance": "Romance", - "horror": "Horror", - "history_biography": "History & biography", - "science_technology": "Science & technology", - "business_economics": "Business & economics", - "self_development": "Self-development", - "society_culture": "Society & culture", - "children_young_adult": "Children & young adult", - "comics_graphic_novels": "Comics & graphic novels", - "poetry": "Poetry", - "other": "Other" - }, - "sources": "Data sources", - "topBooks": "Most-read books", - "recentBooks": "Recently read", - "unknownTitle": "Untitled book", - "top": { - "authors": "Top authors", - "genres": "Top genres", - "series": "Top series", - "narrators": "Top narrators" - }, - "errors": { - "READING_INSIGHTS_PRIVATE": "This user is not sharing reading insights.", - "READING_INSIGHTS_SUMMARY_ONLY": "This user shares summary insights only.", - "READING_INSIGHTS_VIEW_SESSION_REQUIRED": "A profile view session is required.", - "READING_INSIGHTS_VIEW_SESSION_INVALID": "This profile view expired or is no longer valid.", - "LOAD_FAILED": "Shared reading insights could not be loaded.", - "cleared": "No previously loaded profile information is being displayed." - } - }, - "resetLink": { - "title": "Password Reset Link", - "description": "Share this link with the user. It expires in 15 minutes.", - "copy": "Copy", - "copied": "Copied!", - "copyFailed": "Copy failed", - "notShownAgain": "This link will not be shown again." - }, - "userForm": { - "editUser": "Edit User", - "createUser": "Create User", - "createSharedAccount": "Create Shared Account", - "sharedBadge": "Shared", - "active": "Active", - "suspended": "Suspended", - "tabs": { - "general": "general", - "access": "access", - "restrictions": "restrictions" - }, - "sharedAccount": "Shared account", - "sharedAccountHint": "No password. Access is granted via magic links only.", - "sharedAccountManageHint": "Manage login links from Settings - Magic Links.", - "username": "Username", - "fullName": "Full name", - "email": "Email", - "optional": "(optional)", - "libraryAccess": "Library Access", - "noLibrariesSelected": "No libraries selected. User cannot view any books.", - "permissions": "Permissions", - "presetStandard": "Standard", - "presetAdmin": "Admin", - "presetClearAll": "Clear All", - "permissionGroups": { - "content": "Content", - "devicesAccess": "Devices & Access", - "email": "Email", - "administration": "Administration", - "notifications": "Notifications", - "restrictions": "Restrictions" - }, - "superuserTarget": "Superuser Target", - "superuserTargetHint": "Content restrictions cannot be applied to superusers.", - "noRestrictions": "No content restrictions", - "noRestrictionsHint": "This user has full access to all books in their assigned libraries.", - "addRestrictions": "+ Add Content Restrictions", - "contentRestrictions": "Content Restrictions", - "remove": "Remove", - "includeTags": "Include tags", - "includeTagsHint": "(show only books with these tags)", - "excludeTags": "Exclude tags", - "excludeTagsHint": "(hide books with these tags)", - "includeGenres": "Include genres", - "includeGenresHint": "(show only books with these genres)", - "excludeGenres": "Exclude genres", - "excludeGenresHint": "(hide books with these genres)", - "searchTagsPlaceholder": "Search tags...", - "searchGenresPlaceholder": "Search genres...", - "saving": "Saving...", - "errors": { - "updateUser": "Failed to update user", - "updatePermissions": "Failed to update permissions", - "updateLibraryAccess": "Failed to update library access", - "updateContentFilters": "Failed to update content filters", - "emailRequired": "Email is required", - "createSharedAccount": "Failed to create shared account", - "createUser": "Failed to create user" - } - }, - "usersPage": { - "usersTitle": "Users", - "usersSubtitle": "Manage user accounts and permission assignments.", - "createUser": "Create user", - "columns": { - "name": "Name", - "username": "Username", - "email": "Email", - "access": "Access", - "status": "Status", - "actions": "Actions" - }, - "adminBadge": "Admin", - "permissionCount": "{count, plural, =0 {no permissions} one {one permission} other {# permissions}}", - "filteredBadge": "Filtered", - "contentRestrictionsActive": "Content restrictions active", - "statusActive": "Active", - "statusInactive": "Inactive", - "resetPassword": "Reset password", - "resetPasswordOidcHint": "OIDC users reset passwords in their identity provider", - "resetPasswordSharedHint": "Shared accounts do not have passwords", - "resetPasswordOidcHintFull": "OIDC users reset passwords in their identity provider.", - "resetPasswordSharedHintFull": "Shared accounts do not have passwords.", - "deleteUserAction": "Delete user", - "deleteDialogTitle": "Delete user?", - "deleteDialogBody": "Delete user \"{username}\". This action cannot be undone.", - "deleting": "Deleting...", - "errors": { - "load": "Failed to load", - "deleteUser": "Failed to delete user", - "resetPassword": "Failed to create a password reset link" - }, - "defaultLibraryAccess": { - "title": "Default Library Access", - "subtitle": "Viewer access granted to self-registered and OIDC-provisioned users.", - "description": "Select the libraries assigned automatically to new users.", - "noLibraries": "No libraries available.", - "save": "Save defaults", - "saving": "Saving...", - "saveError": "Failed to save default library access" - }, - "filters": { - "search": "Search users", - "searchPlaceholder": "Search by name, username or email", - "sort": "Sort users", - "usernameAsc": "Username A-Z", - "nameAsc": "Name A-Z", - "newest": "Newest first", - "oldest": "Oldest first", - "apply": "Apply", - "clear": "Clear", - "state": "Filter users", - "allUsers": "All users", - "admins": "Administrators", - "active": "Active", - "inactive": "Inactive" - }, - "empty": { - "title": "No users yet", - "description": "Create the first account to get started.", - "filtered": "No users match the current search and filters." - }, - "pagination": { - "label": "Users pagination", - "page": "Page {page} of {totalPages}" - }, - "editUserAria": "Edit {name}", - "resetPasswordAria": "Reset the password for {name}", - "deleteUserAria": "Delete {name}", - "moreActionsAria": "More actions for {name}" - } - }, - "annotations": { - "unknownBook": "Unknown book", - "styles": { - "highlight": "Highlight", - "underline": "Underline", - "strike": "Strike", - "squiggle": "Squiggle", - "invert": "Invert" - }, - "combobox": { - "filterByBook": "Filter by book", - "allBooks": "All books", - "clearBookFilter": "Clear book filter", - "searching": "Searching...", - "noBooksFound": "No books found" - }, - "bulk": { - "countSelected": "{count, plural, one {# selected} other {# selected}}", - "pageSelected": "Page selected", - "selectPage": "Select page", - "clear": "Clear", - "recolorTo": "Recolor to {color}", - "restyleTo": "Restyle to {style}" - }, - "chips": { - "active": "Active:", - "removeFilter": "Remove filter {label}", - "clearAll": "Clear all" - }, - "filters": { - "colors": "Colors", - "dateRange": "Date range", - "fromDate": "From date", - "toDate": "To date", - "to": "to", - "clearDateRange": "Clear date range", - "clearAll": "Clear all" - }, - "pagination": { - "showing": "Showing {start}-{end} of {total}", - "pageOf": "Page {page} of {totalPages}", - "firstPage": "First page", - "previousPage": "Previous page", - "nextPage": "Next page", - "lastPage": "Last page" - }, - "sync": { - "loading": "Loading sync detail", - "positions": "Positions", - "devices": "Devices", - "retryConversion": "Retry conversion", - "noStoredPositions": "No stored positions.", - "notSynced": "Not synced to any device yet.", - "upToDate": "Up to date", - "pendingVersion": "Pending v{version}", - "syncedAt": "synced {date}", - "format": { - "webReader": "Web reader", - "koreader": "KOReader", - "pdf": "PDF", - "kobo": "Kobo" - }, - "status": { - "exact": "Exact", - "repaired": "Repaired", - "failed": "Failed", - "pending": "Pending" - } - }, - "toolbar": { - "searchPlaceholder": "Search text and notes", - "filters": "Filters", - "sortOrder": "Sort order", - "switchToCompact": "Switch to compact view", - "switchToComfortable": "Switch to comfortable view", - "compactView": "Compact view", - "comfortableView": "Comfortable view" - }, - "listItem": { - "pageNumber": "p. {page}", - "chapterNumber": "chapter {chapter}", - "selectAnnotation": "Select annotation", - "collapse": "Collapse", - "expand": "Expand", - "hideSyncDetail": "Hide sync detail", - "showSyncDetail": "Show sync detail", - "exactPositionUnavailable": "Exact reader position unavailable", - "saving": "Saving", - "bookDetails": "Book details", - "openInReader": "Open in reader", - "restore": "Restore", - "deleteForever": "Delete forever", - "editNote": "Edit note", - "addNote": "Add note", - "colorAndStyle": "Color and style", - "copied": "Copied", - "copyText": "Copy text", - "trash": "Trash", - "moveToTrash": "Move to trash" - }, - "hub": { - "title": "Annotations", - "totalCount": "{count} total", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "noteCount": "{count, plural, =0 {no notes} one {# note} other {# notes}}", - "export": "Export", - "exportMarkdown": "Markdown", - "exportCsv": "CSV", - "exportJson": "JSON", - "notesOnly": "Notes only", - "style": "Style", - "source": "Source", - "bulkTrash": "Trash", - "bulkRestore": "Restore", - "tabs": { - "highlights": "Highlights", - "trash": "Trash" - }, - "empty": { - "noMatch": "No highlights match your filters.", - "resetFilters": "Reset filters", - "trashEmpty": "Trash is empty", - "noAnnotations": "No annotations yet. Highlights you create on the web or your e-reader appear here." - }, - "toast": { - "movedToTrash": "Moved to trash", - "annotationRestored": "Annotation restored", - "annotationDeletedForever": "Annotation deleted forever", - "failedToDelete": "Failed to delete", - "bulkTrashed": "{count, plural, =0 {Moved no annotations to trash} one {Moved # annotation to trash} other {Moved # annotations to trash}}", - "bulkRestored": "{count, plural, =0 {Restored no annotations} one {Restored # annotation} other {Restored # annotations}}", - "bulkRecolored": "{count, plural, =0 {Recolored no annotations} one {Recolored # annotation} other {Recolored # annotations}}", - "bulkRestyled": "{count, plural, =0 {Restyled no annotations} one {Restyled # annotation} other {Restyled # annotations}}" - } - } - }, - "audit": { - "pageTitle": "Audit Log", - "pageSubtitle": "A record of admin-significant actions performed across the system.", - "filters": "Filters", - "noActiveFilters": "No active filters", - "clear": "Clear", - "empty": "No audit logs found", - "showMore": "Show more", - "showLess": "Show less", - "details": "Details", - "hideDetails": "Hide details", - "refresh": "Refresh audit log", - "loadError": "Could not load audit events.", - "removeFilter": "Remove filter: {value}", - "allActions": "All actions", - "allEventTypes": "All event types", - "allActors": "All actors", - "noActionsFound": "No matching actions", - "noActorsFound": "No matching actors", - "noResourcesFound": "No matching target types", - "unknownAction": "Unknown action", - "unknownResource": "Other target type", - "allResources": "All resources", - "allTargetTypes": "All target types", - "quickDates": "Quick dates", - "today": "Today", - "sevenDays": "7 days", - "thirtyDays": "30 days", - "userId": "User #{id}", - "userIdCompact": "#{id}", - "targetAdditional": "and {count, plural, one {# more target} other {# more targets}}", - "bookImpact": "{count, plural, one {# book} other {# books}}", - "entryDetailsLabel": "Details for audit event #{id}", - "detailEventId": "Event ID", - "detailOccurredAt": "Occurred", - "detailActor": "Actor", - "detailCategory": "Category", - "detailActionLabel": "Action", - "detailEventTypeLabel": "Event type", - "detailIpLabel": "IP address", - "detailResourceLabel": "Resource", - "detailResourceIdLabel": "Resource ID", - "detailTargetTypeLabel": "Target type", - "detailTargetIdLabel": "Target ID", - "detailAction": "Action: {value}", - "detailIp": "IP: {value}", - "detailResource": "Resource: {value}", - "detailResourceId": "Resource ID: {value}", - "deletedBooks": "Deleted books", - "deletedBookDetail": "{title} (book #{id})", - "untitledBook": "Untitled", - "deletedBooksOmitted": "{count, plural, one {# additional book omitted} other {# additional books omitted}}", - "showing": "Showing {from}-{to} of {total}", - "prev": "Prev", - "chips": { - "search": "Search: {value}", - "action": "Action: {value}", - "eventType": "Event type: {value}", - "actor": "Actor: {value}", - "resource": "Resource: {value}", - "targetType": "Target type: {value}", - "user": "User: {value}", - "from": "From: {value}", - "to": "To: {value}" - }, - "filterLabels": { - "search": "Search events", - "action": "Action", - "eventType": "Event type (what happened)", - "actor": "Actor", - "resource": "Resource", - "targetType": "Target type (what was affected)", - "userId": "User ID", - "from": "From", - "to": "To" - }, - "filterPlaceholders": { - "search": "Description, actor, target, or ID", - "actor": "Username", - "action": "e.g. auth.login", - "userId": "e.g. 1" - }, - "columns": { - "when": "When", - "actor": "Actor", - "event": "Event", - "target": "Target", - "impact": "Impact", - "user": "User", - "action": "Action", - "description": "Description", - "ip": "IP" - }, - "categories": { - "authentication": "Authentication", - "books": "Books", - "users": "Users", - "libraries": "Libraries", - "collections": "Collections", - "integrations": "Integrations", - "settings": "Settings", - "other": "Other" - }, - "resourceLabels": { - "User": "User", - "Library": "Library", - "Book": "Book", - "Collection": "Collection", - "SmartScope": "Smart scope", - "BookDockFile": "Book Dock file", - "Author": "Author", - "AppSettings": "Application settings", - "Genre": "Genre", - "Tag": "Tag", - "KoboDevice": "Kobo device", - "EmailProvider": "Email provider", - "EmailTemplate": "Email template", - "EmailRecipient": "Email recipient", - "EmailRecipientGroup": "Email recipient group", - "Narrator": "Narrator", - "Publisher": "Publisher", - "Language": "Language", - "Series": "Series", - "OidcIdentity": "OIDC identity", - "MagicLinkToken": "Magic link", - "ReadingInsightsProfile": "Reading insights profile" - }, - "actionLabels": { - "AuthRegister": "Register account", - "AuthLogin": "Sign in", - "AuthLoginFailed": "Failed sign-in", - "AuthLogout": "Sign out", - "AuthPasswordChange": "Change password", - "AuthPasswordResetRequest": "Request password reset", - "AuthPasswordReset": "Reset password", - "AuthPasswordAdminReset": "Reset user password", - "AuthSessionRevoke": "Revoke session", - "MagicLinkCreate": "Create magic link", - "MagicLinkLogin": "Sign in with magic link", - "MagicLinkRevoke": "Revoke magic link", - "MagicLinkActivate": "Activate magic link", - "MagicLinkDeactivate": "Deactivate magic link", - "OidcLogin": "Sign in with OIDC", - "OidcUserProvisioned": "Provision OIDC user", - "OidcIdentityLinked": "Link OIDC identity", - "OidcIdentityUnlinked": "Unlink OIDC identity", - "UserCreate": "Create user", - "UserUpdate": "Update user", - "UserSelfUpdate": "Update own profile", - "UserDelete": "Delete user", - "UserPermissionSet": "Update user permissions", - "UserSuperuserEnable": "Enable superuser access", - "UserSuperuserDisable": "Disable superuser access", - "UserContentFiltersSet": "Update content filters", - "ReadingInsightsSharingUpdate": "Update insight sharing", - "ReadingInsightsProfileView": "View shared insights", - "LibraryCreate": "Create library", - "LibraryUpdate": "Update library", - "LibraryDelete": "Delete library", - "LibraryFolderAdd": "Add library folder", - "LibraryFolderRemove": "Remove library folder", - "LibraryAccessGrant": "Grant library access", - "LibraryAccessUpdate": "Update library access", - "LibraryAccessRevoke": "Revoke library access", - "LibraryWriteMetadataToFiles": "Write metadata to files", - "LibraryBulkRename": "Rename library files", - "BookUpload": "Upload book", - "BookMetadataUpdate": "Update book metadata", - "BookMetadataLocksUpdate": "Update metadata locks", - "BookDelete": "Delete book", - "BookBulkMetadataRefresh": "Refresh book metadata", - "BookBulkDelete": "Delete books", - "BookBulkCoverReextract": "Re-extract book covers", - "BookBulkSetStatus": "Set book status", - "BookBulkSetRating": "Set book rating", - "BookBulkSetMetadata": "Set book metadata", - "BookBulkUpdateTags": "Update book tags", - "BookBulkSetMetadataLock": "Set metadata locks", - "BookBulkEditMetadata": "Edit book metadata", - "BookReadingStateReset": "Reset reading state", - "BookWriteAndRename": "Write metadata and rename file", - "CollectionCreate": "Create collection", - "CollectionUpdate": "Update collection", - "CollectionDelete": "Delete collection", - "CollectionBooksAdd": "Add books to collection", - "CollectionBooksRemove": "Remove books from collection", - "SmartScopeCreate": "Create smart scope", - "SmartScopeUpdate": "Update smart scope", - "SmartScopeDelete": "Delete smart scope", - "BookDockFinalize": "Finalize Book Dock file", - "AuthorUpdate": "Update author", - "AuthorDelete": "Delete author", - "AuthorMerge": "Merge authors", - "AuthorEnrichmentConfigUpdate": "Update author enrichment", - "AuthorEnrichmentPause": "Pause author enrichment", - "AuthorEnrichmentResume": "Resume author enrichment", - "AuthorEnrichmentCancel": "Cancel author enrichment", - "EntityManagerMerge": "Merge entities", - "EntityManagerRename": "Rename entity", - "EntityManagerDelete": "Delete entity", - "EntityManagerSplit": "Split entity", - "EntityManagerDismiss": "Dismiss duplicate", - "EntityManagerUndismiss": "Restore dismissed duplicate", - "AppSettingsUpdate": "Update app settings", - "KoboDeviceRegister": "Register Kobo device", - "KoboDeviceRename": "Rename Kobo device", - "KoboDeviceRemove": "Remove Kobo device", - "EmailProviderCreate": "Create email provider", - "EmailProviderUpdate": "Update email provider", - "EmailProviderDelete": "Delete email provider", - "EmailProviderSetDefault": "Set default email provider", - "EmailProviderSetSystem": "Set system email provider", - "EmailProviderClearSystem": "Clear system email provider", - "EmailTemplateCreate": "Create email template", - "EmailTemplateUpdate": "Update email template", - "EmailTemplateDelete": "Delete email template", - "EmailTemplateSetDefault": "Set default email template", - "EmailRecipientCreate": "Create email recipient", - "EmailRecipientUpdate": "Update email recipient", - "EmailRecipientDelete": "Delete email recipient", - "EmailRecipientGroupCreate": "Create recipient group", - "EmailRecipientGroupUpdate": "Update recipient group", - "EmailRecipientGroupDelete": "Delete recipient group", - "EmailRecipientGroupMemberAdd": "Add recipient to group", - "EmailRecipientGroupMemberRemove": "Remove recipient from group" - } - }, - "auth": { - "backToSignIn": "Back to sign in", - "themePicker": { - "switchToLight": "Switch to light", - "switchToDark": "Switch to dark", - "changeRadius": "Change corner radius", - "changeBackground": "Change background", - "changeAccent": "Change accent color" - }, - "fields": { - "username": "Username", - "password": "Password", - "email": "Email", - "emailAddress": "Email address", - "fullName": "Full name", - "newPassword": "New password", - "confirmPassword": "Confirm password", - "confirmNewPassword": "Confirm new password", - "currentPassword": "Current password", - "passwordHint": "Min. 8 characters with uppercase, lowercase, and a digit" - }, - "errors": { - "generic": "Something went wrong. Please try again.", - "passwordsDoNotMatch": "Passwords do not match" - }, - "login": { - "subtitle": "Sign in to your account", - "signIn": "Sign in", - "signingIn": "Signing in...", - "orDivider": "or", - "forgotPassword": "Forgot password?", - "errors": { - "invalidCredentials": "Invalid username or password", - "tooManyAttempts": "Too many login attempts. Please wait a minute and try again." - } - }, - "oidc": { - "loginFailed": "OIDC login failed", - "redirecting": "Redirecting...", - "signInWith": "Sign in with {provider}", - "completingSignIn": "Completing sign in...", - "tryAgain": "Try again", - "errors": { - "stateExpired": "Your login session expired. Please try signing in again.", - "tokenExchangeFailed": "Could not complete sign-in with your provider. Please try again or contact your administrator.", - "userNotProvisioned": "Your account has not been set up. Contact your administrator for access.", - "userInactive": "Your account has been deactivated. Contact your administrator.", - "providerError": "Your identity provider returned an error. Please try again.", - "missingCodeOrState": "Missing code or state parameter" - }, - "providerErrors": { - "accessDenied": "Access was denied by the identity provider.", - "loginRequired": "Authentication is required. Please sign in again.", - "interactionRequired": "Additional user interaction is required." - } - }, - "forgotPassword": { - "subtitle": "Reset your password", - "submitted": "If an account with that email exists, a reset link has been sent. Check your inbox.", - "sending": "Sending...", - "sendResetLink": "Send reset link", - "errors": { - "emailUnavailable": "Password reset via email is not available. Contact your administrator." - } - }, - "resetPassword": { - "subtitle": "Set a new password", - "saving": "Saving...", - "setNewPassword": "Set new password", - "errors": { - "invalidLink": "Invalid reset link. Please request a new one.", - "invalidOrExpired": "Invalid or expired reset link. Please request a new one." - } - }, - "setup": { - "title": "Initial setup", - "subtitle": "Create the first administrator account.", - "setupToken": "Setup token", - "setupTokenHint": "(required in production)", - "creatingAccount": "Creating account...", - "createAccount": "Create administrator account", - "errors": { - "failed": "Failed to complete setup" - } - }, - "changePassword": { - "title": "Change password", - "saving": "Saving…", - "forcedNotice": "You must set a new password before continuing.", - "errors": { - "failed": "Failed to change password" - } - }, - "magicLink": { - "signingIn": "Signing you in...", - "loginFailed": "Login failed", - "goToLogin": "Go to login", - "errors": { - "noToken": "No token provided" - } - } - }, - "author": { - "card": { - "portraitAlt": "{name} portrait", - "viewDetails": "View Author Details", - "refreshMetadata": "Refresh Metadata", - "deleteAuthor": "Delete Author" - }, - "listRow": { - "noRecentAdditions": "No recent additions", - "portraitAlt": "{name} portrait" - }, - "filters": { - "title": "Author Filters", - "clearAll": "Clear all", - "allLibraries": "All Libraries", - "allAuthors": "All authors", - "hasPhoto": "Has photo", - "missingPhoto": "Missing photo", - "minBooks": "Min books", - "anyPlaceholder": "Any" - }, - "header": { - "never": "Never", - "portraitAlt": "{name} portrait", - "actions": "Actions", - "editAuthor": "Edit Author", - "mergeAuthors": "Merge Authors", - "refreshing": "Refreshing...", - "refreshMetadata": "Refresh Metadata", - "deleteAuthor": "Delete Author", - "showLess": "Show less", - "showMore": "Show more", - "lookingUpMetadata": "Looking up author metadata...", - "noBiography": "No biography available. Use the menu to refresh metadata.", - "previewFrom": "Preview from {provider}. Save metadata to persist it.", - "booksLabel": "Books", - "lastAdded": "Last Added" - }, - "list": { - "title": "Authors", - "showControlsAria": "Show author controls", - "searchPlaceholder": "Search authors", - "sortButton": "Sort", - "sortBy": "Sort by", - "ascending": "Ascending", - "descending": "Descending", - "asc": "Asc", - "desc": "Desc", - "filters": "Filters", - "clear": "Clear", - "allLoaded": "All {total} authors loaded", - "sort": { - "name": "Name", - "sortName": "Sort Name", - "bookCount": "Book Count", - "recentAdditions": "Recent Additions", - "lastEnriched": "Last Enriched" - }, - "empty": { - "title": "No authors found", - "hint": "Try changing search text, sort, or library filter." - }, - "deleteDialog": { - "titleOne": "Delete author?", - "titleMany": "Delete {count} authors?", - "descriptionOne": "This removes the author from the catalog and unlinks it from associated books. This action cannot be undone.", - "descriptionMany": "This removes selected authors from the catalog and unlinks them from associated books. This action cannot be undone." - }, - "selection": { - "selectVisible": "Select visible", - "refreshMetadata": "Refresh metadata", - "refreshingMetadata": "Refreshing metadata...", - "deleteSelected": "Delete selected", - "deleting": "Deleting...", - "exitSelection": "Exit selection", - "confirmDeleteCount": "{count, plural, =0 {Delete # author?} one {Delete # author?} other {Delete # authors?}}" - }, - "toast": { - "refreshed": "Author metadata refreshed", - "refreshedNoImage": "Metadata refreshed, but no author image was found.", - "refreshFailed": "Failed to refresh author metadata", - "bulkRefreshPartial": "Refreshed {updated} author(s), {failed} failed", - "bulkRefreshSuccess": "Refreshed metadata for {updated} author(s)", - "bulkRefreshFailed": "Failed to refresh selected authors", - "deleteSuccess": "{count, plural, =0 {Deleted # author; affected {books} books} one {Deleted # author; affected {books} books} other {Deleted # authors; affected {books} books}}", - "deleteFailed": "Failed to delete author(s)" - } - }, - "detail": { - "pageTitle": "Author", - "pageTitleNamed": "Author · {name}", - "pageTitleId": "Author #{id}", - "entityName": "Author", - "loadingAuthor": "Loading author...", - "previewError": "Could not load external author preview metadata right now.", - "edit": { - "name": "Name", - "sortName": "Sort Name", - "description": "Description", - "image": "Image", - "uploading": "Uploading...", - "replaceImage": "Replace image", - "uploadImage": "Upload image", - "removing": "Removing...", - "removeImage": "Remove image", - "imageHint": "PNG/JPEG/WEBP/GIF/BMP up to {size} MB", - "saving": "Saving..." - }, - "merge": { - "searchPlaceholder": "Search authors to merge into this author", - "searching": "Searching...", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "selectedSummary": "Selected {count} author(s), approx. {books} books affected.", - "merging": "Merging...", - "mergeSelected": "Merge Selected", - "confirmLabel": "Merge" - }, - "mergeDialog": { - "title": "Merge {count} author(s) into \"{name}\"?", - "titleFallback": "Merge selected authors?", - "description": "This will merge selected authors into the current author and re-link associated books. This action cannot be undone.", - "descriptionEmpty": "This action cannot be undone." - }, - "deleteDialog": { - "title": "Delete author?", - "description": "This removes the author from the catalog and unlinks it from associated books. This action cannot be undone." - }, - "books": { - "heading": "Books", - "allLibraries": "All Libraries", - "asc": "Asc", - "desc": "Desc", - "ascending": "Ascending", - "descending": "Descending", - "allLoaded": "All {total} books loaded", - "sort": { - "recentlyAdded": "Recently Added", - "title": "Title", - "publishedYear": "Published Year" - }, - "empty": { - "title": "No books found for this author", - "hint": "Try changing sort/order or selecting another library." - } - }, - "toast": { - "refreshed": "Author metadata refreshed", - "refreshedNoImage": "Metadata refreshed, but no author image was found.", - "refreshFailed": "Failed to refresh author metadata", - "nameRequired": "Author name is required", - "updated": "Author updated", - "updateFailed": "Failed to update author", - "imageUpdated": "Author image updated", - "imageUploadFailed": "Failed to upload author image", - "imageRemoved": "Author image removed", - "imageRemoveFailed": "Failed to remove author image", - "mergeSuccess": "Merged {count} author(s); affected {books} books", - "mergeFailed": "Failed to merge authors", - "deleteSuccess": "Deleted author; affected {books} books", - "deleteFailed": "Failed to delete author" - } - } - }, - "book": { - "untitled": "Untitled", - "unknownFormat": "unknown", - "collapsedSeries": { - "label": "Series", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "readCount": "{count} read" - }, - "card": { - "missing": "Missing" - }, - "file": { - "primary": "Primary", - "audiobook": "Audiobook" - }, - "actions": { - "read": "Read", - "listen": "Listen", - "peek": "Peek", - "quickView": "Quick View", - "details": "Details", - "bookDetails": "Book Details", - "download": "Download", - "metadata": "Metadata", - "editMetadata": "Edit Metadata", - "refreshMetadata": "Refresh Metadata", - "regenerateCover": "Regenerate Cover", - "addToCollection": "Add to Collection", - "setStatus": "Set Status", - "sendViaEmail": "Send via Email", - "rate": "Rate {star}", - "openAs": "Open as {format}" - }, - "readStatus": { - "unread": "Unread", - "wantToRead": "Want to Read", - "reading": "Reading", - "onHold": "On Hold", - "rereading": "Rereading", - "read": "Read", - "skimmed": "Skimmed", - "abandoned": "Abandoned" - }, - "download": { - "action": "Download", - "audiobookZip": "Audiobook (ZIP)", - "allFormatsZip": "All formats (ZIP)", - "primaryOnlyZip": "Primary only (ZIP)" - }, - "sort": { - "moveUp": "Move up", - "moveDown": "Move down", - "ascending": "Ascending", - "descending": "Descending", - "fields": { - "author": "Author", - "title": "Title", - "series": "Series", - "seriesIndex": "Series #", - "addedAt": "Date Added", - "updatedAt": "Date Updated", - "publishedDate": "Published Date", - "publishedYear": "Published Year", - "pageCount": "Page Count", - "rating": "Rating", - "publisher": "Publisher", - "fileSize": "File Size", - "readProgress": "Read Progress", - "readStatus": "Read Status", - "format": "Format", - "lastReadAt": "Last Read", - "startedAt": "Date Started", - "finishedAt": "Date Finished", - "random": "Random", - "language": "Language", - "metadataScore": "Metadata Score" - }, - "customFieldsGroup": "Custom fields", - "customFieldFallback": "Custom field", - "remove": "Remove", - "emptyState": "No sort configured. Title ascending will be used.", - "addLevel": "Add sort level" - }, - "filter": { - "match": "Match", - "all": "ALL", - "any": "ANY", - "ofFollowingRules": "of the following rules", - "fields": { - "title": "Title", - "publisher": "Publisher", - "language": "Language", - "series": "Series", - "seriesIndex": "Series Index", - "publishedDate": "Published Date", - "publishedYear": "Published Year", - "pageCount": "Page Count", - "author": "Author", - "genre": "Genre", - "tag": "Tag", - "collection": "Collection", - "library": "Library", - "format": "Format", - "addedAt": "Added Date", - "startedAt": "Date Started", - "finishedAt": "Date Finished", - "fileAvailability": "File Availability", - "rating": "Rating", - "communityRating": "Community Rating", - "readProgress": "Reading Progress", - "readStatus": "Read Status", - "description": "Description", - "isbn": "ISBN", - "metadataScore": "Metadata Score", - "cover": "Cover", - "lockStatus": "Lock Status", - "seriesStatus": "Series Status" - }, - "operators": { - "contains": "contains", - "notContains": "does not contain", - "startsWith": "starts with", - "endsWith": "ends with", - "eq": "is", - "notEq": "is not", - "isEmpty": "is empty", - "isNotEmpty": "is not empty", - "gt": "greater than", - "gte": "at least", - "lt": "less than", - "lte": "at most", - "between": "between", - "includesAny": "includes any of", - "includesAll": "includes all of", - "excludesAll": "excludes all of", - "before": "before", - "after": "after", - "withinLast": "within last", - "isMissing": "is missing", - "isPresent": "is present", - "isUnread": "is unread", - "isInProgress": "is in progress", - "isFinished": "is finished", - "isLocked": "is locked", - "isUnlocked": "is unlocked", - "isUpNext": "is up next" - }, - "anyProvider": "Any provider", - "communityRatingProvider": "Community rating provider", - "loadingLibraries": "Loading libraries...", - "noLibrariesAvailable": "No libraries available", - "selectLibrary": "Select library...", - "selectStatus": "Select status...", - "withinLastPlaceholder": "e.g. 7", - "unit": { - "days": "days", - "weeks": "weeks", - "months": "months" - }, - "scorePreset": { - "outstanding": "Outstanding", - "good": "Good", - "fair": "Fair", - "poor": "Poor" - }, - "scoreRangePlaceholder": "0-100", - "valuePlaceholder": "value", - "maxPlaceholder": "max", - "to": "to", - "group": "Group", - "addRule": "Add rule", - "addGroup": "Add group", - "typeToSearch": "Type to search..." - }, - "deleteDialog": { - "title": "Delete book?", - "description": "This will permanently delete the book and all its metadata, files, reading progress, and bookmarks. This cannot be undone." - }, - "bulkEdit": { - "title": "{count, plural, =0 {Edit metadata - # book} one {Edit metadata - # book} other {Edit metadata - # books}}", - "instructions": "Toggle fields to edit, then configure values. Only toggled fields will be changed.", - "invalidYear": "Enter a valid year (numbers only)", - "clearWarning": "This will remove all {field} from the selected books.", - "searchPlaceholder": "Search {field}...", - "enterPlaceholder": "Enter {field}", - "yearPlaceholder": "e.g. 2024", - "leaveEmptyHint": "Leave empty to clear this field on all selected books.", - "applying": "Applying...", - "apply": "Apply", - "mode": { - "add": "Add", - "remove": "Remove", - "replace": "Replace", - "clear": "Clear" - } - }, - "export": { - "title": "Export Metadata", - "scope": "Scope", - "selectedRows": "Selected rows", - "currentlySelected": "{count} currently selected", - "allMatchingRows": "All matching rows", - "rowsInResult": "{count} rows in current result", - "format": "Format", - "csvDescription": "Spreadsheet-friendly, UTF-8 BOM included", - "jsonDescription": "Structured export with metadata context", - "columns": "Columns", - "canonicalSchema": "Stable canonical schema", - "visibleColumns": "Current visible columns", - "options": "Options", - "includePersonalData": "Include personal reading data", - "includeFilePaths": "Include file paths (advanced)", - "includeContextMeta": "Include context metadata", - "preflight": "Preflight", - "scopeLabel": "Scope: {summary}", - "calculatingSize": "Calculating export size...", - "estimatedSize": "Estimated size:", - "fileLabel": "File: {fileName}", - "exportAction": "Export", - "selectedRowsSummary": "{count, plural, =0 {# selected row} one {# selected row} other {# selected rows}}", - "matchingRowsSummary": "{count, plural, =0 {# matching row} one {# matching row} other {# matching rows}}", - "prepareFailed": "Failed to prepare export", - "exportStarted": "Metadata export started: {fileName}", - "exportFailed": "Metadata export failed" - }, - "columnPanel": { - "columnsHeading": "Columns", - "reset": "Reset", - "tableDensity": "Table density", - "density": { - "compact": "Compact", - "comfortable": "Comfortable", - "roomy": "Roomy" - }, - "presets": "Presets", - "exportBackup": "Export presets and saved views", - "importBackup": "Import presets and saved views", - "rename": "Rename", - "renamePrompt": "Enter a new name", - "builtIn": "Built in", - "saveCurrentPreset": "Save current preset", - "savedViews": "Saved views", - "savedViewsEmpty": "Save sort, layout, and view-specific filters for quick reuse.", - "saveCurrentView": "Save current view", - "pinnedLeft": "Pinned left", - "pinnedRight": "Pinned right", - "columns": { - "cover": "Cover", - "read": "Read", - "actions": "Actions" - } - }, - "shortcuts": { - "title": "Keyboard Shortcuts", - "navigation": { - "title": "Navigation", - "moveFocusVertical": "Move focus up/down", - "moveFocusHorizontal": "Move focus left/right", - "jumpFirstColumn": "Jump to first column", - "jumpLastColumn": "Jump to last column", - "jumpFirstRow": "Jump to first row", - "jumpLastRow": "Jump to last row" - }, - "actions": { - "title": "Actions", - "editCell": "Edit focused cell", - "cancelEditing": "Cancel editing / Close overlay", - "toggleRowSelection": "Toggle row selection", - "copyCell": "Copy cell value", - "copyRow": "Copy focused row" - }, - "general": { - "title": "General", - "toggleHelp": "Toggle this help overlay" - } - }, - "jumpRail": { - "jumpToSection": "Jump to section", - "jumpTo": "Jump to {label}", - "unknownDate": "Unknown date", - "unknownValue": "Unknown value" - }, - "quickView": { - "title": "Book quick view", - "titleFor": "Quick view for {title}", - "description": "Preview book details and run quick actions.", - "openIn": "Open in {provider}", - "pages": "{count, plural, =0 {# page} one {# page} other {# pages}}", - "primaryFile": "Primary File", - "fileNumber": "File #{id}", - "showLess": "Show less", - "showMore": "Show more", - "collections": "Collections", - "noDescription": "No description available.", - "openMetadataEditor": "Open metadata editor", - "coverPreview": "Book cover preview", - "coverPreviewFor": "{title} cover preview", - "coverPreviewDescription": "Enlarged cover image preview dialog." - }, - "tableView": { - "openBookDetails": "Open book details", - "openSeries": "Open series", - "metadataRefreshFailed": "Metadata refresh failed", - "booksSelected": "{count, plural, =0 {# book selected} one {# book selected} other {# books selected}}", - "loadingMoreBooks": "Loading more books", - "sort": "Sort", - "refreshingMetadata": "Refreshing metadata {processed} / {total}", - "failedCount": "{count} failed", - "remainingCount": "{count} remaining", - "readOnlyNotice": "Table editing is disabled on smaller screens. Switch to list or grid for quicker actions.", - "fetching": "Fetching...", - "updated": "Updated", - "failed": "Failed", - "noBooks": "No books to display", - "scrollToTop": "Scroll to top", - "selectedStatus": "{count} selected", - "filtered": "Filtered", - "loadedStatus": "{loaded} of {total} loaded", - "bookCount": "{count, plural, =0 {# book} one {# book} other {# books}}", - "keyboardShortcutsTitle": "Keyboard shortcuts (?)", - "showKeyboardShortcuts": "Show table keyboard shortcuts", - "copyHint": "Copy cell: Ctrl/Cmd+C · Copy row: Ctrl/Cmd+Shift+C" - }, - "detail": { - "authorBooks": { - "alsoByAuthor": "Also by this author", - "alsoByAuthors": "Also by these authors" - }, - "header": { - "previousBook": "Previous book", - "nextBook": "Next book" - }, - "tabs": { - "details": "Details", - "editMetadata": "Edit Metadata", - "files": "Files", - "readingLog": "Reading Log", - "highlights": "Highlights" - }, - "discover": { - "moreInSeries": "More in Series", - "byAuthor": "By Author", - "similarBooks": "Similar Books" - }, - "recommended": { - "moreLikeThis": "More Like This" - }, - "series": { - "moreInSeries": "More in the {series} series" - }, - "writeRename": { - "written": "{count, plural, =0 {no fields written} one {Written (one field)} other {Written (# fields)}}", - "writeFailed": "Write failed", - "skipped": "Skipped", - "renamedTo": "Renamed to {name}", - "fileRenamed": "File renamed", - "renameFailed": "Rename failed", - "autoWriteAndRenameDisabled": "Auto-write and rename are disabled in library settings. Changes won't sync automatically on future saves.", - "autoWriteDisabled": "Auto-write is disabled in library settings. Changes won't sync automatically on future saves.", - "autoRenameDisabled": "Auto-rename is disabled in library settings. Changes won't sync automatically on future saves.", - "writeLabel": "Write:", - "renameLabel": "Rename:" - }, - "addFile": { - "uploading": "Uploading...", - "uploadComplete": "Upload complete", - "title": "Add File", - "dropzone": { - "title": "Drop files here or click to browse", - "hint": "epub, pdf, mobi, cbz, m4b and more - up to {size} MB each" - }, - "addMore": "Add more files", - "fileCount": "{count, plural, =0 {no files} one {one file} other {# files}}", - "clearAll": "Clear all", - "done": "Done", - "retry": "Retry", - "filesAdded": "{count, plural, =0 {no files added} one {one file added} other {# files added}}", - "uploadedFailed": "{done} uploaded, {failed} failed", - "uploadingProgress": "{done} of {total} uploading...", - "renameAfter": "Rename all book files after upload", - "uploadCount": "Upload ({count})", - "upload": "Upload" - }, - "addSession": { - "errors": { - "invalidDate": "Pick a valid date and time.", - "future": "The session cannot start in the future.", - "duration": "Duration must be between 1 and 1440 minutes.", - "endProgress": "End progress must be between 0 and 100." - }, - "title": "Add reading session", - "startedAt": "Started at", - "duration": "Duration (minutes)", - "endProgress": "End progress %", - "optional": "Optional", - "format": "Format", - "noFormat": "No specific format", - "saving": "Saving...", - "submit": "Add session" - }, - "coverEditor": { - "unlockCover": "Unlock cover", - "lockCover": "Lock cover", - "fileTab": "File", - "urlTab": "URL", - "chooseImage": "Choose image...", - "findCoverOnline": "Find cover online", - "saving": "Saving...", - "saveCover": "Save cover", - "revertToOriginal": "Revert to original", - "regenerateCover": "Regenerate Cover" - }, - "coverSearch": { - "title": "Online Search", - "subtitle": "Search for book covers", - "titleField": "Title", - "authorField": "Author", - "sourceField": "Source", - "allSources": "All Sources", - "audiobookCovers": "Audiobook covers", - "squareHint": "(square)", - "searching": "Searching...", - "findCovers": "Find covers", - "selectCover": "Select Cover", - "noResultsTitle": "No results found", - "noResultsHint": "Try adjusting your search terms", - "readyTitle": "Ready to search", - "readyHint": "Enter a title and author above", - "resolutionTip": "Tip: High resolution covers are marked in green" - }, - "details": { - "by": "by", - "narratedBy": "narrated by", - "ratingLocked": "Rating is locked", - "rateStar": "Rate {star}", - "listen": "Listen", - "read": "Read", - "chooseFormat": "Choose format", - "audiobook": "Audiobook", - "primary": "Primary", - "peek": "Peek", - "sendViaEmail": "Send via Email", - "personalReview": { - "title": "Personal Review", - "toggleAria": "Toggle personal review", - "editAria": "Edit personal review", - "placeholder": "Private review", - "clearAria": "Clear personal review", - "cancelEditAria": "Cancel personal review edit" - }, - "editCover": "Edit cover", - "finished": "Finished", - "resetFileProgress": "Reset file progress", - "resetting": "Resetting...", - "resetProgressConfirm": "Reset stored reading progress for {label}?", - "moreCount": "+{count} more", - "untitled": "Untitled", - "metadataScore": "Metadata Score", - "primaryFormat": "Primary format", - "openIn": "Open in {provider}", - "showLess": "Show less", - "showMore": "Show more", - "publisher": "Publisher", - "published": "Published", - "language": "Language", - "pages": "Pages", - "duration": "Duration", - "edition": "Edition", - "abridged": "Abridged", - "unabridged": "Unabridged", - "isbn": "ISBN", - "fileSize": "File Size", - "library": "Library", - "added": "Added", - "dateStarted": "Date Started", - "saving": "Saving...", - "cancelDateStartedEdit": "Cancel date started edit", - "editDateStarted": "Edit date started", - "dateFinished": "Date Finished", - "cancelDateFinishedEdit": "Cancel date finished edit", - "editDateFinished": "Edit date finished", - "customMetadata": "Custom Metadata", - "synopsis": "Synopsis", - "noDescription": "No description available.", - "dateStartedFutureError": "Date Started cannot be in the future.", - "dateFinishedFutureError": "Date Finished cannot be in the future.", - "dateFinishedBeforeStartedError": "Date Finished must be on or after Date Started.", - "saveReadingDatesError": "Failed to save reading dates.", - "koboPendingDelete": "Pending delete from device", - "koboPendingDeleteTooltip": "Kobo will remove it on next sync.", - "koboRemovedByDevice": "Removed by device", - "koboRemovedByDeviceTooltip": "Kobo reported this book removed.", - "koboNotSynced": "Not synced", - "koboNotSyncedTooltip": "Queued for next Kobo sync.", - "filesNotFound": "Files not found", - "filesNotFoundDescription": "The file(s) for this book can no longer be found on disk. Metadata is still available. Run a library scan to confirm, or remove the record." - }, - "editMetadata": { - "fieldCount": "{count, plural, =0 {no fields} one {one field} other {# fields}}", - "bookFilesTarget": "book files", - "formatFilesTarget": "{formats} files", - "noPrimaryFile": "No primary file available", - "formatNotSupported": "This file format does not support write-back", - "formatDisabled": "Write-back is disabled for this format", - "fileExceedsSizeLimit": "This file exceeds the write-back size limit", - "writing": "Writing...", - "saveInProgress": "Save in progress", - "writeManualLibraryDisabled": "Write metadata to file and rename on disk; automatic write-back is disabled for this library", - "writeManualTooltip": "Write {fields} to {target} and rename on disk", - "applyResult": "{skipped}, {updated}", - "skippedLockedFields": "{count, plural, =0 {Skipped no locked fields} one {Skipped one locked field} other {Skipped # locked fields}}", - "updatedFields": "{count, plural, =0 {updated no fields} one {updated one field} other {updated # fields}}", - "wroteFieldsToFile": "Wrote {fields} to file", - "fileWriteFailedReason": "File write failed: {reason}", - "fileWriteFailed": "File write failed", - "fileWriteSkippedReason": "File write skipped: {reason}", - "fileWriteSkipped": "File write skipped", - "metadataSaved": "Metadata saved", - "metadataWrittenToFile": "Metadata written to file", - "savedButWriteFailedReason": "Metadata saved, but file write failed: {reason}", - "savedButWriteFailed": "Metadata saved, but file write failed", - "savedWriteSkippedReason": "Metadata saved, file write skipped: {reason}", - "savedWriteSkipped": "Metadata saved, file write skipped", - "loadFromFileFailed": "Failed to load metadata from file", - "loadedFieldsFromFile": "{count, plural, =0 {Loaded no fields from file} one {Loaded one field from file} other {Loaded # fields from file}}", - "noMetadataInFile": "No metadata found in file", - "loadFromFile": "Load from file", - "loadFromFileTooltip": "Load metadata from the primary book file", - "writeToFile": "Write to file", - "autoFill": "Auto-fill", - "fetchingMetadata": "Fetching metadata...", - "allFieldsLocked": "All fields are locked", - "autoFillTooltip": "Auto-fill fields using your metadata preferences", - "lockAll": "Lock all", - "lockAllTooltip": "Lock all fields", - "unlockAll": "Unlock all", - "unlockAllTooltip": "Unlock all fields", - "saving": "Saving...", - "fileWriteBackDetails": "File write-back details", - "fileWriteBack": "File write-back", - "enabled": "Enabled", - "saveWritesMetadata": "'Save' writes metadata to {target}", - "formats": "Formats", - "bookFiles": "Book files", - "supportedFields": "Supported fields", - "titleLabel": "Title", - "subtitleLabel": "Subtitle", - "authorsLabel": "Authors", - "narratorsLabel": "Narrators", - "genresLabel": "Genres", - "tagsLabel": "Tags", - "ratingLabel": "Rating", - "rateStar": "Rate {star}", - "clear": "Clear", - "communityRatingsLabel": "Community Ratings", - "noProviderRatings": "No provider ratings", - "seriesLabel": "Series", - "publisherLabel": "Publisher", - "languageLabel": "Language", - "yearLabel": "Year", - "pageCountLabel": "Page Count", - "isbn13Label": "ISBN-13", - "isbn10Label": "ISBN-10", - "durationLabel": "Duration (s)", - "abridgedLabel": "Abridged", - "providerIds": "Provider IDs", - "comicDetails": "Comic Details", - "comicIssueNumberLabel": "Issue Number", - "comicVolumeLabel": "Volume", - "comicStoryArcsLabel": "Story Arcs", - "comicPencillersLabel": "Pencillers", - "comicInkersLabel": "Inkers", - "comicColoristsLabel": "Colorists", - "comicLetterersLabel": "Letterers", - "comicCoverArtistsLabel": "Cover Artists", - "comicCharactersLabel": "Characters", - "comicTeamsLabel": "Teams", - "comicLocationsLabel": "Locations", - "customMetadata": "Custom Metadata", - "descriptionLabel": "Description", - "unlockField": "Unlock {field}", - "lockField": "Lock {field}", - "diffPanel": { - "untitled": "Untitled", - "noFieldsSelected": "No fields selected", - "fieldsSelected": "{count, plural, =0 {no fields selected} one {one field selected} other {# fields selected}}", - "results": "Results", - "providerMatches": "{provider} matches", - "selectedOf": "Selected {selected} of {total}", - "yearUnknown": "Year unknown", - "indexOf": "{index} of {total}", - "switchedResult": "Switched result. Previous selections from this provider were cleared.", - "selectFieldsToApply": "Select fields to apply", - "copyMissing": "Copy Missing", - "copyAll": "Copy All", - "hideUnchanged": "Hide unchanged", - "showUnchanged": "Show unchanged", - "current": "Current", - "noMetadata": "No metadata available from this source.", - "noChangedFields": "No changed or missing fields. Use Show unchanged to inspect everything.", - "applyToForm": "Apply to form" - }, - "diff": { - "locked": "Locked", - "previewAlt": "Preview", - "currentCoverAlt": "Current cover", - "newCoverAlt": "New cover", - "pickCoverFromProvider": "Pick cover from another provider", - "pickCoverSource": "Pick cover source", - "pickFromProvider": "Pick from another provider", - "pickSource": "Pick source", - "empty": "empty", - "showLess": "Show less", - "showMore": "Show more", - "coverPreviewAlt": "Cover preview" - }, - "searchDrawer": { - "searchTitle": "Search Metadata", - "compareTitle": "Compare Metadata", - "searchSubtitle": "Find the best provider match for this book.", - "compareSubtitle": "Review differences and apply only what you want." - }, - "searchPanel": { - "untitledQuery": "Untitled query", - "titlePlaceholder": "Title", - "authorPlaceholder": "Author", - "isbnPlaceholder": "ISBN", - "searching": "Searching...", - "activeQuery": "Active query", - "searchScope": "Search scope", - "allEnabled": "All enabled", - "all": "All", - "fieldRules": "Field Rules", - "custom": "Custom", - "providerNotInFieldRules": "{provider} is enabled but not in Field Rules", - "notInFieldRulesLabel": "Not in Field Rules:", - "notInFieldRulesText": "{providers}. Included in manual search with All enabled, but not used by automatic metadata fetch.", - "noResults": "No results found", - "noResultsHint": "Try adjusting the title or author", - "searchPrompt": "Search above, then click a result to start comparing metadata." - }, - "writeAndRename": "Write to File & Rename", - "writeAndRenameShort": "Write & Rename" - }, - "files": { - "title": "Book files", - "fileCount": "{count, plural, =0 {no files} one {# file} other {# files}}", - "synced": "Synced {time}", - "sortAria": "Sort files", - "syncHistory": "Sync history", - "metadataWriteBack": "Metadata write-back", - "relative": { - "seconds": "{value}s ago", - "minutes": "{value}m ago", - "hours": "{value}h ago", - "days": "{value}d ago" - }, - "renameFailed": "Failed to rename file", - "deleteFailed": "Failed to delete file", - "addFile": "Add File", - "lastSynced": "Last synced: {time}", - "sort": { - "label": "Sort:", - "name": "Name", - "format": "Format", - "size": "Size", - "date": "Date" - }, - "hidePaths": "Hide paths", - "showPaths": "Show paths", - "hideLog": "Hide log", - "viewSyncLog": "View sync log", - "noWriteHistory": "No write history yet.", - "fieldsWritten": "{count, plural, =0 {no fields} one {one field} other {# fields}}", - "track": "Track {number}", - "primary": "Primary", - "read": "Read", - "play": "Play", - "peek": "Peek", - "download": "Download", - "moreActions": "More actions", - "rename": "Rename", - "empty": { - "title": "No files attached", - "description": "This book has no associated files." - }, - "renameModal": { - "title": "Rename File", - "description": "Rename the physical file on disk.", - "placeholder": "New filename" - }, - "saving": "Saving...", - "deleteModal": { - "title": "Delete file?", - "description": "Are you sure you want to delete \"{filename}\"? This action cannot be undone." - }, - "deleting": "Deleting..." - }, - "highlights": { - "note": { - "placeholder": "Add a note...", - "saving": "Saving" - }, - "export": { - "trigger": "Export", - "plainText": "Plain Text", - "page": "Export page", - "selected": "Export selected" - }, - "sort": { - "position": "Position", - "newest": "Newest first", - "oldest": "Oldest first" - }, - "summary": { - "highlights": "{count, plural, =0 {no highlights} one {one highlight} other {# highlights}}", - "notes": "{count, plural, =0 {no notes} one {one note} other {# notes}}", - "chapters": "{count, plural, =0 {no chapters} one {one chapter} other {# chapters}}" - }, - "filterByChapter": "Filter by chapter", - "allChapters": "All chapters", - "untitled": "Untitled", - "trash": "Trash", - "empty": { - "noMatch": "No highlights match your filters.", - "resetFilters": "Reset filters", - "none": "No highlights yet", - "hint": "Select text while reading to create highlights" - }, - "uncategorized": "Uncategorized", - "paginationUnit": "highlights" - }, - "readingLog": { - "moreActionsAria": "More reading log actions", - "export": { - "button": "Export" - }, - "weekdays": { - "sun": "Sun", - "mon": "Mon", - "tue": "Tue", - "wed": "Wed", - "thu": "Thu", - "fri": "Fri", - "sat": "Sat" - }, - "months": { - "jan": "Jan", - "feb": "Feb", - "mar": "Mar", - "apr": "Apr", - "may": "May", - "jun": "Jun", - "jul": "Jul", - "aug": "Aug", - "sep": "Sep", - "oct": "Oct", - "nov": "Nov", - "dec": "Dec" - }, - "heatmap": { - "minutesUnit": "min", - "title": "Activity", - "empty": "No reading activity in this window.", - "emptyHint": "Sessions recorded here will build your consistency view." - }, - "hero": { - "summaryAria": "Reading summary", - "notSet": "Not set", - "relative": { - "seconds": "{count}s ago", - "minutes": "{count}m ago", - "hours": "{count}h ago", - "days": "{count}d ago", - "months": "{count, plural, =0 {# month ago} one {# month ago} other {# months ago}}", - "years": "{count, plural, =0 {# year ago} one {# year ago} other {# years ago}}" - }, - "noSessions": "No sessions", - "dateErrors": { - "startFuture": "Start date cannot be in the future.", - "finishFuture": "Finish date cannot be in the future.", - "finishBeforeStart": "Finish date must be on or after the start date.", - "saveFailed": "Failed to save reading dates." - }, - "eta": { - "max": "99h+ to finish", - "minutes": "~{m}m to finish", - "hours": "~{h}h to finish", - "hoursMinutes": "~{h}h {m}m to finish" - }, - "momentum": { - "none": "No activity in the last two weeks", - "new": "New activity this week", - "up": "+{pct}% vs previous 7 days", - "down": "{pct}% vs previous 7 days", - "flat": "Unchanged vs previous 7 days" - }, - "stats": { - "totalTime": "Total Time", - "sessions": "Sessions", - "avgSession": "Avg Session", - "lastRead": "Last Read" - }, - "firstRead": "First Read", - "lastRead": "Last Read", - "dateStarted": "Date Started", - "dateFinished": "Date Finished", - "addSession": "Add session" - }, - "journey": { - "tooltipProgress": "Progress", - "tooltipReading": "Reading", - "minutesUnit": "min", - "title": "Progress journey", - "empty": "No progress data in this window.", - "emptyHint": "Progress will appear after a session records a reading position." - }, - "sourceSplit": { - "title": "Reading sources", - "shortTitle": "Sources" - }, - "untitled": "Untitled", - "addSessionFailed": "Failed to add session", - "filters": { - "show": "Show", - "dateRangeAria": "Reading session date range", - "allTime": "All time", - "last30": "Last 30 days", - "last90": "Last 90 days", - "thisYear": "This year", - "allFormats": "All formats" - }, - "table": { - "title": "Sessions", - "sourceWeb": "Web", - "sourceManual": "Manual", - "colDate": "Date", - "colDateMobile": "Date", - "colDuration": "Duration", - "colDurationMobile": "Duration", - "colProgressChange": "Progress Change", - "colProgressChangeMobile": "Delta", - "colEndProgress": "End Progress", - "colEndProgressMobile": "End", - "empty": "No reading sessions recorded yet.", - "emptyHint": "Add a session to start building this book's reading history.", - "colPace": "Pace", - "colSource": "Source", - "colFormatMobile": "Fmt", - "colFormat": "Format", - "cancelDelete": "Cancel delete", - "cancelDeleteAria": "Cancel delete session", - "confirmDeleteTitle": "Click again to confirm delete", - "confirmDeleteAria": "Confirm delete session", - "deleteAria": "Delete session", - "loadMore": "Load more", - "showing": "Showing {shown} of {total} sessions" - } - }, - "richDescription": { - "linkProtocolError": "Use http, https, or mailto.", - "bold": "Bold", - "italic": "Italic", - "underline": "Underline", - "strikethrough": "Strikethrough", - "bulletList": "Bullet list", - "numberedList": "Numbered list", - "outdentAria": "Outdent list item", - "outdent": "Outdent", - "indentAria": "Indent list item", - "indent": "Indent", - "quote": "Quote", - "editLink": "Edit link", - "link": "Link", - "removeLink": "Remove link", - "undo": "Undo", - "redo": "Redo", - "clearFormatting": "Clear formatting", - "previewDescription": "Preview description", - "preview": "Preview", - "linkUrlLabel": "Link URL", - "applyLink": "Apply link", - "apply": "Apply", - "cancelLink": "Cancel link", - "noDescription": "No description available." - }, - "seriesMembership": { - "addSeries": "Add series", - "seriesPlaceholder": "Series", - "moveUp": "Move up", - "moveDown": "Move down", - "removeSeries": "Remove series" - } - }, - "table": { - "actions": { - "quickView": "Quick View", - "bookDetails": "Book Details", - "editMetadata": "Edit Metadata", - "refreshMetadata": "Refresh Metadata", - "addToCollection": "Add to Collection", - "sendToDevice": "Send to Device" - }, - "boolean": { - "ariaNotSet": "Not set - click to set true", - "ariaTrue": "True - click to set false", - "ariaFalse": "False - click to clear" - }, - "chips": { - "addPlaceholder": "Add..." - }, - "cover": { - "previewDescription": "Book cover preview", - "editDescription": "Edit book cover", - "editTitle": "Edit cover", - "editCover": "Edit Cover", - "view": "View cover" - }, - "date": { - "justNow": "just now" - }, - "format": { - "unknown": "unknown" - }, - "header": { - "sortAscending": "Sort Ascending", - "sortDescending": "Sort Descending", - "clearSort": "Clear Sort", - "hideColumn": "Hide Column", - "pinLeft": "Pin Left", - "pinRight": "Pin Right", - "unpinColumn": "Unpin Column", - "autoFitWidth": "Auto-Fit Width", - "autoFitAllColumns": "Auto-Fit All Columns", - "selectAllBooks": "Select all books", - "shiftClickSecondarySort": "Shift+click to add secondary sort", - "clickToSort": "Click to sort" - }, - "locks": { - "lockAll": "Lock all fields", - "unlockAll": "Unlock all fields", - "lockField": "Lock field", - "unlockField": "Unlock field", - "clickToLock": "Click to lock", - "clickToUnlock": "Click to unlock" - }, - "progress": { - "complete": "{percent} complete" - }, - "rating": { - "label": "Rating", - "remove": "Remove rating", - "rate": "Rate {star} out of 5" - }, - "read": { - "play": "Play", - "read": "Read", - "primary": "Primary", - "peekFormat": "Peek {format}", - "chooseFormat": "Choose format to read or play", - "fileFallback": "FILE" - }, - "readStatus": { - "unread": "Unread" - }, - "series": { - "bookCount": "{count, plural, =0 {(no books)} one {(# book)} other {(# books)}}", - "readOfCount": "{read} of {total} read" - }, - "text": { - "openDetails": "Open details" - } - } - }, - "bookMetadataFetch": { - "book": { - "title": "Metadata Fetch" - }, - "author": { - "title": "Author Enrichment" - }, - "stats": { - "queued": "Queued", - "processing": "Processing", - "rateLimited": "Rate limited", - "failed": "Failed" - }, - "actions": { - "pause": "Pause", - "resume": "Resume", - "cancelQueued": "Cancel queued", - "dismissBookStatus": "Dismiss metadata fetch status", - "dismissAuthorStatus": "Dismiss author enrichment status" - }, - "cancel": { - "processingWillFinish": "Currently processing items will finish.", - "confirm": "Confirm cancel", - "keepRunning": "Keep running" - }, - "viewFailed": "{count, plural, one {View one failed} other {View # failed}}", - "card": { - "fetchingMetadata": "Fetching metadata", - "enrichingAuthors": "Enriching authors", - "metadataFetchFinished": "Metadata fetch finished", - "authorEnrichmentFinished": "Author enrichment finished" - }, - "label": { - "paused": "Paused", - "remaining": "{count} remaining", - "processing": "{count} processing", - "failed": "{count} failed", - "rateLimited": "{count} rate limited" - }, - "report": { - "bookTitle": "Failed Metadata Fetches", - "authorTitle": "Failed Author Enrichments", - "noFailedItems": "No failed items.", - "retryAllFailed": "Retry all failed", - "bookFallback": "Book #{id}", - "authorFallback": "Author #{id}", - "columns": { - "title": "Title", - "library": "Library", - "author": "Author", - "error": "Error", - "http": "HTTP" - } - }, - "toast": { - "failedToPause": "Failed to pause", - "failedToResume": "Failed to resume", - "failedToCancel": "Failed to cancel", - "failedToRetry": "Failed to retry", - "failedItemsRequeued": "Failed items requeued", - "bookComplete": "Metadata fetch complete - {done} books updated", - "bookDoneWithFailures": "Metadata fetch done - {done} processed, {failed} failed", - "authorComplete": "Author enrichment complete - {done} authors updated", - "authorDoneWithFailures": "Author enrichment done - {done} processed, {failed} failed" - } - }, - "bookDock": { - "apply": "Apply", - "done": "Done", - "discard": "Discard", - "finalize": "Finalize", - "rescan": "Rescan", - "uploadAction": "Upload", - "uploading": "Uploading...", - "searchPlaceholder": "Search files...", - "setDestinationAction": "Set Destination", - "bulkEditAction": "Bulk Edit", - "applyFetched": "Apply Fetched", - "retryErrors": "Retry Errors", - "commaSeparated": "comma-separated", - "destinationLibrary": "Destination Library", - "destinationFolder": "Destination Folder", - "nFailed": "{count} failed", - "updatedOfFiles": "Updated {updated} of {total} files", - "errorStatus": "Error {status}", - "tab": { - "all": "All", - "pending": "Pending", - "ready": "Ready", - "error": "Error" - }, - "status": { - "pending": "Pending", - "extracting": "Extracting", - "fetching": "Fetching", - "ready": "Ready", - "error": "Error" - }, - "field": { - "title": "Title", - "subtitle": "Subtitle", - "authors": "Authors", - "authorsCommaSeparated": "Authors (comma-separated)", - "publisher": "Publisher", - "publishedDate": "Published Date", - "year": "Year", - "language": "Language", - "isbn13": "ISBN-13", - "isbn10": "ISBN-10", - "series": "Series", - "seriesIndex": "Series #", - "genres": "Genres", - "genresCommaSeparated": "Genres (comma-separated)", - "description": "Description" - }, - "upload": { - "nDone": "{count} done", - "nFailed": "{count} failed", - "nTotal": "{count} total" - }, - "fileList": { - "emptyTitle": "No files in Book Dock", - "emptyMessageDefault": "Upload files or drop them in the Book Dock folder", - "colCurrent": "Current", - "colNew": "New", - "colFile": "File", - "colSize": "Size", - "colFormat": "Format", - "colMatch": "Match", - "colApply": "Apply", - "colStatus": "Status", - "applyFetchedMetadata": "Apply fetched metadata", - "coverPreview": "Cover preview", - "coverPreviewDescription": "Enlarged cover image preview dialog.", - "currentCoverAlt": "{title} current cover", - "newCoverAlt": "{title} new cover", - "unknownLibrary": "Unknown library", - "unassigned": "Unassigned", - "targetPath": "Target: {library} · {path}", - "targetUnassigned": "Target: Unassigned", - "targetUnknownPath": "Target: {library} · Unknown destination path" - }, - "sheet": { - "saved": "Saved", - "providerMetadataFound": "Provider metadata found", - "providerMetadataFoundEdited": "Provider metadata found - bulk apply will skip this file (you have edits)", - "review": "Review", - "added": "Added {date}", - "searchMetadata": "Search Metadata", - "results": "Results" - }, - "bulkEdit": { - "title": "{count, plural, =0 {Bulk Edit no files} one {Bulk Edit # file} other {Bulk Edit # files}}", - "resultTitle": "Bulk Edit Results", - "instructions": "Toggle the fields you want to update. Only enabled fields will be applied.", - "mergeArrays": "Merge arrays (add to existing values instead of replacing)", - "failed": "Bulk edit failed" - }, - "setDestination": { - "title": "{count, plural, =0 {Set Destination for no files} one {Set Destination for # file} other {Set Destination for # files}}", - "resultTitle": "Destination Updated", - "failed": "Failed to set destination" - }, - "finalizeDialog": { - "title": "{count, plural, =0 {Finalize no files} one {Finalize # file} other {Finalize # files}}", - "resultTitle": "Finalize Results", - "needDestination": "{count, plural, =0 {{without} of # selected files need a destination} one {{without} of # selected file needs a destination} other {{without} of # selected files need a destination}}", - "allHaveDestination": "All selected files already have destination set", - "defaultDestinationLibrary": "Default Destination Library", - "defaultDestinationFolder": "Default Destination Folder", - "renamePreview": "Rename preview", - "moreFiles": "+{count} more files", - "start": "Start", - "filesFinalized": "{succeeded} of {total} files finalized", - "checking": "Checking selected files...", - "readyCount": "{count, plural, =0 {no files ready} one {# file ready} other {# files ready}}", - "duplicateCount": "{count, plural, =0 {none already in library} one {# already in library} other {# already in library}}", - "conflictCount": "{count, plural, =0 {no filename conflicts} one {# filename conflict} other {# filename conflicts}}", - "missingDestinationCount": "{count, plural, =0 {no missing destinations} one {# missing destination} other {# missing destinations}}", - "blockedCount": "{count, plural, =0 {no files blocked} one {# file blocked} other {# files blocked}}", - "moreDuplicates": "+{count} more already in library", - "discardDuplicates": "Discard duplicates", - "failedCount": "{count, plural, =0 {no files failed} one {# file failed} other {# files failed}}", - "failedWithDuplicates": "{count, plural, =0 {{failed} failed (# duplicates)} one {{failed} failed (# duplicate)} other {{failed} failed (# duplicates)}}", - "view": "View", - "viewExisting": "View existing", - "hide": "Hide", - "details": "Details", - "alreadyExistsSaveAs": "Already exists - save as:", - "renamePlaceholder": "e.g. {name} (2)", - "import": "Import" - } - }, - "collection": { - "dialog": { - "name": "Name", - "icon": "Icon", - "iconPlaceholder": "Choose an icon...", - "nameRequired": "Name is required", - "iconRequired": "Choose an icon", - "creating": "Creating...", - "createFailed": "Failed to create collection" - }, - "createDialog": { - "title": "New Collection", - "namePlaceholder": "e.g. Favorites" - }, - "editDialog": { - "title": "Edit Collection", - "syncToKobo": "Sync to Kobo", - "syncToKoboHint": "Books in this collection will appear on your Kobo device", - "deleteCollection": "Delete collection", - "confirmDelete": "Confirm?", - "deleting": "Deleting...", - "saving": "Saving...", - "deleted": "\"{name}\" deleted", - "updateFailed": "Failed to update collection", - "deleteFailed": "Failed to delete collection" - }, - "addToSheet": { - "title": "Manage Collections", - "selectedCount": "{count, plural, =0 {no books selected} one {one book selected} other {# books selected}}", - "newCollection": "New Collection", - "namePlaceholder": "Collection name", - "create": "Create", - "collections": "Collections", - "empty": "No collections yet. Create one above.", - "done": "Done", - "added": "Added", - "allAdded": "All {total} added", - "inCollection": "In this collection", - "allInCollection": "All {total} in this collection", - "partialInCollection": "{partial} of {total} in this collection", - "bookCount": "{count, plural, =0 {no books} one {one book} other {# books}}", - "loadFailed": "Failed to load collections", - "createdAndAdded": "{count, plural, =0 {Created \"{name}\" and added no books} one {Created \"{name}\" and added one book} other {Created \"{name}\" and added # books}}", - "createdButAddFailed": "Created \"{name}\" but failed to add books", - "createFailed": "Failed to create collection", - "addedNewWithExisting": "{count, plural, =0 {Added one new book to \"{name}\" ({alreadyHad} already there)} one {Added one new book to \"{name}\" ({alreadyHad} already there)} other {Added # new books to \"{name}\" ({alreadyHad} already there)}}", - "addedToCollection": "{count, plural, =0 {Added no books to \"{name}\"} one {Added one book to \"{name}\"} other {Added # books to \"{name}\"}}", - "addFailed": "Failed to add to collection", - "removedFromCollection": "{count, plural, =0 {Removed no books from \"{name}\"} one {Removed one book from \"{name}\"} other {Removed # books from \"{name}\"}}", - "removeFailed": "Failed to remove from collection" - } - }, - "components": { - "appHeader": { - "searchAllBooks": "Search all books...", - "searching": "Searching...", - "noResults": "No results", - "loadingMore": "Loading more...", - "loadMore": "Load more ({loaded}/{total})", - "allMatchesShown": "{count, plural, =0 {All 1 match shown} one {All 1 match shown} other {All # matches shown}}", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "fileCount": "{count, plural, =0 {no files} one {# file} other {# files}}", - "uploadedToast": "Uploaded {uploaded}", - "uploadFailedToast": "Upload failed for {failed}", - "uploadPartialToast": "Uploaded {uploaded}, {failed} failed", - "bookDock": "Book Dock", - "statistics": "Statistics", - "achievements": "Achievements", - "annotations": "Annotations", - "uploadBooks": "Upload books", - "appearance": "Appearance", - "theme": "Theme", - "accent": "Accent", - "radius": "Radius", - "background": "Background", - "settings": "Settings", - "whatsNew": "What's New", - "documentation": "Documentation", - "help": "Help", - "starOnGithub": "Star on GitHub", - "new": "New", - "newReleaseNotes": "New release notes available", - "account": "Account", - "changePassword": "Change Password", - "signOut": "Sign out", - "githubStar": { - "title": "Enjoying BookOrbit?", - "body": "If BookOrbit is helping with your library, please consider starring the project on GitHub. It helps more people discover the app and supports ongoing development.", - "cta": "Star BookOrbit on GitHub" - }, - "surfaceOpacity": "Surface opacity", - "surfaceOpacityValue": "{value}%" - }, - "sidebar": { - "dashboard": "Dashboard", - "authors": "Authors", - "series": "Series", - "tools": "Tools", - "libraries": "Libraries", - "newLibrary": "New Library", - "scanProgress": "{processed} / {total} books", - "smartScopes": "Smart Scopes", - "newSmartScope": "New Smart Scope", - "noSmartScopes": "No Smart Scopes yet", - "collections": "Collections", - "newCollection": "New Collection", - "noCollections": "No collections yet", - "newReleaseNotes": "New release notes available", - "support": "Support BookOrbit", - "supportAria": "Support BookOrbit on Ko-fi", - "sectionHeader": { - "add": "Add", - "showAll": "Show all", - "showCount": "Show {count}", - "rowsShown": "Rows shown", - "menuAria": "Section options for {section}", - "reorder": "Reorder", - "doneReordering": "Done reordering" - }, - "noLibraries": "No libraries yet", - "clearFilter": "Clear filter", - "filterSummary": "{shown} of {total} shown", - "filterLibraries": "Filter libraries", - "filterLibrariesPlaceholder": "Filter libraries...", - "filterSmartScopes": "Filter smart scopes", - "filterSmartScopesPlaceholder": "Filter smart scopes...", - "filterCollections": "Filter collections", - "filterCollectionsPlaceholder": "Filter collections...", - "seeAllLibraries": "See all libraries ({count})", - "seeAllSmartScopes": "See all smart scopes ({count})", - "seeAllCollections": "See all collections ({count})", - "updateAvailable": "Update {version}", - "zones": { - "browse": "Browse" - }, - "reorder": { - "gripAria": "Reorder {name}", - "lifted": "{name} lifted, position {position} of {total}. Use the arrow keys to move it.", - "moved": "{name}, position {position} of {total}", - "dropped": "{name} dropped at position {position} of {total}", - "cancelled": "Reorder cancelled. {name} returned to position {position} of {total}.", - "filteredHint": "Clear the filter to reorder" - } - }, - "selectionActionBar": { - "setReadingStatus": "Set reading status", - "setRating": "Set rating", - "openMetadataEditor": "Open metadata editor", - "editIndividually": "Edit books individually", - "addToCollection": "Add to collection", - "removeFromCollection": "Remove from collection", - "sendViaEmail": "Send via email", - "downloadFilesZip": "Download files as ZIP", - "moreActions": "More actions", - "setField": "Set field", - "refreshMetadata": "Refresh metadata", - "reExtractCover": "Re-extract cover", - "metadataLock": "Metadata lock", - "lockAll": "Lock all", - "unlockAll": "Unlock all", - "exportMetadata": "Export metadata", - "deleteSelected": "Delete selected", - "exitSelection": "Exit selection", - "downloadFilesZipLabel": "Download files as ZIP:", - "primaryOnly": "Primary only", - "allFormats": "All formats", - "audioOnly": "Audio only", - "setRatingLabel": "Set rating:", - "clear": "Clear", - "setFieldLabel": "Set field:", - "apply": "Apply", - "fieldPlaceholder": "Leave blank to clear", - "fieldPlaceholderArray": "Comma-separated (leave blank to clear)", - "deleteConfirm": "{count, plural, =0 {Delete # book?} one {Delete # book?} other {Delete # books?}}", - "typeDelete": "Type DELETE" - }, - "viewHeader": { - "select": "Select", - "display": "Display", - "displayDescription": "Adjust cover size, grid spacing, and view display options.", - "columnVisibilityHint": "Use the column visibility panel in the table header to show or hide columns.", - "columnVisibilityMobileHint": "Column visibility can be managed from the table header.", - "searchPlaceholder": "Search title, author, series, narrator...", - "mobileSearch": { - "description": "Search items by title, author, series, or narrator.", - "done": "Done" - }, - "mobileMenu": { - "grid": "Grid", - "list": "List", - "select": "Select", - "exitSelect": "Exit Select" - }, - "displayControls": { - "display": "Display", - "coverSize": "Cover size", - "gridGap": "Grid gap", - "showJumpRails": "Show jump rails", - "columnsHint": "Use the column visibility panel in the table header to show or hide columns.", - "coverShape": "Cover shape", - "circle": "Circle", - "square": "Square" - } - }, - "iconPicker": { - "clearSelectionAria": "Clear selected icon", - "searchLucide": "Search Lucide icons...", - "searchCustom": "Search custom icons...", - "chooseIcon": "Choose an icon...", - "selectIcon": "Select icon", - "customTab": "Custom", - "searching": "Searching...", - "noIconsMatch": "No icons match \"{query}\"", - "typeToSearch": "Type to search all icons", - "noCustomIcons": "No custom icons uploaded", - "noIconsAvailable": "No icons available" - }, - "entityNotFound": { - "title": "{entity} not found", - "description": "This {entity} doesn't exist or has been deleted.", - "goBack": "Go back" - }, - "themePicker": { - "light": "Light", - "dark": "Dark", - "system": "System" - }, - "userAvatar": { - "profilePicture": "Profile picture", - "profilePictureOf": "{name} profile picture" - }, - "ui": { - "sidebar": { - "title": "Sidebar", - "mobileDescription": "Displays the mobile sidebar.", - "toggle": "Toggle Sidebar" - }, - "chipInput": { - "typeAndEnter": "Type and press Enter to add", - "pressEnter": "Press Enter to add" - } - }, - "entityIndex": { - "sortBy": "Sort by", - "sort": { - "custom": "Custom order", - "name": "Name", - "bookCount": "Book count" - }, - "ascending": "Ascending", - "descending": "Descending", - "clearSearch": "Clear search", - "resultCount": "{shown} of {total}", - "noMatches": "No matches", - "noMatchesHint": "Try a different search term.", - "bookCount": "Books: {count}", - "librariesEmptyHint": "Create a library to start adding books.", - "smartScopesEmptyHint": "Smart scopes save a set of filters you use often.", - "collectionsEmptyHint": "Collections group books you pick by hand." - } - }, - "customIcons": { - "dialogTitle": "Upload custom icons", - "dialogDescription": "Review names before adding them to your library.", - "readingFiles": "Reading files...", - "dropPrompt": "Drop SVG files or click to browse", - "fileLimit": "Up to {max} files, 128 KB each", - "namePlaceholder": "Name", - "nameRequired": "Name is required", - "invalidSvg": "Invalid SVG", - "invalidSvgFile": "Invalid SVG file", - "identicalTo": "Identical to \"{name}\"", - "uploadAnyway": "Upload anyway", - "skipThisOne": "Skip this one", - "readyToUpload": "{count} ready to upload", - "noIconsStaged": "No icons staged yet", - "uploading": "Uploading...", - "upload": "Upload", - "uploadCount": "Upload {count}", - "onlySvgSupported": "Only SVG files are supported", - "maxStaged": "You can stage at most {max} icons at once", - "onlyMoreCanStage": "{count, plural, =0 {No more icons can be staged} one {Only # more icon can be staged} other {Only # more icons can be staged}}", - "readFailed": "Failed to read SVG files", - "uploadedCount": "{count, plural, =0 {No icons uploaded} one {Uploaded # icon} other {Uploaded # icons}}", - "uploadedPartial": "Uploaded {created}, {failed} failed", - "noIconsUploaded": "No icons uploaded", - "uploadFailed": "Failed to upload icons", - "uploadFailedEntry": "Upload failed" - }, - "dashboard": { - "common": { - "failedToLoad": "Failed to load", - "retry": "Retry", - "untitled": "Untitled", - "cover": "Cover", - "bookCover": "Book cover" - }, - "scroller": { - "failedToLoad": "Failed to load.", - "empty": { - "continueReading": "No books in progress yet. Start reading one to see it here.", - "continueListening": "No audiobooks in progress yet. Start listening to one to see it here.", - "wantToRead": "No books marked want to read yet.", - "upNextInSeries": "No next-in-series picks yet. Finish a volume to surface the next one.", - "recentlyAdded": "No books in your library yet.", - "smartScope": "No books match this smartScope.", - "default": "No books found." - } - }, - "settings": { - "title": "Customize Dashboard", - "tabs": { - "widgets": "Widgets", - "shelves": "Shelves" - }, - "widgetNames": { - "readingStreak": "Reading Streak", - "currentlyReading": "Currently Reading", - "readingGoal": "Reading Goal", - "readingDna": "Reading DNA", - "monthlyChallenge": "Monthly Challenge", - "highlightOfTheDay": "Highlight of the Day", - "neglectedGems": "Neglected Gems", - "readingRhythm": "Reading Rhythm", - "diversityScore": "Diversity Score", - "libraryOverview": "Library Overview", - "yearProjection": "Year Projection", - "longWait": "The Long Wait" - }, - "shelfNames": { - "recentlyAdded": "Recently Added", - "continueReading": "Continue Reading", - "continueListening": "Continue Listening", - "wantToRead": "Want to Read", - "upNextInSeries": "Up Next in Series", - "random": "Discover Something New", - "smartScope": "Smart Scope" - }, - "reorderHintWidget": "Drag to reorder. Toggle to show or hide a widget.", - "reorderHintShelf": "Drag to reorder. Toggle to show or hide a shelf.", - "smartScope": "Smart Scope", - "noSmartScopes": "No Smart Scopes yet. Create one from the sidebar.", - "addShelf": "Add shelf", - "resetToDefaults": "Reset to defaults" - }, - "welcome": { - "emptyTitle": "Your library is empty", - "noLibrariesTitle": "No libraries yet", - "emptyDescription": "Create a library to start organizing and reading your books. Point it to a folder and it will do the rest.", - "noLibrariesDescription": "Your administrator hasn't set up any libraries yet. Reach out to them to get started.", - "createFirstLibrary": "Create your first library" - }, - "widgets": { - "currentlyReading": { - "title": "Currently Reading", - "empty": "No books in progress. Start reading one to see it here.", - "continueReading": "Continue reading" - }, - "diversityScore": { - "title": "Diversity Score", - "notEnoughData": "Read at least 3 books to see your diversity score", - "booksAnalyzed": "{count, plural, =0 {no books analyzed} one {# book analyzed} other {# books analyzed}}", - "subScores": { - "genre": "Genre", - "author": "Author", - "era": "Era", - "language": "Lang" - } - }, - "highlightOfTheDay": { - "title": "Highlight of the Day", - "empty": "Highlight passages while reading to see them here" - }, - "libraryOverview": { - "title": "Library Overview", - "empty": "Your library is empty. Add some books to get started.", - "addedThisYear": "+{count} added this year", - "stats": { - "books": "Books", - "authors": "Authors", - "series": "Series", - "storage": "Storage" - } - }, - "longWait": { - "title": "The Long Wait", - "empty": "No books waiting. You've started everything!", - "daysWaiting": "days waiting", - "pages": "{count, plural, =0 {no pages} one {# page} other {# pages}}", - "startReading": "Start Reading" - }, - "monthlyChallenge": { - "title": "Monthly Challenge", - "complete": "Complete!" - }, - "neglectedGems": { - "title": "Neglected Gems", - "empty": "All your top-rated books have been read!", - "rating": "{rating}/5", - "daysWaiting": "{count}d waiting", - "queued": "Queued", - "addToQueue": "Add to queue", - "shuffle": "Shuffle" - }, - "readingDna": { - "title": "Reading DNA", - "notEnoughData": "Read at least 5 books to unlock your Reading DNA", - "basedOn": "{count, plural, =0 {Based on no books} one {Based on # book} other {Based on # books}}", - "traits": { - "length": "Length", - "variety": "Variety", - "rhythm": "Rhythm", - "time": "Time", - "speed": "Speed" - } - }, - "readingGoal": { - "title": "Reading Goal {year}", - "setGoalPrompt": "Set a reading goal to track your progress", - "setGoal": "Set goal", - "booksPerYear": "Books per year", - "ofGoal": "of {goal}", - "percentComplete": "{percentage}% complete", - "editGoal": "Edit goal" - }, - "readingRhythm": { - "title": "Reading Rhythm", - "empty": "Start reading to see your rhythm take shape", - "activeDays": "{count, plural, =0 {no active days} one {# active day} other {# active days}}", - "consistency": "{activeDays} · {percent}% consistency", - "avgPerDay": "avg {time}/day" - }, - "readingStreak": { - "title": "Reading Streak", - "empty": "Read today to start your streak", - "streakLabel": "{count, plural, =0 {day streak} one {day streak} other {days streak}}", - "best": "{count, plural, =0 {Best: # day} one {Best: # day} other {Best: # days}}", - "lastSevenDays": "Last 7 days" - }, - "yearProjection": { - "title": "Year Projection", - "books": "books", - "trendUp": "Trending up", - "trendDown": "Trending down", - "trendSteady": "Steady pace", - "pages": "pages", - "hours": "hours", - "readCount": "{count} read", - "daysLeft": "{count}d left" - } - } - }, - "email": { - "title": "Email", - "subtitle": "Send books to your e-reader via email.", - "loadFailed": "Failed to load", - "saveFailed": "Failed to save", - "deleteFailed": "Failed to delete", - "setDefaultFailed": "Failed to set default", - "setAsDefault": "Set as default", - "saving": "Saving...", - "update": "Update", - "create": "Create", - "deleteConfirm": "Delete \"{name}\". This action cannot be undone.", - "badge": { - "default": "Default", - "shared": "Shared", - "system": "System" - }, - "tabs": { - "providers": "Providers", - "recipients": "Recipients", - "groups": "Groups", - "templates": "Templates", - "preferences": "Preferences", - "history": "History" - }, - "providers": { - "heading": "SMTP Providers", - "add": "Add provider", - "newTitle": "New Provider", - "editTitle": "Edit Provider", - "name": "Name", - "namePlaceholder": "e.g. Gmail", - "host": "Host", - "port": "Port", - "username": "Username", - "password": "Password", - "passwordEdit": "Password (leave blank to keep current)", - "fromName": "From Name", - "fromNamePlaceholder": "My Library", - "fromAddress": "From Address", - "authentication": "Authentication", - "verifyTls": "Verify TLS certificate", - "tlsWarning": "TLS verification is disabled. The server's certificate will not be validated - use only for trusted internal servers.", - "noFromAddress": "no from address", - "emptyManage": "No providers yet. Add an SMTP provider to start sending emails.", - "emptyReadonly": "No providers available. Ask an administrator to add one.", - "setSystemTooltip": "Set as system mail provider", - "removeSystemTooltip": "Remove as system mail provider", - "testTooltip": "Test connection", - "toggleSharing": "Toggle sharing", - "removeSystemBeforeDelete": "Remove the system designation before deleting", - "notesHeading": "Provider Notes", - "notesBody": "The {system} provider (superuser only) is used for password reset emails. The {defaultProvider} provider is used when sending books with no explicit provider selected. Providers marked {shared} are available to all users.", - "deleteTitle": "Delete provider?", - "nameHostRequired": "Name and host are required", - "created": "Provider created", - "updated": "Provider updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default", - "unshared": "Provider unshared", - "sharedWithAll": "Provider shared with all users", - "updateSharingFailed": "Failed to update sharing", - "systemRemoved": "\"{name}\" removed as system mail provider", - "systemSet": "\"{name}\" set as system mail provider", - "updateSystemFailed": "Failed to update system provider", - "connectionSuccess": "Connection successful", - "connectionFailed": "Connection failed", - "testFailed": "Test failed" - }, - "recipients": { - "heading": "Recipients", - "add": "Add recipient", - "newTitle": "New Recipient", - "editTitle": "Edit Recipient", - "name": "Name", - "namePlaceholder": "My Kindle", - "emailAddress": "Email address", - "deviceType": "Device type", - "deviceNone": "None", - "deviceOther": "Other", - "preferredFormat": "Preferred format", - "formatAuto": "Auto", - "defaultTemplate": "Default template", - "useAccountDefault": "Use account default", - "kindleNote": "Kindle recipients automatically receive emails with subject \"convert\" to trigger format conversion.", - "empty": "No recipients yet.", - "prefersFormat": "prefers {format}", - "deleteTitle": "Delete recipient?", - "nameEmailRequired": "Name and email are required", - "created": "Recipient created", - "updated": "Recipient updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default" - }, - "groups": { - "heading": "Recipient Groups", - "create": "Create group", - "newTitle": "New Group", - "name": "Group name", - "namePlaceholder": "e.g. Book Club", - "creating": "Creating...", - "empty": "No groups yet. Create a group to send to multiple recipients at once.", - "memberCount": "{count, plural, =0 {no members} one {one member} other {# members}}", - "deleteTooltip": "Delete group", - "noMembers": "No members yet.", - "removeMember": "Remove", - "selectRecipient": "Select recipient...", - "add": "Add", - "addMember": "Add member", - "allRecipientsInGroup": "All recipients are already in this group.", - "deleteTitle": "Delete group?", - "created": "Group created", - "createFailed": "Failed to create group", - "deleted": "\"{name}\" deleted", - "memberAdded": "Member added", - "addMemberFailed": "Failed to add member", - "memberRemoved": "Member removed", - "removeMemberFailed": "Failed to remove member" - }, - "templates": { - "heading": "Email Templates", - "new": "New template", - "newTitle": "New Template", - "editTitle": "Edit Template", - "name": "Name", - "namePlaceholder": "Default", - "subject": "Subject", - "body": "Body", - "availableVariables": "Available variables", - "editTemplate": "Edit template", - "empty": "No templates yet.", - "notesHeading": "Template Notes", - "notesBody": "System templates cannot be deleted. Administrators can edit them. Use variables like {variable} in subjects and bodies - they are replaced with book details at send time.", - "deleteTitle": "Delete template?", - "nameSubjectRequired": "Name and subject are required", - "created": "Template created", - "updated": "Template updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default" - }, - "preferences": { - "heading": "Email Preferences", - "defaultProvider": "Default provider", - "defaultProviderHint": "Used when no provider is specified. If empty, the account default is used.", - "noneAccountDefault": "None (use account default)", - "defaultRecipient": "Default recipient", - "defaultRecipientHint": "Used for quick send. Must be set to use the quick-send action on book cards.", - "none": "None", - "defaultTemplate": "Default template", - "defaultTemplateHint": "Used when no template is specified. Falls back to the system default if empty.", - "noneSystemDefault": "None (use system default)", - "save": "Save preferences", - "saved": "Preferences saved" - }, - "history": { - "heading": "Send History", - "empty": "No emails sent yet.", - "noSubject": "(no subject)", - "loadMore": "Load more", - "resend": "Resend", - "deleteTitle": "Delete history entry?", - "entryDeleted": "Entry deleted", - "queuedForResend": "Queued for resend", - "resendFailed": "Failed to resend", - "statusSent": "Sent", - "statusFailed": "Failed", - "statusQueued": "Queued", - "statusPending": "Pending" - }, - "send": { - "title": "Send via Email", - "bookCount": "{count, plural, =0 {no books} one {one book} other {# books}}", - "recipients": "Recipients", - "noRecipients": "No recipients configured. Add one in Email settings.", - "groups": "Groups", - "options": "Options", - "fileFormat": "File format", - "autoRecipientPreference": "Auto (use recipient preference)", - "unknownFormat": "Unknown", - "primarySuffix": "(primary)", - "provider": "Provider", - "template": "Template", - "default": "Default", - "send": "Send", - "sending": "Sending...", - "queued": "{count, plural, =0 {no emails queued} one {one email queued} other {# emails queued}}", - "failed": "Failed to send" - } - }, - "hardcover": { - "settings": { - "subtitle": "Sync your reading progress, status, and ratings to Hardcover." - }, - "bookSync": { - "label": "Hardcover Sync", - "toggleAriaLabel": "Sync this book with Hardcover", - "syncNow": "Sync now" - }, - "connection": { - "title": "Connection", - "description": "Connect your Hardcover account to sync reading data.", - "connected": "Connected", - "apiToken": "API Token", - "tokenPlaceholder": "Paste your Hardcover API token", - "show": "Show", - "hide": "Hide", - "findTokenAt": "Find your token at", - "validateToken": "Validate token", - "valid": "Valid ({username})", - "invalidToken": "Invalid token", - "syncOptions": "Sync options", - "syncInfo": "Sync runs only for books that are not unread. This applies to status, progress, and rating triggers. These switches control when a sync runs.", - "syncScope": { - "title": "Book sync scope", - "allEligible": { - "label": "All eligible books", - "description": "Sync everything unless you exclude a book." - }, - "selectedOnly": { - "label": "Selected books only", - "description": "Sync only books you explicitly include." - } - }, - "enableSync": { - "title": "Enable sync", - "description": "Pause all Hardcover syncing without disconnecting." - }, - "syncOnStatus": { - "title": "Sync on status change", - "description": "Push updates when you mark a book as reading, read, etc." - }, - "syncOnProgress": { - "title": "Sync on progress update", - "description": "Push reading progress and dates when BookOrbit or KOReader progress changes." - }, - "syncOnRating": { - "title": "Sync on rating change", - "description": "Push your star ratings to Hardcover." - }, - "privacy": { - "title": "Privacy", - "description": "Default visibility for synced books on Hardcover.", - "public": "Public", - "followersOnly": "Followers only", - "private": "Private" - }, - "disconnect": "Disconnect", - "toast": { - "enterToken": "Enter your Hardcover API token first", - "saved": "Hardcover settings saved", - "saveFailed": "Failed to save settings", - "disconnected": "Hardcover disconnected" - } - }, - "sync": { - "title": "Manual sync", - "description": "Push your {scope} to Hardcover now.", - "scope": { - "selected": "selected books", - "eligible": "eligible books" - }, - "checkingPending": "Checking pending items...", - "pendingOf": "{pending} pending of {total} books.", - "noBooksInScope": "No books in sync scope.", - "allSynced": "All books are already synced.", - "lastSyncedLabel": "Last synced", - "lastSuccessfulSync": "Last successful sync", - "syncing": "Syncing...", - "progressCount": "{synced} / {total} books", - "unavailable": { - "permissionDenied": "You do not have permission to use Hardcover sync.", - "userDisabled": "Sync is paused in your Hardcover settings." - }, - "button": { - "unavailable": "Sync unavailable", - "syncNow": "Sync now", - "syncNowCount": "Sync now ({count})" - }, - "lastSynced": { - "justNow": "Just now", - "minutesAgo": "{count} min ago", - "hoursAgo": "{count, plural, =0 {# hour ago} one {# hour ago} other {# hours ago}}", - "daysAgo": "{count, plural, =0 {# day ago} one {# day ago} other {# days ago}}" - } - }, - "import": { - "title": "Pull read status", - "description": "Preview Hardcover matches before filling blank BookOrbit statuses.", - "clear": "Clear", - "preview": "Preview", - "importProgress": "Import progress", - "reviewMatches": "Review matches", - "importReady": "Import ready", - "exactMatches": "{count, plural, =0 {no exact matches can be imported without review} one {# exact match can be imported without review} other {# exact matches can be imported without review}}", - "progressAvailable": "{count, plural, =0 {no progress updates available} one {# progress update available} other {# progress updates available}}", - "progressConflicts": "{count, plural, =0 {no conflicts} one {# conflict} other {# conflicts}}", - "unavailable": { - "permissionDenied": "You do not have permission to use Hardcover sync.", - "missingToken": "Connect Hardcover before importing.", - "userDisabled": "Sync is paused in your Hardcover settings." - }, - "summary": { - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "result": { - "summary": "{applied} imported{progress}, {failed} failed", - "progressUpdated": "{count} progress updated" - }, - "toast": { - "importFailed": "Failed to import Hardcover read status", - "imported": "{count, plural, =0 {no read statuses imported{progress}} one {# read status imported{progress}} other {# read statuses imported{progress}}}", - "progressUpdates": "{count, plural, =0 {no progress updates} one {# progress update} other {# progress updates}}" - } - }, - "review": { - "title": "Hardcover import review", - "subtitle": "{total} Hardcover books, {matched} matched.", - "closeAriaLabel": "Close import review", - "searchPlaceholder": "Search title or author", - "importProgress": "Import progress", - "untitled": "Untitled", - "blank": "blank", - "noRows": "No rows match the current filters.", - "selectRowAriaLabel": "Select {title}", - "selectionSummary": "{count} selected: {ready} ready, {reviewed} reviewed.", - "selectedProgress": "{count, plural, =0 {no progress updates} one {# progress update} other {# progress updates}}", - "selectReady": "Select ready", - "selectPage": "Select page", - "clearPage": "Clear page", - "clearSelection": "Clear selection", - "importSelected": "Import selected", - "previousPage": "Previous page", - "nextPage": "Next page", - "pageRange": "{start}-{end} of {total}", - "tabs": { - "all": "All", - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "summary": { - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "matchOptions": { - "all": "All match types" - }, - "matchMethod": { - "hardcoverId": "Hardcover ID", - "isbn": "ISBN", - "titleAuthor": "Title + author" - }, - "outcome": { - "ready": "Ready", - "review": "Review", - "conflict": "Conflict", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "column": { - "progress": "Progress" - } - } - }, - "library": { - "creator": { - "createTitle": "Create Library", - "editTitle": "Edit: {name}", - "stepOf": "Step {current} of {total}", - "unsaved": "Unsaved", - "required": "Required", - "closeAria": "Close library creator", - "progressAria": "Library setup progress", - "sectionsAria": "Library settings sections", - "loadingAria": "Loading library settings", - "sections": { - "details": "Details", - "folders": "Folders", - "scanner": "Scanner", - "metadata": "Metadata", - "fileWrite": "File Write", - "reading": "Reading", - "schedule": "Schedule", - "access": "Access" - }, - "actions": { - "saving": "Saving…", - "saveChanges": "Save changes", - "creating": "Creating…", - "createLibrary": "Create library" - }, - "details": { - "libraryName": "Library name", - "namePlaceholder": "My Library", - "coverStyle": { - "title": "Cover style", - "portrait": "Portrait", - "square": "Square", - "hint": "Portrait for ebook or mixed libraries. Square for audiobook-only libraries." - }, - "icon": { - "label": "Icon", - "placeholder": "Choose an icon...", - "selected": "Selected" - } - }, - "folders": { - "title": "Scan folders", - "description": "Add one or more directories to scan for books.", - "browseAdd": "Browse and add a folder", - "browseTitle": "Browse server folders", - "browseDescription": "Select one or more folders without leaving the browser.", - "selectedTitle": "Selected folders", - "addFolders": "Add folders", - "manualEntry": "Enter a path manually", - "absolutePath": "Absolute server path", - "addFolder": "Add folder", - "removeFolder": "Remove {folder}", - "manualCheckHint": "Manual paths are checked together with the rest of the selected folders.", - "pathPlaceholder": "/path/to/books", - "test": "Test", - "add": "Add", - "pathNotAccessible": "Path is not accessible on the server.", - "pathAccessible": "Path is accessible.", - "pathNotAccessibleShort": "Path is not accessible", - "overlapsWith": "Overlaps with \"{library}\"", - "noneAdded": "No folders added yet", - "runPrescanHint": "Run a prescan to validate paths before saving.", - "scanning": "Scanning…", - "prescan": "Prescan" - }, - "scanner": { - "scanMode": { - "title": "Scan mode", - "lockedAria": "Organization mode is locked", - "lockTooltip": "Organization mode is fixed after library creation because changing it can create duplicate or missing book entries. To use a different mode, create a new library and rescan.", - "recommended": "Recommended", - "folderAsBook": { - "title": "Folder as Book", - "hint": "All files in a folder are grouped into one book. Works well when you keep multiple formats, like EPUB and MOBI, together." - }, - "fileAsBook": { - "title": "File as Book", - "hint": "Treats every file as an individual book. Best suited for libraries with one format per title. Avoid if your audiobooks span multiple files." - } - }, - "allowedFormats": { - "title": "Allowed formats", - "allowAll": "Allow all", - "allAllowed": "All formats are allowed.", - "onlySelected": "Only the selected formats will be imported.", - "warning": "Books in other formats already in the library will be marked as missing on the next scan." - }, - "excludePatterns": { - "title": "Exclude patterns", - "hintBefore": "Glob patterns to skip during scanning (e.g. ", - "hintAfter": ").", - "add": "Add", - "empty": "No patterns added." - } - }, - "metadata": { - "sourcePrecedence": { - "title": "Source precedence", - "hint": "The highest source in the list is preferred when multiple are available." - }, - "formatPriority": { - "title": "Format priority", - "hint": "When a book has multiple formats, the format highest in the list is preferred." - } - }, - "fileWrite": { - "maxFileSizeMb": "Max file size (MB)", - "formatLimits": "Format limits", - "rename": { - "title": "Rename files after metadata changes", - "hint": "Renames physical files when title, author, series, or year changes, using the library naming pattern." - }, - "write": { - "title": "Write metadata to files", - "hint": "When enabled, saving metadata will also write changes back into the physical file on disk." - }, - "cover": { - "title": "Include cover image", - "hint": "Writes the stored cover back into supported file formats." - }, - "epub": { - "title": "EPUB", - "hint": "Writes metadata into the OPF file inside the EPUB archive.", - "toggleAria": "Write EPUB metadata" - }, - "fb2": { - "title": "FictionBook (FB2)", - "hint": "Rewrites the description block inside FB2 files, leaving the book text untouched.", - "toggleAria": "Write FB2 metadata" - }, - "pdf": { - "title": "PDF", - "hint": "Embeds metadata into PDF Info dictionary and XMP stream.", - "toggleAria": "Write PDF metadata" - }, - "cbx": { - "title": "Comic archives (CBX)", - "hint": "Writes ComicInfo.xml into CBZ and CB7 archives.", - "toggleAria": "Write comic archive metadata" - }, - "kindle": { - "title": "Kindle (MOBI, AZW3)", - "hint": "Writes metadata into the EXTH header of MOBI, AZW3, and AZW files.", - "toggleAria": "Write Kindle metadata" - }, - "audio": { - "title": "Audio", - "hint": "Embeds the stored cover into M4B, M4A, MP3, and FLAC files.", - "toggleAria": "Write audio covers" - } - }, - "reading": { - "readingStart": { - "title": "Reading start", - "hint": "A book is marked as \"reading\" once this percentage of progress is reached." - }, - "markAsFinished": { - "title": "Mark as finished", - "hint": "A book is automatically marked as \"read\" when this percentage of progress is reached." - } - }, - "schedule": { - "fileWatching": "File watching", - "autoScanSchedule": "Auto-scan schedule", - "cronExpression": "Cron expression", - "cronInvalid": "Invalid cron expression.", - "cronFormat": "Format: minute hour day month weekday", - "watchFolders": { - "title": "Watch folders", - "hint": "Automatically detect new files added to library folders." - }, - "presets": { - "never": "Never", - "hourly": "Every hour", - "every6Hours": "Every 6 hours", - "every12Hours": "Every 12 hours", - "daily": "Daily", - "weekly": "Weekly", - "custom": "Custom" - }, - "human": { - "disabled": "Auto-scan disabled", - "hourly": "Every hour", - "every6Hours": "Every 6 hours", - "every12Hours": "Every 12 hours", - "dailyMidnight": "Daily at midnight", - "weeklyMonday": "Weekly on Monday at midnight", - "cron": "Cron: {cron}" - } - }, - "access": { - "title": "Access control", - "description": "Superusers always have full access. Grant access to other users below.", - "notYetCreated": "Access can be configured after the library is created.", - "selectUser": "Select a user…", - "grant": "Grant", - "empty": "No users have been granted access yet.", - "loading": "Loading access settings...", - "userSelectAria": "User to grant access", - "levelSelectAria": "Access level to grant", - "levels": { - "viewer": "Viewer", - "editor": "Editor", - "owner": "Owner" - }, - "columns": { - "user": "User", - "accessLevel": "Access level" - }, - "errors": { - "grant": "Failed to grant access", - "updateLevel": "Failed to update access level", - "revoke": "Failed to revoke access" - } - } - }, - "folderPicker": { - "title": "Browse server folders", - "description": "Select one or more folders for this library.", - "closeAria": "Close folder browser", - "currentFolderAria": "Current folder", - "parentFolder": "Go to parent folder", - "newFolder": "New folder", - "goUp": "Go up", - "filterPlaceholder": "Filter folders…", - "clearFilterAria": "Clear folder filter", - "newFolderNamePlaceholder": "New folder name", - "create": "Create", - "loading": "Loading folders...", - "selectCurrent": "Select current folder", - "noMatches": "No matching folders", - "noMatchesHint": "Try a different filter.", - "empty": "This folder is empty", - "emptyHint": "You can select the current folder or create a new one.", - "openFolderAria": "Open {name}", - "selectedCount": "{count, plural, =0 {no folders selected} one {# folder selected} other {# folders selected}}", - "noFolders": "No folders found", - "selectFolder": "Select this folder", - "errors": { - "readDirectory": "Could not read directory", - "connect": "Could not connect", - "invalidName": "Enter a single folder name without slashes or leading dots", - "createFolder": "Could not create folder" - } - }, - "upload": { - "library": "Library", - "selectLibrary": "Select a library...", - "targetFolder": "Target folder", - "addMoreFiles": "Add more files", - "clearAll": "Clear all", - "done": "Done", - "retry": "Retry", - "upload": "Upload", - "uploadWithCount": "Upload ({count})", - "viewInLibrary": "View in Library", - "fileCount": "{count, plural, =0 {no files} one {# file} other {# files}}", - "booksAdded": "{count, plural, =0 {no books added} one {# book added} other {# books added}}", - "uploadedFailed": "{done} uploaded, {failed} failed", - "progress": "{done} of {total} uploading...", - "header": { - "uploading": "Uploading...", - "complete": "Upload complete", - "uploadTo": "Upload to {library}", - "uploadBooks": "Upload Books" - }, - "dropzone": { - "title": "Drop files here or click to browse", - "hint": "{formats} - up to {size} MB each" - } - } - }, - "metadataScore": { - "missingFields": "{count, plural, =0 {no fields missing - edit metadata} one {# field missing - edit metadata} other {# fields missing - edit metadata}}" - }, - "migration": { - "sidebarTitle": "Booklore Import", - "status": { - "done": "Done", - "saved": "Saved", - "running": "Running", - "failed": "Failed" - }, - "badge": { - "validated": "Validated", - "upToDate": "Up to date", - "completed": "Completed" - }, - "steps": { - "source": { - "short": "Source Connection", - "title": "Source Connection", - "subtitle": "Configure the database connection to your source Booklore instance." - }, - "mappings": { - "short": "User & Path Mapping", - "title": "User & Path Mapping", - "subtitle": "Map source users to target users and translate file paths." - }, - "dryRun": { - "short": "Dry Run", - "title": "Dry Run", - "subtitle": "Preview what will be imported before running the live migration." - }, - "migration": { - "short": "Run Migration", - "title": "Run Migration", - "subtitle": "Start the live import and monitor its progress." - }, - "report": { - "short": "Report", - "title": "Migration Report", - "subtitle": "Review what was imported and export a detailed report." - } - }, - "footer": { - "continueToMappings": "Continue to Mappings", - "continueToDryRun": "Continue to Dry Run", - "continueToMigration": "Continue to Migration", - "viewReport": "View Report", - "resetSetup": "Reset Setup", - "stepOf": "Step {current} of {total}", - "backToSetup": "Back to Setup" - }, - "stages": { - "init": "Initializing", - "sharedOverlays": "Importing metadata", - "bookCovers": "Importing covers", - "userState": "Importing user data" - }, - "source": { - "testConnection": "Test Connection", - "saveAndValidate": "Save & Validate", - "validatedWithWarnings": "Source validated with warnings", - "fields": { - "type": "Source Type", - "name": "Source Name", - "host": "Host", - "port": "Port", - "user": "User", - "password": "Password", - "passwordSaved": "Saved - leave unchanged", - "passwordNotSet": "No password set", - "database": "Database", - "mediaRootPath": "Media Root Path", - "ssl": "Use TLS/SSL" - }, - "mediaPath": { - "hintRequired": "Required for migrating book covers.", - "hintAbsolute": "Use an absolute path (for example: /books). Relative paths are not supported.", - "hintConfigured": "Cover import path configured. Use Test Connection to verify access and Booklore images folder structure.", - "buttonOk": "Path OK", - "buttonIssue": "Path Issue", - "buttonTest": "Test Path" - }, - "compatibility": { - "title": "Tested compatibility", - "verifiedAgainst": "Verified against:", - "note": "Later versions are likely compatible but have not been verified. Run a dry-run first to confirm before committing data." - }, - "snapshot": { - "title": "Last validation snapshot", - "sourceVersion": "Source version: {version}", - "unknown": "Unknown", - "missingTables": "Missing required tables: {tables}" - } - }, - "mappings": { - "suggestionsAutoLoad": "User suggestions load automatically after source validation.", - "refresh": "Refresh", - "sourceUser": "Source User", - "targetUser": "Target User", - "noSourceUsersLoaded": "No source users loaded yet.", - "noActiveTargetUsers": "No active target users found. Create or re-enable a BookOrbit user before mapping.", - "pathPrefixMappings": "Path Prefix Mappings", - "addMapping": "Add Mapping", - "pathMappingsExplanation": "Path mappings translate source file paths to target paths so books can be matched by file location. Books are also matched by ISBN, file hash, and title/author regardless of path mappings.", - "noPrefixesFound": "No prefixes found - validate source first", - "selectSourcePrefix": "Select source prefix...", - "selectTargetFolder": "Select target folder...", - "remove": "Remove", - "saveMappings": "Save Mappings", - "pathValidation": { - "title": "Path validation", - "mappedSummary": "{mapped} of {total} source books have a mapped path", - "unmatched": "{count} mapped paths not found on disk", - "allMatched": "All {count} mapped paths found on disk" - } - }, - "dryRun": { - "run": "Run Dry-Run", - "matched": "Matched:", - "unresolved": "Unresolved:", - "duplicates": "Duplicates:", - "unresolvedSummary": "Unresolved summary" - }, - "duplicates": { - "title": "Resolve duplicate target matches", - "explanation": "For each target book, choose one source book to keep. Recommended choices are preselected when there is a single strongest match.", - "remainingGroups": "Remaining groups:", - "ofCount": "of {total}", - "targetBookId": "Target book #{id}", - "recommended": "Recommended", - "resolveButton": "{count, plural, =0 {Resolve # duplicate} one {Resolve # duplicate} other {Resolve # duplicates}}", - "sourceRecordId": "Source record ID #{id}", - "byAuthor": "by {author} (ID: {id})", - "byFilePath": "{filePath} (ID: {id})", - "bookloreSourceId": "Booklore source ID: {id}", - "libraryBookId": "Library book #{id}" - }, - "preflight": { - "title": "Preflight checks", - "allPassed": "All checks passed - ready to migrate", - "sourceValidated": "Source validated", - "saveAndValidateSource": "Save and validate source connection", - "validateSourceConnection": "Validate source connection", - "mappingsSaved": "Mappings saved", - "saveUserAndPathMappings": "Save user and path mappings", - "pathMappingsValidated": "Path mappings validated", - "savePathMappingsToValidate": "Save path mappings to validate them", - "dryRunUpToDate": "Dry-run is up to date", - "runFreshDryRun": "Run a fresh dry-run", - "issues": { - "saveSource": "Save source connection settings", - "validateSource": "Validate source connection", - "saveMappings": "Save user and path mappings", - "savePathMappings": "Save path mappings to validate them", - "freshDryRun": "Run a fresh dry-run", - "resolveDuplicates": "Resolve duplicate target book matches in the dry-run", - "waitForRun": "Wait for active run to finish" - } - }, - "run": { - "confirmPrompt": "This will start the live migration. Are you sure?", - "confirmStart": "Confirm Start", - "startMigration": "Start Migration", - "cancelRun": "Cancel Run", - "refreshStatus": "Refresh Status", - "pollingStopped": "Status polling stopped due to an error.", - "retry": "Retry", - "stage": "Stage: {stage}", - "initializing": "initializing", - "ended": "Ended {time}" - }, - "report": { - "noRunYet": "No migration run yet. Complete the steps above to start.", - "runNumber": "Run #{id}", - "notStarted": "Not started", - "reloadReport": "Reload Report", - "loadFullReport": "Load Full Report", - "exportJson": "Export JSON", - "exportCsv": "Export CSV", - "migrationFailed": "Migration failed", - "retryFromLastStage": "Retry from last completed stage", - "booksSection": "Books", - "metadataOverlays": "Metadata overlays applied", - "authorMappings": "Author mappings replaced", - "narratorMappings": "Narrator mappings replaced", - "genreMappings": "Genre mappings replaced", - "tagMappings": "Tag mappings replaced", - "coversImported": "Covers imported", - "coverImportSkipped": "Cover import skipped - media root path not configured", - "couldNotMatch": "Could not match", - "userDataSection": "User Data", - "readingStatuses": "Reading statuses", - "readingProgressEntries": "Reading progress entries", - "audiobookProgressEntries": "Audiobook progress entries", - "readingSessions": "Reading sessions", - "bookmarks": "Bookmarks", - "annotations": "Annotations", - "collectionEntries": "Collection entries", - "loadFullReportHint": "Click \"Load Full Report\" to include the dry-run match summary in the exported report.", - "completedNoIssues": "Migration completed with no unresolved books or failures.", - "matchedBooks": "Matched books ({count})", - "matchedBooksExplanation": "These dry-run matches were used to decide which library books received imported data.", - "sourceBook": "Source book {id}", - "libraryBook": "Library book {id}", - "unresolvedBooks": "Unresolved books ({count})", - "unresolvedBooksExplanation": "These books exist in the source but could not be matched to any book in your library.", - "mappedUsers": "Mapped users ({count})", - "mappedUsersExplanation": "Per-user totals come from the dry-run preview cached with the migration plan.", - "coverFailures": "{count} cover import(s) failed. Detailed failure rows are not stored.", - "userPreviewCounts": "{statuses} statuses, {progress} progress entries, {sessions} reading sessions, {bookmarks} bookmarks, {annotations} annotations, {collections} collection entries" - }, - "unresolvedReason": { - "noTitleAuthorMatch": "No matching book found by title or author", - "noFilePathMatch": "File path did not match any book in this library", - "noFileHashMatch": "File hash did not match any book in this library", - "noIsbnMatch": "ISBN did not match any book in this library", - "insufficientSourceData": "Not enough metadata to attempt matching", - "ambiguousIsbnMatch": "Multiple books matched the same ISBN", - "ambiguousFileHashMatch": "Multiple books matched the same file hash", - "ambiguousFilePathMatch": "Multiple books matched the same file path", - "ambiguousTitleAuthorMatch": "Multiple books matched the same title and author", - "unknown": "Could not determine reason" - }, - "matchStrategy": { - "isbn": "Matched by ISBN", - "fileHash": "Matched by file hash", - "pathMapping": "Matched by mapped file path", - "titleAuthor": "Matched by title and author", - "unavailable": "Match strategy unavailable" - }, - "connectionError": { - "unreachable": "Could not reach the database server. Check the host and port.", - "authFailed": "Authentication failed. Check the username and password.", - "databaseNotFound": "Database not found. Check the database name.", - "timeout": "Connection timed out. Check host and firewall settings.", - "generic": "Connection test failed" - }, - "userSelect": { - "placeholder": "Select user", - "noUsersFound": "No users found" - }, - "toast": { - "initFailed": "Failed to initialize migration settings", - "loadSupportedTypesFailed": "Failed to load supported migration source types", - "loadTargetUsersFailed": "Failed to load target users", - "loadTargetFoldersFailed": "Failed to load target library folders", - "noSourceUsers": "No source users were returned", - "suggestionsLoaded": "User mapping suggestions loaded", - "loadSuggestionsFailed": "Failed to load user mapping suggestions", - "sourceFieldsRequired": "Host, user, database, and source name are required", - "connectionPassedWithWarnings": "Connection test passed with warnings", - "connectionPassedWithWarningCount": "Connection test passed with {count} warning(s). First: {warning}", - "connectionPassed": "Connection test passed", - "connectionMissingTables": "Connection ok, but {count} required table(s) are missing", - "cannotTestMediaWhileRunning": "Cannot test media path while a run is active", - "mediaPathRequired": "Media Root Path is required for cover import.", - "mediaPathAbsolute": "Use an absolute path (for example: /books).", - "mediaPathVerified": "Media path verified.", - "mediaPathValid": "Media path is valid and readable", - "mediaPathValidationFailed": "Media path validation failed.", - "connectionFailedBeforeMedia": "Connection test failed before media path validation could complete.", - "cannotModifySourceWhileRunning": "Cannot modify source while a run is active", - "sourceSavedWithWarnings": "Source saved and validated with {count} warning(s)", - "sourceSaved": "Source saved and validated", - "saveSourceFailed": "Failed to save or validate source", - "cannotSaveMappingsWhileRunning": "Cannot save mappings while a run is active", - "saveSourceFirst": "Save source first", - "mapAtLeastOneUser": "Map at least one source user to a target user", - "mapEveryUser": "Map every source user before saving", - "pathValidationFailedButSaved": "Path validation failed, but profile will still be saved", - "mappingsSaved": "Mappings saved", - "saveMappingsFailed": "Failed to save mappings", - "cannotDryRunWhileRunning": "Cannot run dry-run while a run is active", - "saveMappingsFirst": "Save mappings first", - "dryRunCompleted": "Dry-run completed: {matched} matched, {unresolved} unresolved", - "dryRunFailed": "Dry-run failed", - "selectSourceForDuplicates": "Select a source book for all {count} duplicate groups", - "duplicatesResolved": "Duplicate matches resolved", - "resolveDuplicatesFailed": "Failed to resolve duplicates", - "preflightNotReady": "Migration preflight not ready", - "runDryRunFirst": "Run dry-run first", - "runStarted": "Migration run started", - "startFailed": "Failed to start migration", - "runCancelled": "Migration run cancelled", - "cancelFailed": "Failed to cancel migration", - "runRetried": "Migration run retried - resuming from last completed stage", - "retryFailed": "Failed to retry migration", - "loadProgressFailed": "Failed to load run progress", - "startMigrationFirst": "Start migration first", - "reportRefreshed": "Run report refreshed", - "loadReportFailed": "Failed to load run report", - "reportExported": "Report exported as {format}", - "exportFailed": "Failed to export migration report" - } - }, - "notifications": { - "title": "Notifications", - "markAllRead": "Mark all read", - "clear": "Clear", - "empty": "No notifications yet", - "loadMore": "Load more notifications", - "preferences": { - "title": "Notifications", - "subtitle": "Choose which notification categories you want to receive.", - "saving": "Saving...", - "unsavedChanges": "Unsaved changes", - "saved": "Notification preferences saved", - "saveFailed": "Failed to save preferences", - "savePreferenceFailed": "Failed to save preference", - "whatsNewToggle": "Show \"What's New\" after updates", - "whatsNewToggleHint": "A popup highlighting new features after the app updates. The archive stays available either way.", - "groups": { - "library": "Library", - "files": "Files", - "integrations": "Integrations", - "personal": "Personal", - "app": "App updates" - }, - "enabledCount": "{enabled} of {total} enabled", - "categories": { - "scanning": { - "label": "Library scanning", - "description": "When a library scan finishes, fails, or finds missing books." - }, - "metadata": { - "label": "Metadata fetching", - "description": "When metadata lookups for your books complete or fail." - }, - "authorEnrichment": { - "label": "Author enrichment", - "description": "When author biographies and photos finish being fetched." - }, - "fileWriteBack": { - "label": "File write-back", - "description": "When edited metadata is written back into book files on disk." - }, - "fileRename": { - "label": "File rename", - "description": "When a single book file is renamed to match your naming pattern." - }, - "bulkRename": { - "label": "Bulk rename", - "description": "When a bulk rename across many books completes or fails." - }, - "migration": { - "label": "Data migration", - "description": "When an import from another library tool completes or fails." - }, - "bookDock": { - "label": "Book Dock", - "description": "When files dropped into the dock are ready to review or finalized." - }, - "koboSync": { - "label": "Kobo sync", - "description": "When a Kobo device finishes syncing with your library." - }, - "email": { - "label": "Email delivery", - "description": "When sending a book to an email address succeeds or fails." - }, - "achievements": { - "label": "Achievements", - "description": "When you unlock a new reading achievement." - } - } - } - }, - "reader": { - "retry": "Retry", - "pdf": { - "openError": "Unable to open this PDF", - "preparing": "Preparing PDF reader", - "opening": "Opening PDF" - }, - "loadingBook": "Loading book…", - "failedToLoadBook": "Failed to load book", - "chapterNumber": "Chapter {number}", - "peek": { - "badge": "Peeking", - "startReading": "Start reading" - }, - "toast": { - "linkedHighlightError": "Could not open the linked highlight position", - "resumed": "Resumed at {pct}% - {label}" - }, - "header": { - "goBack": "Go back", - "tableOfContents": "Table of contents", - "toggleBookmark": "Toggle bookmark", - "cycleFooterMode": "Cycle footer info mode", - "keyboardShortcutsHint": "Keyboard shortcuts (?)", - "enterFullscreen": "Enter fullscreen", - "exitFullscreen": "Exit fullscreen", - "footerMode": { - "pageProgress": "Footer info: page + progress", - "sessionTimeLeft": "Footer info: reading session + time left", - "chapterTimeLeft": "Footer info: chapter + chapter time left" - } - }, - "footer": { - "previousSection": "Previous section", - "nextSection": "Next section", - "goToPlaceholder": "45 or p123", - "jumpToLocation": "Jump to location", - "jumpTooltip": "Jump to % or page (e.g. 45 or p123)", - "go": "Go" - }, - "settings": { - "title": "Settings", - "ariaLabel": "Reader settings", - "tabs": { - "appearance": "Appearance", - "text": "Text", - "layout": "Layout" - }, - "appearance": { - "mode": "Mode", - "light": "Light", - "dark": "Dark", - "colorTheme": "Color theme" - }, - "text": { - "fontSize": "Font size", - "fontSizeRange": "Range: 10-32px", - "lineHeight": "Line height", - "lineHeightRange": "Range: 0.8-3.0", - "fontFamily": "Font family", - "fontFamilyDescription": "Choose built-in or uploaded fonts for body text.", - "builtIn": "Built-in", - "yourFonts": "Your fonts" - }, - "layout": { - "pageSpreads": "Page spreads", - "pageSpreadsDescription": "Choose how this image-based EPUB pairs pages.", - "bookDefault": "Book default", - "singlePage": "Single page", - "readingFlow": "Reading flow", - "readingFlowDescription": "Switch between paged and continuous scrolling.", - "paginated": "Paginated", - "scrolled": "Scrolled", - "textColumns": "Text columns", - "textColumnsRange": "Range: 1-10", - "columnGap": "Column gap", - "columnGapRange": "Range: 0-50%", - "maxWidth": "Max width", - "maxWidthRange": "Range: 400-1600", - "justifyText": "Justify text", - "justifyTextDescription": "Enable full-width paragraph alignment.", - "hyphenation": "Hyphenation", - "hyphenationDescription": "Enable automatic word-break hyphenation." - } - }, - "search": { - "placeholder": "Search in book (min {min} chars)...", - "searching": "Searching…", - "tooShort": "Type at least {min} characters", - "noResults": "No results found", - "prompt": "Type to search", - "resultCount": "{count, plural, =0 {no results} one {# result} other {# results}}" - }, - "sidebar": { - "tabs": { - "chapters": "Chapters", - "bookmarks": "Bookmarks", - "highlights": "Highlights", - "toc": "Table of contents", - "tocShort": "TOC", - "marksShort": "Marks", - "notesShort": "Notes" - }, - "pin": "Pin sidebar", - "unpin": "Unpin sidebar", - "close": "Close sidebar", - "noChapters": "No chapters found", - "noBookmarks": "No bookmarks yet", - "noBookmarksMatch": "No bookmarks match your filters", - "noHighlights": "No highlights yet", - "noHighlightsMatch": "No highlights match your filters", - "searchBookmarks": "Search bookmarks...", - "searchHighlights": "Search highlights...", - "bookmarkFallback": "Bookmark", - "locationUnavailable": "Location unavailable", - "customColor": "Custom ({color})", - "allColors": "All colors", - "allChapters": "All chapters", - "notesOnly": "Notes only", - "deleteBookmark": "Delete bookmark", - "deleteHighlight": "Delete highlight", - "approximatePosition": "Synced from device; exact position unavailable, jumps to the chapter", - "sort": { - "readingOrder": "Reading order", - "newest": "Newest first", - "oldest": "Oldest first" - } - }, - "selection": { - "copy": "Copy", - "copied": "Copied!", - "highlight": "Highlight", - "translate": "Translate", - "define": "Define", - "deleteAnnotation": "Delete annotation", - "apply": "Apply" - }, - "note": { - "title": "Add note", - "placeholder": "Write your note…" - }, - "dictionary": { - "noDefinition": "No definition found", - "loadError": "Could not load definition" - }, - "translation": { - "original": "Original", - "translation": "Translation", - "translating": "Translating...", - "noTranslation": "No translation yet", - "viaProvider": "via {provider}", - "copyTranslation": "Copy translation" - }, - "shortcuts": { - "title": "Keyboard Shortcuts", - "groups": { - "panels": "Panels", - "reading": "Reading", - "actions": "Actions" - }, - "toggleToc": "Toggle table of contents", - "toggleSearch": "Toggle search", - "toggleHelp": "Show/hide this help", - "closePanel": "Close panel", - "prevNextPage": "Previous/next page", - "goToStart": "Go to start of book", - "goToEnd": "Go to end of book", - "toggleBookmark": "Toggle bookmark", - "toggleFullscreen": "Toggle fullscreen", - "cycleFooterMode": "Cycle footer info mode" - }, - "cbz": { - "tabs": { - "view": "View", - "reading": "Reading", - "layout": "Layout" - }, - "fitMode": "Fit mode", - "background": "Background", - "scrollMode": "Scroll mode", - "scrollModeHint": "Use \"No gaps\" for webtoons and vertical strips.", - "readingDirection": "Reading direction", - "pageView": "Page view", - "autoFallback": "Auto-fallback", - "spreadAlignmentLabel": "Spread alignment", - "spreadAlignmentHint": "Spread alignment is unavailable in auto-fallback mode.", - "spreadGap": "Spread gap", - "spreadGapValue": "{value}px", - "focusTwoPageToggle": "Focus two-page toggle", - "forceTwoPage": "Force two-page", - "off": "Off", - "on": "On", - "widePages": "Wide pages", - "resetBookViewSettings": "Reset book view settings", - "resetConfirm": "Reset view settings for this book to your global defaults?", - "firstPage": "First page", - "lastPage": "Last page", - "fit": { - "page": "Page Fit", - "width": "Page Width", - "height": "Page Height", - "actual": "Actual Size" - }, - "view": { - "single": "Single", - "twoPage": "Two-page" - }, - "scroll": { - "paged": "Paged", - "infinite": "Infinite", - "noGaps": "No gaps" - }, - "direction": { - "ltr": "L to R", - "rtl": "R to L" - }, - "spreadAlignment": { - "normal": "Normal", - "shifted": "Shifted" - }, - "widePage": { - "auto": "Auto", - "inSpreads": "In spreads" - }, - "bg": { - "black": "Black", - "gray": "Gray", - "white": "White" - } - }, - "audiobook": { - "untitled": "Untitled", - "loading": "Loading audiobook...", - "loadError": "Failed to load audiobook", - "noAudioFiles": "No audio files found for this book.", - "speed": "Speed", - "chapters": "Chapters", - "bookmarks": "Bookmarks", - "volume": "Volume", - "muted": "Muted", - "sleep": "Sleep", - "chapterAbbrev": "Ch.", - "sleepTimer": "Sleep timer", - "minutes": "{count, plural, one {# minute} other {# minutes}}", - "endOfChapter": "End of chapter", - "noChaptersAvailable": "No chapters available", - "extend15": "+ 15 minutes", - "timeLeft": "({time} left)", - "playbackSpeed": "Playback speed", - "noChapters": "No chapters available.", - "noBookmarks": "No bookmarks yet.", - "noBookmarksHint": "Tap the bookmark icon at the top to save your current position.", - "playerSettings": "Player settings", - "skipBack": "Skip back", - "skipForward": "Skip forward" - } - }, - "scanner": { - "filesProgress": "{processed}/{total} files", - "booksFound": "{count, plural, =0 {no books found} one {# book found} other {# books found}}" - }, - "series": { - "completion": { - "readOfTotal": "{read} of {total} read ({percentage}%)" - }, - "gaps": { - "label": "Possible gaps:" - }, - "filters": { - "title": "Series Filters", - "clearAll": "Clear all", - "allLibraries": "All Libraries", - "allCompletion": "All completion", - "notStarted": "Not started", - "inProgress": "In progress", - "complete": "Complete" - }, - "list": { - "title": "Series", - "showControlsAria": "Show series controls", - "searchPlaceholder": "Search series or author", - "sortButton": "Sort", - "sortBy": "Sort by", - "ascending": "Ascending", - "descending": "Descending", - "ascShort": "Asc", - "descShort": "Desc", - "filters": "Filters", - "clear": "Clear", - "noMatch": "No series match your filters.", - "empty": "No series found in your libraries.", - "sort": { - "name": "Name", - "bookCount": "Book Count", - "recentAdditions": "Recent Additions", - "readingProgress": "Reading Progress" - } - }, - "detail": { - "pageTitle": "Series", - "pageTitleNamed": "Series · {name}", - "pageTitleWithId": "Series #{id}", - "entityName": "Series", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "byAuthors": "by {authors}", - "moreAuthors": "+{count} more", - "preparingEditor": "Preparing editor...", - "editMetadata": "Edit Metadata", - "firstInSeries": "First in Series", - "untitled": "Untitled", - "loadingFirstBook": "Loading first book preview...", - "showLess": "Show less", - "showMore": "Show more", - "moreGenres": "+{count} more", - "synopsis": "Synopsis", - "noDescription": "No description available.", - "updatingPreview": "Updating preview...", - "noBooksToPreview": "No books available to preview.", - "loadingSeries": "Loading series...", - "booksHeading": "Books", - "allLibraries": "All Libraries", - "groupByMedia": "Group by media", - "noBooksFound": "No books found in this series", - "trySelectingLibrary": "Try selecting another library.", - "allBooksLoaded": "All {count} books loaded", - "leadBookLoadError": "Failed to load lead book details", - "noBooksToEdit": "This series has no books to edit.", - "loadFullSeriesError": "Failed to load the full series for editing.", - "sort": { - "seriesOrder": "Series Order", - "title": "Title", - "recentlyAdded": "Recently Added" - }, - "order": { - "ascending": "Ascending", - "descending": "Descending" - } - } - }, - "smartScope": { - "syncToKobo": "Sync to Kobo", - "syncToKoboHint": "Books matching this scope will appear on your Kobo device", - "visibleToAll": "Visible to all users", - "visibleToAllHint": "Every user can see and use this smart scope", - "dialog": { - "name": "Name", - "namePlaceholder": "e.g. Unread Sci-Fi", - "icon": "Icon", - "iconPlaceholder": "Choose an icon...", - "nameRequired": "Name is required", - "iconRequired": "Choose an icon", - "create": "Create", - "creating": "Creating...", - "saving": "Saving..." - }, - "createDialog": { - "title": "New Smart Scope", - "createFailed": "Failed to create Smart Scope" - }, - "saveAsDialog": { - "title": "Save as SmartScope", - "save": "Save SmartScope", - "saveFailed": "Failed to save Smart Scope" - }, - "editorPanel": { - "untitled": "Untitled SmartScope", - "subtitle": "Configure smart scope settings", - "counting": "counting...", - "bookCount": "{count, plural, =0 {no books} one {one book} other {# books}}", - "identity": "Identity", - "filters": "Filters", - "noFilters": "No filters set. All accessible books will be included in this smart scope.", - "buildFromScratch": "Build from scratch", - "replaceWithTemplate": "Replace with template:", - "defaultSort": "Default Sort", - "saveChanges": "Save changes", - "saveFailed": "Failed to save", - "templates": { - "hasSeries": "Has Series", - "addedRecently": "Added Recently", - "pdfOnly": "PDF Only", - "noGenres": "No Genres", - "epubOnly": "EPUB Only" - } - } - }, - "statistics": { - "tabs": { - "library": "Library Stats", - "user": "My Reading" - }, - "filter": { - "allLibraries": "All Libraries", - "librarySelection": "{count} of {total} Libraries" - }, - "config": { - "button": "Configure", - "title": "Configure Charts", - "description": "Drag to reorder, toggle to show or hide.", - "reset": "Reset to defaults" - }, - "summary": { - "books": "Books", - "authors": "Authors", - "series": "Series", - "publishers": "Publishers", - "storage": "Storage", - "genres": "Genres", - "languages": "Languages", - "published": "Published", - "thisYear": "This Year", - "started": "Started", - "inProgress": "In Progress", - "completed": "Completed", - "avgProgress": "Avg Progress" - }, - "card": { - "loadError": "Failed to load data", - "emptyTitle": "No data yet", - "emptyDescription": "No data available for this chart", - "unknownField": "{count, plural, =0 {no data for this field} one {# book has no data for this field} other {# books have no data for this field}}" - }, - "breakdown": { - "ariaLabel": "Break down by source or format" - }, - "empty": { - "notEnoughData": "Not enough data yet" - }, - "charts": { - "acquisitionLag": { - "title": "Acquisition Lag" - }, - "booksAddedOverTime": { - "title": "Books Added Over Time", - "monthly": "Monthly", - "yearly": "Yearly", - "allTime": "All Time", - "last5Years": "Last 5 Years", - "lastYear": "Last Year" - }, - "formatDistribution": { - "title": "Format Distribution" - }, - "formatShareOverTime": { - "title": "Format Share Over Time" - }, - "genreCooccurrence": { - "title": "Genre Co-occurrence" - }, - "genreDistribution": { - "title": "Genre Distribution" - }, - "languageDistribution": { - "title": "Language Distribution" - }, - "largestBooks": { - "title": "Top 50 Largest Books" - }, - "libraryIntegrity": { - "title": "Library Integrity" - }, - "libraryMetadataCompleteness": { - "title": "Library Metadata Completeness" - }, - "metadataCompleteness": { - "title": "Metadata Completeness" - }, - "metadataFreshness": { - "title": "Metadata Freshness" - }, - "metadataScoreDistribution": { - "title": "Metadata Score Distribution" - }, - "pageCountDistribution": { - "title": "Page Count Distribution" - }, - "publicationDecade": { - "title": "Publication Decade" - }, - "publicationYearTimeline": { - "title": "Publication Year Timeline" - }, - "storageByFormat": { - "title": "Storage by Format" - }, - "topAuthors": { - "title": "Top 25 Authors" - }, - "topSeries": { - "title": "Top 50 Series" - }, - "booksCompleted": { - "title": "Books Completed", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "completionLatency": { - "title": "Completion Latency", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "completionTimeline": { - "title": "Completion Timeline", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "favoriteReadingDays": { - "title": "Favorite Reading Days", - "notEnoughData": "Need at least {count} reading events for this chart." - }, - "genreReadingTime": { - "title": "Genre Reading Time", - "notEnoughData": "Need at least {count} genres with reading time for this chart." - }, - "goalTrajectory": { - "title": "Pace vs Goal", - "noCompletedTitle": "No completed books yet", - "noCompletedDescription": "Complete a book in this period to compare your pace against your yearly goal.", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "peakReadingHours": { - "title": "Peak Reading Hours", - "notEnoughData": "Need at least {count} reading events for this chart." - }, - "progressFunnel": { - "title": "Progress Funnel", - "modePercent": "Percent", - "modeCounts": "Counts", - "modeDropoff": "Drop-off", - "started": "Started {count}", - "notEnoughData": "Need at least {count} started books for this chart.", - "noDropOffTitle": "No drop-off observed", - "noDropOffDescription": "Every started book progressed through all funnel stages in this period." - }, - "readingClock": { - "title": "Reading Clock", - "notEnoughData": "Need at least {count} reading sessions for this chart." - }, - "readingHeatmap": { - "title": "Reading Heatmap", - "notEnoughData": "Need activity on at least {count} days for this chart." - }, - "readingPace": { - "title": "Reading Pace", - "notEnoughData": "Need at least {count} sessions with progress data for this chart." - }, - "readingSessionTimeline": { - "title": "Reading Session Timeline", - "dragOn": "Drag: On", - "dragOff": "Drag: Off", - "prev": "Prev", - "next": "Next", - "week": "Week {week}", - "dragHint": "Drag bars to move sessions. Duration is locked and overlapping sessions are rejected.", - "noSessionsTitle": "No sessions this week", - "noSessionsDescription": "Use Prev/Next or the week selector to view a different week.", - "overlapError": "Session overlaps another session in this window", - "moveError": "Failed to move session" - }, - "sessionArchetypes": { - "title": "Session Archetypes" - }, - "sourceDistribution": { - "title": "Where You Read", - "emptyTitle": "No reading activity yet", - "emptyDescription": "Read on the web, KOReader, or Kobo to see your source split." - } - } - }, - "tools": { - "header": { - "entityManager": "Entity Manager", - "bulkRename": "Bulk Rename", - "duplicateBooks": "Duplicate Books" - }, - "entityTypes": { - "authors": "Authors", - "genres": "Genres", - "tags": "Tags", - "narrators": "Narrators", - "publishers": "Publishers", - "languages": "Languages", - "series": "Series" - }, - "bulkRename": { - "previewToolbar": "Rename preview", - "renameSettings": "Rename settings", - "library": "Library", - "selectLibraryPlaceholder": "Select a library...", - "noEligibleLibraries": "No libraries have file rename enabled. Enable it in Library Settings.", - "refresh": "Refresh", - "applyRename": "Apply Rename", - "showFullPaths": "Show full paths", - "columnsMenu": "Columns", - "renamingInProgress": "Renaming files - you can cancel at any time.", - "executionFailed": "Bulk rename failed", - "previewFailed": "Failed to load preview", - "noBooksMatch": "No books found matching the current filter.", - "openBookDetails": "Open book details", - "columns": { - "title": "Title", - "currentPath": "Current Path", - "newPath": "New Path", - "status": "Status" - }, - "status": { - "willRename": "Will Rename", - "unchanged": "Unchanged", - "collision": "Collision", - "noPattern": "No Pattern", - "error": "Error" - }, - "filter": { - "all": "All" - }, - "summary": { - "label": "Summary", - "toRename": "{count} to rename", - "unchanged": "{count} unchanged", - "collisions": "{count, plural, =0 {# collision} one {# collision} other {# collisions}}", - "errors": "{count, plural, =0 {# error} one {# error} other {# errors}}" - }, - "empty": { - "title": "Pick a Library to Start", - "description": "Select a library above to preview rename changes, filter by status, and apply the bulk rename run.", - "chooseLibrary": "Choose Library" - }, - "completed": { - "title": "Bulk rename completed", - "stats": "{succeeded} renamed, {failed} failed, {skipped} skipped ({processed} total)" - }, - "pagination": { - "showing": "Showing {from}-{to} of {total}" - }, - "confirmDialog": { - "title": "Confirm Bulk Rename", - "body": "{count, plural, =0 {This will rename # book on disk. Files with collisions or errors will be skipped. This action cannot be undone.} one {This will rename # book on disk. Files with collisions or errors will be skipped. This action cannot be undone.} other {This will rename # books on disk. Files with collisions or errors will be skipped. This action cannot be undone.}}", - "renameButton": "{count, plural, =0 {Rename # book} one {Rename # book} other {Rename # books}}" - } - }, - "bookDuplicates": { - "scanSettings": "Scan settings", - "title": "Duplicate Books", - "description": "Scan files and metadata for potential duplicate records. Nothing is deleted during a scan.", - "scope": "Library scope", - "allLibraries": "All accessible libraries", - "similarity": "Similar-title threshold", - "explainSimilarity": "Explain the similar-title threshold", - "similarityHelp": "Only for Similar title and author matches. At least one author and the book type must also match. Lower finds more possible duplicates; higher requires closer titles. Identical files, ISBN, and exact metadata are checked separately.", - "runScan": "Run scan", - "rescan": "Rescan", - "status": { - "queued": "Scan queued", - "running": "Scanning books" - }, - "groupsFound": "{count, plural, =0 {No duplicate groups} one {One duplicate group} other {# duplicate groups}}", - "filter": "Match type", - "allReasons": "All match types", - "reasons": { - "file_hash": "Identical file set", - "isbn": "Same ISBN", - "exact_metadata": "Exact title and authors", - "fuzzy_metadata": "Similar title and author" - }, - "similarityValue": "{percent}% title similarity", - "notDuplicates": "Not duplicates", - "keepThis": "Keep this book", - "discardThis": "Discard this book", - "selectKeeperFirst": "Select a keeper first", - "noDirectMatch": "No direct match with keeper", - "moreFiles": "+{count} more", - "showDetails": "Show details", - "hideDetails": "Hide details", - "deleteSelected": "Delete {count} selected", - "openBook": "Open details for {title}", - "unknownAuthor": "Unknown author", - "unknown": "Unknown", - "none": "None", - "accessDenied": "You do not have permission to use the duplicate book tool.", - "pairDetails": "Match details", - "pairLabel": "{first} and {second}", - "fields": { - "library": "Library", - "isbn": "ISBN", - "formats": "Formats", - "fileLocation": "File", - "files": "Files", - "readingStatus": "Reading status", - "progress": "Progress", - "path": "Library path", - "collections": "Collections", - "added": "Added", - "updated": "Updated" - }, - "initial": { - "title": "Find duplicate books", - "description": "Choose a library scope and similarity level, then run a scan. No books are changed until you explicitly confirm a deletion." - }, - "empty": { - "title": "No duplicate groups found", - "description": "No books matched the current scope, similarity level, and match filter." - }, - "deleteDialog": { - "title": "Permanently delete duplicate books?", - "description": "{count, plural, =0 {This will permanently delete # selected book and its files.} one {This will permanently delete # selected book and its files.} other {This will permanently delete # selected books and their files.}}", - "warning": "Metadata, collections, reading data, and device state are not transferred to the kept book. Associated data for other users is also removed.", - "confirm": "{count, plural, =0 {Delete # book} one {Delete # book} other {Delete # books}}", - "success": "{count, plural, =0 {No books deleted} one {One duplicate book deleted} other {# duplicate books deleted}}" - }, - "errors": { - "start": "Could not start the duplicate scan.", - "status": "Could not load scan progress.", - "scan": "The duplicate scan failed. Try running it again.", - "results": "Could not load duplicate groups.", - "delete": "Could not delete the selected duplicate books." - }, - "pagination": { - "label": "Duplicate groups pages", - "page": "Page {page} of {total}" - } - }, - "entityManager": { - "unknown": "Unknown", - "bookCount": "{count, plural, =0 {no books} one {# book} other {# books}}", - "sortPrefix": "· sort: {sortName}", - "selectTargetToKeep": "Select target to keep", - "writeToFiles": "Write to files", - "writeChangesToFiles": "Write changes to files", - "mergeIntoTarget": "Merge {count} into target", - "modes": { - "browse": "Browse & Manage", - "duplicates": "Find Duplicates" - }, - "actions": { - "rename": "Rename", - "split": "Split" - }, - "duplicates": { - "similarity": "Similarity:", - "scan": "Scan", - "scanning": "Scanning...", - "computing": "Computing candidates...", - "computedAt": "Candidates computed {date}", - "recompute": "Recompute", - "noneComputed": "No candidates computed yet.", - "computeNow": "Compute now", - "emptyTitle": "Find duplicate entities", - "emptyDescription": "Adjust the similarity threshold and click Scan to detect potential duplicates.", - "noneFoundTitle": "No duplicates found", - "noneFoundDescription": "No potential duplicates were detected with the current settings.", - "clustersFound": "{count, plural, =0 {no clusters found} one {# cluster found} other {# clusters found}}", - "plusOthers": "{count, plural, =0 {+ # other} one {+ # other} other {+ # others}}", - "percentSimilar": "{percent}% similar", - "pairDetails": "Pair details", - "dismissEntityTitle": "Dismiss all pairs for this entity", - "dismissPairTitle": "Dismiss this pair" - }, - "dismissed": { - "loading": "Loading dismissed pairs...", - "empty": "No dismissed pairs", - "restore": "Restore", - "restoreTitle": "Restore this pair", - "hidePairs": "Hide dismissed pairs", - "showPairs": "Show dismissed pairs" - }, - "browse": { - "searchPlaceholder": "Search...", - "emptyOnly": "Empty only", - "clear": "Clear", - "noEntities": "No entities found", - "mergeCount": "Merge ({count})", - "deleteCount": "Delete ({count})", - "totalCount": "{count} total", - "sortLabel": "sort: {sortName}", - "sort": { - "nameAsc": "Name A-Z", - "nameDesc": "Name Z-A", - "fewestBooks": "Fewest books", - "mostBooks": "Most books" - } - }, - "deleteMode": { - "label": "Delete mode", - "softTitle": "Soft delete", - "softDescription": "Unlink from all books but keep the entity record", - "softDescriptionPlural": "Unlink from all books but keep the entity records", - "hardTitle": "Hard delete", - "hardDescription": "Remove entity and all associations permanently", - "hardDescriptionPlural": "Remove entities and all associations permanently" - }, - "renameModal": { - "title": "Rename Entity", - "currentName": "Current name", - "newName": "New name" - }, - "deleteModal": { - "title": "Delete Entity", - "confirm": "Are you sure you want to delete {name}?" - }, - "splitModal": { - "title": "Split Entity", - "splitting": "Splitting", - "newNames": "New names (min 2)", - "namePlaceholder": "Enter name...", - "addAnother": "Add another" - }, - "bulkDeleteModal": { - "title": "Bulk Delete", - "confirm": "{count, plural, =0 {Are you sure you want to delete # selected entity?} one {Are you sure you want to delete # selected entity?} other {Are you sure you want to delete # selected entities?}}", - "deleteButton": "Delete {count}" - }, - "mergeModal": { - "title": "Merge Entities", - "description": "Select which entity to keep. The others will be merged into it and removed." - } - } - }, - "views": { - "entity": { - "book": "Book", - "collection": "Collection", - "library": "Library", - "smartScope": "SmartScope" - }, - "common": { - "retry": "Retry" - }, - "bookView": { - "sort": "Sort", - "sortOn": "On", - "resetSort": "Reset sort to default", - "filters": "Filters", - "clear": "Clear", - "clearAllFilters": "Clear all filters", - "expandSeries": "Expand series", - "collapseSeries": "Collapse series", - "expanded": "Expanded", - "exportMetadata": "Export metadata", - "showControlsAria": "Show library controls", - "export": "Export", - "searchPlaceholder": "Search title, author, series, narrator...", - "allBooksLoaded": "All {count} books loaded" - }, - "notFound": { - "title": "Page not found", - "description": "The page you're looking for doesn't exist.", - "goHome": "Go home" - }, - "dashboard": { - "customize": "Customize dashboard", - "allShelvesHidden": "All shelves are hidden.", - "greeting": { - "night": "Good night,", - "morning": "Good morning,", - "afternoon": "Good afternoon,", - "evening": "Good evening,", - "fallbackName": "there" - } - }, - "bookDetail": { - "title": "Book", - "titleWithId": "Book #{id}", - "pageTitle": { - "book": "Book · {base}", - "editMetadata": "Edit Metadata · {base}", - "edit": "Edit · {base}", - "files": "Files · {base}", - "readingLog": "Reading Log · {base}", - "highlights": "Highlights · {base}" - } - }, - "bookDock": { - "title": "Book Dock", - "newFilesDetected": "New files detected", - "reconnecting": "Reconnecting", - "rescanFailed": "Rescan failed", - "totalInDock": "{size} in Book Dock", - "dropFiles": "Drop files into Book Dock", - "supportedFormats": "Supported: {formats}", - "empty": { - "noSearchMatch": "No files match \"{query}\"", - "noStatusFiles": "No {status} files", - "uploadPrompt": "Upload files or drop them in the Book Dock folder" - }, - "retry": { - "noneToRetry": "No error files to retry", - "retrying": "{count, plural, =0 {Retrying one file} one {Retrying one file} other {Retrying # files}}" - }, - "applyFetched": { - "applied": "{count, plural, =0 {Applied to no files} one {Applied to one file} other {Applied to # files}}", - "skippedEdited": "{count, plural, =0 {skipped one file because they have manual edits} one {skipped one file because it has manual edits} other {skipped # files because they have manual edits}}", - "skippedNoMetadata": "{count, plural, =0 {skipped one file because they have no fetched metadata} one {skipped one file because it has no fetched metadata} other {skipped # files because they have no fetched metadata}}", - "noneApplied": "No files applied; {reasons}", - "noneSelected": "No files selected" - } - }, - "collection": { - "title": "Collection", - "pageTitle": "Collection · {name}", - "pageTitleWithId": "Collection #{id}", - "editCollection": "Edit collection", - "showControlsAria": "Show collection controls", - "loadError": "Could not load this collection", - "toast": { - "removed": "{count, plural, =0 {Removed no books from collection} one {Removed one book from collection} other {Removed # books from collection}}", - "removeFailed": "Failed to remove books from collection" - }, - "empty": { - "noSearchMatch": "No books match this search", - "noSearchMatchHint": "Try a different search term or clear the search.", - "noBooks": "No books in this collection", - "noBooksHint": "Select books from your library and add them here." - } - }, - "library": { - "title": "Library", - "pageTitle": "Library · {name}", - "pageTitleWithId": "Library #{id}", - "filterRules": "Filter rules", - "saveAsSmartScope": "Save as Smart Scope", - "saveScope": "Save Scope", - "saveAsSmartScopeTooltip": "Save this filter as a named Smart Scope", - "saved": "Saved", - "saveFilter": "Save filter", - "filterSaved": "Filter saved", - "saveFilterTooltip": "Save filter for this library", - "removeSavedFilter": "Remove saved filter", - "empty": { - "noFilterMatch": "No books match your filters", - "noFilterMatchHint": "Try adjusting or clearing your filters to see more books.", - "clearFilters": "Clear filters", - "scanning": "Scanning your library...", - "scanningHint": "Books will appear here as they are discovered.", - "emptyLibrary": "Your library is empty", - "emptyLibraryHint": "Once you add books to this library, they will appear here." - }, - "querySelection": { - "loadedSelected": "{selected} of {total} loaded books selected.", - "selectAllMatching": "Select all {total} matching books" - } - }, - "smartScope": { - "title": "SmartScope", - "pageTitle": "SmartScope · {name}", - "pageTitleWithId": "SmartScope #{id}", - "defaultName": "Smart scope", - "filter": "Filter", - "edit": "Edit Smart Scope", - "koboSync": { - "label": "Sync to my Kobo", - "enabledHint": "Books in this shared Smart Scope sync to your Kobo device. Turn off to stop syncing them.", - "disabledHint": "Turn on to sync books in this shared Smart Scope to your Kobo device." - }, - "showControlsAria": "Show Smart Scope controls", - "hideFilter": "Hide filter", - "showFilter": "Show filter", - "confirmDelete": "Confirm?", - "loadError": "Could not load this SmartScope", - "toast": { - "deleted": "\"{name}\" deleted", - "deleteFailed": "Failed to delete \"{name}\"", - "koboSyncEnabled": "\"{name}\" now syncs to your Kobo", - "koboSyncDisabled": "\"{name}\" no longer syncs to your Kobo", - "koboSyncFailed": "Failed to update Kobo sync for \"{name}\"" - }, - "empty": { - "noRules": "No rules configured", - "noRulesHint": "Open the editor to define which books appear in this smartScope using filters and sort rules.", - "configure": "Configure SmartScope", - "noMatch": "No books match this smartScope", - "noMatchHint": "Try adjusting the filter rules.", - "edit": "Edit SmartScope" - } - } - }, - "whatsNew": { - "title": "What's New", - "subtitle": "Everything that's shipped, newest first.", - "versionPrefix": "Version {version}", - "newUpdates": "{count, plural, =0 {no new updates} one {one new update} other {# new updates}}", - "remindLater": "Remind me later", - "gotIt": "Got it", - "latest": "Latest", - "fullChangelog": "Full changelog", - "seeAllReleases": "See all releases", - "versions": "Versions", - "currentVersion": "Current version", - "youreHere": "You're here", - "searchPlaceholder": "Search releases…", - "noReleasesFound": "No releases found.", - "noHighlights": "No highlights for this release.", - "showChangelog": "Show full changelog", - "hideChangelog": "Hide full changelog", - "openOnGitHub": "Open on GitHub", - "loadMore": "Load more", - "loadingMore": "Loading…", - "loadFailed": "Failed to load releases", - "loadMoreFailed": "Could not load more releases. Please try again.", - "loadErrorHint": "Couldn't load releases. Check your connection and try again.", - "retry": "Retry", - "imageViewer": "Image viewer", - "closeImage": "Close image", - "previousImage": "Previous image", - "nextImage": "Next image" - }, - "titles": { - "dashboard": "Dashboard", - "libraries": "Libraries", - "opds": "OPDS", - "koboSync": "Kobo Sync", - "koreaderSync": "KOReader Sync", - "bookDock": "Book Dock", - "whatsNew": "What's New", - "annotations": "Annotations", - "achievements": "Achievements", - "statistics": "Statistics", - "authors": "Authors", - "series": "Series", - "entityManager": "Entity Manager", - "bulkRename": "Bulk Rename", - "duplicateBooks": "Duplicate Books", - "notFound": "Not Found", - "signIn": "Sign In", - "initialSetup": "Initial Setup", - "forgotPassword": "Forgot Password", - "resetPassword": "Reset Password", - "completingSignIn": "Completing Sign In", - "magicLinkLogin": "Magic Link Login", - "readPrefix": "Read", - "emailSuffix": "Email", - "library": "Library", - "smartScope": "SmartScope", - "collection": "Collection", - "author": "Author", - "book": "Book", - "seriesItem": "Series", - "appearance": { - "theme": "Display", - "book-covers": "Book Covers", - "icons": "Icons", - "layout": "Display Layout", - "behavior": "Library Behavior" - }, - "reader": { - "general": "Reader Settings", - "ebook": "eBook Reader", - "pdf": "PDF Reader", - "comics": "Comics Reader", - "audio": "Audiobook Player", - "fonts": "Reader Fonts" - }, - "email": { - "providers": "Providers", - "recipients": "Recipients", - "groups": "Groups", - "templates": "Templates", - "preferences": "Preferences", - "history": "History" - }, - "metadata": { - "providers": "Providers", - "field-rules": "Field-Level Rules", - "custom-fields": "Custom Metadata", - "genre-blocklist": "Genre Blocklist", - "score": "Confidence Score", - "auto-fetch": "Book Auto-Fetch", - "authors": "Author Auto-Fetch" - }, - "admin": { - "users": "Users", - "account-activity": "Account Activity", - "magic-links": "Magic Links", - "oidc": "OIDC / SSO" - }, - "system": { - "file-naming": "File Naming", - "book-dock": "Book Dock", - "maintenance": "Maintenance", - "audit-log": "Audit Log" - }, - "account": { - "profile": "Account", - "privacy": "Privacy & Sharing", - "notifications": "Notifications", - "restrictions": "Content Restrictions" - }, - "smartScopes": "Smart Scopes", - "collections": "Collections" - } -} diff --git a/client/src/locales/ko.json b/client/src/locales/ko.json deleted file mode 100644 index 214805152..000000000 --- a/client/src/locales/ko.json +++ /dev/null @@ -1,6909 +0,0 @@ -{ - "common": { - "resetSortAria": "Reset sort to default", - "save": "Save", - "cancel": "Cancel", - "delete": "Delete", - "edit": "Edit", - "close": "Close", - "confirm": "Confirm", - "loading": "Loading...", - "search": "Search", - "back": "Back", - "next": "Next", - "previous": "Previous", - "retry": "Retry", - "yes": "Yes", - "no": "No" - }, - "settings": { - "privacySharing": { - "title": "Privacy & Sharing", - "subtitle": "Control whether administrators can see an identifiable summary of your reading activity.", - "levelLegend": "Reading insights sharing level", - "current": "Current setting", - "levels": { - "private": { - "title": "Private", - "description": "Only you can see your reading statistics." - }, - "summary": { - "title": "Share summary", - "description": "Share aggregate habits without book titles, authors, series, or narrators." - }, - "detailed": { - "title": "Share detailed insights", - "description": "Also share recent and top books, authors, series, genres, and narrators." - } - }, - "fields": { - "frequency": "Reading frequency and active days", - "completion": "Aggregate books started and completed", - "formats": "Format distribution", - "genres": "Broad genre distribution", - "trend": "Aggregate reading trend", - "books": "Current, recent, and most-read book titles", - "authors": "Top authors", - "series": "Top series", - "narrators": "Top narrators" - }, - "confirm": { - "shareTitle": "Enable {level}?", - "shareDescription": "Administrators with permission will be able to see the following information.", - "stopTitle": "Stop sharing reading insights?", - "stopDescription": "Administrator access will be blocked immediately. Existing access records remain in your history.", - "recordedNotice": "Each administrator profile view is recorded and appears in your access history." - }, - "preview": { - "title": "Preview your shared profile", - "description": "See the information currently available to authorized administrators.", - "action": "Load preview", - "readingTime": "Reading time", - "activeDays": "Active days", - "started": "Books started", - "completed": "Books completed", - "topBooks": "Top books" - }, - "history": { - "title": "Profile access history", - "description": "Recent administrator views of your shared reading profile.", - "empty": "No administrator has viewed your shared reading profile.", - "paginationLabel": "Profile access history pages" - }, - "durationMinutes": "{count, plural, other {# minutes}}", - "durationHours": "{count, plural, other {# hours}}", - "unknownTitle": "Untitled book", - "errors": { - "load": "Failed to load sharing settings.", - "save": "Failed to update sharing settings.", - "preview": "Failed to load the shared-profile preview." - } - }, - "appearance": { - "language": { - "title": "Language", - "description": "Choose the language used across the interface.", - "label": "Interface language", - "loadError": "Failed to load the selected language", - "saveError": "Failed to save language preference" - }, - "pageTitle": "Display", - "pageSubtitle": "Control themes, covers, layout, and how your library is presented.", - "mobileSummary": "Theme: {theme} • Accent: {accent} • Background: {background}", - "themeMode": { - "light": "Light", - "dark": "Dark", - "system": "System" - }, - "theme": { - "title": "Theme", - "colorScheme": { - "label": "Color scheme", - "hint": "Light or dark interface" - }, - "accents": { - "grey": "Grey", - "scarlet": "Scarlet", - "vermilion": "Vermilion", - "rose": "Rose", - "copper": "Copper", - "orange": "Orange", - "chartreuse": "Chartreuse", - "marigold": "Marigold", - "wasabi": "Wasabi", - "amber": "Amber", - "malachite": "Malachite", - "yellow": "Yellow", - "viridian": "Viridian", - "turquoise": "Turquoise", - "lime": "Lime", - "green": "Green", - "acid-green": "Acid Green", - "emerald": "Emerald", - "teal": "Teal", - "electric-blue": "Electric Blue", - "cyan": "Cyan", - "jade": "Jade", - "ultramarine": "Ultramarine", - "iris": "Iris", - "purple": "Purple", - "blue": "Blue", - "indigo": "Indigo", - "violet": "Violet", - "amethyst": "Amethyst", - "fuchsia": "Fuchsia", - "raspberry": "Raspberry", - "pink": "Pink", - "white": "White", - "rosewater": "Rosewater", - "salmon": "Salmon", - "coral": "Coral", - "sand": "Sand", - "peach": "Peach", - "pear": "Pear", - "flax": "Flax", - "sprout": "Sprout", - "butter": "Butter", - "aloe": "Aloe", - "lemon": "Lemon", - "foam": "Foam", - "aqua": "Aqua", - "celadon": "Celadon", - "sage": "Sage", - "pistachio": "Pistachio", - "mint": "Mint", - "seafoam": "Seafoam", - "baby-blue": "Baby Blue", - "powder": "Powder", - "sea-glass": "Sea Glass", - "bluebell": "Bluebell", - "cornflower": "Cornflower", - "thistle": "Thistle", - "periwinkle": "Periwinkle", - "wisteria": "Wisteria", - "lavender": "Lavender", - "mauve": "Mauve", - "orchid": "Orchid", - "rose-quartz": "Rose Quartz", - "blush": "Blush" - }, - "accentColor": { - "label": "Accent color", - "hint": "Controls highlights and interactive elements" - }, - "cornerRadius": { - "label": "Corner radius", - "hint": "Roundness of cards and UI elements" - }, - "surfaceBrightness": { - "label": "Surface brightness", - "hint": "Lighten dark mode surfaces", - "reset": "Reset" - }, - "libraryBackground": { - "title": "Library Background", - "pattern": { - "label": "Background pattern", - "hint": "Pattern shown behind the book grid" - } - }, - "backgroundGroups": { - "fundamental": "Fundamental", - "structural": "Structural", - "ambient": "Ambient", - "refractive": "Refractive" - } - }, - "storage": { - "title": "Where to save appearance preferences", - "active": "Active", - "notAvailable": "Not available", - "device": { - "title": "This device only", - "description": "Preferences stay in your browser. Best if you want a different look on different devices." - }, - "account": { - "title": "My account", - "description": "Preferences are saved to your account. Best if you want the same appearance on every device." - }, - "toasts": { - "synced": "Preferences will now be synced", - "local": "Preferences will stay on this device" - }, - "errors": { - "demoRestricted": "Demo-restricted account cannot change theme storage mode", - "update": "Failed to update storage mode", - "generic": "An error occurred while updating storage mode" - } - }, - "bookCovers": { - "title": "Book Covers", - "displayMode": { - "title": "Cover display mode", - "hint": "Controls how real covers fit inside book slots when aspect ratios differ", - "blurredFit": { - "label": "Blurred fit", - "hint": "Show the full cover with a blurred fill behind it" - }, - "fillCrop": { - "label": "Fill card", - "hint": "Fill the entire slot by cropping edges when aspect ratios differ" - }, - "naturalBottom": { - "label": "Natural bottom", - "hint": "Keep the original cover ratio and anchor the cover to the bottom" - } - }, - "spine": { - "title": "Book spine overlay", - "hint": "Adds a stylized spine and gloss effect to cover cards", - "off": { - "label": "Off", - "hint": "No spine/gloss effect on covers" - }, - "subtle": { - "label": "Subtle", - "hint": "Light spine and sheen, closer to the default look" - }, - "strong": { - "label": "Strong", - "hint": "More pronounced spine and gloss treatment" - } - }, - "showSpineOnComics": { - "label": "Show spine on comics", - "hint": "Apply the spine and gloss effect to comic covers (cbz, cbr, cb7)" - }, - "shadow": { - "title": "Cover shadow strength", - "hint": "Controls depth under covers across grid, list, table, and dashboard thumbnails", - "default": { - "label": "Default", - "hint": "Current elevation and depth" - }, - "strong": { - "label": "Strong", - "hint": "Heavier shelf-like drop shadow under covers" - } - }, - "overlays": { - "title": "Card overlays", - "hint": "Choose metadata shown directly on book cover cards", - "progressBar": { - "label": "Progress bar", - "hint": "Thin colored line along the bottom edge" - }, - "format": { - "label": "File format", - "hint": "Color-coded EPUB, PDF, CBZ badge at bottom-right" - }, - "rating": { - "label": "Rating", - "hint": "Star rating indicator at bottom-left" - }, - "readStatus": { - "label": "Read status", - "hint": "Color icon showing the current reading status at top-left" - }, - "seriesPosition": { - "label": "Series number", - "hint": "Badge showing the book position in its series at top-right (e.g. #3, #1.5)" - }, - "lockStatus": { - "label": "Lock status", - "hint": "Metadata lock icon at top-right - orange when locked, green when unlocked" - } - } - }, - "layout": { - "coverSize": "Cover size", - "gridSpacing": "Grid spacing", - "gridLayout": { - "title": "Library Grid Layout" - }, - "coverSizeBehavior": { - "label": "Cover size behavior", - "hint": "Control whether portrait/square sizes and grid spacing are shared across all views or kept per-view", - "perViewHint": "Per-view mode: adjust cover size and spacing from each view's Display panel.", - "syncAll": "Sync all views", - "perView": "Per-view sizes" - }, - "portraitCoverSize": { - "label": "Portrait cover size", - "hint": "Used for portrait libraries and views" - }, - "squareCoverSize": { - "label": "Square cover size", - "hint": "Used for square libraries and views" - }, - "portraitGridSpacing": { - "label": "Portrait grid spacing", - "hint": "Gap between portrait covers" - }, - "squareGridSpacing": { - "label": "Square grid spacing", - "hint": "Gap between square covers" - }, - "cardInfoMode": { - "label": "Card info mode", - "hint": "Where to show book title and author on grid cards", - "onHover": "On hover", - "belowCover": "Below cover", - "off": "Off" - }, - "primaryCardLabel": { - "label": "Primary card label", - "hint": "Text shown below each book cover (first line)" - }, - "secondaryCardLabel": { - "label": "Secondary card label", - "hint": "Additional text below the primary label (second line)" - }, - "labelField": { - "hidden": "Hidden", - "bookTitle": "Book title", - "seriesTitle": "Series title", - "seriesTitlePosition": "Series title + position", - "author": "Author" - }, - "seriesDisplay": { - "title": "Series Display", - "collapsedCover": { - "label": "Collapsed series cover", - "hint": "Choose which cover to show when series are collapsed in the book grid" - }, - "stack": "Stack", - "mosaic": "Mosaic", - "first": "First", - "latest": "Latest", - "firstUnread": "First Unread" - }, - "authorGrid": { - "title": "Author Grid", - "coverSize": { - "label": "Cover size", - "hint": "Width of author covers in the grid" - }, - "coverShape": { - "label": "Cover shape", - "hint": "Shape of author covers in the grid" - }, - "circle": "Circle", - "square": "Square" - }, - "listTableViews": { - "title": "List and Table Views" - }, - "zebraStriping": { - "label": "Zebra striping", - "hint": "Alternate row background colors for easier scanning" - } - }, - "behavior": { - "title": "Library Behavior", - "thumbnailClicks": { - "label": "Thumbnail clicks", - "hint": "Choose what happens when opening a book from grid and list views", - "readFirst": "Read first", - "readFirstHint": "Open the reader when a readable file exists", - "openDetails": "Open details", - "openDetailsHint": "Go to the book details page from grid and list thumbnails" - }, - "filterPreview": { - "label": "Show filter preview by default", - "hint": "Expand the active filter and sort summary when opening a smartScope" - }, - "collapseSeries": { - "label": "Collapse series by default", - "hint": "Group books in the same series into a single card in library and collection views" - } - }, - "icons": { - "title": "Custom Icons", - "uploadIcons": "Upload icons", - "uploadedCount": "{count, plural, =0 {no icons uploaded} other {# icons uploaded}}", - "searchPlaceholder": "Search icons", - "sort": { - "newest": "Newest", - "name": "Name" - }, - "selectedCount": "{count, plural, other {# selected}}", - "clear": "Clear", - "deleteSelected": "Delete selected", - "loading": "Loading icons...", - "emptySearch": "No icons match your search.", - "emptyNoIcons": "No custom icons uploaded yet.", - "namePlaceholder": "Name", - "checkingUsage": "Checking usage...", - "usedBy": "Used by {count}", - "notUsedYet": "Not used yet", - "rename": "Rename", - "replace": "Replace", - "usage": { - "libraries": "{count, plural, =0 {no libraries} other {# libraries}}", - "collections": "{count, plural, =0 {no collections} other {# collections}}", - "smartScopes": "{count, plural, =0 {no smart scopes} other {# smart scopes}}" - }, - "confirm": { - "deleteOne": "Delete \"{name}\"? Existing uses will fall back to their default icon.", - "deleteMany": "{count, plural, =0 {Delete no icons?} other {Delete # icons? Existing uses will fall back to their default icon.}}" - }, - "toasts": { - "saved": "Icon saved", - "updated": "Icon updated", - "deleted": "Icon deleted", - "bulkDeleted": "{count, plural, =0 {Deleted no icons} other {Deleted # icons}}", - "bulkDeletePartial": "Deleted {deleted}, {failed} failed" - }, - "errors": { - "load": "Failed to load icons", - "save": "Failed to save icon", - "replace": "Failed to replace icon", - "delete": "Failed to delete icon", - "bulkDelete": "Failed to delete icons" - } - }, - "tabs": { - "theme": "Theme", - "book-covers": "Book Covers", - "icons": "Icons", - "layout": "Layout", - "behavior": "Behavior" - } - }, - "account": { - "title": "Account", - "subtitle": "Manage your personal profile settings.", - "subtitleAll": "Manage your profile and notification preferences.", - "tabs": { - "profile": "Profile", - "privacy": "Privacy & Sharing", - "notifications": "Notifications", - "restrictions": "Restrictions" - }, - "demoRestricted": { - "cannotEdit": "Demo-restricted account cannot edit account settings", - "notice": "Demo-restricted account: editing profile, password, avatar, and linked identities is disabled." - }, - "feedback": { - "unsavedChanges": "Unsaved changes", - "discard": "Discard" - }, - "profile": { - "securityHeading": "Profile & Security", - "username": "Username", - "fullName": "Full name", - "email": "Email", - "emailHint": "Contact an administrator to change your email address.", - "save": "Save profile", - "saving": "Saving...", - "changePassword": "Change password", - "accountType": "Account type:", - "accountTypeOidc": "OIDC / SSO", - "accountTypeShared": "Shared", - "accountTypeLocal": "Local", - "nameRequired": "Name is required", - "updateFailed": "Failed to update profile", - "updated": "Profile updated", - "usernameHint": "Your username cannot be changed.", - "passwordHint": "Change the password you use to sign in.", - "passwordHintOidc": "Your password is managed by your identity provider.", - "passwordHintShared": "Shared accounts sign in through a magic link and have no password." - }, - "readingPreferences": { - "title": "Reading Preferences", - "timezoneHint": "Timezone is used for time-sensitive achievements like Early Bird and All-nighter.", - "timezone": "Timezone", - "save": "Save preferences", - "enableAchievements": "Enable achievements", - "enableAchievementsHint": "Track achievement progress and show achievement-related interface. Manage achievement notifications separately in Notifications.", - "achievementsEnabled": "Achievements enabled", - "achievementsDisabled": "Achievements disabled", - "achievementsSaveFailed": "Failed to update the achievement preference" - }, - "preferences": { - "saveFailed": "Failed to save preferences", - "saved": "Preferences saved" - }, - "avatar": { - "title": "Profile Picture", - "unknownUser": "Unknown user", - "formatHint": "PNG/JPEG/WEBP up to {size} MB", - "upload": "Upload picture", - "replace": "Replace picture", - "uploading": "Uploading...", - "remove": "Remove picture", - "removing": "Removing...", - "updated": "Profile picture updated", - "uploadFailed": "Failed to upload profile picture", - "removed": "Profile picture removed", - "removeFailed": "Failed to remove profile picture", - "removeConfirm": { - "title": "Remove profile picture?", - "description": "Your avatar will be removed and replaced with initials.", - "confirm": "Remove" - } - }, - "connectedAccounts": { - "title": "Connected Accounts", - "unlink": "Unlink", - "unlinking": "Unlinking...", - "linkAdditional": "Link additional providers:", - "linkProvider": "Link {provider}", - "redirecting": "Redirecting...", - "noneConfigured": "No OIDC providers are configured. Ask an administrator to set up SSO.", - "linkStateFailed": "Failed to generate link state", - "startLinkFailed": "Failed to start OIDC link", - "unlinkFailed": "Failed to unlink", - "unlinked": "Identity unlinked", - "unlinkIdentityFailed": "Failed to unlink identity", - "unlinkDialog": { - "title": "Unlink {provider} identity?", - "description": "Enter your password to confirm. You will no longer be able to sign in with this provider.", - "currentPassword": "Current password" - }, - "description": "Sign in with an external identity provider linked to this account.", - "unlinkAria": "Unlink {provider}" - }, - "tour": { - "title": "Guided Tour", - "description": "Replay the walkthrough that highlights key features of the app.", - "action": "Take the tour again" - }, - "restrictions": { - "none": { - "title": "No content restrictions", - "description": "Your account has full access to all content within your assigned libraries." - }, - "banner": "Your account has content restrictions applied by an administrator. Some books may not be visible to you.", - "allowedTags": { - "title": "Allowed tags", - "description": "Only books that have at least one of these tags are shown to you." - }, - "blockedTags": { - "title": "Blocked tags", - "description": "Books with any of these tags are hidden from you." - }, - "allowedGenres": { - "title": "Allowed genres", - "description": "Only books that have at least one of these genres are shown to you." - }, - "blockedGenres": { - "title": "Blocked genres", - "description": "Books with any of these genres are hidden from you." - } - }, - "groups": { - "profile": "Profile", - "preferences": "Preferences", - "security": "Security & access" - } - }, - "magicLinks": { - "title": "Magic Links", - "subtitle": "Create shareable login links for shared accounts.", - "createLink": "Create link", - "noSharedAccounts": "No shared accounts found", - "noSharedAccountsHint": "Create a shared account from the {usersPage} first to generate magic links.", - "activeLinks": "Active links", - "inactiveLinks": "Inactive links", - "paused": "Paused", - "deletedUser": "Deleted user", - "expiredPrefix": "Expired ", - "never": "No recorded activity", - "noExpiry": "No expiry", - "expired": "Expired", - "expiresOn": "Expires {date}", - "revokedOn": "Revoked {date}", - "expiredOn": "Expired {date}", - "usesCount": "{count, plural, =0 {no uses} other {# uses}}", - "copied": "Copied!", - "copyLink": "Copy link", - "pause": "Pause", - "resume": "Resume", - "revoke": "Revoke", - "revoking": "Revoking...", - "emptyState": "No magic links created yet. Click \"{action}\" to generate a shareable login URL.", - "columns": { - "label": "Label", - "account": "Account", - "createdBy": "Created by", - "expires": "Expires", - "uses": "Uses", - "created": "Created", - "status": "Status", - "totalUses": "Total uses", - "actions": "Actions" - }, - "createDialog": { - "title": "Create magic link", - "description": "Generate a shareable login URL for a shared account.", - "sharedAccount": "Shared account", - "selectAccount": "Select a shared account", - "label": "Label", - "labelPlaceholder": "e.g. Demo link for conference", - "expiresAt": "Expires at", - "optional": "(optional)", - "create": "Create", - "creating": "Creating..." - }, - "revokeDialog": { - "title": "Revoke magic link?", - "description": "This will immediately invalidate the link and terminate all active sessions for the linked account." - }, - "errors": { - "create": "Failed to create", - "copy": "Failed to copy magic link", - "update": "Failed to update magic link", - "revoke": "Failed to revoke" - }, - "usersPage": "Users page", - "emptyTitle": "No magic links created yet", - "emptyHint": "Click \"{action}\" to generate a shareable login URL.", - "noActiveTitle": "No active magic links", - "noActiveHint": "All generated magic links for this page have expired or been revoked.", - "copyLinkAria": "Copy the link for {label}", - "pauseAria": "Pause {label}", - "resumeAria": "Resume {label}", - "revokeAria": "Revoke {label}", - "lastUsedLabel": "Last used {date}" - }, - "oidc": { - "title": "OIDC / SSO", - "subtitle": "Manage OpenID Connect providers for single sign-on.", - "providers": "Providers", - "addProvider": "Add Provider", - "editProvider": "Edit Provider", - "configureNew": "Configure a new OIDC provider.", - "editing": "Editing {slug}", - "enabled": "Enabled", - "disabled": "Disabled", - "empty": { - "title": "No providers yet", - "description": "Add an OIDC provider to enable single sign-on for your users." - }, - "form": { - "status": "Status", - "enableProvider": "Enable provider", - "enableProviderHint": "Show this provider on the login page.", - "identity": "Provider Identity", - "slug": "Slug", - "slugHint": "Unique identifier (lowercase, hyphens). Cannot be changed later.", - "displayName": "Display Name", - "displayNameHint": "Shown on the login button.", - "iconUrl": "Icon URL", - "iconUrlHint": "Optional logo shown next to the login button.", - "iconPreviewAlt": "icon preview", - "connection": "Connection", - "issuerUri": "Issuer URI", - "issuerUriHint": "The provider's base URL.", - "test": "Test", - "testing": "Testing...", - "clientId": "Client ID", - "clientSecret": "Client Secret", - "clientSecretPlaceholder": "Leave blank to keep existing", - "scopes": "Scopes", - "claimMapping": "Claim Mapping", - "previewClaims": "Preview claims", - "redirecting": "Redirecting...", - "mappedClaims": "Mapped claims", - "rawClaims": "Raw claims", - "usernameClaim": "Username claim", - "nameClaim": "Name claim", - "emailClaim": "Email claim", - "groupsClaim": "Groups claim", - "autoProvisioning": "Auto-Provisioning", - "autoProvisionUsers": "Auto-provision users", - "autoProvisionUsersHint": "Create accounts on first OIDC login if user does not exist.", - "allowLocalLinking": "Allow local account linking", - "allowLocalLinkingHint": "Link OIDC identity to an existing local account by username match.", - "defaultPermissions": "Default permissions", - "defaultPermissionsHint": "Permissions granted to new users on first OIDC login.", - "createProvider": "Create Provider", - "saveChanges": "Save Changes", - "saving": "Saving...", - "deleteProvider": "Delete Provider", - "deleting": "Deleting..." - }, - "test": { - "connected": "Connected - {issuer}", - "connectionFailed": "Connection failed", - "hide": "Hide", - "details": "Details", - "supported": "supported", - "notSupported": "not supported" - }, - "groupMappings": { - "title": "Group Mappings", - "description": "Map OIDC group claims to BookOrbit permissions. Synced on every login.", - "noPermission": "No permission", - "empty": "No group mappings configured.", - "addMapping": "Add mapping", - "claimPlaceholder": "OIDC group claim (e.g. admins)", - "add": "Add", - "adding": "Adding..." - }, - "toasts": { - "providerCreated": "Provider created", - "providerSaved": "Provider saved", - "providerDeleted": "Provider deleted", - "mappingAdded": "Group mapping added", - "mappingRemoved": "Group mapping removed" - }, - "errors": { - "loadProvider": "Failed to load provider", - "createProvider": "Failed to create provider", - "save": "Failed to save", - "delete": "Failed to delete", - "deleteProvider": "Failed to delete provider", - "requestFailed": "Request failed", - "previewState": "Failed to generate preview state", - "startPreview": "Failed to start preview", - "addMapping": "Failed to add mapping", - "removeMapping": "Failed to remove group mapping" - } - }, - "admin": { - "title": "Admin", - "subtitle": "Manage users and authentication settings.", - "system": { - "title": "System", - "subtitle": "File organization, ingestion, and maintenance settings." - }, - "maintenance": { - "title": "Maintenance", - "subtitle": "Manage background tasks, system indices, and maintenance operations.", - "importGroup": "Import", - "recommendationsGroup": "Recommendations", - "achievementsGroup": "Achievements", - "updatesGroup": "Updates", - "importFromBooklore": "Import from Booklore", - "bookloreImportConfigured": "Booklore import configured", - "migrationRunning": "Migration running", - "migrationCompleted": "Migration completed", - "migrationFailed": "Migration failed", - "importDescription": "One-time import of books, metadata, and reading progress from a previous Booklore installation.", - "configuredDescription": "Source: {name}. No migration run yet - continue setup to run the import.", - "runningDescription": "Stage: {stage} - started {started}", - "completedDescription": "From {name} - completed {date}", - "migrationErrorGeneric": "An error occurred during migration.", - "stageInitializing": "initializing", - "recently": "recently", - "getStarted": "Get Started", - "continueSetup": "Continue Setup", - "viewDetails": "View Details", - "refreshRecommendationIndex": "Refresh recommendation index", - "refreshRecommendationHint": "Update the recommendations engine with your latest library changes. This process runs in the background.", - "booksQueuedForProcessing": "{count, plural, =0 {no books queued for processing} other {# books queued for processing}}", - "run": "Run", - "running": "Running...", - "backfillAchievements": "Backfill achievements", - "backfillAchievementsHint": "Re-evaluate achievements across all users.", - "backfillResult": "Processed {users} users; granted {awards} awards.", - "runBackfill": "Run Backfill", - "checkForUpdates": "Check for updates", - "checkForUpdatesHint": "Automatically check GitHub for a new release on startup and show an indicator in the sidebar when one is available.", - "updateChecksEnabled": "Update checks enabled", - "updateChecksDisabled": "Update checks disabled", - "updateSettingFailed": "Failed to update setting", - "booksQueuedForEmbedding": "{count, plural, =0 {no books queued for embedding} other {# books queued for embedding}}", - "failed": "Failed", - "unknownError": "Unknown error", - "rebuildEmbeddingsFailed": "Failed to rebuild embeddings: {error}", - "achievementBackfillConfirm": "Run achievement backfill for all achievements across all users? This may take a while.", - "achievementBackfillComplete": "Achievement backfill complete: {count} awards granted", - "backfillRunFailed": "Failed to run backfill", - "achievementBackfillFailed": "Failed to run achievement backfill: {error}", - "uploadsGroup": "Uploads", - "maxUploadSize": "Maximum upload file size limit", - "maxUploadSizeHint": "Configure the maximum size limit for file uploads across the system.", - "save": "Save", - "uploadSizeInvalid": "Upload size limit must be greater than 0", - "uploadSizeUpdated": "Upload size limit updated" - }, - "migration": { - "title": "Migration", - "subtitle": "One-time Booklore import: connect source, map users, dry-run, start migration, and export a report.", - "progress": "Progress", - "stepSourceConnection": "Source Connection", - "stepUserPathMapping": "User & Path Mapping", - "stepDryRun": "Dry-Run", - "stepDryRunTitle": "Dry Run", - "stepRunMigration": "Run Migration", - "stepReport": "Report", - "stepReportTitle": "Migration Report", - "subtitleSource": "Configure the database connection to your source Booklore instance.", - "subtitleMappings": "Map source users to target users and translate file paths.", - "subtitleDryRun": "Preview what will be imported before running the live migration.", - "subtitleRun": "Start the live import and monitor its progress.", - "subtitleReport": "Review what was imported and export a detailed report.", - "continueToMappings": "Continue to Mappings", - "continueToDryRun": "Continue to Dry Run", - "continueToMigration": "Continue to Migration", - "viewReport": "View Report", - "badgeValidated": "Validated", - "badgeSaved": "Saved", - "badgeUpToDate": "Up to date", - "badgeCompleted": "Completed", - "badgeRunning": "Running", - "badgeFailed": "Failed", - "mediaPathRequired": "Required for migrating book covers.", - "mediaPathAbsolute": "Use an absolute path (for example: /books). Relative paths are not supported.", - "mediaPathConfigured": "Cover import path configured. Use Test Connection to verify access and Booklore images folder structure.", - "issueSaveSource": "Save source connection settings", - "issueValidateSource": "Validate source connection", - "issueSaveMappings": "Save user and path mappings", - "issueSavePathMappings": "Save path mappings to validate them", - "issueFreshDryRun": "Run a fresh dry-run", - "issueResolveDuplicates": "Resolve duplicate target book matches in the dry-run", - "issueWaitActiveRun": "Wait for active run to finish", - "sourceRecordId": "Source record ID #{id}", - "byAuthorWithId": "by {author} (ID: {id})", - "filePathWithId": "{path} (ID: {id})", - "bookloreSourceId": "Booklore source ID: {id}", - "libraryBookNum": "Library book #{id}", - "errorInitialize": "Failed to initialize migration settings", - "errorLoadSourceTypes": "Failed to load supported migration source types", - "errorLoadTargetUsers": "Failed to load target users", - "errorLoadLibraryFolders": "Failed to load target library folders", - "noSourceUsersReturned": "No source users were returned", - "userMappingSuggestionsLoaded": "User mapping suggestions loaded", - "errorLoadSuggestions": "Failed to load user mapping suggestions", - "requiredFields": "Host, user, database, and source name are required", - "connectionTestPassedWithWarnings": "Connection test passed with warnings", - "connectionTestPassedWithCount": "Connection test passed with {count} warning(s). First: {first}", - "connectionTestPassed": "Connection test passed", - "connectionOkMissingTables": "Connection ok, but {count} required table(s) are missing", - "cannotTestMediaPathActiveRun": "Cannot test media path while a run is active", - "mediaRootPathRequiredCover": "Media Root Path is required for cover import.", - "useAbsolutePath": "Use an absolute path (for example: /books).", - "mediaPathVerified": "Media path verified.", - "mediaPathValidReadable": "Media path is valid and readable", - "mediaPathValidationFailed": "Media path validation failed.", - "connectionFailedBeforeMediaPath": "Connection test failed before media path validation could complete.", - "cannotModifySourceActiveRun": "Cannot modify source while a run is active", - "sourceSavedValidatedWarnings": "Source saved and validated with {count} warning(s)", - "sourceSavedValidated": "Source saved and validated", - "errorSaveValidateSource": "Failed to save or validate source", - "cannotSaveMappingsActiveRun": "Cannot save mappings while a run is active", - "saveSourceFirst": "Save source first", - "mapAtLeastOneUser": "Map at least one source user to a target user", - "mapEveryUser": "Map every source user before saving", - "pathValidationFailedProfileSaved": "Path validation failed, but profile will still be saved", - "mappingsSaved": "Mappings saved", - "errorSaveMappings": "Failed to save mappings", - "cannotRunDryRunActiveRun": "Cannot run dry-run while a run is active", - "saveMappingsFirst": "Save mappings first", - "dryRunCompleted": "Dry-run completed: {matched} matched, {unresolved} unresolved", - "dryRunFailed": "Dry-run failed", - "selectSourceForAllGroups": "Select a source book for all {count} duplicate groups", - "duplicatesResolved": "Duplicate matches resolved", - "errorResolveDuplicates": "Failed to resolve duplicates", - "preflightNotReady": "Migration preflight not ready", - "runDryRunFirst": "Run dry-run first", - "runStarted": "Migration run started", - "errorStartMigration": "Failed to start migration", - "runCancelled": "Migration run cancelled", - "errorCancelMigration": "Failed to cancel migration", - "runRetried": "Migration run retried - resuming from last completed stage", - "errorRetryMigration": "Failed to retry migration", - "errorLoadRunProgress": "Failed to load run progress", - "startMigrationFirst": "Start migration first", - "reportRefreshed": "Run report refreshed", - "errorLoadReport": "Failed to load run report", - "reportExported": "Report exported as {format}", - "errorExportReport": "Failed to export migration report", - "reasonNoTitleAuthorMatch": "No matching book found by title or author", - "reasonNoFilePathMatch": "File path did not match any book in this library", - "reasonNoFileHashMatch": "File hash did not match any book in this library", - "reasonNoIsbnMatch": "ISBN did not match any book in this library", - "reasonInsufficientSourceData": "Not enough metadata to attempt matching", - "reasonAmbiguousIsbnMatch": "Multiple books matched the same ISBN", - "reasonAmbiguousFileHashMatch": "Multiple books matched the same file hash", - "reasonAmbiguousFilePathMatch": "Multiple books matched the same file path", - "reasonAmbiguousTitleAuthorMatch": "Multiple books matched the same title and author", - "reasonUnknown": "Could not determine reason", - "strategyIsbn": "Matched by ISBN", - "strategyFileHash": "Matched by file hash", - "strategyPathMapping": "Matched by mapped file path", - "strategyTitleAuthor": "Matched by title and author", - "strategyUnavailable": "Match strategy unavailable", - "userPreviewCounts": "{statuses} statuses, {progress} progress entries, {bookmarks} bookmarks, {annotations} annotations, {collections} collection entries", - "connErrorUnreachable": "Could not reach the database server. Check the host and port.", - "connErrorAuth": "Authentication failed. Check the username and password.", - "connErrorUnknownDatabase": "Database not found. Check the database name.", - "connErrorTimeout": "Connection timed out. Check host and firewall settings.", - "connErrorGeneric": "Connection test failed", - "sourceType": "Source Type", - "sourceName": "Source Name", - "host": "Host", - "port": "Port", - "user": "User", - "password": "Password", - "passwordSavedPlaceholder": "Saved - leave unchanged", - "passwordEmptyPlaceholder": "No password set", - "database": "Database", - "mediaRootPath": "Media Root Path", - "pathOk": "Path OK", - "pathIssue": "Path Issue", - "testPath": "Test Path", - "useTls": "Use TLS/SSL", - "testConnection": "Test Connection", - "saveAndValidate": "Save & Validate", - "sourceValidatedWithWarnings": "Source validated with warnings", - "lastValidationSnapshot": "Last validation snapshot", - "sourceVersion": "Source version: {version}", - "unknown": "Unknown", - "missingRequiredTables": "Missing required tables: {tables}", - "suggestionsAutoLoad": "User suggestions load automatically after source validation.", - "refresh": "Refresh", - "sourceUser": "Source User", - "targetUser": "Target User", - "noSourceUsersLoaded": "No source users loaded yet.", - "noActiveTargetUsers": "No active target users found. Create or re-enable a BookOrbit user before mapping.", - "pathPrefixMappings": "Path Prefix Mappings", - "addMapping": "Add Mapping", - "pathMappingsHelp1": "Path mappings translate source file paths to target paths so books can be matched by file location. For example, if your Booklore library stored files under", - "pathMappingsHelp2": "and the same files now live under", - "pathMappingsHelp3": ", add that mapping here. Books are also matched by ISBN, file hash, and title/author regardless of path mappings - path mapping is only one of four strategies and does not limit which source books are included in the migration.", - "noPrefixesFound": "No prefixes found - validate source first", - "selectSourcePrefix": "Select source prefix...", - "selectTargetFolder": "Select target folder...", - "remove": "Remove", - "pathValidation": "Path validation", - "pathValidationMapped": "{mapped} of {total} source books have a mapped path", - "pathValidationUnmatched": "{count} mapped paths not found on disk - those books will fall back to ISBN / title matching", - "pathValidationAllMatched": "All {count} mapped paths found on disk", - "saveMappings": "Save Mappings", - "runDryRun": "Run Dry-Run", - "matched": "Matched:", - "unresolved": "Unresolved:", - "duplicateMatches": "Duplicate matches:", - "unresolvedSummary": "Unresolved summary", - "resolveDuplicateMatches": "Resolve duplicate target matches", - "resolveDuplicateHint": "For each target book, choose one source book to keep. Recommended choices are preselected when there is a single strongest match.", - "remainingGroups": "Remaining groups:", - "ofCount": "of {count}", - "targetBookNum": "Target book #{id}", - "recommended": "Recommended", - "resolveDuplicatesButton": "{count, plural, =0 {Resolve # duplicate} other {Resolve # duplicates}}", - "preflightChecks": "Preflight checks", - "allChecksPassed": "All checks passed - ready to migrate", - "checkSourceValidated": "Source validated", - "checkSaveValidateSource": "Save and validate source connection", - "checkValidateSource": "Validate source connection", - "checkMappingsSaved": "Mappings saved", - "checkSaveMappings": "Save user and path mappings", - "checkPathMappingsValidated": "Path mappings validated", - "checkSavePathMappings": "Save path mappings to validate them", - "checkDryRunUpToDate": "Dry-run is up to date", - "checkFreshDryRun": "Run a fresh dry-run", - "startConfirmPrompt": "This will start the live migration. Are you sure?", - "confirmStart": "Confirm Start", - "startMigration": "Start Migration", - "cancelRun": "Cancel Run", - "refreshStatus": "Refresh Status", - "statusPollingStopped": "Status polling stopped due to an error.", - "retry": "Retry", - "stageLabel": "Stage: {stage}", - "stageInitializing": "initializing", - "endedLabel": "Ended {date}", - "stageCompleted": "Completed", - "stageInit": "Initializing", - "stageSharedOverlays": "Importing metadata", - "stageBookCovers": "Importing covers", - "stageUserState": "Importing user data", - "noRunYet": "No migration run yet. Complete the steps above to start.", - "runNum": "Run #{id}", - "notStarted": "Not started", - "reloadReport": "Reload Report", - "loadFullReport": "Load Full Report", - "exportJson": "Export JSON", - "exportCsv": "Export CSV", - "migrationFailed": "Migration failed", - "retryFromLastStage": "Retry from last completed stage", - "booksCard": "Books", - "metadataOverlaysApplied": "Metadata overlays applied", - "authorMappingsReplaced": "Author mappings replaced", - "narratorMappingsReplaced": "Narrator mappings replaced", - "genreMappingsReplaced": "Genre mappings replaced", - "tagMappingsReplaced": "Tag mappings replaced", - "coversImported": "Covers imported", - "coverImportSkipped": "Cover import was skipped - media root path is not configured on the source", - "couldNotMatch": "Could not match", - "userDataCard": "User Data", - "readingStatuses": "Reading statuses", - "readingProgressEntries": "Reading progress entries", - "audiobookProgressEntries": "Audiobook progress entries", - "bookmarksLabel": "Bookmarks", - "annotationsLabel": "Annotations", - "collectionEntries": "Collection entries", - "loadFullReportHint": "Click \"Load Full Report\" to include the dry-run match summary in the exported report.", - "completedNoIssues": "Migration completed with no unresolved books or failures.", - "matchedBooksHeading": "Matched books ({count})", - "matchedBooksHint": "These dry-run matches were used to decide which library books received imported data.", - "sourceBookFallback": "Source book {id}", - "libraryBookFallback": "Library book {id}", - "unresolvedBooksHeading": "Unresolved books ({count})", - "unresolvedBooksHint": "These books exist in the source but could not be matched to any book in your library.", - "mappedUsersHeading": "Mapped users ({count})", - "mappedUsersHint": "Per-user totals come from the dry-run preview cached with the migration plan.", - "coverImportsFailed": "{count} cover import(s) failed. Detailed failure rows are not stored.", - "backToSetup": "Back to Setup" - }, - "libraries": { - "title": "Libraries", - "subtitle": "Manage your media libraries and trigger content scans.", - "scanAll": "Scan All", - "scanning": "Scanning...", - "addLibrary": "Add Library", - "scan": "Scan", - "editLibrary": "Edit library", - "refreshCovers": "Refresh covers", - "syncMetadataToFiles": "Sync metadata to files", - "deleteLibrary": "Delete library", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "addedDate": "Added {date}", - "fileMode": "File mode", - "folderMode": "Folder mode", - "folderCount": "{count, plural, =0 {no folders} other {# folders}}", - "watching": "Watching", - "fileWrite": "File write", - "fileRename": "File rename", - "emptyTitle": "No libraries yet", - "emptyHint": "Add a library to start organizing your books.", - "addFirstLibrary": "Add your first library", - "deleteConfirmTitle": "Delete \"{name}\"?", - "deleteConfirmBody": "This will permanently remove all books, metadata, reading progress, bookmarks, and annotations in this library. This cannot be undone.", - "deleteConfirmTypeName": "Type the library name to confirm:", - "deleting": "Deleting...", - "deleteLibraryButton": "Delete Library", - "syncConfirmTitle": "Sync metadata to files?", - "syncConfirmBodyPrefix": "This will overwrite the metadata inside every supported file in", - "syncConfirmBodySuffix": "directly on disk. This cannot be undone.", - "syncFiles": "Sync files", - "metadataSynced": "Metadata synced to files for \"{name}\"", - "fileWriteNotEnabled": "Metadata file write is not enabled for this library. Enable it in the library settings.", - "fileSyncFailed": "File sync failed for \"{name}\"", - "scanStarted": "Scan started for \"{name}\"", - "scanStartFailed": "Failed to start scan for \"{name}\"", - "refreshCoversFailed": "Failed to refresh covers for \"{name}\"", - "scanStartedAll": "Scan started for all libraries", - "librariesFailedToStart": "{count, plural, =0 {no libraries failed to start} other {# libraries failed to start}}", - "scansStartFailed": "Failed to start scans", - "libraryCreated": "Library \"{name}\" created", - "libraryUpdated": "Library \"{name}\" updated", - "libraryDeleted": "\"{name}\" deleted", - "deleteFailed": "Failed to delete library", - "scanningProgress": "Scanning {pct}% ({processed}/{total})", - "scanDone": "Done - {added} added, {updated} updated", - "scanFailedWithError": "Failed: {error}", - "scanFailed": "Scan failed", - "refreshingCovers": "Refreshing covers {pct}% ({processed}/{total})", - "coversRefreshed": "Covers refreshed ({count} processed)" - }, - "authorEnrichment": { - "configuration": "Configuration", - "saving": "Saving...", - "running": "Running...", - "runEligibleShort": "Run eligible", - "runAllShort": "Run all", - "enableTitle": "Enable auto author enrichment", - "enableHint": "Automatically fetch author biographies and profile photos when books are added or updated.", - "updateStrategyTitle": "Update strategy", - "updateStrategyHint": "What to do when an author already has a biography or photo.", - "writeModeMissingOnly": "Only fill missing data (recommended)", - "writeModeAlwaysRefetch": "Always refresh existing data", - "triggerOnImportTitle": "Trigger on import", - "triggerOnImportHint": "Queue authors for enrichment when books are first added to a library.", - "eligibilityTitle": "Eligibility conditions", - "eligibilityHint": "An author is eligible if it matches any enabled condition.", - "neverEnrichedTitle": "Never enriched", - "neverEnrichedHint": "Enrich authors that have never had a successful enrichment.", - "missingBioTitle": "Missing bio", - "missingBioHint": "Enrich if the author has no biography.", - "missingPhotoTitle": "Missing photo", - "missingPhotoHint": "Enrich if the author has no profile photo.", - "runForEligibleAuthors": "Run for eligible authors", - "eligibleCount": "~{count} eligible", - "runForAllAuthors": "Run for all authors", - "saved": "Author enrichment settings saved", - "saveFailed": "Failed to save author enrichment settings", - "noEligibleAuthors": "No eligible authors found", - "noAuthorsToEnrich": "No authors to enrich", - "queueFailed": "Failed to queue author backfill" - }, - "scoreWeights": { - "groupLabel": "Score Weights", - "assignHintPrefix": "Assign a weight to each field. Total weight:", - "areYouSure": "Are you sure?", - "resetToDefaultsButton": "Reset to defaults", - "recalculateAll": "Recalculate all", - "confirmReset": "Confirm reset", - "reset": "Reset", - "recalculate": "Recalculate", - "subtotal": "subtotal: {count}", - "savedRecalculating": "Score weights saved. Recalculating library scores...", - "saveFailed": "Failed to save score weights", - "recalcStarted": "Score recalculation started in the background", - "recalcFailed": "Recalculation failed", - "resetToDefaults": "Weights reset to defaults. Save to apply." - }, - "tabs": { - "users": "Users", - "account-activity": "Account Activity", - "magic-links": "Magic Links", - "oidc": "OIDC / SSO" - } - }, - "common": { - "nav": { - "libraries": "Libraries", - "display": "Display", - "reader": "Reader", - "metadata": "Metadata", - "email": "Email", - "opds": "OPDS", - "kobo": "Kobo", - "koreader": "KOReader", - "hardcover": "Hardcover", - "admin": "Admin", - "system": "System", - "account": "Account" - } - }, - "metadata": { - "title": "Metadata", - "noPermission": "You do not have permission to manage metadata settings.", - "fields": { - "title": "Title", - "subtitle": "Subtitle", - "description": "Description", - "cover": "Cover", - "authors": "Authors", - "publisher": "Publisher", - "publishedYear": "Published year", - "language": "Language", - "pageCount": "Page count", - "communityRating": "Community rating", - "seriesName": "Series name", - "seriesIndex": "Series index", - "genres": "Genres", - "narrators": "Narrators", - "duration": "Duration", - "abridged": "Abridged" - }, - "mergeStrategy": { - "fillMissing": { - "label": "Fill missing", - "description": "Only write if field is currently empty" - }, - "overwriteIfProvided": { - "label": "Overwrite if provided", - "description": "Write if provider returned a value" - }, - "overwrite": { - "label": "Always overwrite", - "description": "Always replace existing value" - } - }, - "autoFetch": { - "globalSettings": "Global Settings", - "perLibraryOverrides": "Per-Library Overrides", - "saving": "Saving...", - "running": "Running...", - "runNow": "Run now", - "runForEligible": "Run for eligible books", - "enable": { - "label": "Enable auto-fetch", - "hint": "Automatically fetch metadata for eligible books." - }, - "triggerOnImport": { - "label": "Trigger on import", - "hint": "Queue eligible books when they are first added to a library." - }, - "status": { - "inQueuePaused": "{count} in queue - paused", - "remaining": "{count} remaining", - "eligible": "~{count} eligible" - }, - "trigger": { - "queued": "{count, plural, other {Queued # books}}", - "noneFound": "No eligible books found" - }, - "lastRun": { - "justNow": "just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "yesterday": "yesterday", - "daysAgo": "{count, plural, other {# days ago}}", - "label": "Last run: {when}", - "labelQueued": "Last run: {when} - queued {count} books", - "labelNoneEligible": "Last run: {when} - no eligible books" - }, - "conditions": { - "title": "Eligibility conditions", - "hint": "A book is eligible if it matches any enabled condition.", - "noneEnabled": "No conditions enabled", - "neverFetched": { - "label": "Never fetched", - "hint": "Fetch books that have never had a metadata fetch attempt.", - "summary": "Never fetched" - }, - "scoreThreshold": { - "label": "Low metadata score", - "hint": "Fetch if the metadata score is below a threshold.", - "scoreBelow": "Score below", - "summary": "Score < {threshold}" - }, - "missingFields": { - "label": "Missing fields", - "hint": "Fetch if any of the selected fields are empty.", - "summary": "{count, plural, other {Missing # fields}}" - } - }, - "library": { - "inheritingGlobal": "Inheriting global defaults", - "inheritFromGlobal": "Inherit from global", - "usingGlobalDefaults": "Using global defaults.", - "saveOverride": "Save override" - } - }, - "providers": { - "availableSources": "Available Sources", - "saveChanges": "Save Changes", - "test": "Test", - "testing": "Testing...", - "enabled": "Enabled", - "retryIn": "Retry in {duration}", - "runTestBeforeEnabling": "Run Test before enabling", - "hardcoverEnableHint": "Run Test with the current token to unlock the enable switch.", - "badge": { - "setupRequired": "Setup Required", - "throttled": "Throttled", - "ready": "Ready" - }, - "fields": { - "apiKey": "API Key", - "region": "Region", - "cookie": "Cookie", - "coverResolution": "Cover Resolution", - "country": "Country", - "language": "Language", - "ttbKey": "TTB Key" - }, - "helpers": { - "googleApiKey": "Google Books API key from Google Cloud." - }, - "hints": { - "google": "Broad coverage from Google's book index. Google Books now requires an API key before this provider can be enabled.", - "amazon": "Session cookie is recommended. Paste cookie value only (no \"Cookie:\").", - "goodreads": "The largest reading community on the web. No setup required.", - "hardcover": "A modern alternative to Goodreads. Token from hardcover.app/account/api. \"Bearer \" prefix is optional.", - "openLibrary": "The Internet Archive's free book catalog. No setup required.", - "itunes": "Apple's digital book catalog. Choose whether to fetch high or standard resolution covers.", - "kobo": "Scrapes Kobo's public book pages. Country and language must match Kobo URL paths; bot protection can block requests.", - "audible": "Pulls audiobook metadata from Audible. No additional setup is required.", - "audnexus": "Community-driven audiobook metadata. No setup required.", - "comicvine": "Comic book metadata from ComicVine. A free API key is required from comicvine.gamespot.com.", - "ranobedb": "Japanese light novel metadata from RanobeDB. No setup required.", - "lubimyczytac": "Polish book catalog (lubimyczytac.pl). Scrapes public book pages. No setup required.", - "aladin": "Korean book metadata from Aladin (알라딘). A TTB Key from aladin.co.kr is required." - }, - "blocked": { - "google": "Google Books requires an API key before it can be enabled", - "hardcover": "Hardcover requires an API key before it can be enabled", - "hardcoverTest": "Hardcover token must pass Test before it can be enabled", - "comicvine": "ComicVine requires an API key before it can be enabled", - "aladin": "Aladin requires a TTB Key before it can be enabled" - } - }, - "fieldRules": { - "clearAllProviders": "Clear All Providers", - "clearAll": "Clear All", - "resetToDefault": "Reset to Default", - "reset": "Reset", - "dragProvidersHint": "Drag providers from here onto any field to add them", - "dragProviderHere": "drag a provider here", - "howItWorks": { - "title": "How Field Rules Work", - "priorityOrder": { - "title": "Priority Order", - "body": "Drag providers in the list to reorder them. The top-most provider that returns a result will be the primary source for that field." - }, - "mergeStrategy": { - "title": "Merge Strategy", - "fillMissingTerm": "Fill missing:", - "fillMissingBody": "Only write if current value is empty.", - "overwriteTerm": "Overwrite:", - "overwriteBody": "Replace whenever a provider has data." - } - }, - "libraryOverrides": { - "title": "Library Overrides", - "hint": "Expand a library to customize individual fields. Fields not overridden inherit global defaults." - }, - "global": { - "title": "Global Defaults", - "hint": "Default rules applied to every library. Override per-library below.", - "saveDefaults": "Save Defaults", - "clearAllConfirm": "Remove all active providers from every field? This will be saved immediately and cannot be undone.", - "resetConfirm": "Reset all global field rules to system defaults? This will overwrite your current configuration." - }, - "advanced": { - "title": "Advanced Fetch Behavior", - "combineGenres": { - "label": "Combine genres from all selected providers", - "hint": "Collect and deduplicate genres from every provider assigned to the Genres field, rather than stopping at the first result." - }, - "storeProviderIds": { - "label": "Store provider IDs on books", - "hint": "When fetching metadata, save the returned provider IDs (ISBN, ASIN, Goodreads ID, etc.) on the book record for more accurate future lookups." - } - }, - "library": { - "primary": "Primary:", - "overrideCount": "{count, plural, other {# Overrides}}", - "unsavedSuffix": "(unsaved)", - "unsavedChanges": "Unsaved changes", - "globalDefaults": "Global Defaults", - "overriding": "Overriding: {fields}", - "inheritingAll": "Inheriting all global metadata rules", - "subHint": "Fields not overridden inherit global defaults.", - "resetTooltip": "Remove all overrides and inherit global defaults", - "clearAllConfirm": "Remove all active providers from every field in \"{library}\"?", - "resetConfirm": "Reset \"{library}\" to global defaults? All library overrides will be removed." - }, - "groups": { - "core": "Core", - "contributors": "Contributors", - "publication": "Publication", - "series": "Series", - "classification": "Classification", - "audiobook": "Audiobook" - }, - "groupSummary": { - "base": "{fields} fields · {enabled} enabled", - "withOverrides": "{base} · {overrides} overrides" - }, - "table": { - "field": "Field", - "activeProviders": "Active Providers (ordered by priority)", - "mergeStrategy": "Merge Strategy", - "status": "Status" - }, - "field": { - "noProviders": "Enabled but has no providers", - "empty": "Empty", - "config": "Config", - "custom": "Custom", - "default": "Default", - "resetToDefault": "Reset to default" - }, - "reservoir": { - "disabled": "{provider} - disabled", - "notConfigured": "{provider} - not configured", - "dragToAssign": "Drag to assign {provider} to a field" - }, - "sheet": { - "subtitle": "Tap providers to assign, use arrows to reorder", - "enableField": "Enable this field during refresh", - "providers": "Providers", - "statusDisabled": "disabled", - "statusNotConfigured": "not configured", - "done": "Done" - } - }, - "genreBlocklist": { - "heading": "Global Genre Exclusions", - "hint": "Exact genre values in this list are stripped from provider results before metadata is written.", - "saving": "Saving", - "genreValueLabel": "Genre value", - "addPlaceholder": "Add a genre value, for example Audiobook", - "duplicate": "This genre is already blocked.", - "add": "Add", - "filterPlaceholder": "Filter blocklist", - "entryCount": "{count, plural, other {# entries}}", - "filteredCount": "{shown} of {total}", - "noFilterMatch": "No blocked genres match the current filter.", - "emptyTitle": "No blocked genres", - "emptyHint": "Add exact values such as Audiobook or Adult to keep them out of fetched metadata.", - "removeLabel": "Remove {genre}" - }, - "customFields": { - "label": "Label", - "labelPlaceholder": "e.g. Original Title", - "labelTooLong": "Label must be 255 characters or fewer", - "labelDuplicate": "A field with this label already exists", - "type": "Type", - "usage": "{count, plural, other {Used by # books}}", - "newField": { - "title": "New Field", - "hint": "Define a custom metadata field and choose which libraries use it." - }, - "previewToggle": "Preview how this field appears when editing a book", - "untitledField": "Untitled field", - "addField": "Add field", - "fields": "Fields", - "fieldsHint": "Drag to reorder, edit labels, toggle libraries, or archive fields you no longer need.", - "searchPlaceholder": "Search fields", - "searchAriaLabel": "Search custom fields", - "emptyTitle": "No custom fields yet", - "emptyHint": "Use the form above to define your first custom metadata field.", - "noMatchTitle": "No fields match \"{query}\"", - "noMatchHint": "Try a different label, key, or type.", - "clearSearchToReorder": "Clear search to reorder", - "dragToReorder": "Drag to reorder", - "dragToReorderField": "Drag to reorder field", - "unsaved": "Unsaved", - "archive": "Archive", - "archivedFields": "Archived Fields", - "archivedSummary": "{count, plural, other {# archived fields - restore or permanently delete.}}", - "archivedAt": "Archived {when}", - "restore": "Restore", - "deleteForever": "Delete forever", - "deleteDialog": { - "title": "Permanently delete field", - "bodyBefore": "This will permanently delete", - "bodyMiddle": "and remove its stored values from", - "bodyAfter": ". This cannot be undone.", - "confirmBefore": "Type", - "confirmAfter": "to confirm", - "confirmPlaceholder": "Type the field label to confirm" - }, - "preview": "Preview", - "sampleValue": "Sample value", - "enabledLibraries": "Enabled Libraries", - "countOf": "{selected} of {total}", - "selectAll": "Select all", - "clear": "Clear", - "noLibraries": "No libraries available yet.", - "allLibraries": "All libraries" - }, - "tabs": { - "providers": "Providers", - "field-rules": "Field Rules", - "custom-fields": "Custom Fields", - "genre-blocklist": "Genre Blocklist", - "score": "Score", - "auto-fetch": "Books", - "authors": "Authors" - }, - "tabTitles": { - "providers": "Providers", - "field-rules": "Field-Level Rules", - "custom-fields": "Custom Metadata", - "genre-blocklist": "Genre Blocklist", - "score": "Confidence Score", - "auto-fetch": "Book Auto-Fetch", - "authors": "Author Auto-Fetch" - }, - "tabSubtitles": { - "providers": "Enable external metadata sources and configure their credentials.", - "field-rules": "Control which provider supplies each metadata field and how values are merged across your libraries.", - "custom-fields": "Define custom metadata fields and choose which libraries use them.", - "genre-blocklist": "Prevent unwanted provider genre values from being written to books.", - "score": "Assign weights to metadata fields to calculate how much to trust fetched results.", - "auto-fetch": "Automatically fetch covers, descriptions, and other details when new books are added to your library.", - "authors": "Automatically fetch biographies and profile photos when new authors appear in your library." - } - }, - "reader": { - "resetToDefaults": "Reset to defaults", - "all": { - "title": "Reader", - "subtitle": "Configure defaults for all reading modes in one place." - }, - "general": { - "title": "Reading", - "subtitle": "General behavior that applies across all reader types.", - "storageLabel": "Where to save reader preferences", - "deviceOnly": "This device only", - "deviceOnlyHint": "Preferences stay in your browser. Best if you always read on this device, or want different settings per device.", - "myAccount": "My account", - "myAccountHint": "Preferences are saved to your account. Best if you log in from multiple devices and want a consistent experience everywhere.", - "active": "Active", - "notAvailable": "Not available", - "demoCannotChangeStorage": "Demo-restricted account cannot change reader storage mode", - "preferencesSynced": "Preferences will now be synced", - "preferencesLocal": "Preferences will stay on this device", - "storageUpdateFailed": "Failed to update storage mode", - "storageUpdateError": "An error occurred while updating storage mode" - }, - "ebook": { - "title": "eBook Reader", - "subtitle": "Default settings applied when opening EPUB, MOBI, FB2, and TXT files.", - "newBooks": "New Books", - "applySettings": "Apply my settings to new books", - "applySettingsHint": "When off, new books open with the publisher's own fonts and layout. Your settings only apply once you change something in-reader.", - "layout": "Layout", - "readingFlow": "Reading flow", - "readingFlowHint": "Paginated flips pages; scrolled flows continuously", - "paginated": "Paginated", - "scrolled": "Scrolled", - "fixedLayoutSpread": "Fixed-layout page spreads", - "fixedLayoutSpreadHint": "Default for manga, comics, and image-based EPUBs", - "bookDefault": "Book default", - "singlePage": "Single page", - "columns": "Columns", - "columnsHint": "Number of text columns per page", - "theme": "Theme", - "darkMode": "Dark mode", - "darkModeHint": "Use the dark variant of the selected theme", - "typography": "Typography", - "font": "Font", - "fontHint": "Typeface used for body text", - "builtInFonts": "Built-in fonts", - "yourFonts": "Your Fonts", - "fontSize": "Font size", - "fontSizeHint": "Base text size in pixels", - "lineHeight": "Line height", - "lineHeightHint": "Vertical spacing between lines", - "justify": "Justify text", - "justifyHint": "Align text to both margins", - "hyphenation": "Hyphenation", - "hyphenationHint": "Automatically break long words with hyphens", - "advanced": "Advanced", - "maxContentWidth": "Max content width", - "maxContentWidthHint": "Maximum width of the text area in pixels", - "columnGap": "Column gap", - "columnGapHint": "Horizontal padding on each side of the text area" - }, - "pdf": { - "title": "PDF Reader", - "subtitle": "Default settings applied when opening PDF files.", - "layout": "Layout", - "scrollMode": "Scroll mode", - "scrollModeHint": "Page flips one at a time; continuous scrolls through all pages", - "page": "Page", - "scrolled": "Scrolled", - "pageSpread": "Page spread", - "pageSpreadHint": "Which page number starts on the right in two-page view", - "spreadNone": "None", - "spreadOdd": "Odd", - "spreadEven": "Even", - "zoom": "Zoom", - "defaultFit": "Default fit", - "defaultFitHint": "How pages are scaled when a PDF is opened", - "fitPage": "Fit Page", - "fitWidth": "Fit Width", - "custom": "Custom", - "zoomLevel": "Zoom level", - "zoomLevelHint": "Scale factor for custom zoom mode" - }, - "comics": { - "title": "Comics Reader", - "subtitle": "Default settings applied when opening CBZ, CBR, and CB7 files.", - "view": "View", - "readingMode": "Reading mode", - "readingModeHint": "How pages are navigated - use \"Infinite (no gaps)\" for webtoons", - "paginated": "Paginated", - "infiniteSpaced": "Infinite (spaced)", - "infiniteNoGaps": "Infinite (no gaps)", - "pageView": "Page view", - "pageViewHint": "Show one or two pages side by side", - "single": "Single", - "twoPage": "Two-page", - "fitMode": "Fit mode", - "fitModeHint": "How pages are scaled to fit the screen", - "fitPage": "Page", - "fitWidth": "Width", - "fitHeight": "Height", - "fitActual": "Actual", - "readingDirection": "Reading direction", - "readingDirectionHint": "Left-to-right for western comics; right-to-left for manga", - "ltr": "L to R", - "rtl": "R to L", - "spreadAlignment": "Spread alignment", - "spreadAlignmentHint": "Shift pairing by one page after the cover for off-by-one scans", - "alignmentNormal": "Normal", - "alignmentShifted": "Shifted", - "spreadGap": "Spread gap", - "spreadGapHint": "Space between pages in two-page view", - "spreadGapValue": "{value}px", - "widePageHandling": "Wide-page handling", - "widePageHandlingHint": "Auto shows wide scans alone in two-page paginated mode", - "widePageAuto": "Auto", - "widePageDisable": "Disable", - "forceTwoPage": "Force two-page on small screens", - "forceTwoPageHint": "Bypass mobile auto-fallback when paginated two-page mode is selected", - "off": "Off", - "on": "On", - "display": "Display", - "backgroundColor": "Background color", - "backgroundColorHint": "Canvas color behind pages", - "bgBlack": "Black", - "bgGray": "Gray", - "bgWhite": "White" - }, - "audio": { - "title": "Audiobook Player", - "subtitle": "Default settings applied when playing M4B, MP3, and other audio formats.", - "playback": "Playback", - "playbackSpeed": "Default playback speed", - "playbackSpeedHint": "Speed multiplier applied when opening a new audiobook", - "volume": "Default volume", - "volumeHint": "Initial volume level (0 to 100%)", - "skipControls": "Skip controls", - "skipBack": "Skip back duration", - "skipBackHint": "Seconds rewound on skip-back press", - "skipForward": "Skip forward duration", - "skipForwardHint": "Seconds advanced on skip-forward press" - }, - "fonts": { - "title": "Fonts", - "subtitle": "Upload custom fonts for use in the eBook reader.", - "uploadFonts": "Upload Fonts", - "notAvailableDemo": "Not available for demo accounts", - "uploading": "Uploading...", - "dropFilesHere": "Drop files here", - "dragFontsPrefix": "Drag font files here, or", - "browse": "browse", - "fileTypesHint": "TTF, OTF, WOFF, WOFF2 - max 10 MB each", - "yourFonts": "Your Fonts", - "fontsUsed": "{count} / {max} used", - "noFontsYet": "No fonts uploaded yet", - "noFontsHint": "Drag a font file above to get started.", - "fileCount": "{count, plural, =0 {no files} other {# files}}", - "pangram": "The quick brown fox jumps over the lazy dog", - "renameFamily": "Rename family", - "deleteFamily": "Delete family", - "editVariant": "Edit weight/style", - "deleteVariant": "Delete variant", - "styleNormal": "Normal", - "styleItalic": "Italic", - "weightThin": "Thin", - "weightExtraLight": "Extra Light", - "weightLight": "Light", - "weightRegular": "Regular", - "weightMedium": "Medium", - "weightSemiBold": "Semi Bold", - "weightBold": "Bold", - "weightExtraBold": "Extra Bold", - "weightBlack": "Black", - "renameFamilyFailed": "Failed to rename font family", - "renamedTo": "Renamed to \"{name}\"", - "updateVariantFailed": "Failed to update font variant", - "deleteFontFailed": "Failed to delete font", - "deleteFamilyFailed": "Failed to delete font family", - "demoCannotManage": "Demo-restricted account cannot manage fonts", - "fileAdded": "\"{name}\" added", - "uploadFailed": "Upload failed" - }, - "bookDock": { - "title": "Book Dock", - "subtitle": "Configure how files are processed when they enter Book Dock.", - "dropFolder": "Drop folder", - "containerPath": "Container path", - "containerPathHint": "Copy or move book files into this folder and they will be automatically picked up and processed by Book Dock. Subdirectories are supported.", - "changePathPrefix": "To change this path, set", - "changePathMiddle": "in your", - "changePathSuffix": "file.", - "metadata": "Metadata", - "autoFetch": "Auto-fetch metadata from providers", - "autoFetchHint": "Automatically fetch metadata from configured providers (Google Books, iTunes, Open Library, etc.) after a file is added to Book Dock.", - "autoFinalize": "Auto-finalize", - "enableAutoFinalize": "Enable auto-finalize", - "enableAutoFinalizeHint": "Files with a metadata confidence score at or above the threshold will be finalized automatically.", - "confidenceThreshold": "Confidence threshold: {value}%", - "thresholdIgnored": "(ignored in Embedded only mode)", - "destinationLibrary": "Destination library", - "selectLibrary": "Select a library...", - "metadataMode": "Metadata mode", - "metadataModeSafeMerge": "Safe merge (recommended)", - "metadataModeFetchedOnly": "Fetched only", - "metadataModeEmbeddedOnly": "Embedded only", - "destinationFolder": "Destination folder", - "selectFolder": "Select a folder...", - "saveSettingFailed": "Failed to save setting", - "updateSettingFailed": "Failed to update setting", - "autoFetchEnabled": "Auto-fetch enabled", - "autoFetchDisabled": "Auto-fetch disabled", - "autoFinalizeEnabled": "Auto-finalize enabled", - "autoFinalizeDisabled": "Auto-finalize disabled", - "destinationLibraryUpdated": "Destination library updated", - "destinationFolderUpdated": "Destination folder updated", - "confidenceThresholdUpdated": "Confidence threshold updated", - "metadataModeUpdated": "Metadata mode updated" - }, - "fileNaming": { - "title": "File Naming", - "subtitle": "Control how files are organized on disk when uploaded and how they are named when downloaded using placeholder tokens.", - "copy": "Copy", - "previewLabel": "Preview:", - "globalDefaults": "Global Defaults", - "crossPlatform": "Cross-platform path sanitization", - "crossPlatformHint": "Make generated file and folder names safe on Windows by replacing invalid characters and reserved names, and removing trailing dots and spaces. Disable only for Linux-only setups that intentionally keep those characters.", - "fileAsBookDefault": "File as Book default", - "fileAsBookDefaultHint": "Upload pattern for libraries using File as Book mode. Each file is one book.", - "folderAsBookDefault": "Folder as Book default", - "folderAsBookDefaultHint": "Upload pattern for libraries using Folder as Book mode. Each book must be in its own folder.", - "downloadPattern": "Download Pattern", - "downloadPatternHint": "Suggested filenames for single-file downloads and files inside export ZIPs.", - "libraryOverrides": "Library Overrides", - "noLibraries": "No libraries configured. Create one in Library settings to set custom naming patterns.", - "badgeCustom": "Custom", - "badgeDefault": "Default", - "orgFolderAsBook": "Folder as Book", - "orgFileAsBook": "File as Book", - "resetToDefault": "Reset to default", - "tokens": "Tokens", - "clickTokenHint": "Click any token to copy it to your clipboard.", - "copyValue": "Copy {value}", - "modifiers": "Modifiers", - "modifiersExplain": "Append a modifier inside a token to transform its value:", - "modFirst": "First value only", - "modSort": "Last, First format", - "modInitial": "First letter only", - "modFixed2": "Two decimal places", - "folderOnlyPrefix": "End a pattern with", - "folderOnlySuffix": "to specify a folder only. The original filename will be preserved inside it.", - "conditionalLogic": "Conditional Logic", - "conditionalPart1": "Wrap in", - "conditionalPart2": "to skip a segment when its token is empty. Use", - "conditionalPart3": "for a default value.", - "examples": "Examples", - "exCalibre": "Calibre-style default", - "exSeriesReader": "Series reader", - "exCleanDownload": "Clean download filename", - "exAlphabetical": "Alphabetical grouping with series", - "exSeriesFallback": "Series or Standalone fallback", - "exOptionalSubtitle": "Download with optional subtitle", - "exMultilingual": "Multilingual library", - "exPublisher": "Publisher-organized", - "exStacked": "Stacked optional folders", - "exFolderDrop": "Folder-drop with sort name", - "caseWithYear": "with year", - "caseNoYear": "no year", - "caseInSeries": "in series", - "caseStandalone": "standalone", - "caseNoSeries": "no series", - "caseFull": "full", - "caseMinimal": "minimal", - "caseWithLanguage": "with language", - "caseNoLanguage": "no language", - "caseWithPublisher": "with publisher", - "caseNoPublisher": "no publisher", - "caseAllSet": "all set", - "copiedToClipboard": "{value} copied to clipboard", - "copyTokenFailed": "Failed to copy token", - "patternCopied": "Pattern copied to clipboard", - "copyPatternFailed": "Failed to copy pattern", - "labelCopied": "{label} copied to clipboard", - "copyLabelFailed": "Failed to copy {label}", - "patternHelp": "Pattern help", - "patternHelpDescription": "Tokens, modifiers and ready-made patterns you can copy into any field.", - "copyPreview": "Copy {label}", - "copyExample": "Copy the {label} pattern", - "invalidCharacters": "Pattern contains invalid characters", - "fileAsBookSaved": "File as Book default saved", - "folderAsBookSaved": "Folder as Book default saved", - "downloadPatternSaved": "Download pattern saved", - "savePatternFailed": "Failed to save pattern", - "saveDownloadPatternFailed": "Failed to save download pattern", - "crossPlatformEnabled": "Cross-platform path sanitization enabled", - "crossPlatformDisabled": "Cross-platform path sanitization disabled", - "crossPlatformSaveFailed": "Failed to save cross-platform path sanitization", - "librarySaved": "Pattern saved for {name}", - "librarySaveFailed": "Failed to save library pattern", - "saveLibraryPattern": "Save pattern for {name}", - "resetLibraryPattern": "Reset {name} to the default pattern", - "tokenTitle": "Book title", - "tokenSubtitle": "Book subtitle", - "tokenAuthors": "Author(s), comma-separated", - "tokenYear": "Publication year", - "tokenSeries": "Series name", - "tokenSeriesIndex": "Series index (zero-padded)", - "tokenPublisher": "Publisher", - "tokenIsbn": "ISBN-13", - "tokenLanguage": "Language", - "tokenOriginalFilename": "Original filename (without extension)", - "tokenExtension": "File extension (without dot)", - "patternHelpIntro": "Patterns use tokens like {titleToken} and {authorsToken}, plus modifiers and optional segments.", - "browseTokensAndExamples": "Browse tokens and examples" - }, - "kobo": { - "title": "Kobo Sync", - "subtitle": "Pair your Kobo device to sync your library.", - "copy": "Copy", - "never": "Never", - "justNow": "Just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "daysAgo": "{count}d ago", - "loadFailed": "Failed to load", - "devicePaired": "Device paired successfully", - "devicePairedHint": "You're ready to set up your Kobo. Follow the instructions below.", - "syncUrl": "Sync URL", - "urlNotShownAgain": "This URL will not be shown again. Keep it private.", - "registeredDevices": "Registered Devices", - "addDevice": "Add device", - "deviceName": "Device name", - "deviceNamePlaceholder": "e.g. My Kobo Libra", - "creating": "Creating...", - "createDevice": "Create device", - "createDeviceFailed": "Failed to create device", - "deviceRegistered": "Device \"{name}\" registered", - "noDevicesYet": "No devices yet", - "noDevicesHint": "Add a device to start syncing your books to your Kobo.", - "lastSync": "Last sync: {time}", - "renameDevice": "Rename device", - "revokeAccess": "Revoke access", - "deviceRenamed": "Device renamed", - "renameDeviceFailed": "Failed to rename device", - "revokeConfirm": "Revoke access for \"{name}\"? The device will not be able to sync until re-paired.", - "accessRevoked": "Access revoked for \"{name}\"", - "revokeFailed": "Failed to revoke access", - "syncUrlCopied": "Sync URL copied to clipboard", - "syncUrlCopyFailed": "Failed to copy sync URL", - "syncPreferences": "Sync Preferences", - "twoWaySync": "Two-way progress sync", - "twoWaySyncHint": "Sync reading position between BookOrbit and Kobo. Requires KEPUB delivery for precise locations and reliable page restore.", - "syncHighlights": "Sync BookOrbit highlights to Kobo", - "syncHighlightsHint": "Send highlights made in BookOrbit or KOReader to your Kobo. Kobo highlights are imported into BookOrbit even when this is off. Linked annotations sync edits and deletes both ways. Requires KEPUB delivery; the book on Kobo must be the KEPUB downloaded from BookOrbit.", - "convertKepub": "Convert to KEPUB", - "convertKepubHint": "Send eligible EPUBs as KEPUB. This stays on when progress sync or BookOrbit-to-Kobo highlights are enabled. On the next Kobo sync, affected books are offered again as KEPUB downloads; remove any old EPUB copy if Kobo keeps opening it.", - "forceHyphenation": "Force hyphenation", - "forceHyphenationHint": "Ensures consistent text justification. This will regenerate cached KEPUBs.", - "progressThresholds": "Progress Thresholds", - "progressThresholdsHint": "Define when Kobo reading progress updates your library status.", - "markAsReading": "Mark as Reading", - "markAsReadingHint": "Minimum percentage to move a book to \"Reading\".", - "markAsFinished": "Mark as Finished", - "markAsFinishedHint": "Percentage threshold to mark a book as \"Finished\".", - "kepubLimit": "KEPUB conversion limit", - "kepubLimitHint": "Books above this limit are sent as regular EPUBs, so BookOrbit will not sync their reader position back to Kobo.", - "changesMustBeSaved": "Changes must be saved to take effect.", - "saving": "Saving...", - "saveSyncSettings": "Save Sync Settings", - "thresholdOrderError": "Reading threshold must be less than finished threshold", - "saveSettingsFailed": "Failed to save settings", - "settingsSaved": "Kobo sync settings saved", - "saveFailed": "Failed to save", - "activity": { - "waitingForActivity": "Waiting for activity", - "needsAttention": "Needs attention", - "syncHealthy": "Sync healthy", - "never": "Never", - "none": "None", - "unknown": "Unknown", - "failureCount": "{count, plural, other {# failures}}", - "noActivityRecorded": "No Kobo sync activity has been recorded.", - "lastSuccess": "Last success {time}", - "lastFailure": "Last failure {time}", - "noFailedActivity": "No failed Kobo activity in recent history.", - "noActivityYet": "No Kobo activity yet.", - "event": { - "librarySync": "Library checked for updates", - "bookDownload": "Book downloaded", - "progressUpdate": "Reading position updated", - "annotationsPull": "Highlights sent to Kobo", - "annotationsPush": "Highlights received from Kobo" - }, - "outcome": { - "failed": "Failed", - "noUpdates": "No updates", - "noChanges": "No changes", - "pending": "Pending", - "completed": "Completed", - "downloaded": "Downloaded", - "updated": "Updated", - "sent": "Sent", - "imported": "Imported" - }, - "failure": { - "librarySync": "Library check did not complete", - "bookDownload": "Download did not complete", - "progressUpdate": "Reading position did not update", - "annotationsPull": "Highlights were not sent", - "annotationsPush": "Highlights were not imported" - }, - "chip": { - "morePending": "More pending", - "noUpdatesPending": "No updates pending", - "bookCount": "{count, plural, other {# books}}", - "deletedAnnotations": "{count} deleted annotations", - "deviceAlreadyCurrent": "Device already current", - "freshHighlightData": "Fresh highlight data", - "created": "{count} created", - "updated": "{count} updated", - "deleted": "{count} deleted", - "unchanged": "{count} unchanged" - }, - "readingPositionSyncedTitle": "Reading position synced: {title}", - "readingPositionSynced": "Reading position synced", - "labelWithTitle": "{label}: {title}", - "updateCount": "{count, plural, other {# updates}}", - "directionToKobo": "BookOrbit -> Kobo", - "directionToBookOrbit": "Kobo -> BookOrbit", - "twoWaySyncEnabled": "Two-way sync enabled", - "deviceProgressSaved": "Device progress saved", - "summary": { - "noLibraryUpdatesPending": "No library updates are pending for this device", - "libraryUpdatesPrepared": "{count, plural, other {# library updates prepared for the device}}", - "bookDownloadedBy": "{title} was downloaded by {device}", - "booksDownloaded": "{count, plural, other {# books downloaded}}", - "progressUpdatesSyncedFor": "{count, plural, other {# progress updates synced for {title}}}", - "progressUpdatesSynced": "{count, plural, other {# progress updates synced}}", - "newReadingPositionFor": "Kobo reported a new reading position for {title}", - "newReadingPosition": "Kobo reported a new reading position", - "noHighlightChangesNeededFor": "No highlight changes needed for {title}", - "noHighlightChangesNeeded": "No highlight changes needed", - "highlightsSentToKoboFor": "{count, plural, other {# highlights sent to Kobo for {title}}}", - "highlightsSentToKobo": "{count, plural, other {# highlights sent to Kobo}}", - "noKoboHighlightChangesFor": "No Kobo highlight changes for {title}", - "noKoboHighlightChanges": "No Kobo highlight changes", - "highlightsImportedFromKoboFor": "{count, plural, other {# highlights imported from Kobo for {title}}}", - "highlightsImportedFromKobo": "{count, plural, other {# highlights imported from Kobo}}" - }, - "timeRange": "{from} to {to}", - "eventsGrouped": "{count, plural, other {# events grouped}}", - "removedDevice": "Removed device", - "loadMoreFailed": "Failed to load more history", - "historyRefreshed": "Kobo sync history refreshed", - "refreshFailed": "Failed to refresh history", - "recentActivity": "Recent Kobo Activity", - "filterAll": "All", - "filterFailures": "Failures", - "refresh": "Refresh", - "loadingActivity": "Loading Kobo activity...", - "noActivityHint": "Recent sync activity will appear after a paired Kobo contacts BookOrbit.", - "error": "Error", - "loading": "Loading...", - "loadMore": "Load more activity" - }, - "howBooksSynced": { - "title": "How books are synced", - "body": "To send books to your Kobo device, you must enable {syncToKobo} on the collections containing those books. Open any collection from the sidebar, click the Edit icon, and toggle {syncToKobo}. Books that are not part of an enabled collection will not sync." - }, - "nextSteps": { - "title": "Next Steps", - "step1": "1. Configure your Kobo device to sync with the Sync URL above.", - "step2": "2. In BookOrbit, go to any collection from the sidebar, click the Edit icon, and enable {syncToKobo}. Only books inside sync-enabled collections will download to your device." - }, - "syncToKobo": "Sync to Kobo", - "tabs": { - "syncSettings": "Sync Settings", - "activityLog": "Activity Log" - } - }, - "koreader": { - "title": "KOReader Sync", - "subtitle": "Browse your BookOrbit catalog in KOReader and sync progress, reading activity, highlights, and annotation changes.", - "tabs": { - "sync": "Sync Settings", - "fileNaming": "File Naming" - }, - "fileNaming": { - "accountTitle": "Account default KOReader pattern", - "accountDescription": "Sets the default relative folder and filename used by BookOrbit plugin downloads for your KOReader account. Device-specific rules can override it below.", - "defaultPattern": "Default book path pattern", - "accountHelp": "Your account default for KOReader plugin downloads unless a device has a custom rule.", - "accountHint": "Used by your KOReader devices that do not have a custom override.", - "preview": "Preview", - "saveAccount": "Save account default", - "deviceTitle": "KOReader device overrides", - "deviceDescription": "Customize any combination of default, series, and standalone paths. Empty device-specific rows inherit the device default, which itself can inherit the account default KOReader pattern.", - "noDevices": "Devices appear here after they sync with BookOrbit.", - "customOrganization": "Custom organization", - "usingAccountDefault": "Using account default", - "deviceDefaultHelp": "Fallback for this device. Leave it equal to the account default to inherit future changes automatically.", - "seriesBooks": "Books in a series", - "seriesHelp": "Optional path used only for books with series metadata. Leave empty to use this device's default path pattern.", - "standaloneBooks": "Books without a series", - "standaloneHelp": "Optional path used only for books without series metadata. Leave empty to use this device's default path pattern.", - "inheritPlaceholder": "Leave empty to use this device's default pattern", - "useAccount": "Use account default", - "saveOverride": "Save override", - "loadFailed": "Failed to load file organization settings", - "accountRequired": "Enter a default book path pattern before saving.", - "accountSaved": "Account default KOReader pattern saved", - "accountSaveFailed": "Failed to save file organization settings", - "deviceUsesAccount": "Device now uses the account default KOReader pattern", - "deviceSaved": "Device organization override saved", - "deviceSaveFailed": "Failed to save device override", - "deviceResetFailed": "Failed to reset device override" - }, - "loadingSettings": "Loading KOReader settings...", - "loadFailed": "Failed to load KOReader settings", - "never": "Never", - "justNow": "Just now", - "minutesAgo": "{count}m ago", - "hoursAgo": "{count}h ago", - "daysAgo": "{count}d ago", - "unknown": "Unknown", - "updateAvailable": "Update available", - "upToDate": "Up to date", - "versionUnknown": "Version unknown", - "latestPlugin": "Latest plugin: v{version}", - "latestPluginUnavailable": "Latest plugin unavailable", - "notConfigured": "KOReader sync is not configured", - "notConfiguredHint": "Create one set of sync credentials, then use them with the BookOrbit KOReader plugin for browsing, downloads, progress, reading events, highlights, and deletes.", - "createCredentials": "Create credentials", - "createFormTitle": "Create KOReader Sync Credentials", - "createFormHint": "These credentials authenticate your KOReader devices with BookOrbit.", - "username": "Username", - "usernamePlaceholder": "e.g. myreader", - "password": "Password", - "passwordPlaceholder": "Min 6 characters", - "creating": "Creating...", - "create": "Create", - "credentialsCreated": "KOReader sync credentials created", - "createCredentialsFailed": "Failed to create credentials", - "status": "KOReader Status", - "refresh": "Refresh", - "progressSync": "Progress sync", - "progressSyncHint": "Allow KOReader devices to sync progress, reading activity, highlights, and annotation deletes with BookOrbit.", - "lastSync": "Last sync", - "syncedBooks": "Synced books", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "devices": "Devices", - "deviceCount": "{count, plural, =0 {no devices} other {# devices}}", - "credentialsCreatedLabel": "Credentials created", - "setup": "Setup", - "pluginServerUrl": "Plugin server URL", - "copied": "Copied", - "copyUrl": "Copy URL", - "preconfiguredPlugin": "Preconfigured BookOrbit plugin", - "preconfiguredPluginHintPrefix": "Download a zip with the server URL and your sync login already configured. The plugin includes catalog browsing and sync. Copy the folder to", - "preconfiguredPluginHintSuffix": "and restart KOReader.", - "latestPluginNote": "{label}. Device updates run from the BookOrbit menu in KOReader.", - "preparing": "Preparing...", - "downloadPlugin": "Download Plugin", - "noDevicesSynced": "No devices have synced yet", - "noDevicesSyncedHint": "Install the BookOrbit plugin for full sync, or configure KOReader's stock progress sync for progress-only updates.", - "lastSyncLabel": "Last sync:", - "lastBookLabel": "Last book:", - "noneYet": "None yet", - "pluginActivity": "Plugin Activity", - "noPluginActivity": "No plugin activity has been reported yet.", - "lastFullSync": "Last full sync: {time}", - "latestPluginSuffix": "- latest plugin v{version}", - "matchedBooks": "Matched books", - "readingEvents": "Reading events", - "highlights": "Highlights", - "syncedTotals": "Synced totals", - "trashedHighlights": "Trashed highlights", - "pendingDeletes": "{count, plural, =0 {no deleted highlights awaiting KOReader plugin acknowledgement.} other {# deleted highlights awaiting KOReader plugin acknowledgement.}}", - "failedPositions": "{count, plural, =0 {no highlight positions need attention.} other {# highlight positions need attention.}}", - "setupGuide": "Setup Guide", - "setupSteps": "KOReader setup steps", - "setupStepsHint": "Use the BookOrbit plugin for catalog browsing, downloads, progress, reading events, and highlights. Use the stock plugin for progress only.", - "pluginGuideTitle": "BookOrbit plugin", - "pluginStep1": "Download the preconfigured plugin above.", - "pluginStep2Prefix": "Unzip it and copy", - "pluginStep2Middle": "to", - "pluginStep2Suffix": "on your device.", - "pluginStep3": "Restart KOReader. The server and login are configured automatically.", - "pluginStep4Prefix": "Open", - "pluginStep4Suffix": "to search, download, and link books to sync.", - "stockGuideTitle": "Stock progress sync plugin", - "stockStep1Prefix": "On your KOReader device, go to", - "stockStep1Suffix": ".", - "stockStep2": "Set the custom sync server to the URL shown above.", - "stockStep3": "Enter the username and password you created, then tap Login.", - "locationNote": "BookOrbit saves KOReader-compatible EPUB locations from the web reader. Restore should land close to the same position, though exact line placement can vary by reader and EPUB layout.", - "dangerZone": "Danger Zone", - "deleteCredentials": "Delete KOReader credentials", - "deleteCredentialsHint": "Remove sync credentials and disconnect all devices. Progress data will be retained.", - "credentialsDeleted": "KOReader credentials deleted", - "deleteCredentialsFailed": "Failed to delete credentials", - "deleteConfirmTitle": "Delete KOReader credentials?", - "deleteConfirmBody": "This will remove your sync credentials and disconnect all KOReader devices. Existing progress data will be kept.", - "syncEnabled": "KOReader sync enabled", - "syncDisabled": "KOReader sync disabled", - "toggleSyncFailed": "Failed to toggle sync", - "syncUrlCopied": "Sync URL copied to clipboard", - "syncUrlCopyFailed": "Failed to copy sync URL", - "statusRefreshed": "Sync status refreshed", - "refreshFailed": "Failed to refresh", - "pluginDownloaded": "Plugin downloaded. Copy bookorbit.koplugin from the zip to koreader/plugins/ on your device.", - "pluginDownloadFailed": "Failed to download the plugin", - "hashLinks": { - "unmatchedTitle": "Unmatched KOReader Books", - "unmatchedBooks": "Unmatched books", - "manualTitle": "Manual KOReader Links", - "refresh": "Refresh", - "link": "Link", - "change": "Change", - "unlink": "Unlink", - "hash": "Hash:", - "lastOpened": "Last opened:", - "firstSeen": "First seen:", - "lastSeen": "Last seen:", - "linked": "Linked:", - "updated": "Updated:", - "linkedTo": "Linked to {title}", - "loadingUnmatched": "Loading unmatched books...", - "loadingManual": "Loading manual hash links...", - "noUnmatched": "No unmatched KOReader books.", - "noManual": "No manual KOReader links.", - "pageOf": "Page {page} of {total}", - "showingRange": "Showing {start}-{end} of {total}", - "unknownFile": "Unknown KOReader file {hash}", - "unknownAuthor": "Unknown author", - "noTitleOrAuthor": "No title or author reported", - "bookNumber": "BookOrbit book #{id}", - "toast": { - "unmatchedRefreshed": "Unmatched books refreshed", - "unmatchedRefreshFailed": "Failed to refresh unmatched books", - "manualRefreshed": "Manual hash links refreshed", - "manualRefreshFailed": "Failed to refresh manual hash links", - "bookLinked": "Book linked", - "linkUpdated": "Link updated", - "linkFailed": "Failed to link book", - "linkRemoved": "Link removed", - "unlinkFailed": "Failed to unlink book", - "unmatchedDismissed": "Unmatched book dismissed", - "dismissFailed": "Failed to dismiss unmatched book", - "allDismissed": "{count, plural, =0 {Dismissed no unmatched books} other {Dismissed # unmatched books}}", - "dismissAllFailed": "Failed to dismiss all unmatched books" - }, - "modal": { - "linkTitle": "Link KOReader book", - "changeTitle": "Change KOReader link", - "bookOrbitBook": "BookOrbit book", - "searchPlaceholder": "Search your BookOrbit library", - "minChars": "Enter at least 2 characters.", - "searching": "Searching...", - "noBooksFound": "No books found.", - "untitledBook": "Untitled book", - "selected": "Selected", - "select": "Select", - "loadMore": "Load more", - "confirmTitle": "Confirm KOReader link", - "koreader": "KOReader", - "bookOrbit": "BookOrbit", - "bookId": "Book ID: {id}", - "syncedStatsNote": "Already synced stats will stay on their current BookOrbit book.", - "chooseDifferent": "Choose different", - "saving": "Saving...", - "confirmLink": "Confirm link", - "unlinkTitle": "Unlink KOReader book?", - "unlinkBody": "Future syncs for this hash will stop resolving to {title} until it is linked again. Already synced stats will stay on their current BookOrbit book.", - "unlinking": "Unlinking..." - }, - "dismiss": "Dismiss", - "dismissAll": "Dismiss all", - "dismissing": "Dismissing...", - "unlinking": "Unlinking...", - "unlinkConfirmTitle": "Unlink KOReader book?", - "unlinkConfirmBody": "Future syncs for this hash will stop resolving to {title} until it is linked again. Already synced stats will stay on their current BookOrbit book.", - "dismissConfirmTitle": "Dismiss {title}?", - "dismissConfirmBody": "This removes it from your unmatched books list. If any device reports this hash again, it will reappear as a new entry.", - "dismissAllConfirmTitle": "{count, plural, =0 {no unmatched books} other {Dismiss all # unmatched books?}}", - "dismissAllConfirmBody": "This clears your entire unmatched books list, not just the current page. If any device reports one of these hashes again, it will reappear as a new entry.", - "changeLinkTitle": "Change KOReader link", - "linkBookTitle": "Link KOReader book", - "bookOrbitBook": "BookOrbit book", - "searchLibraryPlaceholder": "Search your BookOrbit library", - "enterMinChars": "Enter at least 2 characters.", - "searching": "Searching...", - "noBooksFound": "No books found.", - "untitledBook": "Untitled book", - "selected": "Selected", - "select": "Select", - "loadMore": "Load more", - "loadingMore": "Loading...", - "confirmLinkTitle": "Confirm KOReader link", - "bookId": "Book ID: {id}", - "syncedStatsNote": "Already synced stats will stay on their current BookOrbit book.", - "chooseDifferent": "Choose different", - "saving": "Saving...", - "confirmLink": "Confirm link" - }, - "remove": "Remove", - "removing": "Removing...", - "unmatchedBooks": "Unmatched books", - "deviceRemoved": "Device removed", - "removeDeviceFailed": "Failed to remove device", - "removeDeviceConfirmTitle": "Remove {device}?", - "removeDeviceConfirmBody": "This permanently deletes this device's synced progress, reading activity, and any unmatched-book entries no longer reported by another device. If the device syncs again later, it will reappear as a new entry." - }, - "opds": { - "title": "OPDS", - "subtitle": "Connect OPDS-compatible reading apps like KOReader or Thorium Reader to your library.", - "copy": "Copy", - "loadFailed": "Failed to load", - "server": "Server", - "catalogServer": "OPDS Catalog Server", - "catalogServerHint": "Allow OPDS clients to browse and download books", - "endpoint": "Endpoint", - "accounts": "OPDS Accounts", - "add": "Add", - "addAccount": "Add account", - "username": "Username", - "usernameLabel": "Username", - "usernamePlaceholder": "e.g. koreader", - "password": "Password", - "passwordPlaceholder": "Min 8 characters", - "defaultSort": "Default Sort", - "sortLabel": "Sort", - "creating": "Creating...", - "create": "Create", - "noAccounts": "No OPDS accounts yet. Create one to start using OPDS clients.", - "hideDetails": "Hide details", - "showDetails": "Show details", - "copyUsername": "Copy username", - "notes": "OPDS Notes", - "notesBody": "Use OPDS accounts in reader apps. Keep credentials private and rotate passwords if shared accidentally.", - "deleteConfirmTitle": "Delete OPDS account?", - "deleteConfirmBody": "Delete \"{username}\". This action cannot be undone.", - "sortRecent": "Recently Added", - "sortTitleAsc": "Title (A-Z)", - "sortTitleDesc": "Title (Z-A)", - "sortAuthorAsc": "Author (A-Z)", - "sortAuthorDesc": "Author (Z-A)", - "sortSeriesAsc": "Series (A-Z)", - "sortSeriesDesc": "Series (Z-A)", - "serverEnabled": "OPDS server enabled", - "serverDisabled": "OPDS server disabled", - "updateSettingsFailed": "Failed to update OPDS settings", - "urlCopied": "OPDS URL copied to clipboard", - "urlCopyFailed": "Failed to copy OPDS URL", - "createUserFailed": "Failed to create OPDS user", - "userCreated": "OPDS user \"{username}\" created", - "sortOrderUpdated": "Sort order updated for \"{username}\"", - "updateSortFailed": "Failed to update sort order", - "userDeleted": "OPDS user \"{username}\" deleted", - "deleteUserFailed": "Failed to delete OPDS user", - "labelCopied": "{label} copied", - "copyLabelFailed": "Failed to copy {label}" - }, - "tabs": { - "general": "General", - "ebook": "eBook", - "pdf": "PDF", - "comics": "Comics", - "audio": "Audiobook", - "fonts": "Fonts" - } - }, - "system": { - "tabs": { - "file-naming": "File Naming", - "book-dock": "Book Dock", - "maintenance": "Maintenance", - "audit-log": "Audit Log" - } - } - }, - "achievements": { - "title": "Achievements", - "tiersCount": "{earned} / {total} tiers", - "loadFailed": "Failed to load achievements", - "tryAgain": "Try again", - "noMatchFilter": "No achievements match this filter", - "secretAchievement": "Secret Achievement", - "earnedOn": "Earned {date}", - "whileReading": "While reading “{title}”", - "tierProgress": "Tier {earned} of {total}", - "progressToNext": "{current} / {threshold} to {name}", - "rarity": { - "common": "Common", - "rare": "Rare", - "epic": "Epic", - "legendary": "Legendary" - }, - "filter": { - "all": "All", - "earned": "Earned ({count})", - "inProgress": "In Progress ({count})", - "locked": "Locked ({count})" - } - }, - "adminFeature": { - "accountActivity": { - "title": "Account Activity", - "subtitle": "Review account authentication activity without exposing reading history.", - "privacyNotice": "This page reports sign-ins and authentication refreshes only. It does not use reading history, book progress, or library activity.", - "privacyLabel": "About account activity privacy", - "never": "Never", - "openInsightsFor": "Open shared reading insights for {name}", - "permissionLabel": "View user activity", - "states": { - "recent": "Recently active", - "dormant": "Dormant", - "never": "No recorded activity", - "disabled": "Disabled" - }, - "filters": { - "search": "Search accounts", - "searchPlaceholder": "Search name or username", - "state": "Activity state", - "allStates": "All activity states", - "provisioning": "Authentication method", - "allMethods": "All authentication methods", - "sort": "Sort accounts", - "mostRecent": "Most recently active", - "leastRecent": "Least recently active", - "lastLogin": "Most recent login", - "newest": "Newest accounts", - "oldest": "Oldest accounts", - "name": "Name", - "apply": "Apply", - "clear": "Clear" - }, - "methods": { - "local": "Local", - "manual": "Administrator-created", - "oidc": "OIDC / SSO", - "shared": "Shared magic link" - }, - "columns": { - "user": "User", - "state": "Account state", - "lastLogin": "Last login", - "lastAuthenticated": "Last authenticated", - "created": "Created", - "readingInsights": "Reading insights" - }, - "sharing": { - "private": "Not shared", - "summary": "Summary shared", - "detailed": "Detailed shared" - }, - "empty": { - "title": "No accounts found", - "description": "Try changing or clearing the current filters." - }, - "pagination": { - "label": "Account activity pages", - "page": "Page {page} of {totalPages}" - }, - "errors": { - "load": "Failed to load account activity." - } - }, - "sharedInsights": { - "title": "Shared reading insights", - "subtitle": "Reading information this user voluntarily chose to share.", - "auditNotice": "Access to this profile is recorded and visible to the user.", - "period": "Reporting period", - "periodDays": "Last {count} days", - "durationMinutes": "{count, plural, other {# minutes}}", - "durationHours": "{count, plural, other {# hours}}", - "metrics": { - "sessions": "Sessions", - "readingTime": "Reading time", - "activeDays": "Active days", - "started": "Books started", - "completed": "Books completed" - }, - "trend": "Daily reading trend", - "emptyTitle": "No reading activity in this period", - "noData": "No recorded reading data for this period.", - "sourceNames": { - "web": "Web reader", - "koreader": "KOReader", - "manual": "Manual", - "kobo": "Kobo", - "unknown": "Unknown" - }, - "formats": "Formats", - "genres": "Genres", - "broadGenres": { - "science_fiction": "Science fiction", - "fantasy": "Fantasy", - "mystery_thriller": "Mystery & thriller", - "romance": "Romance", - "horror": "Horror", - "history_biography": "History & biography", - "science_technology": "Science & technology", - "business_economics": "Business & economics", - "self_development": "Self-development", - "society_culture": "Society & culture", - "children_young_adult": "Children & young adult", - "comics_graphic_novels": "Comics & graphic novels", - "poetry": "Poetry", - "other": "Other" - }, - "sources": "Data sources", - "topBooks": "Most-read books", - "recentBooks": "Recently read", - "unknownTitle": "Untitled book", - "top": { - "authors": "Top authors", - "genres": "Top genres", - "series": "Top series", - "narrators": "Top narrators" - }, - "errors": { - "READING_INSIGHTS_PRIVATE": "This user is not sharing reading insights.", - "READING_INSIGHTS_SUMMARY_ONLY": "This user shares summary insights only.", - "READING_INSIGHTS_VIEW_SESSION_REQUIRED": "A profile view session is required.", - "READING_INSIGHTS_VIEW_SESSION_INVALID": "This profile view expired or is no longer valid.", - "LOAD_FAILED": "Shared reading insights could not be loaded.", - "cleared": "No previously loaded profile information is being displayed." - } - }, - "resetLink": { - "title": "Password Reset Link", - "description": "Share this link with the user. It expires in 15 minutes.", - "copy": "Copy", - "copied": "Copied!", - "copyFailed": "Copy failed", - "notShownAgain": "This link will not be shown again." - }, - "userForm": { - "editUser": "Edit User", - "createUser": "Create User", - "createSharedAccount": "Create Shared Account", - "sharedBadge": "Shared", - "active": "Active", - "suspended": "Suspended", - "tabs": { - "general": "general", - "access": "access", - "restrictions": "restrictions" - }, - "sharedAccount": "Shared account", - "sharedAccountHint": "No password. Access is granted via magic links only.", - "sharedAccountManageHint": "Manage login links from Settings - Magic Links.", - "username": "Username", - "fullName": "Full name", - "email": "Email", - "optional": "(optional)", - "libraryAccess": "Library Access", - "noLibrariesSelected": "No libraries selected. User cannot view any books.", - "permissions": "Permissions", - "presetStandard": "Standard", - "presetAdmin": "Admin", - "presetClearAll": "Clear All", - "permissionGroups": { - "content": "Content", - "devicesAccess": "Devices & Access", - "email": "Email", - "administration": "Administration", - "notifications": "Notifications", - "restrictions": "Restrictions" - }, - "superuserTarget": "Superuser Target", - "superuserTargetHint": "Content restrictions cannot be applied to superusers.", - "noRestrictions": "No content restrictions", - "noRestrictionsHint": "This user has full access to all books in their assigned libraries.", - "addRestrictions": "+ Add Content Restrictions", - "contentRestrictions": "Content Restrictions", - "remove": "Remove", - "includeTags": "Include tags", - "includeTagsHint": "(show only books with these tags)", - "excludeTags": "Exclude tags", - "excludeTagsHint": "(hide books with these tags)", - "includeGenres": "Include genres", - "includeGenresHint": "(show only books with these genres)", - "excludeGenres": "Exclude genres", - "excludeGenresHint": "(hide books with these genres)", - "searchTagsPlaceholder": "Search tags...", - "searchGenresPlaceholder": "Search genres...", - "saving": "Saving...", - "errors": { - "updateUser": "Failed to update user", - "updatePermissions": "Failed to update permissions", - "updateLibraryAccess": "Failed to update library access", - "updateContentFilters": "Failed to update content filters", - "emailRequired": "Email is required", - "createSharedAccount": "Failed to create shared account", - "createUser": "Failed to create user" - } - }, - "usersPage": { - "usersTitle": "Users", - "usersSubtitle": "Manage user accounts and permission assignments.", - "createUser": "Create user", - "columns": { - "name": "Name", - "username": "Username", - "email": "Email", - "access": "Access", - "status": "Status", - "actions": "Actions" - }, - "adminBadge": "Admin", - "permissionCount": "{count, plural, =0 {no permissions} other {# permissions}}", - "filteredBadge": "Filtered", - "contentRestrictionsActive": "Content restrictions active", - "statusActive": "Active", - "statusInactive": "Inactive", - "resetPassword": "Reset password", - "resetPasswordOidcHint": "OIDC users reset passwords in their identity provider", - "resetPasswordSharedHint": "Shared accounts do not have passwords", - "resetPasswordOidcHintFull": "OIDC users reset passwords in their identity provider.", - "resetPasswordSharedHintFull": "Shared accounts do not have passwords.", - "deleteUserAction": "Delete user", - "deleteDialogTitle": "Delete user?", - "deleteDialogBody": "Delete user \"{username}\". This action cannot be undone.", - "deleting": "Deleting...", - "errors": { - "load": "Failed to load", - "deleteUser": "Failed to delete user", - "resetPassword": "Failed to create a password reset link" - }, - "defaultLibraryAccess": { - "title": "Default Library Access", - "subtitle": "Viewer access granted to self-registered and OIDC-provisioned users.", - "description": "Select the libraries assigned automatically to new users.", - "noLibraries": "No libraries available.", - "save": "Save defaults", - "saving": "Saving...", - "saveError": "Failed to save default library access" - }, - "filters": { - "search": "Search users", - "searchPlaceholder": "Search by name, username or email", - "sort": "Sort users", - "usernameAsc": "Username A-Z", - "nameAsc": "Name A-Z", - "newest": "Newest first", - "oldest": "Oldest first", - "apply": "Apply", - "clear": "Clear", - "state": "Filter users", - "allUsers": "All users", - "admins": "Administrators", - "active": "Active", - "inactive": "Inactive" - }, - "empty": { - "title": "No users yet", - "description": "Create the first account to get started.", - "filtered": "No users match the current search and filters." - }, - "pagination": { - "label": "Users pagination", - "page": "Page {page} of {totalPages}" - }, - "editUserAria": "Edit {name}", - "resetPasswordAria": "Reset the password for {name}", - "deleteUserAria": "Delete {name}", - "moreActionsAria": "More actions for {name}" - } - }, - "annotations": { - "unknownBook": "Unknown book", - "styles": { - "highlight": "Highlight", - "underline": "Underline", - "strike": "Strike", - "squiggle": "Squiggle", - "invert": "Invert" - }, - "combobox": { - "filterByBook": "Filter by book", - "allBooks": "All books", - "clearBookFilter": "Clear book filter", - "searching": "Searching...", - "noBooksFound": "No books found" - }, - "bulk": { - "countSelected": "{count, plural, other {# selected}}", - "pageSelected": "Page selected", - "selectPage": "Select page", - "clear": "Clear", - "recolorTo": "Recolor to {color}", - "restyleTo": "Restyle to {style}" - }, - "chips": { - "active": "Active:", - "removeFilter": "Remove filter {label}", - "clearAll": "Clear all" - }, - "filters": { - "colors": "Colors", - "dateRange": "Date range", - "fromDate": "From date", - "toDate": "To date", - "to": "to", - "clearDateRange": "Clear date range", - "clearAll": "Clear all" - }, - "pagination": { - "showing": "Showing {start}-{end} of {total}", - "pageOf": "Page {page} of {totalPages}", - "firstPage": "First page", - "previousPage": "Previous page", - "nextPage": "Next page", - "lastPage": "Last page" - }, - "sync": { - "loading": "Loading sync detail", - "positions": "Positions", - "devices": "Devices", - "retryConversion": "Retry conversion", - "noStoredPositions": "No stored positions.", - "notSynced": "Not synced to any device yet.", - "upToDate": "Up to date", - "pendingVersion": "Pending v{version}", - "syncedAt": "synced {date}", - "format": { - "webReader": "Web reader", - "koreader": "KOReader", - "pdf": "PDF", - "kobo": "Kobo" - }, - "status": { - "exact": "Exact", - "repaired": "Repaired", - "failed": "Failed", - "pending": "Pending" - } - }, - "toolbar": { - "searchPlaceholder": "Search text and notes", - "filters": "Filters", - "sortOrder": "Sort order", - "switchToCompact": "Switch to compact view", - "switchToComfortable": "Switch to comfortable view", - "compactView": "Compact view", - "comfortableView": "Comfortable view" - }, - "listItem": { - "pageNumber": "p. {page}", - "chapterNumber": "chapter {chapter}", - "selectAnnotation": "Select annotation", - "collapse": "Collapse", - "expand": "Expand", - "hideSyncDetail": "Hide sync detail", - "showSyncDetail": "Show sync detail", - "exactPositionUnavailable": "Exact reader position unavailable", - "saving": "Saving", - "bookDetails": "Book details", - "openInReader": "Open in reader", - "restore": "Restore", - "deleteForever": "Delete forever", - "editNote": "Edit note", - "addNote": "Add note", - "colorAndStyle": "Color and style", - "copied": "Copied", - "copyText": "Copy text", - "trash": "Trash", - "moveToTrash": "Move to trash" - }, - "hub": { - "title": "Annotations", - "totalCount": "{count} total", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "noteCount": "{count, plural, =0 {no notes} other {# notes}}", - "export": "Export", - "exportMarkdown": "Markdown", - "exportCsv": "CSV", - "exportJson": "JSON", - "notesOnly": "Notes only", - "style": "Style", - "source": "Source", - "bulkTrash": "Trash", - "bulkRestore": "Restore", - "tabs": { - "highlights": "Highlights", - "trash": "Trash" - }, - "empty": { - "noMatch": "No highlights match your filters.", - "resetFilters": "Reset filters", - "trashEmpty": "Trash is empty", - "noAnnotations": "No annotations yet. Highlights you create on the web or your e-reader appear here." - }, - "toast": { - "movedToTrash": "Moved to trash", - "annotationRestored": "Annotation restored", - "annotationDeletedForever": "Annotation deleted forever", - "failedToDelete": "Failed to delete", - "bulkTrashed": "{count, plural, =0 {Moved no annotations to trash} other {Moved # annotations to trash}}", - "bulkRestored": "{count, plural, =0 {Restored no annotations} other {Restored # annotations}}", - "bulkRecolored": "{count, plural, =0 {Recolored no annotations} other {Recolored # annotations}}", - "bulkRestyled": "{count, plural, =0 {Restyled no annotations} other {Restyled # annotations}}" - } - } - }, - "audit": { - "pageTitle": "Audit Log", - "pageSubtitle": "A record of admin-significant actions performed across the system.", - "filters": "Filters", - "noActiveFilters": "No active filters", - "clear": "Clear", - "empty": "No audit logs found", - "showMore": "Show more", - "showLess": "Show less", - "details": "Details", - "hideDetails": "Hide details", - "refresh": "Refresh audit log", - "loadError": "Could not load audit events.", - "removeFilter": "Remove filter: {value}", - "allActions": "All actions", - "allEventTypes": "All event types", - "allActors": "All actors", - "noActionsFound": "No matching actions", - "noActorsFound": "No matching actors", - "noResourcesFound": "No matching target types", - "unknownAction": "Unknown action", - "unknownResource": "Other target type", - "allResources": "All resources", - "allTargetTypes": "All target types", - "quickDates": "Quick dates", - "today": "Today", - "sevenDays": "7 days", - "thirtyDays": "30 days", - "userId": "User #{id}", - "userIdCompact": "#{id}", - "targetAdditional": "and {count, plural, other {# more targets}}", - "bookImpact": "{count, plural, other {# books}}", - "entryDetailsLabel": "Details for audit event #{id}", - "detailEventId": "Event ID", - "detailOccurredAt": "Occurred", - "detailActor": "Actor", - "detailCategory": "Category", - "detailActionLabel": "Action", - "detailEventTypeLabel": "Event type", - "detailIpLabel": "IP address", - "detailResourceLabel": "Resource", - "detailResourceIdLabel": "Resource ID", - "detailTargetTypeLabel": "Target type", - "detailTargetIdLabel": "Target ID", - "detailAction": "Action: {value}", - "detailIp": "IP: {value}", - "detailResource": "Resource: {value}", - "detailResourceId": "Resource ID: {value}", - "deletedBooks": "Deleted books", - "deletedBookDetail": "{title} (book #{id})", - "untitledBook": "Untitled", - "deletedBooksOmitted": "{count, plural, other {# additional books omitted}}", - "showing": "Showing {from}-{to} of {total}", - "prev": "Prev", - "chips": { - "search": "Search: {value}", - "action": "Action: {value}", - "eventType": "Event type: {value}", - "actor": "Actor: {value}", - "resource": "Resource: {value}", - "targetType": "Target type: {value}", - "user": "User: {value}", - "from": "From: {value}", - "to": "To: {value}" - }, - "filterLabels": { - "search": "Search events", - "action": "Action", - "eventType": "Event type (what happened)", - "actor": "Actor", - "resource": "Resource", - "targetType": "Target type (what was affected)", - "userId": "User ID", - "from": "From", - "to": "To" - }, - "filterPlaceholders": { - "search": "Description, actor, target, or ID", - "actor": "Username", - "action": "e.g. auth.login", - "userId": "e.g. 1" - }, - "columns": { - "when": "When", - "actor": "Actor", - "event": "Event", - "target": "Target", - "impact": "Impact", - "user": "User", - "action": "Action", - "description": "Description", - "ip": "IP" - }, - "categories": { - "authentication": "Authentication", - "books": "Books", - "users": "Users", - "libraries": "Libraries", - "collections": "Collections", - "integrations": "Integrations", - "settings": "Settings", - "other": "Other" - }, - "resourceLabels": { - "User": "User", - "Library": "Library", - "Book": "Book", - "Collection": "Collection", - "SmartScope": "Smart scope", - "BookDockFile": "Book Dock file", - "Author": "Author", - "AppSettings": "Application settings", - "Genre": "Genre", - "Tag": "Tag", - "KoboDevice": "Kobo device", - "EmailProvider": "Email provider", - "EmailTemplate": "Email template", - "EmailRecipient": "Email recipient", - "EmailRecipientGroup": "Email recipient group", - "Narrator": "Narrator", - "Publisher": "Publisher", - "Language": "Language", - "Series": "Series", - "OidcIdentity": "OIDC identity", - "MagicLinkToken": "Magic link", - "ReadingInsightsProfile": "Reading insights profile" - }, - "actionLabels": { - "AuthRegister": "Register account", - "AuthLogin": "Sign in", - "AuthLoginFailed": "Failed sign-in", - "AuthLogout": "Sign out", - "AuthPasswordChange": "Change password", - "AuthPasswordResetRequest": "Request password reset", - "AuthPasswordReset": "Reset password", - "AuthPasswordAdminReset": "Reset user password", - "AuthSessionRevoke": "Revoke session", - "MagicLinkCreate": "Create magic link", - "MagicLinkLogin": "Sign in with magic link", - "MagicLinkRevoke": "Revoke magic link", - "MagicLinkActivate": "Activate magic link", - "MagicLinkDeactivate": "Deactivate magic link", - "OidcLogin": "Sign in with OIDC", - "OidcUserProvisioned": "Provision OIDC user", - "OidcIdentityLinked": "Link OIDC identity", - "OidcIdentityUnlinked": "Unlink OIDC identity", - "UserCreate": "Create user", - "UserUpdate": "Update user", - "UserSelfUpdate": "Update own profile", - "UserDelete": "Delete user", - "UserPermissionSet": "Update user permissions", - "UserSuperuserEnable": "Enable superuser access", - "UserSuperuserDisable": "Disable superuser access", - "UserContentFiltersSet": "Update content filters", - "ReadingInsightsSharingUpdate": "Update insight sharing", - "ReadingInsightsProfileView": "View shared insights", - "LibraryCreate": "Create library", - "LibraryUpdate": "Update library", - "LibraryDelete": "Delete library", - "LibraryFolderAdd": "Add library folder", - "LibraryFolderRemove": "Remove library folder", - "LibraryAccessGrant": "Grant library access", - "LibraryAccessUpdate": "Update library access", - "LibraryAccessRevoke": "Revoke library access", - "LibraryWriteMetadataToFiles": "Write metadata to files", - "LibraryBulkRename": "Rename library files", - "BookUpload": "Upload book", - "BookMetadataUpdate": "Update book metadata", - "BookMetadataLocksUpdate": "Update metadata locks", - "BookDelete": "Delete book", - "BookBulkMetadataRefresh": "Refresh book metadata", - "BookBulkDelete": "Delete books", - "BookBulkCoverReextract": "Re-extract book covers", - "BookBulkSetStatus": "Set book status", - "BookBulkSetRating": "Set book rating", - "BookBulkSetMetadata": "Set book metadata", - "BookBulkUpdateTags": "Update book tags", - "BookBulkSetMetadataLock": "Set metadata locks", - "BookBulkEditMetadata": "Edit book metadata", - "BookReadingStateReset": "Reset reading state", - "BookWriteAndRename": "Write metadata and rename file", - "CollectionCreate": "Create collection", - "CollectionUpdate": "Update collection", - "CollectionDelete": "Delete collection", - "CollectionBooksAdd": "Add books to collection", - "CollectionBooksRemove": "Remove books from collection", - "SmartScopeCreate": "Create smart scope", - "SmartScopeUpdate": "Update smart scope", - "SmartScopeDelete": "Delete smart scope", - "BookDockFinalize": "Finalize Book Dock file", - "AuthorUpdate": "Update author", - "AuthorDelete": "Delete author", - "AuthorMerge": "Merge authors", - "AuthorEnrichmentConfigUpdate": "Update author enrichment", - "AuthorEnrichmentPause": "Pause author enrichment", - "AuthorEnrichmentResume": "Resume author enrichment", - "AuthorEnrichmentCancel": "Cancel author enrichment", - "EntityManagerMerge": "Merge entities", - "EntityManagerRename": "Rename entity", - "EntityManagerDelete": "Delete entity", - "EntityManagerSplit": "Split entity", - "EntityManagerDismiss": "Dismiss duplicate", - "EntityManagerUndismiss": "Restore dismissed duplicate", - "AppSettingsUpdate": "Update app settings", - "KoboDeviceRegister": "Register Kobo device", - "KoboDeviceRename": "Rename Kobo device", - "KoboDeviceRemove": "Remove Kobo device", - "EmailProviderCreate": "Create email provider", - "EmailProviderUpdate": "Update email provider", - "EmailProviderDelete": "Delete email provider", - "EmailProviderSetDefault": "Set default email provider", - "EmailProviderSetSystem": "Set system email provider", - "EmailProviderClearSystem": "Clear system email provider", - "EmailTemplateCreate": "Create email template", - "EmailTemplateUpdate": "Update email template", - "EmailTemplateDelete": "Delete email template", - "EmailTemplateSetDefault": "Set default email template", - "EmailRecipientCreate": "Create email recipient", - "EmailRecipientUpdate": "Update email recipient", - "EmailRecipientDelete": "Delete email recipient", - "EmailRecipientGroupCreate": "Create recipient group", - "EmailRecipientGroupUpdate": "Update recipient group", - "EmailRecipientGroupDelete": "Delete recipient group", - "EmailRecipientGroupMemberAdd": "Add recipient to group", - "EmailRecipientGroupMemberRemove": "Remove recipient from group" - } - }, - "auth": { - "backToSignIn": "Back to sign in", - "themePicker": { - "switchToLight": "Switch to light", - "switchToDark": "Switch to dark", - "changeRadius": "Change corner radius", - "changeBackground": "Change background", - "changeAccent": "Change accent color" - }, - "fields": { - "username": "Username", - "password": "Password", - "email": "Email", - "emailAddress": "Email address", - "fullName": "Full name", - "newPassword": "New password", - "confirmPassword": "Confirm password", - "confirmNewPassword": "Confirm new password", - "currentPassword": "Current password", - "passwordHint": "Min. 8 characters with uppercase, lowercase, and a digit" - }, - "errors": { - "generic": "Something went wrong. Please try again.", - "passwordsDoNotMatch": "Passwords do not match" - }, - "login": { - "subtitle": "Sign in to your account", - "signIn": "Sign in", - "signingIn": "Signing in...", - "orDivider": "or", - "forgotPassword": "Forgot password?", - "errors": { - "invalidCredentials": "Invalid username or password", - "tooManyAttempts": "Too many login attempts. Please wait a minute and try again." - } - }, - "oidc": { - "loginFailed": "OIDC login failed", - "redirecting": "Redirecting...", - "signInWith": "Sign in with {provider}", - "completingSignIn": "Completing sign in...", - "tryAgain": "Try again", - "errors": { - "stateExpired": "Your login session expired. Please try signing in again.", - "tokenExchangeFailed": "Could not complete sign-in with your provider. Please try again or contact your administrator.", - "userNotProvisioned": "Your account has not been set up. Contact your administrator for access.", - "userInactive": "Your account has been deactivated. Contact your administrator.", - "providerError": "Your identity provider returned an error. Please try again.", - "missingCodeOrState": "Missing code or state parameter" - }, - "providerErrors": { - "accessDenied": "Access was denied by the identity provider.", - "loginRequired": "Authentication is required. Please sign in again.", - "interactionRequired": "Additional user interaction is required." - } - }, - "forgotPassword": { - "subtitle": "Reset your password", - "submitted": "If an account with that email exists, a reset link has been sent. Check your inbox.", - "sending": "Sending...", - "sendResetLink": "Send reset link", - "errors": { - "emailUnavailable": "Password reset via email is not available. Contact your administrator." - } - }, - "resetPassword": { - "subtitle": "Set a new password", - "saving": "Saving...", - "setNewPassword": "Set new password", - "errors": { - "invalidLink": "Invalid reset link. Please request a new one.", - "invalidOrExpired": "Invalid or expired reset link. Please request a new one." - } - }, - "setup": { - "title": "Initial setup", - "subtitle": "Create the first administrator account.", - "setupToken": "Setup token", - "setupTokenHint": "(required in production)", - "creatingAccount": "Creating account...", - "createAccount": "Create administrator account", - "errors": { - "failed": "Failed to complete setup" - } - }, - "changePassword": { - "title": "Change password", - "saving": "Saving…", - "forcedNotice": "You must set a new password before continuing.", - "errors": { - "failed": "Failed to change password" - } - }, - "magicLink": { - "signingIn": "Signing you in...", - "loginFailed": "Login failed", - "goToLogin": "Go to login", - "errors": { - "noToken": "No token provided" - } - } - }, - "author": { - "card": { - "portraitAlt": "{name} portrait", - "viewDetails": "View Author Details", - "refreshMetadata": "Refresh Metadata", - "deleteAuthor": "Delete Author" - }, - "listRow": { - "noRecentAdditions": "No recent additions", - "portraitAlt": "{name} portrait" - }, - "filters": { - "title": "Author Filters", - "clearAll": "Clear all", - "allLibraries": "All Libraries", - "allAuthors": "All authors", - "hasPhoto": "Has photo", - "missingPhoto": "Missing photo", - "minBooks": "Min books", - "anyPlaceholder": "Any" - }, - "header": { - "never": "Never", - "portraitAlt": "{name} portrait", - "actions": "Actions", - "editAuthor": "Edit Author", - "mergeAuthors": "Merge Authors", - "refreshing": "Refreshing...", - "refreshMetadata": "Refresh Metadata", - "deleteAuthor": "Delete Author", - "showLess": "Show less", - "showMore": "Show more", - "lookingUpMetadata": "Looking up author metadata...", - "noBiography": "No biography available. Use the menu to refresh metadata.", - "previewFrom": "Preview from {provider}. Save metadata to persist it.", - "booksLabel": "Books", - "lastAdded": "Last Added" - }, - "list": { - "title": "Authors", - "showControlsAria": "Show author controls", - "searchPlaceholder": "Search authors", - "sortButton": "Sort", - "sortBy": "Sort by", - "ascending": "Ascending", - "descending": "Descending", - "asc": "Asc", - "desc": "Desc", - "filters": "Filters", - "clear": "Clear", - "allLoaded": "All {total} authors loaded", - "sort": { - "name": "Name", - "sortName": "Sort Name", - "bookCount": "Book Count", - "recentAdditions": "Recent Additions", - "lastEnriched": "Last Enriched" - }, - "empty": { - "title": "No authors found", - "hint": "Try changing search text, sort, or library filter." - }, - "deleteDialog": { - "titleOne": "Delete author?", - "titleMany": "Delete {count} authors?", - "descriptionOne": "This removes the author from the catalog and unlinks it from associated books. This action cannot be undone.", - "descriptionMany": "This removes selected authors from the catalog and unlinks them from associated books. This action cannot be undone." - }, - "selection": { - "selectVisible": "Select visible", - "refreshMetadata": "Refresh metadata", - "refreshingMetadata": "Refreshing metadata...", - "deleteSelected": "Delete selected", - "deleting": "Deleting...", - "exitSelection": "Exit selection", - "confirmDeleteCount": "{count, plural, =0 {Delete # author?} other {Delete # authors?}}" - }, - "toast": { - "refreshed": "Author metadata refreshed", - "refreshedNoImage": "Metadata refreshed, but no author image was found.", - "refreshFailed": "Failed to refresh author metadata", - "bulkRefreshPartial": "Refreshed {updated} author(s), {failed} failed", - "bulkRefreshSuccess": "Refreshed metadata for {updated} author(s)", - "bulkRefreshFailed": "Failed to refresh selected authors", - "deleteSuccess": "{count, plural, =0 {Deleted # author; affected {books} books} other {Deleted # authors; affected {books} books}}", - "deleteFailed": "Failed to delete author(s)" - } - }, - "detail": { - "pageTitle": "Author", - "pageTitleNamed": "Author · {name}", - "pageTitleId": "Author #{id}", - "entityName": "Author", - "loadingAuthor": "Loading author...", - "previewError": "Could not load external author preview metadata right now.", - "edit": { - "name": "Name", - "sortName": "Sort Name", - "description": "Description", - "image": "Image", - "uploading": "Uploading...", - "replaceImage": "Replace image", - "uploadImage": "Upload image", - "removing": "Removing...", - "removeImage": "Remove image", - "imageHint": "PNG/JPEG/WEBP/GIF/BMP up to {size} MB", - "saving": "Saving..." - }, - "merge": { - "searchPlaceholder": "Search authors to merge into this author", - "searching": "Searching...", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "selectedSummary": "Selected {count} author(s), approx. {books} books affected.", - "merging": "Merging...", - "mergeSelected": "Merge Selected", - "confirmLabel": "Merge" - }, - "mergeDialog": { - "title": "Merge {count} author(s) into \"{name}\"?", - "titleFallback": "Merge selected authors?", - "description": "This will merge selected authors into the current author and re-link associated books. This action cannot be undone.", - "descriptionEmpty": "This action cannot be undone." - }, - "deleteDialog": { - "title": "Delete author?", - "description": "This removes the author from the catalog and unlinks it from associated books. This action cannot be undone." - }, - "books": { - "heading": "Books", - "allLibraries": "All Libraries", - "asc": "Asc", - "desc": "Desc", - "ascending": "Ascending", - "descending": "Descending", - "allLoaded": "All {total} books loaded", - "sort": { - "recentlyAdded": "Recently Added", - "title": "Title", - "publishedYear": "Published Year" - }, - "empty": { - "title": "No books found for this author", - "hint": "Try changing sort/order or selecting another library." - } - }, - "toast": { - "refreshed": "Author metadata refreshed", - "refreshedNoImage": "Metadata refreshed, but no author image was found.", - "refreshFailed": "Failed to refresh author metadata", - "nameRequired": "Author name is required", - "updated": "Author updated", - "updateFailed": "Failed to update author", - "imageUpdated": "Author image updated", - "imageUploadFailed": "Failed to upload author image", - "imageRemoved": "Author image removed", - "imageRemoveFailed": "Failed to remove author image", - "mergeSuccess": "Merged {count} author(s); affected {books} books", - "mergeFailed": "Failed to merge authors", - "deleteSuccess": "Deleted author; affected {books} books", - "deleteFailed": "Failed to delete author" - } - } - }, - "book": { - "untitled": "Untitled", - "unknownFormat": "unknown", - "collapsedSeries": { - "label": "Series", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "readCount": "{count} read" - }, - "card": { - "missing": "Missing" - }, - "file": { - "primary": "Primary", - "audiobook": "Audiobook" - }, - "actions": { - "read": "Read", - "listen": "Listen", - "peek": "Peek", - "quickView": "Quick View", - "details": "Details", - "bookDetails": "Book Details", - "download": "Download", - "metadata": "Metadata", - "editMetadata": "Edit Metadata", - "refreshMetadata": "Refresh Metadata", - "regenerateCover": "Regenerate Cover", - "addToCollection": "Add to Collection", - "setStatus": "Set Status", - "sendViaEmail": "Send via Email", - "rate": "Rate {star}", - "openAs": "Open as {format}" - }, - "readStatus": { - "unread": "Unread", - "wantToRead": "Want to Read", - "reading": "Reading", - "onHold": "On Hold", - "rereading": "Rereading", - "read": "Read", - "skimmed": "Skimmed", - "abandoned": "Abandoned" - }, - "download": { - "action": "Download", - "audiobookZip": "Audiobook (ZIP)", - "allFormatsZip": "All formats (ZIP)", - "primaryOnlyZip": "Primary only (ZIP)" - }, - "sort": { - "moveUp": "Move up", - "moveDown": "Move down", - "ascending": "Ascending", - "descending": "Descending", - "fields": { - "author": "Author", - "title": "Title", - "series": "Series", - "seriesIndex": "Series #", - "addedAt": "Date Added", - "updatedAt": "Date Updated", - "publishedDate": "Published Date", - "publishedYear": "Published Year", - "pageCount": "Page Count", - "rating": "Rating", - "publisher": "Publisher", - "fileSize": "File Size", - "readProgress": "Read Progress", - "readStatus": "Read Status", - "format": "Format", - "lastReadAt": "Last Read", - "startedAt": "Date Started", - "finishedAt": "Date Finished", - "random": "Random", - "language": "Language", - "metadataScore": "Metadata Score" - }, - "customFieldsGroup": "Custom fields", - "customFieldFallback": "Custom field", - "remove": "Remove", - "emptyState": "No sort configured. Title ascending will be used.", - "addLevel": "Add sort level" - }, - "filter": { - "match": "Match", - "all": "ALL", - "any": "ANY", - "ofFollowingRules": "of the following rules", - "fields": { - "title": "Title", - "publisher": "Publisher", - "language": "Language", - "series": "Series", - "seriesIndex": "Series Index", - "publishedDate": "Published Date", - "publishedYear": "Published Year", - "pageCount": "Page Count", - "author": "Author", - "genre": "Genre", - "tag": "Tag", - "collection": "Collection", - "library": "Library", - "format": "Format", - "addedAt": "Added Date", - "startedAt": "Date Started", - "finishedAt": "Date Finished", - "fileAvailability": "File Availability", - "rating": "Rating", - "communityRating": "Community Rating", - "readProgress": "Reading Progress", - "readStatus": "Read Status", - "description": "Description", - "isbn": "ISBN", - "metadataScore": "Metadata Score", - "cover": "Cover", - "lockStatus": "Lock Status", - "seriesStatus": "Series Status" - }, - "operators": { - "contains": "contains", - "notContains": "does not contain", - "startsWith": "starts with", - "endsWith": "ends with", - "eq": "is", - "notEq": "is not", - "isEmpty": "is empty", - "isNotEmpty": "is not empty", - "gt": "greater than", - "gte": "at least", - "lt": "less than", - "lte": "at most", - "between": "between", - "includesAny": "includes any of", - "includesAll": "includes all of", - "excludesAll": "excludes all of", - "before": "before", - "after": "after", - "withinLast": "within last", - "isMissing": "is missing", - "isPresent": "is present", - "isUnread": "is unread", - "isInProgress": "is in progress", - "isFinished": "is finished", - "isLocked": "is locked", - "isUnlocked": "is unlocked", - "isUpNext": "is up next" - }, - "anyProvider": "Any provider", - "communityRatingProvider": "Community rating provider", - "loadingLibraries": "Loading libraries...", - "noLibrariesAvailable": "No libraries available", - "selectLibrary": "Select library...", - "selectStatus": "Select status...", - "withinLastPlaceholder": "e.g. 7", - "unit": { - "days": "days", - "weeks": "weeks", - "months": "months" - }, - "scorePreset": { - "outstanding": "Outstanding", - "good": "Good", - "fair": "Fair", - "poor": "Poor" - }, - "scoreRangePlaceholder": "0-100", - "valuePlaceholder": "value", - "maxPlaceholder": "max", - "to": "to", - "group": "Group", - "addRule": "Add rule", - "addGroup": "Add group", - "typeToSearch": "Type to search..." - }, - "deleteDialog": { - "title": "Delete book?", - "description": "This will permanently delete the book and all its metadata, files, reading progress, and bookmarks. This cannot be undone." - }, - "bulkEdit": { - "title": "{count, plural, =0 {Edit metadata - # book} other {Edit metadata - # books}}", - "instructions": "Toggle fields to edit, then configure values. Only toggled fields will be changed.", - "invalidYear": "Enter a valid year (numbers only)", - "clearWarning": "This will remove all {field} from the selected books.", - "searchPlaceholder": "Search {field}...", - "enterPlaceholder": "Enter {field}", - "yearPlaceholder": "e.g. 2024", - "leaveEmptyHint": "Leave empty to clear this field on all selected books.", - "applying": "Applying...", - "apply": "Apply", - "mode": { - "add": "Add", - "remove": "Remove", - "replace": "Replace", - "clear": "Clear" - } - }, - "export": { - "title": "Export Metadata", - "scope": "Scope", - "selectedRows": "Selected rows", - "currentlySelected": "{count} currently selected", - "allMatchingRows": "All matching rows", - "rowsInResult": "{count} rows in current result", - "format": "Format", - "csvDescription": "Spreadsheet-friendly, UTF-8 BOM included", - "jsonDescription": "Structured export with metadata context", - "columns": "Columns", - "canonicalSchema": "Stable canonical schema", - "visibleColumns": "Current visible columns", - "options": "Options", - "includePersonalData": "Include personal reading data", - "includeFilePaths": "Include file paths (advanced)", - "includeContextMeta": "Include context metadata", - "preflight": "Preflight", - "scopeLabel": "Scope: {summary}", - "calculatingSize": "Calculating export size...", - "estimatedSize": "Estimated size:", - "fileLabel": "File: {fileName}", - "exportAction": "Export", - "selectedRowsSummary": "{count, plural, =0 {# selected row} other {# selected rows}}", - "matchingRowsSummary": "{count, plural, =0 {# matching row} other {# matching rows}}", - "prepareFailed": "Failed to prepare export", - "exportStarted": "Metadata export started: {fileName}", - "exportFailed": "Metadata export failed" - }, - "columnPanel": { - "columnsHeading": "Columns", - "reset": "Reset", - "tableDensity": "Table density", - "density": { - "compact": "Compact", - "comfortable": "Comfortable", - "roomy": "Roomy" - }, - "presets": "Presets", - "exportBackup": "Export presets and saved views", - "importBackup": "Import presets and saved views", - "rename": "Rename", - "renamePrompt": "Enter a new name", - "builtIn": "Built in", - "saveCurrentPreset": "Save current preset", - "savedViews": "Saved views", - "savedViewsEmpty": "Save sort, layout, and view-specific filters for quick reuse.", - "saveCurrentView": "Save current view", - "pinnedLeft": "Pinned left", - "pinnedRight": "Pinned right", - "columns": { - "cover": "Cover", - "read": "Read", - "actions": "Actions" - } - }, - "shortcuts": { - "title": "Keyboard Shortcuts", - "navigation": { - "title": "Navigation", - "moveFocusVertical": "Move focus up/down", - "moveFocusHorizontal": "Move focus left/right", - "jumpFirstColumn": "Jump to first column", - "jumpLastColumn": "Jump to last column", - "jumpFirstRow": "Jump to first row", - "jumpLastRow": "Jump to last row" - }, - "actions": { - "title": "Actions", - "editCell": "Edit focused cell", - "cancelEditing": "Cancel editing / Close overlay", - "toggleRowSelection": "Toggle row selection", - "copyCell": "Copy cell value", - "copyRow": "Copy focused row" - }, - "general": { - "title": "General", - "toggleHelp": "Toggle this help overlay" - } - }, - "jumpRail": { - "jumpToSection": "Jump to section", - "jumpTo": "Jump to {label}", - "unknownDate": "Unknown date", - "unknownValue": "Unknown value" - }, - "quickView": { - "title": "Book quick view", - "titleFor": "Quick view for {title}", - "description": "Preview book details and run quick actions.", - "openIn": "Open in {provider}", - "pages": "{count, plural, =0 {# page} other {# pages}}", - "primaryFile": "Primary File", - "fileNumber": "File #{id}", - "showLess": "Show less", - "showMore": "Show more", - "collections": "Collections", - "noDescription": "No description available.", - "openMetadataEditor": "Open metadata editor", - "coverPreview": "Book cover preview", - "coverPreviewFor": "{title} cover preview", - "coverPreviewDescription": "Enlarged cover image preview dialog." - }, - "tableView": { - "openBookDetails": "Open book details", - "openSeries": "Open series", - "metadataRefreshFailed": "Metadata refresh failed", - "booksSelected": "{count, plural, =0 {# book selected} other {# books selected}}", - "loadingMoreBooks": "Loading more books", - "sort": "Sort", - "refreshingMetadata": "Refreshing metadata {processed} / {total}", - "failedCount": "{count} failed", - "remainingCount": "{count} remaining", - "readOnlyNotice": "Table editing is disabled on smaller screens. Switch to list or grid for quicker actions.", - "fetching": "Fetching...", - "updated": "Updated", - "failed": "Failed", - "noBooks": "No books to display", - "scrollToTop": "Scroll to top", - "selectedStatus": "{count} selected", - "filtered": "Filtered", - "loadedStatus": "{loaded} of {total} loaded", - "bookCount": "{count, plural, =0 {# book} other {# books}}", - "keyboardShortcutsTitle": "Keyboard shortcuts (?)", - "showKeyboardShortcuts": "Show table keyboard shortcuts", - "copyHint": "Copy cell: Ctrl/Cmd+C · Copy row: Ctrl/Cmd+Shift+C" - }, - "detail": { - "authorBooks": { - "alsoByAuthor": "Also by this author", - "alsoByAuthors": "Also by these authors" - }, - "header": { - "previousBook": "Previous book", - "nextBook": "Next book" - }, - "tabs": { - "details": "Details", - "editMetadata": "Edit Metadata", - "files": "Files", - "readingLog": "Reading Log", - "highlights": "Highlights" - }, - "discover": { - "moreInSeries": "More in Series", - "byAuthor": "By Author", - "similarBooks": "Similar Books" - }, - "recommended": { - "moreLikeThis": "More Like This" - }, - "series": { - "moreInSeries": "More in the {series} series" - }, - "writeRename": { - "written": "{count, plural, =0 {no fields written} other {Written (# fields)}}", - "writeFailed": "Write failed", - "skipped": "Skipped", - "renamedTo": "Renamed to {name}", - "fileRenamed": "File renamed", - "renameFailed": "Rename failed", - "autoWriteAndRenameDisabled": "Auto-write and rename are disabled in library settings. Changes won't sync automatically on future saves.", - "autoWriteDisabled": "Auto-write is disabled in library settings. Changes won't sync automatically on future saves.", - "autoRenameDisabled": "Auto-rename is disabled in library settings. Changes won't sync automatically on future saves.", - "writeLabel": "Write:", - "renameLabel": "Rename:" - }, - "addFile": { - "uploading": "Uploading...", - "uploadComplete": "Upload complete", - "title": "Add File", - "dropzone": { - "title": "Drop files here or click to browse", - "hint": "epub, pdf, mobi, cbz, m4b and more - up to {size} MB each" - }, - "addMore": "Add more files", - "fileCount": "{count, plural, =0 {no files} other {# files}}", - "clearAll": "Clear all", - "done": "Done", - "retry": "Retry", - "filesAdded": "{count, plural, =0 {no files added} other {# files added}}", - "uploadedFailed": "{done} uploaded, {failed} failed", - "uploadingProgress": "{done} of {total} uploading...", - "renameAfter": "Rename all book files after upload", - "uploadCount": "Upload ({count})", - "upload": "Upload" - }, - "addSession": { - "errors": { - "invalidDate": "Pick a valid date and time.", - "future": "The session cannot start in the future.", - "duration": "Duration must be between 1 and 1440 minutes.", - "endProgress": "End progress must be between 0 and 100." - }, - "title": "Add reading session", - "startedAt": "Started at", - "duration": "Duration (minutes)", - "endProgress": "End progress %", - "optional": "Optional", - "format": "Format", - "noFormat": "No specific format", - "saving": "Saving...", - "submit": "Add session" - }, - "coverEditor": { - "unlockCover": "Unlock cover", - "lockCover": "Lock cover", - "fileTab": "File", - "urlTab": "URL", - "chooseImage": "Choose image...", - "findCoverOnline": "Find cover online", - "saving": "Saving...", - "saveCover": "Save cover", - "revertToOriginal": "Revert to original", - "regenerateCover": "Regenerate Cover" - }, - "coverSearch": { - "title": "Online Search", - "subtitle": "Search for book covers", - "titleField": "Title", - "authorField": "Author", - "sourceField": "Source", - "allSources": "All Sources", - "audiobookCovers": "Audiobook covers", - "squareHint": "(square)", - "searching": "Searching...", - "findCovers": "Find covers", - "selectCover": "Select Cover", - "noResultsTitle": "No results found", - "noResultsHint": "Try adjusting your search terms", - "readyTitle": "Ready to search", - "readyHint": "Enter a title and author above", - "resolutionTip": "Tip: High resolution covers are marked in green" - }, - "details": { - "by": "by", - "narratedBy": "narrated by", - "ratingLocked": "Rating is locked", - "rateStar": "Rate {star}", - "listen": "Listen", - "read": "Read", - "chooseFormat": "Choose format", - "audiobook": "Audiobook", - "primary": "Primary", - "peek": "Peek", - "sendViaEmail": "Send via Email", - "personalReview": { - "title": "Personal Review", - "toggleAria": "Toggle personal review", - "editAria": "Edit personal review", - "placeholder": "Private review", - "clearAria": "Clear personal review", - "cancelEditAria": "Cancel personal review edit" - }, - "editCover": "Edit cover", - "finished": "Finished", - "resetFileProgress": "Reset file progress", - "resetting": "Resetting...", - "resetProgressConfirm": "Reset stored reading progress for {label}?", - "moreCount": "+{count} more", - "untitled": "Untitled", - "metadataScore": "Metadata Score", - "primaryFormat": "Primary format", - "openIn": "Open in {provider}", - "showLess": "Show less", - "showMore": "Show more", - "publisher": "Publisher", - "published": "Published", - "language": "Language", - "pages": "Pages", - "duration": "Duration", - "edition": "Edition", - "abridged": "Abridged", - "unabridged": "Unabridged", - "isbn": "ISBN", - "fileSize": "File Size", - "library": "Library", - "added": "Added", - "dateStarted": "Date Started", - "saving": "Saving...", - "cancelDateStartedEdit": "Cancel date started edit", - "editDateStarted": "Edit date started", - "dateFinished": "Date Finished", - "cancelDateFinishedEdit": "Cancel date finished edit", - "editDateFinished": "Edit date finished", - "customMetadata": "Custom Metadata", - "synopsis": "Synopsis", - "noDescription": "No description available.", - "dateStartedFutureError": "Date Started cannot be in the future.", - "dateFinishedFutureError": "Date Finished cannot be in the future.", - "dateFinishedBeforeStartedError": "Date Finished must be on or after Date Started.", - "saveReadingDatesError": "Failed to save reading dates.", - "koboPendingDelete": "Pending delete from device", - "koboPendingDeleteTooltip": "Kobo will remove it on next sync.", - "koboRemovedByDevice": "Removed by device", - "koboRemovedByDeviceTooltip": "Kobo reported this book removed.", - "koboNotSynced": "Not synced", - "koboNotSyncedTooltip": "Queued for next Kobo sync.", - "filesNotFound": "Files not found", - "filesNotFoundDescription": "The file(s) for this book can no longer be found on disk. Metadata is still available. Run a library scan to confirm, or remove the record." - }, - "editMetadata": { - "fieldCount": "{count, plural, =0 {no fields} other {# fields}}", - "bookFilesTarget": "book files", - "formatFilesTarget": "{formats} files", - "noPrimaryFile": "No primary file available", - "formatNotSupported": "This file format does not support write-back", - "formatDisabled": "Write-back is disabled for this format", - "fileExceedsSizeLimit": "This file exceeds the write-back size limit", - "writing": "Writing...", - "saveInProgress": "Save in progress", - "writeManualLibraryDisabled": "Write metadata to file and rename on disk; automatic write-back is disabled for this library", - "writeManualTooltip": "Write {fields} to {target} and rename on disk", - "applyResult": "{skipped}, {updated}", - "skippedLockedFields": "{count, plural, =0 {Skipped no locked fields} other {Skipped # locked fields}}", - "updatedFields": "{count, plural, =0 {updated no fields} other {updated # fields}}", - "wroteFieldsToFile": "Wrote {fields} to file", - "fileWriteFailedReason": "File write failed: {reason}", - "fileWriteFailed": "File write failed", - "fileWriteSkippedReason": "File write skipped: {reason}", - "fileWriteSkipped": "File write skipped", - "metadataSaved": "Metadata saved", - "metadataWrittenToFile": "Metadata written to file", - "savedButWriteFailedReason": "Metadata saved, but file write failed: {reason}", - "savedButWriteFailed": "Metadata saved, but file write failed", - "savedWriteSkippedReason": "Metadata saved, file write skipped: {reason}", - "savedWriteSkipped": "Metadata saved, file write skipped", - "loadFromFileFailed": "Failed to load metadata from file", - "loadedFieldsFromFile": "{count, plural, =0 {Loaded no fields from file} other {Loaded # fields from file}}", - "noMetadataInFile": "No metadata found in file", - "loadFromFile": "Load from file", - "loadFromFileTooltip": "Load metadata from the primary book file", - "writeToFile": "Write to file", - "autoFill": "Auto-fill", - "fetchingMetadata": "Fetching metadata...", - "allFieldsLocked": "All fields are locked", - "autoFillTooltip": "Auto-fill fields using your metadata preferences", - "lockAll": "Lock all", - "lockAllTooltip": "Lock all fields", - "unlockAll": "Unlock all", - "unlockAllTooltip": "Unlock all fields", - "saving": "Saving...", - "fileWriteBackDetails": "File write-back details", - "fileWriteBack": "File write-back", - "enabled": "Enabled", - "saveWritesMetadata": "'Save' writes metadata to {target}", - "formats": "Formats", - "bookFiles": "Book files", - "supportedFields": "Supported fields", - "titleLabel": "Title", - "subtitleLabel": "Subtitle", - "authorsLabel": "Authors", - "narratorsLabel": "Narrators", - "genresLabel": "Genres", - "tagsLabel": "Tags", - "ratingLabel": "Rating", - "rateStar": "Rate {star}", - "clear": "Clear", - "communityRatingsLabel": "Community Ratings", - "noProviderRatings": "No provider ratings", - "seriesLabel": "Series", - "publisherLabel": "Publisher", - "languageLabel": "Language", - "yearLabel": "Year", - "pageCountLabel": "Page Count", - "isbn13Label": "ISBN-13", - "isbn10Label": "ISBN-10", - "durationLabel": "Duration (s)", - "abridgedLabel": "Abridged", - "providerIds": "Provider IDs", - "comicDetails": "Comic Details", - "comicIssueNumberLabel": "Issue Number", - "comicVolumeLabel": "Volume", - "comicStoryArcsLabel": "Story Arcs", - "comicPencillersLabel": "Pencillers", - "comicInkersLabel": "Inkers", - "comicColoristsLabel": "Colorists", - "comicLetterersLabel": "Letterers", - "comicCoverArtistsLabel": "Cover Artists", - "comicCharactersLabel": "Characters", - "comicTeamsLabel": "Teams", - "comicLocationsLabel": "Locations", - "customMetadata": "Custom Metadata", - "descriptionLabel": "Description", - "unlockField": "Unlock {field}", - "lockField": "Lock {field}", - "diffPanel": { - "untitled": "Untitled", - "noFieldsSelected": "No fields selected", - "fieldsSelected": "{count, plural, =0 {no fields selected} other {# fields selected}}", - "results": "Results", - "providerMatches": "{provider} matches", - "selectedOf": "Selected {selected} of {total}", - "yearUnknown": "Year unknown", - "indexOf": "{index} of {total}", - "switchedResult": "Switched result. Previous selections from this provider were cleared.", - "selectFieldsToApply": "Select fields to apply", - "copyMissing": "Copy Missing", - "copyAll": "Copy All", - "hideUnchanged": "Hide unchanged", - "showUnchanged": "Show unchanged", - "current": "Current", - "noMetadata": "No metadata available from this source.", - "noChangedFields": "No changed or missing fields. Use Show unchanged to inspect everything.", - "applyToForm": "Apply to form" - }, - "diff": { - "locked": "Locked", - "previewAlt": "Preview", - "currentCoverAlt": "Current cover", - "newCoverAlt": "New cover", - "pickCoverFromProvider": "Pick cover from another provider", - "pickCoverSource": "Pick cover source", - "pickFromProvider": "Pick from another provider", - "pickSource": "Pick source", - "empty": "empty", - "showLess": "Show less", - "showMore": "Show more", - "coverPreviewAlt": "Cover preview" - }, - "searchDrawer": { - "searchTitle": "Search Metadata", - "compareTitle": "Compare Metadata", - "searchSubtitle": "Find the best provider match for this book.", - "compareSubtitle": "Review differences and apply only what you want." - }, - "searchPanel": { - "untitledQuery": "Untitled query", - "titlePlaceholder": "Title", - "authorPlaceholder": "Author", - "isbnPlaceholder": "ISBN", - "searching": "Searching...", - "activeQuery": "Active query", - "searchScope": "Search scope", - "allEnabled": "All enabled", - "all": "All", - "fieldRules": "Field Rules", - "custom": "Custom", - "providerNotInFieldRules": "{provider} is enabled but not in Field Rules", - "notInFieldRulesLabel": "Not in Field Rules:", - "notInFieldRulesText": "{providers}. Included in manual search with All enabled, but not used by automatic metadata fetch.", - "noResults": "No results found", - "noResultsHint": "Try adjusting the title or author", - "searchPrompt": "Search above, then click a result to start comparing metadata." - }, - "writeAndRename": "Write to File & Rename", - "writeAndRenameShort": "Write & Rename" - }, - "files": { - "title": "Book files", - "fileCount": "{count, plural, =0 {no files} other {# files}}", - "synced": "Synced {time}", - "sortAria": "Sort files", - "syncHistory": "Sync history", - "metadataWriteBack": "Metadata write-back", - "relative": { - "seconds": "{value}s ago", - "minutes": "{value}m ago", - "hours": "{value}h ago", - "days": "{value}d ago" - }, - "renameFailed": "Failed to rename file", - "deleteFailed": "Failed to delete file", - "addFile": "Add File", - "lastSynced": "Last synced: {time}", - "sort": { - "label": "Sort:", - "name": "Name", - "format": "Format", - "size": "Size", - "date": "Date" - }, - "hidePaths": "Hide paths", - "showPaths": "Show paths", - "hideLog": "Hide log", - "viewSyncLog": "View sync log", - "noWriteHistory": "No write history yet.", - "fieldsWritten": "{count, plural, =0 {no fields} other {# fields}}", - "track": "Track {number}", - "primary": "Primary", - "read": "Read", - "play": "Play", - "peek": "Peek", - "download": "Download", - "moreActions": "More actions", - "rename": "Rename", - "empty": { - "title": "No files attached", - "description": "This book has no associated files." - }, - "renameModal": { - "title": "Rename File", - "description": "Rename the physical file on disk.", - "placeholder": "New filename" - }, - "saving": "Saving...", - "deleteModal": { - "title": "Delete file?", - "description": "Are you sure you want to delete \"{filename}\"? This action cannot be undone." - }, - "deleting": "Deleting..." - }, - "highlights": { - "note": { - "placeholder": "Add a note...", - "saving": "Saving" - }, - "export": { - "trigger": "Export", - "plainText": "Plain Text", - "page": "Export page", - "selected": "Export selected" - }, - "sort": { - "position": "Position", - "newest": "Newest first", - "oldest": "Oldest first" - }, - "summary": { - "highlights": "{count, plural, =0 {no highlights} other {# highlights}}", - "notes": "{count, plural, =0 {no notes} other {# notes}}", - "chapters": "{count, plural, =0 {no chapters} other {# chapters}}" - }, - "filterByChapter": "Filter by chapter", - "allChapters": "All chapters", - "untitled": "Untitled", - "trash": "Trash", - "empty": { - "noMatch": "No highlights match your filters.", - "resetFilters": "Reset filters", - "none": "No highlights yet", - "hint": "Select text while reading to create highlights" - }, - "uncategorized": "Uncategorized", - "paginationUnit": "highlights" - }, - "readingLog": { - "moreActionsAria": "More reading log actions", - "export": { - "button": "Export" - }, - "weekdays": { - "sun": "Sun", - "mon": "Mon", - "tue": "Tue", - "wed": "Wed", - "thu": "Thu", - "fri": "Fri", - "sat": "Sat" - }, - "months": { - "jan": "Jan", - "feb": "Feb", - "mar": "Mar", - "apr": "Apr", - "may": "May", - "jun": "Jun", - "jul": "Jul", - "aug": "Aug", - "sep": "Sep", - "oct": "Oct", - "nov": "Nov", - "dec": "Dec" - }, - "heatmap": { - "minutesUnit": "min", - "title": "Activity", - "empty": "No reading activity in this window.", - "emptyHint": "Sessions recorded here will build your consistency view." - }, - "hero": { - "summaryAria": "Reading summary", - "notSet": "Not set", - "relative": { - "seconds": "{count}s ago", - "minutes": "{count}m ago", - "hours": "{count}h ago", - "days": "{count}d ago", - "months": "{count, plural, =0 {# month ago} other {# months ago}}", - "years": "{count, plural, =0 {# year ago} other {# years ago}}" - }, - "noSessions": "No sessions", - "dateErrors": { - "startFuture": "Start date cannot be in the future.", - "finishFuture": "Finish date cannot be in the future.", - "finishBeforeStart": "Finish date must be on or after the start date.", - "saveFailed": "Failed to save reading dates." - }, - "eta": { - "max": "99h+ to finish", - "minutes": "~{m}m to finish", - "hours": "~{h}h to finish", - "hoursMinutes": "~{h}h {m}m to finish" - }, - "momentum": { - "none": "No activity in the last two weeks", - "new": "New activity this week", - "up": "+{pct}% vs previous 7 days", - "down": "{pct}% vs previous 7 days", - "flat": "Unchanged vs previous 7 days" - }, - "stats": { - "totalTime": "Total Time", - "sessions": "Sessions", - "avgSession": "Avg Session", - "lastRead": "Last Read" - }, - "firstRead": "First Read", - "lastRead": "Last Read", - "dateStarted": "Date Started", - "dateFinished": "Date Finished", - "addSession": "Add session" - }, - "journey": { - "tooltipProgress": "Progress", - "tooltipReading": "Reading", - "minutesUnit": "min", - "title": "Progress journey", - "empty": "No progress data in this window.", - "emptyHint": "Progress will appear after a session records a reading position." - }, - "sourceSplit": { - "title": "Reading sources", - "shortTitle": "Sources" - }, - "untitled": "Untitled", - "addSessionFailed": "Failed to add session", - "filters": { - "show": "Show", - "dateRangeAria": "Reading session date range", - "allTime": "All time", - "last30": "Last 30 days", - "last90": "Last 90 days", - "thisYear": "This year", - "allFormats": "All formats" - }, - "table": { - "title": "Sessions", - "sourceWeb": "Web", - "sourceManual": "Manual", - "colDate": "Date", - "colDateMobile": "Date", - "colDuration": "Duration", - "colDurationMobile": "Duration", - "colProgressChange": "Progress Change", - "colProgressChangeMobile": "Delta", - "colEndProgress": "End Progress", - "colEndProgressMobile": "End", - "empty": "No reading sessions recorded yet.", - "emptyHint": "Add a session to start building this book's reading history.", - "colPace": "Pace", - "colSource": "Source", - "colFormatMobile": "Fmt", - "colFormat": "Format", - "cancelDelete": "Cancel delete", - "cancelDeleteAria": "Cancel delete session", - "confirmDeleteTitle": "Click again to confirm delete", - "confirmDeleteAria": "Confirm delete session", - "deleteAria": "Delete session", - "loadMore": "Load more", - "showing": "Showing {shown} of {total} sessions" - } - }, - "richDescription": { - "linkProtocolError": "Use http, https, or mailto.", - "bold": "Bold", - "italic": "Italic", - "underline": "Underline", - "strikethrough": "Strikethrough", - "bulletList": "Bullet list", - "numberedList": "Numbered list", - "outdentAria": "Outdent list item", - "outdent": "Outdent", - "indentAria": "Indent list item", - "indent": "Indent", - "quote": "Quote", - "editLink": "Edit link", - "link": "Link", - "removeLink": "Remove link", - "undo": "Undo", - "redo": "Redo", - "clearFormatting": "Clear formatting", - "previewDescription": "Preview description", - "preview": "Preview", - "linkUrlLabel": "Link URL", - "applyLink": "Apply link", - "apply": "Apply", - "cancelLink": "Cancel link", - "noDescription": "No description available." - }, - "seriesMembership": { - "addSeries": "Add series", - "seriesPlaceholder": "Series", - "moveUp": "Move up", - "moveDown": "Move down", - "removeSeries": "Remove series" - } - }, - "table": { - "actions": { - "quickView": "Quick View", - "bookDetails": "Book Details", - "editMetadata": "Edit Metadata", - "refreshMetadata": "Refresh Metadata", - "addToCollection": "Add to Collection", - "sendToDevice": "Send to Device" - }, - "boolean": { - "ariaNotSet": "Not set - click to set true", - "ariaTrue": "True - click to set false", - "ariaFalse": "False - click to clear" - }, - "chips": { - "addPlaceholder": "Add..." - }, - "cover": { - "previewDescription": "Book cover preview", - "editDescription": "Edit book cover", - "editTitle": "Edit cover", - "editCover": "Edit Cover", - "view": "View cover" - }, - "date": { - "justNow": "just now" - }, - "format": { - "unknown": "unknown" - }, - "header": { - "sortAscending": "Sort Ascending", - "sortDescending": "Sort Descending", - "clearSort": "Clear Sort", - "hideColumn": "Hide Column", - "pinLeft": "Pin Left", - "pinRight": "Pin Right", - "unpinColumn": "Unpin Column", - "autoFitWidth": "Auto-Fit Width", - "autoFitAllColumns": "Auto-Fit All Columns", - "selectAllBooks": "Select all books", - "shiftClickSecondarySort": "Shift+click to add secondary sort", - "clickToSort": "Click to sort" - }, - "locks": { - "lockAll": "Lock all fields", - "unlockAll": "Unlock all fields", - "lockField": "Lock field", - "unlockField": "Unlock field", - "clickToLock": "Click to lock", - "clickToUnlock": "Click to unlock" - }, - "progress": { - "complete": "{percent} complete" - }, - "rating": { - "label": "Rating", - "remove": "Remove rating", - "rate": "Rate {star} out of 5" - }, - "read": { - "play": "Play", - "read": "Read", - "primary": "Primary", - "peekFormat": "Peek {format}", - "chooseFormat": "Choose format to read or play", - "fileFallback": "FILE" - }, - "readStatus": { - "unread": "Unread" - }, - "series": { - "bookCount": "{count, plural, =0 {(no books)} other {(# books)}}", - "readOfCount": "{read} of {total} read" - }, - "text": { - "openDetails": "Open details" - } - } - }, - "bookMetadataFetch": { - "book": { - "title": "Metadata Fetch" - }, - "author": { - "title": "Author Enrichment" - }, - "stats": { - "queued": "Queued", - "processing": "Processing", - "rateLimited": "Rate limited", - "failed": "Failed" - }, - "actions": { - "pause": "Pause", - "resume": "Resume", - "cancelQueued": "Cancel queued", - "dismissBookStatus": "Dismiss metadata fetch status", - "dismissAuthorStatus": "Dismiss author enrichment status" - }, - "cancel": { - "processingWillFinish": "Currently processing items will finish.", - "confirm": "Confirm cancel", - "keepRunning": "Keep running" - }, - "viewFailed": "{count, plural, other {View # failed}}", - "card": { - "fetchingMetadata": "Fetching metadata", - "enrichingAuthors": "Enriching authors", - "metadataFetchFinished": "Metadata fetch finished", - "authorEnrichmentFinished": "Author enrichment finished" - }, - "label": { - "paused": "Paused", - "remaining": "{count} remaining", - "processing": "{count} processing", - "failed": "{count} failed", - "rateLimited": "{count} rate limited" - }, - "report": { - "bookTitle": "Failed Metadata Fetches", - "authorTitle": "Failed Author Enrichments", - "noFailedItems": "No failed items.", - "retryAllFailed": "Retry all failed", - "bookFallback": "Book #{id}", - "authorFallback": "Author #{id}", - "columns": { - "title": "Title", - "library": "Library", - "author": "Author", - "error": "Error", - "http": "HTTP" - } - }, - "toast": { - "failedToPause": "Failed to pause", - "failedToResume": "Failed to resume", - "failedToCancel": "Failed to cancel", - "failedToRetry": "Failed to retry", - "failedItemsRequeued": "Failed items requeued", - "bookComplete": "Metadata fetch complete - {done} books updated", - "bookDoneWithFailures": "Metadata fetch done - {done} processed, {failed} failed", - "authorComplete": "Author enrichment complete - {done} authors updated", - "authorDoneWithFailures": "Author enrichment done - {done} processed, {failed} failed" - } - }, - "bookDock": { - "apply": "Apply", - "done": "Done", - "discard": "Discard", - "finalize": "Finalize", - "rescan": "Rescan", - "uploadAction": "Upload", - "uploading": "Uploading...", - "searchPlaceholder": "Search files...", - "setDestinationAction": "Set Destination", - "bulkEditAction": "Bulk Edit", - "applyFetched": "Apply Fetched", - "retryErrors": "Retry Errors", - "commaSeparated": "comma-separated", - "destinationLibrary": "Destination Library", - "destinationFolder": "Destination Folder", - "nFailed": "{count} failed", - "updatedOfFiles": "Updated {updated} of {total} files", - "errorStatus": "Error {status}", - "tab": { - "all": "All", - "pending": "Pending", - "ready": "Ready", - "error": "Error" - }, - "status": { - "pending": "Pending", - "extracting": "Extracting", - "fetching": "Fetching", - "ready": "Ready", - "error": "Error" - }, - "field": { - "title": "Title", - "subtitle": "Subtitle", - "authors": "Authors", - "authorsCommaSeparated": "Authors (comma-separated)", - "publisher": "Publisher", - "publishedDate": "Published Date", - "year": "Year", - "language": "Language", - "isbn13": "ISBN-13", - "isbn10": "ISBN-10", - "series": "Series", - "seriesIndex": "Series #", - "genres": "Genres", - "genresCommaSeparated": "Genres (comma-separated)", - "description": "Description" - }, - "upload": { - "nDone": "{count} done", - "nFailed": "{count} failed", - "nTotal": "{count} total" - }, - "fileList": { - "emptyTitle": "No files in Book Dock", - "emptyMessageDefault": "Upload files or drop them in the Book Dock folder", - "colCurrent": "Current", - "colNew": "New", - "colFile": "File", - "colSize": "Size", - "colFormat": "Format", - "colMatch": "Match", - "colApply": "Apply", - "colStatus": "Status", - "applyFetchedMetadata": "Apply fetched metadata", - "coverPreview": "Cover preview", - "coverPreviewDescription": "Enlarged cover image preview dialog.", - "currentCoverAlt": "{title} current cover", - "newCoverAlt": "{title} new cover", - "unknownLibrary": "Unknown library", - "unassigned": "Unassigned", - "targetPath": "Target: {library} · {path}", - "targetUnassigned": "Target: Unassigned", - "targetUnknownPath": "Target: {library} · Unknown destination path" - }, - "sheet": { - "saved": "Saved", - "providerMetadataFound": "Provider metadata found", - "providerMetadataFoundEdited": "Provider metadata found - bulk apply will skip this file (you have edits)", - "review": "Review", - "added": "Added {date}", - "searchMetadata": "Search Metadata", - "results": "Results" - }, - "bulkEdit": { - "title": "{count, plural, =0 {Bulk Edit no files} other {Bulk Edit # files}}", - "resultTitle": "Bulk Edit Results", - "instructions": "Toggle the fields you want to update. Only enabled fields will be applied.", - "mergeArrays": "Merge arrays (add to existing values instead of replacing)", - "failed": "Bulk edit failed" - }, - "setDestination": { - "title": "{count, plural, =0 {Set Destination for no files} other {Set Destination for # files}}", - "resultTitle": "Destination Updated", - "failed": "Failed to set destination" - }, - "finalizeDialog": { - "title": "{count, plural, =0 {Finalize no files} other {Finalize # files}}", - "resultTitle": "Finalize Results", - "needDestination": "{count, plural, =0 {{without} of # selected files need a destination} other {{without} of # selected files need a destination}}", - "allHaveDestination": "All selected files already have destination set", - "defaultDestinationLibrary": "Default Destination Library", - "defaultDestinationFolder": "Default Destination Folder", - "renamePreview": "Rename preview", - "moreFiles": "+{count} more files", - "start": "Start", - "filesFinalized": "{succeeded} of {total} files finalized", - "checking": "Checking selected files...", - "readyCount": "{count, plural, =0 {no files ready} other {# files ready}}", - "duplicateCount": "{count, plural, =0 {none already in library} other {# already in library}}", - "conflictCount": "{count, plural, =0 {no filename conflicts} other {# filename conflicts}}", - "missingDestinationCount": "{count, plural, =0 {no missing destinations} other {# missing destinations}}", - "blockedCount": "{count, plural, =0 {no files blocked} other {# files blocked}}", - "moreDuplicates": "+{count} more already in library", - "discardDuplicates": "Discard duplicates", - "failedCount": "{count, plural, =0 {no files failed} other {# files failed}}", - "failedWithDuplicates": "{count, plural, =0 {{failed} failed (# duplicates)} other {{failed} failed (# duplicates)}}", - "view": "View", - "viewExisting": "View existing", - "hide": "Hide", - "details": "Details", - "alreadyExistsSaveAs": "Already exists - save as:", - "renamePlaceholder": "e.g. {name} (2)", - "import": "Import" - } - }, - "collection": { - "dialog": { - "name": "Name", - "icon": "Icon", - "iconPlaceholder": "Choose an icon...", - "nameRequired": "Name is required", - "iconRequired": "Choose an icon", - "creating": "Creating...", - "createFailed": "Failed to create collection" - }, - "createDialog": { - "title": "New Collection", - "namePlaceholder": "e.g. Favorites" - }, - "editDialog": { - "title": "Edit Collection", - "syncToKobo": "Sync to Kobo", - "syncToKoboHint": "Books in this collection will appear on your Kobo device", - "deleteCollection": "Delete collection", - "confirmDelete": "Confirm?", - "deleting": "Deleting...", - "saving": "Saving...", - "deleted": "\"{name}\" deleted", - "updateFailed": "Failed to update collection", - "deleteFailed": "Failed to delete collection" - }, - "addToSheet": { - "title": "Manage Collections", - "selectedCount": "{count, plural, =0 {no books selected} other {# books selected}}", - "newCollection": "New Collection", - "namePlaceholder": "Collection name", - "create": "Create", - "collections": "Collections", - "empty": "No collections yet. Create one above.", - "done": "Done", - "added": "Added", - "allAdded": "All {total} added", - "inCollection": "In this collection", - "allInCollection": "All {total} in this collection", - "partialInCollection": "{partial} of {total} in this collection", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "loadFailed": "Failed to load collections", - "createdAndAdded": "{count, plural, =0 {Created \"{name}\" and added no books} other {Created \"{name}\" and added # books}}", - "createdButAddFailed": "Created \"{name}\" but failed to add books", - "createFailed": "Failed to create collection", - "addedNewWithExisting": "{count, plural, =0 {Added one new book to \"{name}\" ({alreadyHad} already there)} other {Added # new books to \"{name}\" ({alreadyHad} already there)}}", - "addedToCollection": "{count, plural, =0 {Added no books to \"{name}\"} other {Added # books to \"{name}\"}}", - "addFailed": "Failed to add to collection", - "removedFromCollection": "{count, plural, =0 {Removed no books from \"{name}\"} other {Removed # books from \"{name}\"}}", - "removeFailed": "Failed to remove from collection" - } - }, - "components": { - "appHeader": { - "searchAllBooks": "Search all books...", - "searching": "Searching...", - "noResults": "No results", - "loadingMore": "Loading more...", - "loadMore": "Load more ({loaded}/{total})", - "allMatchesShown": "{count, plural, =0 {All 1 match shown} other {All # matches shown}}", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "fileCount": "{count, plural, =0 {no files} other {# files}}", - "uploadedToast": "Uploaded {uploaded}", - "uploadFailedToast": "Upload failed for {failed}", - "uploadPartialToast": "Uploaded {uploaded}, {failed} failed", - "bookDock": "Book Dock", - "statistics": "Statistics", - "achievements": "Achievements", - "annotations": "Annotations", - "uploadBooks": "Upload books", - "appearance": "Appearance", - "theme": "Theme", - "accent": "Accent", - "radius": "Radius", - "background": "Background", - "settings": "Settings", - "whatsNew": "What's New", - "documentation": "Documentation", - "help": "Help", - "starOnGithub": "Star on GitHub", - "new": "New", - "newReleaseNotes": "New release notes available", - "account": "Account", - "changePassword": "Change Password", - "signOut": "Sign out", - "githubStar": { - "title": "Enjoying BookOrbit?", - "body": "If BookOrbit is helping with your library, please consider starring the project on GitHub. It helps more people discover the app and supports ongoing development.", - "cta": "Star BookOrbit on GitHub" - }, - "surfaceOpacity": "Surface opacity", - "surfaceOpacityValue": "{value}%" - }, - "sidebar": { - "dashboard": "Dashboard", - "authors": "Authors", - "series": "Series", - "tools": "Tools", - "libraries": "Libraries", - "newLibrary": "New Library", - "scanProgress": "{processed} / {total} books", - "smartScopes": "Smart Scopes", - "newSmartScope": "New Smart Scope", - "noSmartScopes": "No Smart Scopes yet", - "collections": "Collections", - "newCollection": "New Collection", - "noCollections": "No collections yet", - "newReleaseNotes": "New release notes available", - "support": "Support BookOrbit", - "supportAria": "Support BookOrbit on Ko-fi", - "sectionHeader": { - "add": "Add", - "showAll": "Show all", - "showCount": "Show {count}", - "rowsShown": "Rows shown", - "menuAria": "Section options for {section}", - "reorder": "Reorder", - "doneReordering": "Done reordering" - }, - "noLibraries": "No libraries yet", - "clearFilter": "Clear filter", - "filterSummary": "{shown} of {total} shown", - "filterLibraries": "Filter libraries", - "filterLibrariesPlaceholder": "Filter libraries...", - "filterSmartScopes": "Filter smart scopes", - "filterSmartScopesPlaceholder": "Filter smart scopes...", - "filterCollections": "Filter collections", - "filterCollectionsPlaceholder": "Filter collections...", - "seeAllLibraries": "See all libraries ({count})", - "seeAllSmartScopes": "See all smart scopes ({count})", - "seeAllCollections": "See all collections ({count})", - "updateAvailable": "Update {version}", - "zones": { - "browse": "Browse" - }, - "reorder": { - "gripAria": "Reorder {name}", - "lifted": "{name} lifted, position {position} of {total}. Use the arrow keys to move it.", - "moved": "{name}, position {position} of {total}", - "dropped": "{name} dropped at position {position} of {total}", - "cancelled": "Reorder cancelled. {name} returned to position {position} of {total}.", - "filteredHint": "Clear the filter to reorder" - } - }, - "selectionActionBar": { - "setReadingStatus": "Set reading status", - "setRating": "Set rating", - "openMetadataEditor": "Open metadata editor", - "editIndividually": "Edit books individually", - "addToCollection": "Add to collection", - "removeFromCollection": "Remove from collection", - "sendViaEmail": "Send via email", - "downloadFilesZip": "Download files as ZIP", - "moreActions": "More actions", - "setField": "Set field", - "refreshMetadata": "Refresh metadata", - "reExtractCover": "Re-extract cover", - "metadataLock": "Metadata lock", - "lockAll": "Lock all", - "unlockAll": "Unlock all", - "exportMetadata": "Export metadata", - "deleteSelected": "Delete selected", - "exitSelection": "Exit selection", - "downloadFilesZipLabel": "Download files as ZIP:", - "primaryOnly": "Primary only", - "allFormats": "All formats", - "audioOnly": "Audio only", - "setRatingLabel": "Set rating:", - "clear": "Clear", - "setFieldLabel": "Set field:", - "apply": "Apply", - "fieldPlaceholder": "Leave blank to clear", - "fieldPlaceholderArray": "Comma-separated (leave blank to clear)", - "deleteConfirm": "{count, plural, =0 {Delete # book?} other {Delete # books?}}", - "typeDelete": "Type DELETE" - }, - "viewHeader": { - "select": "Select", - "display": "Display", - "displayDescription": "Adjust cover size, grid spacing, and view display options.", - "columnVisibilityHint": "Use the column visibility panel in the table header to show or hide columns.", - "columnVisibilityMobileHint": "Column visibility can be managed from the table header.", - "searchPlaceholder": "Search title, author, series, narrator...", - "mobileSearch": { - "description": "Search items by title, author, series, or narrator.", - "done": "Done" - }, - "mobileMenu": { - "grid": "Grid", - "list": "List", - "select": "Select", - "exitSelect": "Exit Select" - }, - "displayControls": { - "display": "Display", - "coverSize": "Cover size", - "gridGap": "Grid gap", - "showJumpRails": "Show jump rails", - "columnsHint": "Use the column visibility panel in the table header to show or hide columns.", - "coverShape": "Cover shape", - "circle": "Circle", - "square": "Square" - } - }, - "iconPicker": { - "clearSelectionAria": "Clear selected icon", - "searchLucide": "Search Lucide icons...", - "searchCustom": "Search custom icons...", - "chooseIcon": "Choose an icon...", - "selectIcon": "Select icon", - "customTab": "Custom", - "searching": "Searching...", - "noIconsMatch": "No icons match \"{query}\"", - "typeToSearch": "Type to search all icons", - "noCustomIcons": "No custom icons uploaded", - "noIconsAvailable": "No icons available" - }, - "entityNotFound": { - "title": "{entity} not found", - "description": "This {entity} doesn't exist or has been deleted.", - "goBack": "Go back" - }, - "themePicker": { - "light": "Light", - "dark": "Dark", - "system": "System" - }, - "userAvatar": { - "profilePicture": "Profile picture", - "profilePictureOf": "{name} profile picture" - }, - "ui": { - "sidebar": { - "title": "Sidebar", - "mobileDescription": "Displays the mobile sidebar.", - "toggle": "Toggle Sidebar" - }, - "chipInput": { - "typeAndEnter": "Type and press Enter to add", - "pressEnter": "Press Enter to add" - } - }, - "entityIndex": { - "sortBy": "Sort by", - "sort": { - "custom": "Custom order", - "name": "Name", - "bookCount": "Book count" - }, - "ascending": "Ascending", - "descending": "Descending", - "clearSearch": "Clear search", - "resultCount": "{shown} of {total}", - "noMatches": "No matches", - "noMatchesHint": "Try a different search term.", - "bookCount": "Books: {count}", - "librariesEmptyHint": "Create a library to start adding books.", - "smartScopesEmptyHint": "Smart scopes save a set of filters you use often.", - "collectionsEmptyHint": "Collections group books you pick by hand." - } - }, - "customIcons": { - "dialogTitle": "Upload custom icons", - "dialogDescription": "Review names before adding them to your library.", - "readingFiles": "Reading files...", - "dropPrompt": "Drop SVG files or click to browse", - "fileLimit": "Up to {max} files, 128 KB each", - "namePlaceholder": "Name", - "nameRequired": "Name is required", - "invalidSvg": "Invalid SVG", - "invalidSvgFile": "Invalid SVG file", - "identicalTo": "Identical to \"{name}\"", - "uploadAnyway": "Upload anyway", - "skipThisOne": "Skip this one", - "readyToUpload": "{count} ready to upload", - "noIconsStaged": "No icons staged yet", - "uploading": "Uploading...", - "upload": "Upload", - "uploadCount": "Upload {count}", - "onlySvgSupported": "Only SVG files are supported", - "maxStaged": "You can stage at most {max} icons at once", - "onlyMoreCanStage": "{count, plural, =0 {No more icons can be staged} other {Only # more icons can be staged}}", - "readFailed": "Failed to read SVG files", - "uploadedCount": "{count, plural, =0 {No icons uploaded} other {Uploaded # icons}}", - "uploadedPartial": "Uploaded {created}, {failed} failed", - "noIconsUploaded": "No icons uploaded", - "uploadFailed": "Failed to upload icons", - "uploadFailedEntry": "Upload failed" - }, - "dashboard": { - "common": { - "failedToLoad": "Failed to load", - "retry": "Retry", - "untitled": "Untitled", - "cover": "Cover", - "bookCover": "Book cover" - }, - "scroller": { - "failedToLoad": "Failed to load.", - "empty": { - "continueReading": "No books in progress yet. Start reading one to see it here.", - "continueListening": "No audiobooks in progress yet. Start listening to one to see it here.", - "wantToRead": "No books marked want to read yet.", - "upNextInSeries": "No next-in-series picks yet. Finish a volume to surface the next one.", - "recentlyAdded": "No books in your library yet.", - "smartScope": "No books match this smartScope.", - "default": "No books found." - } - }, - "settings": { - "title": "Customize Dashboard", - "tabs": { - "widgets": "Widgets", - "shelves": "Shelves" - }, - "widgetNames": { - "readingStreak": "Reading Streak", - "currentlyReading": "Currently Reading", - "readingGoal": "Reading Goal", - "readingDna": "Reading DNA", - "monthlyChallenge": "Monthly Challenge", - "highlightOfTheDay": "Highlight of the Day", - "neglectedGems": "Neglected Gems", - "readingRhythm": "Reading Rhythm", - "diversityScore": "Diversity Score", - "libraryOverview": "Library Overview", - "yearProjection": "Year Projection", - "longWait": "The Long Wait" - }, - "shelfNames": { - "recentlyAdded": "Recently Added", - "continueReading": "Continue Reading", - "continueListening": "Continue Listening", - "wantToRead": "Want to Read", - "upNextInSeries": "Up Next in Series", - "random": "Discover Something New", - "smartScope": "Smart Scope" - }, - "reorderHintWidget": "Drag to reorder. Toggle to show or hide a widget.", - "reorderHintShelf": "Drag to reorder. Toggle to show or hide a shelf.", - "smartScope": "Smart Scope", - "noSmartScopes": "No Smart Scopes yet. Create one from the sidebar.", - "addShelf": "Add shelf", - "resetToDefaults": "Reset to defaults" - }, - "welcome": { - "emptyTitle": "Your library is empty", - "noLibrariesTitle": "No libraries yet", - "emptyDescription": "Create a library to start organizing and reading your books. Point it to a folder and it will do the rest.", - "noLibrariesDescription": "Your administrator hasn't set up any libraries yet. Reach out to them to get started.", - "createFirstLibrary": "Create your first library" - }, - "widgets": { - "currentlyReading": { - "title": "Currently Reading", - "empty": "No books in progress. Start reading one to see it here.", - "continueReading": "Continue reading" - }, - "diversityScore": { - "title": "Diversity Score", - "notEnoughData": "Read at least 3 books to see your diversity score", - "booksAnalyzed": "{count, plural, =0 {no books analyzed} other {# books analyzed}}", - "subScores": { - "genre": "Genre", - "author": "Author", - "era": "Era", - "language": "Lang" - } - }, - "highlightOfTheDay": { - "title": "Highlight of the Day", - "empty": "Highlight passages while reading to see them here" - }, - "libraryOverview": { - "title": "Library Overview", - "empty": "Your library is empty. Add some books to get started.", - "addedThisYear": "+{count} added this year", - "stats": { - "books": "Books", - "authors": "Authors", - "series": "Series", - "storage": "Storage" - } - }, - "longWait": { - "title": "The Long Wait", - "empty": "No books waiting. You've started everything!", - "daysWaiting": "days waiting", - "pages": "{count, plural, =0 {no pages} other {# pages}}", - "startReading": "Start Reading" - }, - "monthlyChallenge": { - "title": "Monthly Challenge", - "complete": "Complete!" - }, - "neglectedGems": { - "title": "Neglected Gems", - "empty": "All your top-rated books have been read!", - "rating": "{rating}/5", - "daysWaiting": "{count}d waiting", - "queued": "Queued", - "addToQueue": "Add to queue", - "shuffle": "Shuffle" - }, - "readingDna": { - "title": "Reading DNA", - "notEnoughData": "Read at least 5 books to unlock your Reading DNA", - "basedOn": "{count, plural, =0 {Based on no books} other {Based on # books}}", - "traits": { - "length": "Length", - "variety": "Variety", - "rhythm": "Rhythm", - "time": "Time", - "speed": "Speed" - } - }, - "readingGoal": { - "title": "Reading Goal {year}", - "setGoalPrompt": "Set a reading goal to track your progress", - "setGoal": "Set goal", - "booksPerYear": "Books per year", - "ofGoal": "of {goal}", - "percentComplete": "{percentage}% complete", - "editGoal": "Edit goal" - }, - "readingRhythm": { - "title": "Reading Rhythm", - "empty": "Start reading to see your rhythm take shape", - "activeDays": "{count, plural, =0 {no active days} other {# active days}}", - "consistency": "{activeDays} · {percent}% consistency", - "avgPerDay": "avg {time}/day" - }, - "readingStreak": { - "title": "Reading Streak", - "empty": "Read today to start your streak", - "streakLabel": "{count, plural, =0 {day streak} other {days streak}}", - "best": "{count, plural, =0 {Best: # day} other {Best: # days}}", - "lastSevenDays": "Last 7 days" - }, - "yearProjection": { - "title": "Year Projection", - "books": "books", - "trendUp": "Trending up", - "trendDown": "Trending down", - "trendSteady": "Steady pace", - "pages": "pages", - "hours": "hours", - "readCount": "{count} read", - "daysLeft": "{count}d left" - } - } - }, - "email": { - "title": "Email", - "subtitle": "Send books to your e-reader via email.", - "loadFailed": "Failed to load", - "saveFailed": "Failed to save", - "deleteFailed": "Failed to delete", - "setDefaultFailed": "Failed to set default", - "setAsDefault": "Set as default", - "saving": "Saving...", - "update": "Update", - "create": "Create", - "deleteConfirm": "Delete \"{name}\". This action cannot be undone.", - "badge": { - "default": "Default", - "shared": "Shared", - "system": "System" - }, - "tabs": { - "providers": "Providers", - "recipients": "Recipients", - "groups": "Groups", - "templates": "Templates", - "preferences": "Preferences", - "history": "History" - }, - "providers": { - "heading": "SMTP Providers", - "add": "Add provider", - "newTitle": "New Provider", - "editTitle": "Edit Provider", - "name": "Name", - "namePlaceholder": "e.g. Gmail", - "host": "Host", - "port": "Port", - "username": "Username", - "password": "Password", - "passwordEdit": "Password (leave blank to keep current)", - "fromName": "From Name", - "fromNamePlaceholder": "My Library", - "fromAddress": "From Address", - "authentication": "Authentication", - "verifyTls": "Verify TLS certificate", - "tlsWarning": "TLS verification is disabled. The server's certificate will not be validated - use only for trusted internal servers.", - "noFromAddress": "no from address", - "emptyManage": "No providers yet. Add an SMTP provider to start sending emails.", - "emptyReadonly": "No providers available. Ask an administrator to add one.", - "setSystemTooltip": "Set as system mail provider", - "removeSystemTooltip": "Remove as system mail provider", - "testTooltip": "Test connection", - "toggleSharing": "Toggle sharing", - "removeSystemBeforeDelete": "Remove the system designation before deleting", - "notesHeading": "Provider Notes", - "notesBody": "The {system} provider (superuser only) is used for password reset emails. The {defaultProvider} provider is used when sending books with no explicit provider selected. Providers marked {shared} are available to all users.", - "deleteTitle": "Delete provider?", - "nameHostRequired": "Name and host are required", - "created": "Provider created", - "updated": "Provider updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default", - "unshared": "Provider unshared", - "sharedWithAll": "Provider shared with all users", - "updateSharingFailed": "Failed to update sharing", - "systemRemoved": "\"{name}\" removed as system mail provider", - "systemSet": "\"{name}\" set as system mail provider", - "updateSystemFailed": "Failed to update system provider", - "connectionSuccess": "Connection successful", - "connectionFailed": "Connection failed", - "testFailed": "Test failed" - }, - "recipients": { - "heading": "Recipients", - "add": "Add recipient", - "newTitle": "New Recipient", - "editTitle": "Edit Recipient", - "name": "Name", - "namePlaceholder": "My Kindle", - "emailAddress": "Email address", - "deviceType": "Device type", - "deviceNone": "None", - "deviceOther": "Other", - "preferredFormat": "Preferred format", - "formatAuto": "Auto", - "defaultTemplate": "Default template", - "useAccountDefault": "Use account default", - "kindleNote": "Kindle recipients automatically receive emails with subject \"convert\" to trigger format conversion.", - "empty": "No recipients yet.", - "prefersFormat": "prefers {format}", - "deleteTitle": "Delete recipient?", - "nameEmailRequired": "Name and email are required", - "created": "Recipient created", - "updated": "Recipient updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default" - }, - "groups": { - "heading": "Recipient Groups", - "create": "Create group", - "newTitle": "New Group", - "name": "Group name", - "namePlaceholder": "e.g. Book Club", - "creating": "Creating...", - "empty": "No groups yet. Create a group to send to multiple recipients at once.", - "memberCount": "{count, plural, =0 {no members} other {# members}}", - "deleteTooltip": "Delete group", - "noMembers": "No members yet.", - "removeMember": "Remove", - "selectRecipient": "Select recipient...", - "add": "Add", - "addMember": "Add member", - "allRecipientsInGroup": "All recipients are already in this group.", - "deleteTitle": "Delete group?", - "created": "Group created", - "createFailed": "Failed to create group", - "deleted": "\"{name}\" deleted", - "memberAdded": "Member added", - "addMemberFailed": "Failed to add member", - "memberRemoved": "Member removed", - "removeMemberFailed": "Failed to remove member" - }, - "templates": { - "heading": "Email Templates", - "new": "New template", - "newTitle": "New Template", - "editTitle": "Edit Template", - "name": "Name", - "namePlaceholder": "Default", - "subject": "Subject", - "body": "Body", - "availableVariables": "Available variables", - "editTemplate": "Edit template", - "empty": "No templates yet.", - "notesHeading": "Template Notes", - "notesBody": "System templates cannot be deleted. Administrators can edit them. Use variables like {variable} in subjects and bodies - they are replaced with book details at send time.", - "deleteTitle": "Delete template?", - "nameSubjectRequired": "Name and subject are required", - "created": "Template created", - "updated": "Template updated", - "deleted": "\"{name}\" deleted", - "setDefaultSuccess": "\"{name}\" set as default" - }, - "preferences": { - "heading": "Email Preferences", - "defaultProvider": "Default provider", - "defaultProviderHint": "Used when no provider is specified. If empty, the account default is used.", - "noneAccountDefault": "None (use account default)", - "defaultRecipient": "Default recipient", - "defaultRecipientHint": "Used for quick send. Must be set to use the quick-send action on book cards.", - "none": "None", - "defaultTemplate": "Default template", - "defaultTemplateHint": "Used when no template is specified. Falls back to the system default if empty.", - "noneSystemDefault": "None (use system default)", - "save": "Save preferences", - "saved": "Preferences saved" - }, - "history": { - "heading": "Send History", - "empty": "No emails sent yet.", - "noSubject": "(no subject)", - "loadMore": "Load more", - "resend": "Resend", - "deleteTitle": "Delete history entry?", - "entryDeleted": "Entry deleted", - "queuedForResend": "Queued for resend", - "resendFailed": "Failed to resend", - "statusSent": "Sent", - "statusFailed": "Failed", - "statusQueued": "Queued", - "statusPending": "Pending" - }, - "send": { - "title": "Send via Email", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "recipients": "Recipients", - "noRecipients": "No recipients configured. Add one in Email settings.", - "groups": "Groups", - "options": "Options", - "fileFormat": "File format", - "autoRecipientPreference": "Auto (use recipient preference)", - "unknownFormat": "Unknown", - "primarySuffix": "(primary)", - "provider": "Provider", - "template": "Template", - "default": "Default", - "send": "Send", - "sending": "Sending...", - "queued": "{count, plural, =0 {no emails queued} other {# emails queued}}", - "failed": "Failed to send" - } - }, - "hardcover": { - "settings": { - "subtitle": "Sync your reading progress, status, and ratings to Hardcover." - }, - "bookSync": { - "label": "Hardcover Sync", - "toggleAriaLabel": "Sync this book with Hardcover", - "syncNow": "Sync now" - }, - "connection": { - "title": "Connection", - "description": "Connect your Hardcover account to sync reading data.", - "connected": "Connected", - "apiToken": "API Token", - "tokenPlaceholder": "Paste your Hardcover API token", - "show": "Show", - "hide": "Hide", - "findTokenAt": "Find your token at", - "validateToken": "Validate token", - "valid": "Valid ({username})", - "invalidToken": "Invalid token", - "syncOptions": "Sync options", - "syncInfo": "Sync runs only for books that are not unread. This applies to status, progress, and rating triggers. These switches control when a sync runs.", - "syncScope": { - "title": "Book sync scope", - "allEligible": { - "label": "All eligible books", - "description": "Sync everything unless you exclude a book." - }, - "selectedOnly": { - "label": "Selected books only", - "description": "Sync only books you explicitly include." - } - }, - "enableSync": { - "title": "Enable sync", - "description": "Pause all Hardcover syncing without disconnecting." - }, - "syncOnStatus": { - "title": "Sync on status change", - "description": "Push updates when you mark a book as reading, read, etc." - }, - "syncOnProgress": { - "title": "Sync on progress update", - "description": "Push reading progress and dates when BookOrbit or KOReader progress changes." - }, - "syncOnRating": { - "title": "Sync on rating change", - "description": "Push your star ratings to Hardcover." - }, - "privacy": { - "title": "Privacy", - "description": "Default visibility for synced books on Hardcover.", - "public": "Public", - "followersOnly": "Followers only", - "private": "Private" - }, - "disconnect": "Disconnect", - "toast": { - "enterToken": "Enter your Hardcover API token first", - "saved": "Hardcover settings saved", - "saveFailed": "Failed to save settings", - "disconnected": "Hardcover disconnected" - } - }, - "sync": { - "title": "Manual sync", - "description": "Push your {scope} to Hardcover now.", - "scope": { - "selected": "selected books", - "eligible": "eligible books" - }, - "checkingPending": "Checking pending items...", - "pendingOf": "{pending} pending of {total} books.", - "noBooksInScope": "No books in sync scope.", - "allSynced": "All books are already synced.", - "lastSyncedLabel": "Last synced", - "lastSuccessfulSync": "Last successful sync", - "syncing": "Syncing...", - "progressCount": "{synced} / {total} books", - "unavailable": { - "permissionDenied": "You do not have permission to use Hardcover sync.", - "userDisabled": "Sync is paused in your Hardcover settings." - }, - "button": { - "unavailable": "Sync unavailable", - "syncNow": "Sync now", - "syncNowCount": "Sync now ({count})" - }, - "lastSynced": { - "justNow": "Just now", - "minutesAgo": "{count} min ago", - "hoursAgo": "{count, plural, =0 {# hour ago} other {# hours ago}}", - "daysAgo": "{count, plural, =0 {# day ago} other {# days ago}}" - } - }, - "import": { - "title": "Pull read status", - "description": "Preview Hardcover matches before filling blank BookOrbit statuses.", - "clear": "Clear", - "preview": "Preview", - "importProgress": "Import progress", - "reviewMatches": "Review matches", - "importReady": "Import ready", - "exactMatches": "{count, plural, =0 {no exact matches can be imported without review} other {# exact matches can be imported without review}}", - "progressAvailable": "{count, plural, =0 {no progress updates available} other {# progress updates available}}", - "progressConflicts": "{count, plural, =0 {no conflicts} other {# conflicts}}", - "unavailable": { - "permissionDenied": "You do not have permission to use Hardcover sync.", - "missingToken": "Connect Hardcover before importing.", - "userDisabled": "Sync is paused in your Hardcover settings." - }, - "summary": { - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "result": { - "summary": "{applied} imported{progress}, {failed} failed", - "progressUpdated": "{count} progress updated" - }, - "toast": { - "importFailed": "Failed to import Hardcover read status", - "imported": "{count, plural, =0 {no read statuses imported{progress}} other {# read statuses imported{progress}}}", - "progressUpdates": "{count, plural, =0 {no progress updates} other {# progress updates}}" - } - }, - "review": { - "title": "Hardcover import review", - "subtitle": "{total} Hardcover books, {matched} matched.", - "closeAriaLabel": "Close import review", - "searchPlaceholder": "Search title or author", - "importProgress": "Import progress", - "untitled": "Untitled", - "blank": "blank", - "noRows": "No rows match the current filters.", - "selectRowAriaLabel": "Select {title}", - "selectionSummary": "{count} selected: {ready} ready, {reviewed} reviewed.", - "selectedProgress": "{count, plural, =0 {no progress updates} other {# progress updates}}", - "selectReady": "Select ready", - "selectPage": "Select page", - "clearPage": "Clear page", - "clearSelection": "Clear selection", - "importSelected": "Import selected", - "previousPage": "Previous page", - "nextPage": "Next page", - "pageRange": "{start}-{end} of {total}", - "tabs": { - "all": "All", - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "summary": { - "ready": "Ready", - "review": "Review", - "conflicts": "Conflicts", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "matchOptions": { - "all": "All match types" - }, - "matchMethod": { - "hardcoverId": "Hardcover ID", - "isbn": "ISBN", - "titleAuthor": "Title + author" - }, - "outcome": { - "ready": "Ready", - "review": "Review", - "conflict": "Conflict", - "unmatched": "Unmatched", - "skipped": "Skipped" - }, - "column": { - "progress": "Progress" - } - } - }, - "library": { - "creator": { - "createTitle": "Create Library", - "editTitle": "Edit: {name}", - "stepOf": "Step {current} of {total}", - "unsaved": "Unsaved", - "required": "Required", - "closeAria": "Close library creator", - "progressAria": "Library setup progress", - "sectionsAria": "Library settings sections", - "loadingAria": "Loading library settings", - "sections": { - "details": "Details", - "folders": "Folders", - "scanner": "Scanner", - "metadata": "Metadata", - "fileWrite": "File Write", - "reading": "Reading", - "schedule": "Schedule", - "access": "Access" - }, - "actions": { - "saving": "Saving…", - "saveChanges": "Save changes", - "creating": "Creating…", - "createLibrary": "Create library" - }, - "details": { - "libraryName": "Library name", - "namePlaceholder": "My Library", - "coverStyle": { - "title": "Cover style", - "portrait": "Portrait", - "square": "Square", - "hint": "Portrait for ebook or mixed libraries. Square for audiobook-only libraries." - }, - "icon": { - "label": "Icon", - "placeholder": "Choose an icon...", - "selected": "Selected" - } - }, - "folders": { - "title": "Scan folders", - "description": "Add one or more directories to scan for books.", - "browseAdd": "Browse and add a folder", - "browseTitle": "Browse server folders", - "browseDescription": "Select one or more folders without leaving the browser.", - "selectedTitle": "Selected folders", - "addFolders": "Add folders", - "manualEntry": "Enter a path manually", - "absolutePath": "Absolute server path", - "addFolder": "Add folder", - "removeFolder": "Remove {folder}", - "manualCheckHint": "Manual paths are checked together with the rest of the selected folders.", - "pathPlaceholder": "/path/to/books", - "test": "Test", - "add": "Add", - "pathNotAccessible": "Path is not accessible on the server.", - "pathAccessible": "Path is accessible.", - "pathNotAccessibleShort": "Path is not accessible", - "overlapsWith": "Overlaps with \"{library}\"", - "noneAdded": "No folders added yet", - "runPrescanHint": "Run a prescan to validate paths before saving.", - "scanning": "Scanning…", - "prescan": "Prescan" - }, - "scanner": { - "scanMode": { - "title": "Scan mode", - "lockedAria": "Organization mode is locked", - "lockTooltip": "Organization mode is fixed after library creation because changing it can create duplicate or missing book entries. To use a different mode, create a new library and rescan.", - "recommended": "Recommended", - "folderAsBook": { - "title": "Folder as Book", - "hint": "All files in a folder are grouped into one book. Works well when you keep multiple formats, like EPUB and MOBI, together." - }, - "fileAsBook": { - "title": "File as Book", - "hint": "Treats every file as an individual book. Best suited for libraries with one format per title. Avoid if your audiobooks span multiple files." - } - }, - "allowedFormats": { - "title": "Allowed formats", - "allowAll": "Allow all", - "allAllowed": "All formats are allowed.", - "onlySelected": "Only the selected formats will be imported.", - "warning": "Books in other formats already in the library will be marked as missing on the next scan." - }, - "excludePatterns": { - "title": "Exclude patterns", - "hintBefore": "Glob patterns to skip during scanning (e.g. ", - "hintAfter": ").", - "add": "Add", - "empty": "No patterns added." - } - }, - "metadata": { - "sourcePrecedence": { - "title": "Source precedence", - "hint": "The highest source in the list is preferred when multiple are available." - }, - "formatPriority": { - "title": "Format priority", - "hint": "When a book has multiple formats, the format highest in the list is preferred." - } - }, - "fileWrite": { - "maxFileSizeMb": "Max file size (MB)", - "formatLimits": "Format limits", - "rename": { - "title": "Rename files after metadata changes", - "hint": "Renames physical files when title, author, series, or year changes, using the library naming pattern." - }, - "write": { - "title": "Write metadata to files", - "hint": "When enabled, saving metadata will also write changes back into the physical file on disk." - }, - "cover": { - "title": "Include cover image", - "hint": "Writes the stored cover back into supported file formats." - }, - "epub": { - "title": "EPUB", - "hint": "Writes metadata into the OPF file inside the EPUB archive.", - "toggleAria": "Write EPUB metadata" - }, - "fb2": { - "title": "FictionBook (FB2)", - "hint": "Rewrites the description block inside FB2 files, leaving the book text untouched.", - "toggleAria": "Write FB2 metadata" - }, - "pdf": { - "title": "PDF", - "hint": "Embeds metadata into PDF Info dictionary and XMP stream.", - "toggleAria": "Write PDF metadata" - }, - "cbx": { - "title": "Comic archives (CBX)", - "hint": "Writes ComicInfo.xml into CBZ and CB7 archives.", - "toggleAria": "Write comic archive metadata" - }, - "kindle": { - "title": "Kindle (MOBI, AZW3)", - "hint": "Writes metadata into the EXTH header of MOBI, AZW3, and AZW files.", - "toggleAria": "Write Kindle metadata" - }, - "audio": { - "title": "Audio", - "hint": "Embeds the stored cover into M4B, M4A, MP3, and FLAC files.", - "toggleAria": "Write audio covers" - } - }, - "reading": { - "readingStart": { - "title": "Reading start", - "hint": "A book is marked as \"reading\" once this percentage of progress is reached." - }, - "markAsFinished": { - "title": "Mark as finished", - "hint": "A book is automatically marked as \"read\" when this percentage of progress is reached." - } - }, - "schedule": { - "fileWatching": "File watching", - "autoScanSchedule": "Auto-scan schedule", - "cronExpression": "Cron expression", - "cronInvalid": "Invalid cron expression.", - "cronFormat": "Format: minute hour day month weekday", - "watchFolders": { - "title": "Watch folders", - "hint": "Automatically detect new files added to library folders." - }, - "presets": { - "never": "Never", - "hourly": "Every hour", - "every6Hours": "Every 6 hours", - "every12Hours": "Every 12 hours", - "daily": "Daily", - "weekly": "Weekly", - "custom": "Custom" - }, - "human": { - "disabled": "Auto-scan disabled", - "hourly": "Every hour", - "every6Hours": "Every 6 hours", - "every12Hours": "Every 12 hours", - "dailyMidnight": "Daily at midnight", - "weeklyMonday": "Weekly on Monday at midnight", - "cron": "Cron: {cron}" - } - }, - "access": { - "title": "Access control", - "description": "Superusers always have full access. Grant access to other users below.", - "notYetCreated": "Access can be configured after the library is created.", - "selectUser": "Select a user…", - "grant": "Grant", - "empty": "No users have been granted access yet.", - "loading": "Loading access settings...", - "userSelectAria": "User to grant access", - "levelSelectAria": "Access level to grant", - "levels": { - "viewer": "Viewer", - "editor": "Editor", - "owner": "Owner" - }, - "columns": { - "user": "User", - "accessLevel": "Access level" - }, - "errors": { - "grant": "Failed to grant access", - "updateLevel": "Failed to update access level", - "revoke": "Failed to revoke access" - } - } - }, - "folderPicker": { - "title": "Browse server folders", - "description": "Select one or more folders for this library.", - "closeAria": "Close folder browser", - "currentFolderAria": "Current folder", - "parentFolder": "Go to parent folder", - "newFolder": "New folder", - "goUp": "Go up", - "filterPlaceholder": "Filter folders…", - "clearFilterAria": "Clear folder filter", - "newFolderNamePlaceholder": "New folder name", - "create": "Create", - "loading": "Loading folders...", - "selectCurrent": "Select current folder", - "noMatches": "No matching folders", - "noMatchesHint": "Try a different filter.", - "empty": "This folder is empty", - "emptyHint": "You can select the current folder or create a new one.", - "openFolderAria": "Open {name}", - "selectedCount": "{count, plural, =0 {no folders selected} other {# folders selected}}", - "noFolders": "No folders found", - "selectFolder": "Select this folder", - "errors": { - "readDirectory": "Could not read directory", - "connect": "Could not connect", - "invalidName": "Enter a single folder name without slashes or leading dots", - "createFolder": "Could not create folder" - } - }, - "upload": { - "library": "Library", - "selectLibrary": "Select a library...", - "targetFolder": "Target folder", - "addMoreFiles": "Add more files", - "clearAll": "Clear all", - "done": "Done", - "retry": "Retry", - "upload": "Upload", - "uploadWithCount": "Upload ({count})", - "viewInLibrary": "View in Library", - "fileCount": "{count, plural, =0 {no files} other {# files}}", - "booksAdded": "{count, plural, =0 {no books added} other {# books added}}", - "uploadedFailed": "{done} uploaded, {failed} failed", - "progress": "{done} of {total} uploading...", - "header": { - "uploading": "Uploading...", - "complete": "Upload complete", - "uploadTo": "Upload to {library}", - "uploadBooks": "Upload Books" - }, - "dropzone": { - "title": "Drop files here or click to browse", - "hint": "{formats} - up to {size} MB each" - } - } - }, - "metadataScore": { - "missingFields": "{count, plural, =0 {no fields missing - edit metadata} other {# fields missing - edit metadata}}" - }, - "migration": { - "sidebarTitle": "Booklore Import", - "status": { - "done": "Done", - "saved": "Saved", - "running": "Running", - "failed": "Failed" - }, - "badge": { - "validated": "Validated", - "upToDate": "Up to date", - "completed": "Completed" - }, - "steps": { - "source": { - "short": "Source Connection", - "title": "Source Connection", - "subtitle": "Configure the database connection to your source Booklore instance." - }, - "mappings": { - "short": "User & Path Mapping", - "title": "User & Path Mapping", - "subtitle": "Map source users to target users and translate file paths." - }, - "dryRun": { - "short": "Dry Run", - "title": "Dry Run", - "subtitle": "Preview what will be imported before running the live migration." - }, - "migration": { - "short": "Run Migration", - "title": "Run Migration", - "subtitle": "Start the live import and monitor its progress." - }, - "report": { - "short": "Report", - "title": "Migration Report", - "subtitle": "Review what was imported and export a detailed report." - } - }, - "footer": { - "continueToMappings": "Continue to Mappings", - "continueToDryRun": "Continue to Dry Run", - "continueToMigration": "Continue to Migration", - "viewReport": "View Report", - "resetSetup": "Reset Setup", - "stepOf": "Step {current} of {total}", - "backToSetup": "Back to Setup" - }, - "stages": { - "init": "Initializing", - "sharedOverlays": "Importing metadata", - "bookCovers": "Importing covers", - "userState": "Importing user data" - }, - "source": { - "testConnection": "Test Connection", - "saveAndValidate": "Save & Validate", - "validatedWithWarnings": "Source validated with warnings", - "fields": { - "type": "Source Type", - "name": "Source Name", - "host": "Host", - "port": "Port", - "user": "User", - "password": "Password", - "passwordSaved": "Saved - leave unchanged", - "passwordNotSet": "No password set", - "database": "Database", - "mediaRootPath": "Media Root Path", - "ssl": "Use TLS/SSL" - }, - "mediaPath": { - "hintRequired": "Required for migrating book covers.", - "hintAbsolute": "Use an absolute path (for example: /books). Relative paths are not supported.", - "hintConfigured": "Cover import path configured. Use Test Connection to verify access and Booklore images folder structure.", - "buttonOk": "Path OK", - "buttonIssue": "Path Issue", - "buttonTest": "Test Path" - }, - "compatibility": { - "title": "Tested compatibility", - "verifiedAgainst": "Verified against:", - "note": "Later versions are likely compatible but have not been verified. Run a dry-run first to confirm before committing data." - }, - "snapshot": { - "title": "Last validation snapshot", - "sourceVersion": "Source version: {version}", - "unknown": "Unknown", - "missingTables": "Missing required tables: {tables}" - } - }, - "mappings": { - "suggestionsAutoLoad": "User suggestions load automatically after source validation.", - "refresh": "Refresh", - "sourceUser": "Source User", - "targetUser": "Target User", - "noSourceUsersLoaded": "No source users loaded yet.", - "noActiveTargetUsers": "No active target users found. Create or re-enable a BookOrbit user before mapping.", - "pathPrefixMappings": "Path Prefix Mappings", - "addMapping": "Add Mapping", - "pathMappingsExplanation": "Path mappings translate source file paths to target paths so books can be matched by file location. Books are also matched by ISBN, file hash, and title/author regardless of path mappings.", - "noPrefixesFound": "No prefixes found - validate source first", - "selectSourcePrefix": "Select source prefix...", - "selectTargetFolder": "Select target folder...", - "remove": "Remove", - "saveMappings": "Save Mappings", - "pathValidation": { - "title": "Path validation", - "mappedSummary": "{mapped} of {total} source books have a mapped path", - "unmatched": "{count} mapped paths not found on disk", - "allMatched": "All {count} mapped paths found on disk" - } - }, - "dryRun": { - "run": "Run Dry-Run", - "matched": "Matched:", - "unresolved": "Unresolved:", - "duplicates": "Duplicates:", - "unresolvedSummary": "Unresolved summary" - }, - "duplicates": { - "title": "Resolve duplicate target matches", - "explanation": "For each target book, choose one source book to keep. Recommended choices are preselected when there is a single strongest match.", - "remainingGroups": "Remaining groups:", - "ofCount": "of {total}", - "targetBookId": "Target book #{id}", - "recommended": "Recommended", - "resolveButton": "{count, plural, =0 {Resolve # duplicate} other {Resolve # duplicates}}", - "sourceRecordId": "Source record ID #{id}", - "byAuthor": "by {author} (ID: {id})", - "byFilePath": "{filePath} (ID: {id})", - "bookloreSourceId": "Booklore source ID: {id}", - "libraryBookId": "Library book #{id}" - }, - "preflight": { - "title": "Preflight checks", - "allPassed": "All checks passed - ready to migrate", - "sourceValidated": "Source validated", - "saveAndValidateSource": "Save and validate source connection", - "validateSourceConnection": "Validate source connection", - "mappingsSaved": "Mappings saved", - "saveUserAndPathMappings": "Save user and path mappings", - "pathMappingsValidated": "Path mappings validated", - "savePathMappingsToValidate": "Save path mappings to validate them", - "dryRunUpToDate": "Dry-run is up to date", - "runFreshDryRun": "Run a fresh dry-run", - "issues": { - "saveSource": "Save source connection settings", - "validateSource": "Validate source connection", - "saveMappings": "Save user and path mappings", - "savePathMappings": "Save path mappings to validate them", - "freshDryRun": "Run a fresh dry-run", - "resolveDuplicates": "Resolve duplicate target book matches in the dry-run", - "waitForRun": "Wait for active run to finish" - } - }, - "run": { - "confirmPrompt": "This will start the live migration. Are you sure?", - "confirmStart": "Confirm Start", - "startMigration": "Start Migration", - "cancelRun": "Cancel Run", - "refreshStatus": "Refresh Status", - "pollingStopped": "Status polling stopped due to an error.", - "retry": "Retry", - "stage": "Stage: {stage}", - "initializing": "initializing", - "ended": "Ended {time}" - }, - "report": { - "noRunYet": "No migration run yet. Complete the steps above to start.", - "runNumber": "Run #{id}", - "notStarted": "Not started", - "reloadReport": "Reload Report", - "loadFullReport": "Load Full Report", - "exportJson": "Export JSON", - "exportCsv": "Export CSV", - "migrationFailed": "Migration failed", - "retryFromLastStage": "Retry from last completed stage", - "booksSection": "Books", - "metadataOverlays": "Metadata overlays applied", - "authorMappings": "Author mappings replaced", - "narratorMappings": "Narrator mappings replaced", - "genreMappings": "Genre mappings replaced", - "tagMappings": "Tag mappings replaced", - "coversImported": "Covers imported", - "coverImportSkipped": "Cover import skipped - media root path not configured", - "couldNotMatch": "Could not match", - "userDataSection": "User Data", - "readingStatuses": "Reading statuses", - "readingProgressEntries": "Reading progress entries", - "audiobookProgressEntries": "Audiobook progress entries", - "readingSessions": "Reading sessions", - "bookmarks": "Bookmarks", - "annotations": "Annotations", - "collectionEntries": "Collection entries", - "loadFullReportHint": "Click \"Load Full Report\" to include the dry-run match summary in the exported report.", - "completedNoIssues": "Migration completed with no unresolved books or failures.", - "matchedBooks": "Matched books ({count})", - "matchedBooksExplanation": "These dry-run matches were used to decide which library books received imported data.", - "sourceBook": "Source book {id}", - "libraryBook": "Library book {id}", - "unresolvedBooks": "Unresolved books ({count})", - "unresolvedBooksExplanation": "These books exist in the source but could not be matched to any book in your library.", - "mappedUsers": "Mapped users ({count})", - "mappedUsersExplanation": "Per-user totals come from the dry-run preview cached with the migration plan.", - "coverFailures": "{count} cover import(s) failed. Detailed failure rows are not stored.", - "userPreviewCounts": "{statuses} statuses, {progress} progress entries, {sessions} reading sessions, {bookmarks} bookmarks, {annotations} annotations, {collections} collection entries" - }, - "unresolvedReason": { - "noTitleAuthorMatch": "No matching book found by title or author", - "noFilePathMatch": "File path did not match any book in this library", - "noFileHashMatch": "File hash did not match any book in this library", - "noIsbnMatch": "ISBN did not match any book in this library", - "insufficientSourceData": "Not enough metadata to attempt matching", - "ambiguousIsbnMatch": "Multiple books matched the same ISBN", - "ambiguousFileHashMatch": "Multiple books matched the same file hash", - "ambiguousFilePathMatch": "Multiple books matched the same file path", - "ambiguousTitleAuthorMatch": "Multiple books matched the same title and author", - "unknown": "Could not determine reason" - }, - "matchStrategy": { - "isbn": "Matched by ISBN", - "fileHash": "Matched by file hash", - "pathMapping": "Matched by mapped file path", - "titleAuthor": "Matched by title and author", - "unavailable": "Match strategy unavailable" - }, - "connectionError": { - "unreachable": "Could not reach the database server. Check the host and port.", - "authFailed": "Authentication failed. Check the username and password.", - "databaseNotFound": "Database not found. Check the database name.", - "timeout": "Connection timed out. Check host and firewall settings.", - "generic": "Connection test failed" - }, - "userSelect": { - "placeholder": "Select user", - "noUsersFound": "No users found" - }, - "toast": { - "initFailed": "Failed to initialize migration settings", - "loadSupportedTypesFailed": "Failed to load supported migration source types", - "loadTargetUsersFailed": "Failed to load target users", - "loadTargetFoldersFailed": "Failed to load target library folders", - "noSourceUsers": "No source users were returned", - "suggestionsLoaded": "User mapping suggestions loaded", - "loadSuggestionsFailed": "Failed to load user mapping suggestions", - "sourceFieldsRequired": "Host, user, database, and source name are required", - "connectionPassedWithWarnings": "Connection test passed with warnings", - "connectionPassedWithWarningCount": "Connection test passed with {count} warning(s). First: {warning}", - "connectionPassed": "Connection test passed", - "connectionMissingTables": "Connection ok, but {count} required table(s) are missing", - "cannotTestMediaWhileRunning": "Cannot test media path while a run is active", - "mediaPathRequired": "Media Root Path is required for cover import.", - "mediaPathAbsolute": "Use an absolute path (for example: /books).", - "mediaPathVerified": "Media path verified.", - "mediaPathValid": "Media path is valid and readable", - "mediaPathValidationFailed": "Media path validation failed.", - "connectionFailedBeforeMedia": "Connection test failed before media path validation could complete.", - "cannotModifySourceWhileRunning": "Cannot modify source while a run is active", - "sourceSavedWithWarnings": "Source saved and validated with {count} warning(s)", - "sourceSaved": "Source saved and validated", - "saveSourceFailed": "Failed to save or validate source", - "cannotSaveMappingsWhileRunning": "Cannot save mappings while a run is active", - "saveSourceFirst": "Save source first", - "mapAtLeastOneUser": "Map at least one source user to a target user", - "mapEveryUser": "Map every source user before saving", - "pathValidationFailedButSaved": "Path validation failed, but profile will still be saved", - "mappingsSaved": "Mappings saved", - "saveMappingsFailed": "Failed to save mappings", - "cannotDryRunWhileRunning": "Cannot run dry-run while a run is active", - "saveMappingsFirst": "Save mappings first", - "dryRunCompleted": "Dry-run completed: {matched} matched, {unresolved} unresolved", - "dryRunFailed": "Dry-run failed", - "selectSourceForDuplicates": "Select a source book for all {count} duplicate groups", - "duplicatesResolved": "Duplicate matches resolved", - "resolveDuplicatesFailed": "Failed to resolve duplicates", - "preflightNotReady": "Migration preflight not ready", - "runDryRunFirst": "Run dry-run first", - "runStarted": "Migration run started", - "startFailed": "Failed to start migration", - "runCancelled": "Migration run cancelled", - "cancelFailed": "Failed to cancel migration", - "runRetried": "Migration run retried - resuming from last completed stage", - "retryFailed": "Failed to retry migration", - "loadProgressFailed": "Failed to load run progress", - "startMigrationFirst": "Start migration first", - "reportRefreshed": "Run report refreshed", - "loadReportFailed": "Failed to load run report", - "reportExported": "Report exported as {format}", - "exportFailed": "Failed to export migration report" - } - }, - "notifications": { - "title": "Notifications", - "markAllRead": "Mark all read", - "clear": "Clear", - "empty": "No notifications yet", - "loadMore": "Load more notifications", - "preferences": { - "title": "Notifications", - "subtitle": "Choose which notification categories you want to receive.", - "saving": "Saving...", - "unsavedChanges": "Unsaved changes", - "saved": "Notification preferences saved", - "saveFailed": "Failed to save preferences", - "savePreferenceFailed": "Failed to save preference", - "whatsNewToggle": "Show \"What's New\" after updates", - "whatsNewToggleHint": "A popup highlighting new features after the app updates. The archive stays available either way.", - "groups": { - "library": "Library", - "files": "Files", - "integrations": "Integrations", - "personal": "Personal", - "app": "App updates" - }, - "enabledCount": "{enabled} of {total} enabled", - "categories": { - "scanning": { - "label": "Library scanning", - "description": "When a library scan finishes, fails, or finds missing books." - }, - "metadata": { - "label": "Metadata fetching", - "description": "When metadata lookups for your books complete or fail." - }, - "authorEnrichment": { - "label": "Author enrichment", - "description": "When author biographies and photos finish being fetched." - }, - "fileWriteBack": { - "label": "File write-back", - "description": "When edited metadata is written back into book files on disk." - }, - "fileRename": { - "label": "File rename", - "description": "When a single book file is renamed to match your naming pattern." - }, - "bulkRename": { - "label": "Bulk rename", - "description": "When a bulk rename across many books completes or fails." - }, - "migration": { - "label": "Data migration", - "description": "When an import from another library tool completes or fails." - }, - "bookDock": { - "label": "Book Dock", - "description": "When files dropped into the dock are ready to review or finalized." - }, - "koboSync": { - "label": "Kobo sync", - "description": "When a Kobo device finishes syncing with your library." - }, - "email": { - "label": "Email delivery", - "description": "When sending a book to an email address succeeds or fails." - }, - "achievements": { - "label": "Achievements", - "description": "When you unlock a new reading achievement." - } - } - } - }, - "reader": { - "retry": "Retry", - "pdf": { - "openError": "Unable to open this PDF", - "preparing": "Preparing PDF reader", - "opening": "Opening PDF" - }, - "loadingBook": "Loading book…", - "failedToLoadBook": "Failed to load book", - "chapterNumber": "Chapter {number}", - "peek": { - "badge": "Peeking", - "startReading": "Start reading" - }, - "toast": { - "linkedHighlightError": "Could not open the linked highlight position", - "resumed": "Resumed at {pct}% - {label}" - }, - "header": { - "goBack": "Go back", - "tableOfContents": "Table of contents", - "toggleBookmark": "Toggle bookmark", - "cycleFooterMode": "Cycle footer info mode", - "keyboardShortcutsHint": "Keyboard shortcuts (?)", - "enterFullscreen": "Enter fullscreen", - "exitFullscreen": "Exit fullscreen", - "footerMode": { - "pageProgress": "Footer info: page + progress", - "sessionTimeLeft": "Footer info: reading session + time left", - "chapterTimeLeft": "Footer info: chapter + chapter time left" - } - }, - "footer": { - "previousSection": "Previous section", - "nextSection": "Next section", - "goToPlaceholder": "45 or p123", - "jumpToLocation": "Jump to location", - "jumpTooltip": "Jump to % or page (e.g. 45 or p123)", - "go": "Go" - }, - "settings": { - "title": "Settings", - "ariaLabel": "Reader settings", - "tabs": { - "appearance": "Appearance", - "text": "Text", - "layout": "Layout" - }, - "appearance": { - "mode": "Mode", - "light": "Light", - "dark": "Dark", - "colorTheme": "Color theme" - }, - "text": { - "fontSize": "Font size", - "fontSizeRange": "Range: 10-32px", - "lineHeight": "Line height", - "lineHeightRange": "Range: 0.8-3.0", - "fontFamily": "Font family", - "fontFamilyDescription": "Choose built-in or uploaded fonts for body text.", - "builtIn": "Built-in", - "yourFonts": "Your fonts" - }, - "layout": { - "pageSpreads": "Page spreads", - "pageSpreadsDescription": "Choose how this image-based EPUB pairs pages.", - "bookDefault": "Book default", - "singlePage": "Single page", - "readingFlow": "Reading flow", - "readingFlowDescription": "Switch between paged and continuous scrolling.", - "paginated": "Paginated", - "scrolled": "Scrolled", - "textColumns": "Text columns", - "textColumnsRange": "Range: 1-10", - "columnGap": "Column gap", - "columnGapRange": "Range: 0-50%", - "maxWidth": "Max width", - "maxWidthRange": "Range: 400-1600", - "justifyText": "Justify text", - "justifyTextDescription": "Enable full-width paragraph alignment.", - "hyphenation": "Hyphenation", - "hyphenationDescription": "Enable automatic word-break hyphenation." - } - }, - "search": { - "placeholder": "Search in book (min {min} chars)...", - "searching": "Searching…", - "tooShort": "Type at least {min} characters", - "noResults": "No results found", - "prompt": "Type to search", - "resultCount": "{count, plural, =0 {no results} other {# results}}" - }, - "sidebar": { - "tabs": { - "chapters": "Chapters", - "bookmarks": "Bookmarks", - "highlights": "Highlights", - "toc": "Table of contents", - "tocShort": "TOC", - "marksShort": "Marks", - "notesShort": "Notes" - }, - "pin": "Pin sidebar", - "unpin": "Unpin sidebar", - "close": "Close sidebar", - "noChapters": "No chapters found", - "noBookmarks": "No bookmarks yet", - "noBookmarksMatch": "No bookmarks match your filters", - "noHighlights": "No highlights yet", - "noHighlightsMatch": "No highlights match your filters", - "searchBookmarks": "Search bookmarks...", - "searchHighlights": "Search highlights...", - "bookmarkFallback": "Bookmark", - "locationUnavailable": "Location unavailable", - "customColor": "Custom ({color})", - "allColors": "All colors", - "allChapters": "All chapters", - "notesOnly": "Notes only", - "deleteBookmark": "Delete bookmark", - "deleteHighlight": "Delete highlight", - "approximatePosition": "Synced from device; exact position unavailable, jumps to the chapter", - "sort": { - "readingOrder": "Reading order", - "newest": "Newest first", - "oldest": "Oldest first" - } - }, - "selection": { - "copy": "Copy", - "copied": "Copied!", - "highlight": "Highlight", - "translate": "Translate", - "define": "Define", - "deleteAnnotation": "Delete annotation", - "apply": "Apply" - }, - "note": { - "title": "Add note", - "placeholder": "Write your note…" - }, - "dictionary": { - "noDefinition": "No definition found", - "loadError": "Could not load definition" - }, - "translation": { - "original": "Original", - "translation": "Translation", - "translating": "Translating...", - "noTranslation": "No translation yet", - "viaProvider": "via {provider}", - "copyTranslation": "Copy translation" - }, - "shortcuts": { - "title": "Keyboard Shortcuts", - "groups": { - "panels": "Panels", - "reading": "Reading", - "actions": "Actions" - }, - "toggleToc": "Toggle table of contents", - "toggleSearch": "Toggle search", - "toggleHelp": "Show/hide this help", - "closePanel": "Close panel", - "prevNextPage": "Previous/next page", - "goToStart": "Go to start of book", - "goToEnd": "Go to end of book", - "toggleBookmark": "Toggle bookmark", - "toggleFullscreen": "Toggle fullscreen", - "cycleFooterMode": "Cycle footer info mode" - }, - "cbz": { - "tabs": { - "view": "View", - "reading": "Reading", - "layout": "Layout" - }, - "fitMode": "Fit mode", - "background": "Background", - "scrollMode": "Scroll mode", - "scrollModeHint": "Use \"No gaps\" for webtoons and vertical strips.", - "readingDirection": "Reading direction", - "pageView": "Page view", - "autoFallback": "Auto-fallback", - "spreadAlignmentLabel": "Spread alignment", - "spreadAlignmentHint": "Spread alignment is unavailable in auto-fallback mode.", - "spreadGap": "Spread gap", - "spreadGapValue": "{value}px", - "focusTwoPageToggle": "Focus two-page toggle", - "forceTwoPage": "Force two-page", - "off": "Off", - "on": "On", - "widePages": "Wide pages", - "resetBookViewSettings": "Reset book view settings", - "resetConfirm": "Reset view settings for this book to your global defaults?", - "firstPage": "First page", - "lastPage": "Last page", - "fit": { - "page": "Page Fit", - "width": "Page Width", - "height": "Page Height", - "actual": "Actual Size" - }, - "view": { - "single": "Single", - "twoPage": "Two-page" - }, - "scroll": { - "paged": "Paged", - "infinite": "Infinite", - "noGaps": "No gaps" - }, - "direction": { - "ltr": "L to R", - "rtl": "R to L" - }, - "spreadAlignment": { - "normal": "Normal", - "shifted": "Shifted" - }, - "widePage": { - "auto": "Auto", - "inSpreads": "In spreads" - }, - "bg": { - "black": "Black", - "gray": "Gray", - "white": "White" - } - }, - "audiobook": { - "untitled": "Untitled", - "loading": "Loading audiobook...", - "loadError": "Failed to load audiobook", - "noAudioFiles": "No audio files found for this book.", - "speed": "Speed", - "chapters": "Chapters", - "bookmarks": "Bookmarks", - "volume": "Volume", - "muted": "Muted", - "sleep": "Sleep", - "chapterAbbrev": "Ch.", - "sleepTimer": "Sleep timer", - "minutes": "{count, plural, other {# minutes}}", - "endOfChapter": "End of chapter", - "noChaptersAvailable": "No chapters available", - "extend15": "+ 15 minutes", - "timeLeft": "({time} left)", - "playbackSpeed": "Playback speed", - "noChapters": "No chapters available.", - "noBookmarks": "No bookmarks yet.", - "noBookmarksHint": "Tap the bookmark icon at the top to save your current position.", - "playerSettings": "Player settings", - "skipBack": "Skip back", - "skipForward": "Skip forward" - } - }, - "scanner": { - "filesProgress": "{processed}/{total} files", - "booksFound": "{count, plural, =0 {no books found} other {# books found}}" - }, - "series": { - "completion": { - "readOfTotal": "{read} of {total} read ({percentage}%)" - }, - "gaps": { - "label": "Possible gaps:" - }, - "filters": { - "title": "Series Filters", - "clearAll": "Clear all", - "allLibraries": "All Libraries", - "allCompletion": "All completion", - "notStarted": "Not started", - "inProgress": "In progress", - "complete": "Complete" - }, - "list": { - "title": "Series", - "showControlsAria": "Show series controls", - "searchPlaceholder": "Search series or author", - "sortButton": "Sort", - "sortBy": "Sort by", - "ascending": "Ascending", - "descending": "Descending", - "ascShort": "Asc", - "descShort": "Desc", - "filters": "Filters", - "clear": "Clear", - "noMatch": "No series match your filters.", - "empty": "No series found in your libraries.", - "sort": { - "name": "Name", - "bookCount": "Book Count", - "recentAdditions": "Recent Additions", - "readingProgress": "Reading Progress" - } - }, - "detail": { - "pageTitle": "Series", - "pageTitleNamed": "Series · {name}", - "pageTitleWithId": "Series #{id}", - "entityName": "Series", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "byAuthors": "by {authors}", - "moreAuthors": "+{count} more", - "preparingEditor": "Preparing editor...", - "editMetadata": "Edit Metadata", - "firstInSeries": "First in Series", - "untitled": "Untitled", - "loadingFirstBook": "Loading first book preview...", - "showLess": "Show less", - "showMore": "Show more", - "moreGenres": "+{count} more", - "synopsis": "Synopsis", - "noDescription": "No description available.", - "updatingPreview": "Updating preview...", - "noBooksToPreview": "No books available to preview.", - "loadingSeries": "Loading series...", - "booksHeading": "Books", - "allLibraries": "All Libraries", - "groupByMedia": "Group by media", - "noBooksFound": "No books found in this series", - "trySelectingLibrary": "Try selecting another library.", - "allBooksLoaded": "All {count} books loaded", - "leadBookLoadError": "Failed to load lead book details", - "noBooksToEdit": "This series has no books to edit.", - "loadFullSeriesError": "Failed to load the full series for editing.", - "sort": { - "seriesOrder": "Series Order", - "title": "Title", - "recentlyAdded": "Recently Added" - }, - "order": { - "ascending": "Ascending", - "descending": "Descending" - } - } - }, - "smartScope": { - "syncToKobo": "Sync to Kobo", - "syncToKoboHint": "Books matching this scope will appear on your Kobo device", - "visibleToAll": "Visible to all users", - "visibleToAllHint": "Every user can see and use this smart scope", - "dialog": { - "name": "Name", - "namePlaceholder": "e.g. Unread Sci-Fi", - "icon": "Icon", - "iconPlaceholder": "Choose an icon...", - "nameRequired": "Name is required", - "iconRequired": "Choose an icon", - "create": "Create", - "creating": "Creating...", - "saving": "Saving..." - }, - "createDialog": { - "title": "New Smart Scope", - "createFailed": "Failed to create Smart Scope" - }, - "saveAsDialog": { - "title": "Save as SmartScope", - "save": "Save SmartScope", - "saveFailed": "Failed to save Smart Scope" - }, - "editorPanel": { - "untitled": "Untitled SmartScope", - "subtitle": "Configure smart scope settings", - "counting": "counting...", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "identity": "Identity", - "filters": "Filters", - "noFilters": "No filters set. All accessible books will be included in this smart scope.", - "buildFromScratch": "Build from scratch", - "replaceWithTemplate": "Replace with template:", - "defaultSort": "Default Sort", - "saveChanges": "Save changes", - "saveFailed": "Failed to save", - "templates": { - "hasSeries": "Has Series", - "addedRecently": "Added Recently", - "pdfOnly": "PDF Only", - "noGenres": "No Genres", - "epubOnly": "EPUB Only" - } - } - }, - "statistics": { - "tabs": { - "library": "Library Stats", - "user": "My Reading" - }, - "filter": { - "allLibraries": "All Libraries", - "librarySelection": "{count} of {total} Libraries" - }, - "config": { - "button": "Configure", - "title": "Configure Charts", - "description": "Drag to reorder, toggle to show or hide.", - "reset": "Reset to defaults" - }, - "summary": { - "books": "Books", - "authors": "Authors", - "series": "Series", - "publishers": "Publishers", - "storage": "Storage", - "genres": "Genres", - "languages": "Languages", - "published": "Published", - "thisYear": "This Year", - "started": "Started", - "inProgress": "In Progress", - "completed": "Completed", - "avgProgress": "Avg Progress" - }, - "card": { - "loadError": "Failed to load data", - "emptyTitle": "No data yet", - "emptyDescription": "No data available for this chart", - "unknownField": "{count, plural, =0 {no data for this field} other {# books have no data for this field}}" - }, - "breakdown": { - "ariaLabel": "Break down by source or format" - }, - "empty": { - "notEnoughData": "Not enough data yet" - }, - "charts": { - "acquisitionLag": { - "title": "Acquisition Lag" - }, - "booksAddedOverTime": { - "title": "Books Added Over Time", - "monthly": "Monthly", - "yearly": "Yearly", - "allTime": "All Time", - "last5Years": "Last 5 Years", - "lastYear": "Last Year" - }, - "formatDistribution": { - "title": "Format Distribution" - }, - "formatShareOverTime": { - "title": "Format Share Over Time" - }, - "genreCooccurrence": { - "title": "Genre Co-occurrence" - }, - "genreDistribution": { - "title": "Genre Distribution" - }, - "languageDistribution": { - "title": "Language Distribution" - }, - "largestBooks": { - "title": "Top 50 Largest Books" - }, - "libraryIntegrity": { - "title": "Library Integrity" - }, - "libraryMetadataCompleteness": { - "title": "Library Metadata Completeness" - }, - "metadataCompleteness": { - "title": "Metadata Completeness" - }, - "metadataFreshness": { - "title": "Metadata Freshness" - }, - "metadataScoreDistribution": { - "title": "Metadata Score Distribution" - }, - "pageCountDistribution": { - "title": "Page Count Distribution" - }, - "publicationDecade": { - "title": "Publication Decade" - }, - "publicationYearTimeline": { - "title": "Publication Year Timeline" - }, - "storageByFormat": { - "title": "Storage by Format" - }, - "topAuthors": { - "title": "Top 25 Authors" - }, - "topSeries": { - "title": "Top 50 Series" - }, - "booksCompleted": { - "title": "Books Completed", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "completionLatency": { - "title": "Completion Latency", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "completionTimeline": { - "title": "Completion Timeline", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "favoriteReadingDays": { - "title": "Favorite Reading Days", - "notEnoughData": "Need at least {count} reading events for this chart." - }, - "genreReadingTime": { - "title": "Genre Reading Time", - "notEnoughData": "Need at least {count} genres with reading time for this chart." - }, - "goalTrajectory": { - "title": "Pace vs Goal", - "noCompletedTitle": "No completed books yet", - "noCompletedDescription": "Complete a book in this period to compare your pace against your yearly goal.", - "notEnoughData": "Need at least {count} completed books for this chart." - }, - "peakReadingHours": { - "title": "Peak Reading Hours", - "notEnoughData": "Need at least {count} reading events for this chart." - }, - "progressFunnel": { - "title": "Progress Funnel", - "modePercent": "Percent", - "modeCounts": "Counts", - "modeDropoff": "Drop-off", - "started": "Started {count}", - "notEnoughData": "Need at least {count} started books for this chart.", - "noDropOffTitle": "No drop-off observed", - "noDropOffDescription": "Every started book progressed through all funnel stages in this period." - }, - "readingClock": { - "title": "Reading Clock", - "notEnoughData": "Need at least {count} reading sessions for this chart." - }, - "readingHeatmap": { - "title": "Reading Heatmap", - "notEnoughData": "Need activity on at least {count} days for this chart." - }, - "readingPace": { - "title": "Reading Pace", - "notEnoughData": "Need at least {count} sessions with progress data for this chart." - }, - "readingSessionTimeline": { - "title": "Reading Session Timeline", - "dragOn": "Drag: On", - "dragOff": "Drag: Off", - "prev": "Prev", - "next": "Next", - "week": "Week {week}", - "dragHint": "Drag bars to move sessions. Duration is locked and overlapping sessions are rejected.", - "noSessionsTitle": "No sessions this week", - "noSessionsDescription": "Use Prev/Next or the week selector to view a different week.", - "overlapError": "Session overlaps another session in this window", - "moveError": "Failed to move session" - }, - "sessionArchetypes": { - "title": "Session Archetypes" - }, - "sourceDistribution": { - "title": "Where You Read", - "emptyTitle": "No reading activity yet", - "emptyDescription": "Read on the web, KOReader, or Kobo to see your source split." - } - } - }, - "tools": { - "header": { - "entityManager": "Entity Manager", - "bulkRename": "Bulk Rename", - "duplicateBooks": "Duplicate Books" - }, - "entityTypes": { - "authors": "Authors", - "genres": "Genres", - "tags": "Tags", - "narrators": "Narrators", - "publishers": "Publishers", - "languages": "Languages", - "series": "Series" - }, - "bulkRename": { - "previewToolbar": "Rename preview", - "renameSettings": "Rename settings", - "library": "Library", - "selectLibraryPlaceholder": "Select a library...", - "noEligibleLibraries": "No libraries have file rename enabled. Enable it in Library Settings.", - "refresh": "Refresh", - "applyRename": "Apply Rename", - "showFullPaths": "Show full paths", - "columnsMenu": "Columns", - "renamingInProgress": "Renaming files - you can cancel at any time.", - "executionFailed": "Bulk rename failed", - "previewFailed": "Failed to load preview", - "noBooksMatch": "No books found matching the current filter.", - "openBookDetails": "Open book details", - "columns": { - "title": "Title", - "currentPath": "Current Path", - "newPath": "New Path", - "status": "Status" - }, - "status": { - "willRename": "Will Rename", - "unchanged": "Unchanged", - "collision": "Collision", - "noPattern": "No Pattern", - "error": "Error" - }, - "filter": { - "all": "All" - }, - "summary": { - "label": "Summary", - "toRename": "{count} to rename", - "unchanged": "{count} unchanged", - "collisions": "{count, plural, =0 {# collision} other {# collisions}}", - "errors": "{count, plural, =0 {# error} other {# errors}}" - }, - "empty": { - "title": "Pick a Library to Start", - "description": "Select a library above to preview rename changes, filter by status, and apply the bulk rename run.", - "chooseLibrary": "Choose Library" - }, - "completed": { - "title": "Bulk rename completed", - "stats": "{succeeded} renamed, {failed} failed, {skipped} skipped ({processed} total)" - }, - "pagination": { - "showing": "Showing {from}-{to} of {total}" - }, - "confirmDialog": { - "title": "Confirm Bulk Rename", - "body": "{count, plural, =0 {This will rename # book on disk. Files with collisions or errors will be skipped. This action cannot be undone.} other {This will rename # books on disk. Files with collisions or errors will be skipped. This action cannot be undone.}}", - "renameButton": "{count, plural, =0 {Rename # book} other {Rename # books}}" - } - }, - "bookDuplicates": { - "scanSettings": "Scan settings", - "title": "Duplicate Books", - "description": "Scan files and metadata for potential duplicate records. Nothing is deleted during a scan.", - "scope": "Library scope", - "allLibraries": "All accessible libraries", - "similarity": "Similar-title threshold", - "explainSimilarity": "Explain the similar-title threshold", - "similarityHelp": "Only for Similar title and author matches. At least one author and the book type must also match. Lower finds more possible duplicates; higher requires closer titles. Identical files, ISBN, and exact metadata are checked separately.", - "runScan": "Run scan", - "rescan": "Rescan", - "status": { - "queued": "Scan queued", - "running": "Scanning books" - }, - "groupsFound": "{count, plural, =0 {No duplicate groups} other {# duplicate groups}}", - "filter": "Match type", - "allReasons": "All match types", - "reasons": { - "file_hash": "Identical file set", - "isbn": "Same ISBN", - "exact_metadata": "Exact title and authors", - "fuzzy_metadata": "Similar title and author" - }, - "similarityValue": "{percent}% title similarity", - "notDuplicates": "Not duplicates", - "keepThis": "Keep this book", - "discardThis": "Discard this book", - "selectKeeperFirst": "Select a keeper first", - "noDirectMatch": "No direct match with keeper", - "moreFiles": "+{count} more", - "showDetails": "Show details", - "hideDetails": "Hide details", - "deleteSelected": "Delete {count} selected", - "openBook": "Open details for {title}", - "unknownAuthor": "Unknown author", - "unknown": "Unknown", - "none": "None", - "accessDenied": "You do not have permission to use the duplicate book tool.", - "pairDetails": "Match details", - "pairLabel": "{first} and {second}", - "fields": { - "library": "Library", - "isbn": "ISBN", - "formats": "Formats", - "fileLocation": "File", - "files": "Files", - "readingStatus": "Reading status", - "progress": "Progress", - "path": "Library path", - "collections": "Collections", - "added": "Added", - "updated": "Updated" - }, - "initial": { - "title": "Find duplicate books", - "description": "Choose a library scope and similarity level, then run a scan. No books are changed until you explicitly confirm a deletion." - }, - "empty": { - "title": "No duplicate groups found", - "description": "No books matched the current scope, similarity level, and match filter." - }, - "deleteDialog": { - "title": "Permanently delete duplicate books?", - "description": "{count, plural, =0 {This will permanently delete # selected book and its files.} other {This will permanently delete # selected books and their files.}}", - "warning": "Metadata, collections, reading data, and device state are not transferred to the kept book. Associated data for other users is also removed.", - "confirm": "{count, plural, =0 {Delete # book} other {Delete # books}}", - "success": "{count, plural, =0 {No books deleted} other {# duplicate books deleted}}" - }, - "errors": { - "start": "Could not start the duplicate scan.", - "status": "Could not load scan progress.", - "scan": "The duplicate scan failed. Try running it again.", - "results": "Could not load duplicate groups.", - "delete": "Could not delete the selected duplicate books." - }, - "pagination": { - "label": "Duplicate groups pages", - "page": "Page {page} of {total}" - } - }, - "entityManager": { - "unknown": "Unknown", - "bookCount": "{count, plural, =0 {no books} other {# books}}", - "sortPrefix": "· sort: {sortName}", - "selectTargetToKeep": "Select target to keep", - "writeToFiles": "Write to files", - "writeChangesToFiles": "Write changes to files", - "mergeIntoTarget": "Merge {count} into target", - "modes": { - "browse": "Browse & Manage", - "duplicates": "Find Duplicates" - }, - "actions": { - "rename": "Rename", - "split": "Split" - }, - "duplicates": { - "similarity": "Similarity:", - "scan": "Scan", - "scanning": "Scanning...", - "computing": "Computing candidates...", - "computedAt": "Candidates computed {date}", - "recompute": "Recompute", - "noneComputed": "No candidates computed yet.", - "computeNow": "Compute now", - "emptyTitle": "Find duplicate entities", - "emptyDescription": "Adjust the similarity threshold and click Scan to detect potential duplicates.", - "noneFoundTitle": "No duplicates found", - "noneFoundDescription": "No potential duplicates were detected with the current settings.", - "clustersFound": "{count, plural, =0 {no clusters found} other {# clusters found}}", - "plusOthers": "{count, plural, =0 {+ # other} other {+ # others}}", - "percentSimilar": "{percent}% similar", - "pairDetails": "Pair details", - "dismissEntityTitle": "Dismiss all pairs for this entity", - "dismissPairTitle": "Dismiss this pair" - }, - "dismissed": { - "loading": "Loading dismissed pairs...", - "empty": "No dismissed pairs", - "restore": "Restore", - "restoreTitle": "Restore this pair", - "hidePairs": "Hide dismissed pairs", - "showPairs": "Show dismissed pairs" - }, - "browse": { - "searchPlaceholder": "Search...", - "emptyOnly": "Empty only", - "clear": "Clear", - "noEntities": "No entities found", - "mergeCount": "Merge ({count})", - "deleteCount": "Delete ({count})", - "totalCount": "{count} total", - "sortLabel": "sort: {sortName}", - "sort": { - "nameAsc": "Name A-Z", - "nameDesc": "Name Z-A", - "fewestBooks": "Fewest books", - "mostBooks": "Most books" - } - }, - "deleteMode": { - "label": "Delete mode", - "softTitle": "Soft delete", - "softDescription": "Unlink from all books but keep the entity record", - "softDescriptionPlural": "Unlink from all books but keep the entity records", - "hardTitle": "Hard delete", - "hardDescription": "Remove entity and all associations permanently", - "hardDescriptionPlural": "Remove entities and all associations permanently" - }, - "renameModal": { - "title": "Rename Entity", - "currentName": "Current name", - "newName": "New name" - }, - "deleteModal": { - "title": "Delete Entity", - "confirm": "Are you sure you want to delete {name}?" - }, - "splitModal": { - "title": "Split Entity", - "splitting": "Splitting", - "newNames": "New names (min 2)", - "namePlaceholder": "Enter name...", - "addAnother": "Add another" - }, - "bulkDeleteModal": { - "title": "Bulk Delete", - "confirm": "{count, plural, =0 {Are you sure you want to delete # selected entity?} other {Are you sure you want to delete # selected entities?}}", - "deleteButton": "Delete {count}" - }, - "mergeModal": { - "title": "Merge Entities", - "description": "Select which entity to keep. The others will be merged into it and removed." - } - } - }, - "views": { - "entity": { - "book": "Book", - "collection": "Collection", - "library": "Library", - "smartScope": "SmartScope" - }, - "common": { - "retry": "Retry" - }, - "bookView": { - "sort": "Sort", - "sortOn": "On", - "resetSort": "Reset sort to default", - "filters": "Filters", - "clear": "Clear", - "clearAllFilters": "Clear all filters", - "expandSeries": "Expand series", - "collapseSeries": "Collapse series", - "expanded": "Expanded", - "exportMetadata": "Export metadata", - "showControlsAria": "Show library controls", - "export": "Export", - "searchPlaceholder": "Search title, author, series, narrator...", - "allBooksLoaded": "All {count} books loaded" - }, - "notFound": { - "title": "Page not found", - "description": "The page you're looking for doesn't exist.", - "goHome": "Go home" - }, - "dashboard": { - "customize": "Customize dashboard", - "allShelvesHidden": "All shelves are hidden.", - "greeting": { - "night": "Good night,", - "morning": "Good morning,", - "afternoon": "Good afternoon,", - "evening": "Good evening,", - "fallbackName": "there" - } - }, - "bookDetail": { - "title": "Book", - "titleWithId": "Book #{id}", - "pageTitle": { - "book": "Book · {base}", - "editMetadata": "Edit Metadata · {base}", - "edit": "Edit · {base}", - "files": "Files · {base}", - "readingLog": "Reading Log · {base}", - "highlights": "Highlights · {base}" - } - }, - "bookDock": { - "title": "Book Dock", - "newFilesDetected": "New files detected", - "reconnecting": "Reconnecting", - "rescanFailed": "Rescan failed", - "totalInDock": "{size} in Book Dock", - "dropFiles": "Drop files into Book Dock", - "supportedFormats": "Supported: {formats}", - "empty": { - "noSearchMatch": "No files match \"{query}\"", - "noStatusFiles": "No {status} files", - "uploadPrompt": "Upload files or drop them in the Book Dock folder" - }, - "retry": { - "noneToRetry": "No error files to retry", - "retrying": "{count, plural, =0 {Retrying one file} other {Retrying # files}}" - }, - "applyFetched": { - "applied": "{count, plural, =0 {Applied to no files} other {Applied to # files}}", - "skippedEdited": "{count, plural, =0 {skipped one file because they have manual edits} other {skipped # files because they have manual edits}}", - "skippedNoMetadata": "{count, plural, =0 {skipped one file because they have no fetched metadata} other {skipped # files because they have no fetched metadata}}", - "noneApplied": "No files applied; {reasons}", - "noneSelected": "No files selected" - } - }, - "collection": { - "title": "Collection", - "pageTitle": "Collection · {name}", - "pageTitleWithId": "Collection #{id}", - "editCollection": "Edit collection", - "showControlsAria": "Show collection controls", - "loadError": "Could not load this collection", - "toast": { - "removed": "{count, plural, =0 {Removed no books from collection} other {Removed # books from collection}}", - "removeFailed": "Failed to remove books from collection" - }, - "empty": { - "noSearchMatch": "No books match this search", - "noSearchMatchHint": "Try a different search term or clear the search.", - "noBooks": "No books in this collection", - "noBooksHint": "Select books from your library and add them here." - } - }, - "library": { - "title": "Library", - "pageTitle": "Library · {name}", - "pageTitleWithId": "Library #{id}", - "filterRules": "Filter rules", - "saveAsSmartScope": "Save as Smart Scope", - "saveScope": "Save Scope", - "saveAsSmartScopeTooltip": "Save this filter as a named Smart Scope", - "saved": "Saved", - "saveFilter": "Save filter", - "filterSaved": "Filter saved", - "saveFilterTooltip": "Save filter for this library", - "removeSavedFilter": "Remove saved filter", - "empty": { - "noFilterMatch": "No books match your filters", - "noFilterMatchHint": "Try adjusting or clearing your filters to see more books.", - "clearFilters": "Clear filters", - "scanning": "Scanning your library...", - "scanningHint": "Books will appear here as they are discovered.", - "emptyLibrary": "Your library is empty", - "emptyLibraryHint": "Once you add books to this library, they will appear here." - }, - "querySelection": { - "loadedSelected": "{selected} of {total} loaded books selected.", - "selectAllMatching": "Select all {total} matching books" - } - }, - "smartScope": { - "title": "SmartScope", - "pageTitle": "SmartScope · {name}", - "pageTitleWithId": "SmartScope #{id}", - "defaultName": "Smart scope", - "filter": "Filter", - "edit": "Edit Smart Scope", - "koboSync": { - "label": "Sync to my Kobo", - "enabledHint": "Books in this shared Smart Scope sync to your Kobo device. Turn off to stop syncing them.", - "disabledHint": "Turn on to sync books in this shared Smart Scope to your Kobo device." - }, - "showControlsAria": "Show Smart Scope controls", - "hideFilter": "Hide filter", - "showFilter": "Show filter", - "confirmDelete": "Confirm?", - "loadError": "Could not load this SmartScope", - "toast": { - "deleted": "\"{name}\" deleted", - "deleteFailed": "Failed to delete \"{name}\"", - "koboSyncEnabled": "\"{name}\" now syncs to your Kobo", - "koboSyncDisabled": "\"{name}\" no longer syncs to your Kobo", - "koboSyncFailed": "Failed to update Kobo sync for \"{name}\"" - }, - "empty": { - "noRules": "No rules configured", - "noRulesHint": "Open the editor to define which books appear in this smartScope using filters and sort rules.", - "configure": "Configure SmartScope", - "noMatch": "No books match this smartScope", - "noMatchHint": "Try adjusting the filter rules.", - "edit": "Edit SmartScope" - } - } - }, - "whatsNew": { - "title": "What's New", - "subtitle": "Everything that's shipped, newest first.", - "versionPrefix": "Version {version}", - "newUpdates": "{count, plural, =0 {no new updates} other {# new updates}}", - "remindLater": "Remind me later", - "gotIt": "Got it", - "latest": "Latest", - "fullChangelog": "Full changelog", - "seeAllReleases": "See all releases", - "versions": "Versions", - "currentVersion": "Current version", - "youreHere": "You're here", - "searchPlaceholder": "Search releases…", - "noReleasesFound": "No releases found.", - "noHighlights": "No highlights for this release.", - "showChangelog": "Show full changelog", - "hideChangelog": "Hide full changelog", - "openOnGitHub": "Open on GitHub", - "loadMore": "Load more", - "loadingMore": "Loading…", - "loadFailed": "Failed to load releases", - "loadMoreFailed": "Could not load more releases. Please try again.", - "loadErrorHint": "Couldn't load releases. Check your connection and try again.", - "retry": "Retry", - "imageViewer": "Image viewer", - "closeImage": "Close image", - "previousImage": "Previous image", - "nextImage": "Next image" - }, - "titles": { - "dashboard": "Dashboard", - "libraries": "Libraries", - "opds": "OPDS", - "koboSync": "Kobo Sync", - "koreaderSync": "KOReader Sync", - "bookDock": "Book Dock", - "whatsNew": "What's New", - "annotations": "Annotations", - "achievements": "Achievements", - "statistics": "Statistics", - "authors": "Authors", - "series": "Series", - "entityManager": "Entity Manager", - "bulkRename": "Bulk Rename", - "duplicateBooks": "Duplicate Books", - "notFound": "Not Found", - "signIn": "Sign In", - "initialSetup": "Initial Setup", - "forgotPassword": "Forgot Password", - "resetPassword": "Reset Password", - "completingSignIn": "Completing Sign In", - "magicLinkLogin": "Magic Link Login", - "readPrefix": "Read", - "emailSuffix": "Email", - "library": "Library", - "smartScope": "SmartScope", - "collection": "Collection", - "author": "Author", - "book": "Book", - "seriesItem": "Series", - "appearance": { - "theme": "Display", - "book-covers": "Book Covers", - "icons": "Icons", - "layout": "Display Layout", - "behavior": "Library Behavior" - }, - "reader": { - "general": "Reader Settings", - "ebook": "eBook Reader", - "pdf": "PDF Reader", - "comics": "Comics Reader", - "audio": "Audiobook Player", - "fonts": "Reader Fonts" - }, - "email": { - "providers": "Providers", - "recipients": "Recipients", - "groups": "Groups", - "templates": "Templates", - "preferences": "Preferences", - "history": "History" - }, - "metadata": { - "providers": "Providers", - "field-rules": "Field-Level Rules", - "custom-fields": "Custom Metadata", - "genre-blocklist": "Genre Blocklist", - "score": "Confidence Score", - "auto-fetch": "Book Auto-Fetch", - "authors": "Author Auto-Fetch" - }, - "admin": { - "users": "Users", - "account-activity": "Account Activity", - "magic-links": "Magic Links", - "oidc": "OIDC / SSO" - }, - "system": { - "file-naming": "File Naming", - "book-dock": "Book Dock", - "maintenance": "Maintenance", - "audit-log": "Audit Log" - }, - "account": { - "profile": "Account", - "privacy": "Privacy & Sharing", - "notifications": "Notifications", - "restrictions": "Content Restrictions" - }, - "smartScopes": "Smart Scopes", - "collections": "Collections" - } -} diff --git a/client/src/stores/__tests__/locale.spec.ts b/client/src/stores/__tests__/locale.spec.ts index 0b25e0206..630066b71 100644 --- a/client/src/stores/__tests__/locale.spec.ts +++ b/client/src/stores/__tests__/locale.spec.ts @@ -42,8 +42,6 @@ describe('locale store', () => { expect(matchSupportedLocale(['cs-CZ', 'en-GB'])).toBe('cs') expect(matchSupportedLocale(['da-DK', 'en-GB'])).toBe('da') expect(matchSupportedLocale(['fi-FI', 'en-GB'])).toBe('fi') - expect(matchSupportedLocale(['hu-HU', 'en-GB'])).toBe('hu') - expect(matchSupportedLocale(['ko-KR', 'en-GB'])).toBe('ko') expect(matchSupportedLocale(['sv-SE', 'en-GB'])).toBe('sv') expect(matchSupportedLocale(['sv-FI', 'en-GB'])).toBe('sv') }) diff --git a/crowdin.yml b/crowdin.yml index 2f322ebab..6064daf9c 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -7,9 +7,7 @@ export_languages: - es-ES - fi - fr - - hu - it - - ko - nl - pl - pt-BR diff --git a/docs/LOCALIZATION.md b/docs/LOCALIZATION.md index 381654977..3df514951 100644 --- a/docs/LOCALIZATION.md +++ b/docs/LOCALIZATION.md @@ -13,9 +13,7 @@ BookOrbit uses Vue I18n catalogs under `client/src/locales/`. English is the sou | Spanish | `es-ES` | `es.json` | | Finnish | `fi` | `fi.json` | | French | `fr` | `fr.json` | -| Hungarian | `hu` | `hu.json` | | Italian | `it` | `it.json` | -| Korean | `ko` | `ko.json` | | Dutch | `nl` | `nl.json` | | Polish | `pl` | `pl.json` | | Brazilian Portuguese | `pt-BR` | `pt.json` | @@ -89,9 +87,11 @@ After an English source change reaches `main`: 2. Translators update target strings in Crowdin. 3. Crowdin exports the target catalogs to `l10n_main`. 4. Crowdin opens a pull request to `main`. -5. CI verifies that the pull request changes only the seventeen target catalogs and runs the normal client checks. +5. CI verifies that the pull request changes only the fifteen target catalogs and runs the normal client checks. 6. A maintainer reviews and squash-merges the pull request. -7. The `l10n_main` service branch is deleted. Crowdin recreates it for the next export. +7. The `.github/workflows/crowdin-branch-cleanup.yml` workflow deletes the `l10n_main` service branch. Crowdin recreates it from the current `main` for the next export. + +Deleting that branch is required, not tidiness. Crowdin appends every export to the same service branch and never rebases it, so a branch that outlives its pull request keeps its original merge base. Each later export then diverges further from `main` and eventually conflicts on every catalog. The workflow runs when a pull request from `l10n_main` is closed as well as merged, because Crowdin reuses the branch either way. Crowdin pull requests must retain the configured `i18n(client)` title and commit format. The `i18n` commit type produces a patch release and an Internationalization release-note section. Crowdin's default `[ci skip]` commit suffix is disabled so pull-request validation runs before merge. diff --git a/packages/types/src/locale.ts b/packages/types/src/locale.ts index b92f9e7f7..ae63cd625 100644 --- a/packages/types/src/locale.ts +++ b/packages/types/src/locale.ts @@ -1,23 +1,4 @@ -export const SUPPORTED_LOCALES = [ - "en", - "cs", - "da", - "de", - "es", - "fi", - "fr", - "hu", - "it", - "ko", - "nl", - "pl", - "pt", - "ru", - "sl", - "sv", - "uk", - "zh", -] as const; +export const SUPPORTED_LOCALES = ["en", "cs", "da", "de", "es", "fi", "fr", "it", "nl", "pl", "pt", "ru", "sl", "sv", "uk", "zh"] as const; export type Locale = (typeof SUPPORTED_LOCALES)[number]; export const DEFAULT_LOCALE: Locale = "en"; @@ -31,9 +12,7 @@ export const LOCALE_LABELS: Record = { es: "Español", fi: "Suomi", fr: "Français", - hu: "Magyar", it: "Italiano", - ko: "한국어", nl: "Nederlands", pl: "Polski", pt: "Português", @@ -52,9 +31,7 @@ export const LOCALE_DIRECTIONS: Record = { es: "ltr", fi: "ltr", fr: "ltr", - hu: "ltr", it: "ltr", - ko: "ltr", nl: "ltr", pl: "ltr", pt: "ltr", diff --git a/scripts/classify-crowdin-pr.sh b/scripts/classify-crowdin-pr.sh index 968bb7b3e..b8ef3793f 100755 --- a/scripts/classify-crowdin-pr.sh +++ b/scripts/classify-crowdin-pr.sh @@ -25,9 +25,7 @@ allowed_paths=( "client/src/locales/es.json" "client/src/locales/fi.json" "client/src/locales/fr.json" - "client/src/locales/hu.json" "client/src/locales/it.json" - "client/src/locales/ko.json" "client/src/locales/nl.json" "client/src/locales/pl.json" "client/src/locales/pt.json"