mirror of
https://github.com/booklore-app/booklore.git
synced 2026-02-18 00:17:53 +01:00
fix(i18n): align translation keys in metadata viewer, searcher, sidecar, and tabs components (EN/ES)
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<div class="search-field search-field-provider">
|
||||
<label>
|
||||
<i class="pi pi-globe"></i>
|
||||
{{ t('providers') }}
|
||||
{{ t('providersLabel') }}
|
||||
</label>
|
||||
<p-multiselect
|
||||
[filter]="false"
|
||||
@@ -29,7 +29,7 @@
|
||||
<div class="search-field">
|
||||
<label>
|
||||
<i class="pi pi-barcode"></i>
|
||||
{{ t('isbn') }}
|
||||
{{ t('isbnLabel') }}
|
||||
<i
|
||||
class="pi pi-info-circle"
|
||||
[pTooltip]="t('isbnTooltip')"
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="search-field">
|
||||
<label>
|
||||
<i class="pi pi-book"></i>
|
||||
{{ t('title') }}
|
||||
{{ t('titleLabel') }}
|
||||
</label>
|
||||
<input
|
||||
pInputText
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="search-field">
|
||||
<label>
|
||||
<i class="pi pi-user"></i>
|
||||
{{ t('author') }}
|
||||
{{ t('authorLabel') }}
|
||||
</label>
|
||||
<input
|
||||
pInputText
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
<div class="search-field search-button-field">
|
||||
<p-button
|
||||
[label]="t('search')"
|
||||
[label]="t('searchBtn')"
|
||||
type="submit"
|
||||
[disabled]="!isSearchEnabled || loading"
|
||||
icon="pi pi-search"
|
||||
@@ -128,7 +128,7 @@
|
||||
<i class="pi pi-search"></i>
|
||||
</div>
|
||||
<h3>{{ t('readyToSearch') }}</h3>
|
||||
<p>{{ t('readyToSearchDescription') }}</p>
|
||||
<p>{{ t('readyToSearchHint') }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
<i class="pi pi-inbox"></i>
|
||||
</div>
|
||||
<h3>{{ t('noResultsFound') }}</h3>
|
||||
<p>{{ t('noResultsDescription') }}</p>
|
||||
<p>{{ t('noResultsHint') }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
loading="lazy"/>
|
||||
<div class="card-overlay">
|
||||
<i class="pi pi-eye"></i>
|
||||
<span>{{ t('select') }}</span>
|
||||
<span>{{ t('selectOverlay') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
@if (isPhysicalBook()) {
|
||||
<div class="empty-state">
|
||||
<i class="pi pi-book empty-state-icon"></i>
|
||||
<h4 class="empty-state-title">{{ t('physicalBook') }}</h4>
|
||||
<h4 class="empty-state-title">{{ t('physicalBookTitle') }}</h4>
|
||||
<p class="empty-state-message">{{ t('physicalBookMessage') }}</p>
|
||||
<p class="empty-state-hint">{{ t('physicalBookHint') }}</p>
|
||||
</div>
|
||||
@@ -151,7 +151,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('read')"
|
||||
[pTooltip]="t('readTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id)">
|
||||
</p-button>
|
||||
@@ -160,7 +160,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="info"
|
||||
[pTooltip]="t('streamingReader')"
|
||||
[pTooltip]="t('streamingReaderTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, 'pdf-streaming')">
|
||||
</p-button>
|
||||
@@ -170,7 +170,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('read')"
|
||||
[pTooltip]="t('readTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id)">
|
||||
</p-button>
|
||||
@@ -179,7 +179,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="info"
|
||||
[pTooltip]="t('streamingReader')"
|
||||
[pTooltip]="t('streamingReaderTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, 'epub-streaming')">
|
||||
</p-button>
|
||||
@@ -189,7 +189,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('read')"
|
||||
[pTooltip]="t('readTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id)">
|
||||
</p-button>
|
||||
@@ -199,7 +199,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('play')"
|
||||
[pTooltip]="t('playTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id)">
|
||||
</p-button>
|
||||
@@ -209,7 +209,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="success"
|
||||
[pTooltip]="t('download')"
|
||||
[pTooltip]="t('downloadTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="download(book)">
|
||||
</p-button>
|
||||
@@ -218,7 +218,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="danger"
|
||||
[pTooltip]="t('delete')"
|
||||
[pTooltip]="t('deleteTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="deleteFile(book, book.primaryFile!.id, book.primaryFile!.fileName || 'file', true)">
|
||||
</p-button>
|
||||
@@ -247,7 +247,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('read')"
|
||||
[pTooltip]="t('readTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, undefined, format.bookType)">
|
||||
</p-button>
|
||||
@@ -256,7 +256,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="info"
|
||||
[pTooltip]="t('streamingReader')"
|
||||
[pTooltip]="t('streamingReaderTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, format.bookType === 'PDF' ? 'pdf-streaming' : 'epub-streaming', format.bookType)">
|
||||
</p-button>
|
||||
@@ -266,7 +266,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('read')"
|
||||
[pTooltip]="t('readTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, undefined, format.bookType)">
|
||||
</p-button>
|
||||
@@ -276,7 +276,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="primary"
|
||||
[pTooltip]="t('play')"
|
||||
[pTooltip]="t('playTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="read(book.id, undefined, format.bookType)">
|
||||
</p-button>
|
||||
@@ -286,7 +286,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="success"
|
||||
[pTooltip]="t('download')"
|
||||
[pTooltip]="t('downloadTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="downloadAdditionalFile(book, format.id)">
|
||||
</p-button>
|
||||
@@ -295,7 +295,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="danger"
|
||||
[pTooltip]="t('delete')"
|
||||
[pTooltip]="t('deleteTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="deleteFile(book, format.id, format.fileName || 'file', false)">
|
||||
</p-button>
|
||||
@@ -322,7 +322,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="success"
|
||||
[pTooltip]="t('download')"
|
||||
[pTooltip]="t('downloadTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="downloadAdditionalFile(book, file.id)">
|
||||
</p-button>
|
||||
@@ -331,7 +331,7 @@
|
||||
size="small"
|
||||
text
|
||||
severity="danger"
|
||||
[pTooltip]="t('delete')"
|
||||
[pTooltip]="t('deleteTooltip')"
|
||||
tooltipPosition="top"
|
||||
(onClick)="deleteSupplementary(book.id, file.id, file.fileName || 'file')">
|
||||
</p-button>
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
<div class="tags-section">
|
||||
@if (book?.metadata?.categories?.length) {
|
||||
<div class="tag-row">
|
||||
<span class="tag-label">{{ t('genres') }}</span>
|
||||
<span class="tag-label">{{ t('genresLabel') }}</span>
|
||||
<div class="tag-scroll">
|
||||
<div class="tag-container">
|
||||
@for (category of book.metadata!.categories; track category) {
|
||||
@@ -285,7 +285,7 @@
|
||||
|
||||
@if (book?.metadata?.moods?.length) {
|
||||
<div class="tag-row">
|
||||
<span class="tag-label">{{ t('moods') }}</span>
|
||||
<span class="tag-label">{{ t('moodsLabel') }}</span>
|
||||
<div class="tag-scroll">
|
||||
<div class="tag-container">
|
||||
@for (mood of book.metadata!.moods; track mood) {
|
||||
@@ -300,7 +300,7 @@
|
||||
|
||||
@if (book?.metadata?.tags?.length) {
|
||||
<div class="tag-row">
|
||||
<span class="tag-label">{{ t('tags') }}</span>
|
||||
<span class="tag-label">{{ t('tagsLabel') }}</span>
|
||||
<div class="tag-scroll">
|
||||
<div class="tag-container">
|
||||
@for (tag of book.metadata!.tags; track tag) {
|
||||
@@ -316,7 +316,7 @@
|
||||
|
||||
<div class="metadata-grid">
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('library') }}</span>
|
||||
<span class="metadata-key">{{ t('libraryLabel') }}</span>
|
||||
@if (book?.libraryName) {
|
||||
<span class="metadata-value metadata-link" (click)="goToLibrary(book.libraryId!)">
|
||||
{{ book?.libraryName }}
|
||||
@@ -327,7 +327,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('publisher') }}</span>
|
||||
<span class="metadata-key">{{ t('publisherLabel') }}</span>
|
||||
@if (book?.metadata?.publisher) {
|
||||
<span class="metadata-value metadata-link" (click)="goToPublisher(book?.metadata?.publisher!)">
|
||||
{{ book?.metadata?.publisher }}
|
||||
@@ -338,7 +338,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('published') }}</span>
|
||||
<span class="metadata-key">{{ t('publishedLabel') }}</span>
|
||||
@if (book?.metadata!.publishedDate) {
|
||||
<span class="metadata-value metadata-link" (click)="goToPublishedYear(book?.metadata!.publishedDate!)">
|
||||
{{ book?.metadata!.publishedDate }}
|
||||
@@ -349,7 +349,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('language') }}</span>
|
||||
<span class="metadata-key">{{ t('languageLabel') }}</span>
|
||||
@if (book?.metadata!.language) {
|
||||
<span class="metadata-value metadata-link" (click)="goToLanguage(book?.metadata!.language!)">
|
||||
{{ book?.metadata!.language }}
|
||||
@@ -360,14 +360,14 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('formats') }}</span>
|
||||
<span class="metadata-key">{{ t('formatsLabel') }}</span>
|
||||
<span class="metadata-value-group format-tags">
|
||||
@if (getDisplayFormat(book?.primaryFile); as displayFormat) {
|
||||
<span class="format-tag-wrapper primary-format" (click)="goToFileType(book?.primaryFile?.filePath)" [pTooltip]="book?.primaryFile?.fileName ?? ''" tooltipPosition="top">
|
||||
<app-tag size="3xs" variant="pill" [customBgColor]="getFileTypeBgColor(displayFormat)" customTextColor="#fff">
|
||||
{{ displayFormat }}
|
||||
</app-tag>
|
||||
<span class="format-badge">{{ t('primary') }}</span>
|
||||
<span class="format-badge">{{ t('primaryBadge') }}</span>
|
||||
</span>
|
||||
}
|
||||
@for (formatExt of getUniqueAlternativeFormats(book); track formatExt) {
|
||||
@@ -378,13 +378,13 @@
|
||||
</span>
|
||||
}
|
||||
@if (!book?.primaryFile?.filePath && !book?.alternativeFormats?.length) {
|
||||
<app-tag size="3xs" variant="pill" [customBgColor]="'var(--book-type-physical-color)'" customTextColor="#fff">{{ t('physical') }}</app-tag>
|
||||
<app-tag size="3xs" variant="pill" [customBgColor]="'var(--book-type-physical-color)'" customTextColor="#fff">{{ t('physicalBadge') }}</app-tag>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('bookloreProgress') }}</span>
|
||||
<span class="metadata-key">{{ t('bookloreProgressLabel') }}</span>
|
||||
<span class="metadata-value-group">
|
||||
<app-tag size="3xs" variant="pill" [color]="getProgressColor(getProgressPercent(book))">
|
||||
{{ getProgressPercent(book) !== null ? getProgressPercent(book) + '%' : 'N/A' }}
|
||||
@@ -405,7 +405,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('metadataMatch') }}</span>
|
||||
<span class="metadata-key">{{ t('metadataMatchLabel') }}</span>
|
||||
@if (book?.metadataMatchScore != null) {
|
||||
<span (click)="goToMatchScoreRange(book?.metadataMatchScore!)" style="cursor: pointer;">
|
||||
<app-tag size="3xs" variant="pill" [color]="getMatchScoreColor(book?.metadataMatchScore!)">
|
||||
@@ -433,7 +433,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('readStatus') }}</span>
|
||||
<span class="metadata-key">{{ t('readStatusLabel') }}</span>
|
||||
<span class="metadata-value-group">
|
||||
<span (click)="goToReadStatus(selectedReadStatus)" style="cursor: pointer;">
|
||||
<app-tag size="3xs" variant="pill" [color]="getStatusColor(selectedReadStatus)">
|
||||
@@ -447,7 +447,7 @@
|
||||
|
||||
@if (book?.koreaderProgress && book.koreaderProgress?.percentage != null) {
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('koreaderProgress') }}</span>
|
||||
<span class="metadata-key">{{ t('koreaderProgressLabel') }}</span>
|
||||
<span class="metadata-value-group">
|
||||
<app-tag size="3xs" variant="pill" [color]="getKoProgressColor(getKOReaderPercentage(book))">
|
||||
{{ getKOReaderPercentage(book) + '%' }}
|
||||
@@ -468,7 +468,7 @@
|
||||
|
||||
@if (book?.koboProgress && book.koboProgress?.percentage != null) {
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('koboProgress') }}</span>
|
||||
<span class="metadata-key">{{ t('koboProgressLabel') }}</span>
|
||||
<span class="metadata-value-group">
|
||||
<app-tag size="3xs" variant="pill" [color]="getKoProgressColor(book.koboProgress?.percentage)">
|
||||
{{ book.koboProgress?.percentage | number:'1.0-1' }}%
|
||||
@@ -490,7 +490,7 @@
|
||||
@if (selectedReadStatus === ReadStatus.READ) {
|
||||
<div class="metadata-item">
|
||||
@if (book?.dateFinished) {
|
||||
<span class="metadata-key">{{ t('finishedOn') }}</span>
|
||||
<span class="metadata-key">{{ t('finishedOnLabel') }}</span>
|
||||
@if (!isEditingDateFinished) {
|
||||
<span class="metadata-value-group">
|
||||
<span class="metadata-value">{{ formatDate(book.dateFinished) }}</span>
|
||||
@@ -515,7 +515,7 @@
|
||||
}
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('pageCount') }}</span>
|
||||
<span class="metadata-key">{{ t('pageCountLabel') }}</span>
|
||||
@if (book?.metadata!.pageCount) {
|
||||
<span class="metadata-value metadata-link" (click)="goToPageCountRange(book?.metadata!.pageCount!)">
|
||||
{{ book?.metadata!.pageCount }}
|
||||
@@ -526,7 +526,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('ageRating') }}</span>
|
||||
<span class="metadata-key">{{ t('ageRatingLabel') }}</span>
|
||||
@if (book?.metadata?.ageRating != null) {
|
||||
<span class="metadata-value metadata-link" (click)="goToAgeRating(book?.metadata?.ageRating!)">
|
||||
{{ getAgeRatingLabel(book?.metadata?.ageRating) }}
|
||||
@@ -537,7 +537,7 @@
|
||||
</div>
|
||||
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('contentRating') }}</span>
|
||||
<span class="metadata-key">{{ t('contentRatingLabel') }}</span>
|
||||
@if (book?.metadata?.contentRating) {
|
||||
<span class="metadata-value metadata-link" (click)="goToContentRating(book?.metadata?.contentRating!)">
|
||||
{{ getContentRatingLabel(book?.metadata?.contentRating) }}
|
||||
@@ -549,7 +549,7 @@
|
||||
|
||||
@if (hasDigitalFile(book)) {
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-key">{{ t('fileSize') }}</span>
|
||||
<span class="metadata-key">{{ t('fileSizeLabel') }}</span>
|
||||
@if (book?.primaryFile?.fileSizeKb) {
|
||||
<span class="metadata-value metadata-link" (click)="goToFileSizeRange(book?.primaryFile?.fileSizeKb!)">
|
||||
{{ formatFileSize(book?.primaryFile) }}
|
||||
@@ -563,7 +563,7 @@
|
||||
|
||||
@if (hasDigitalFile(book)) {
|
||||
<div class="file-path-section">
|
||||
<span class="metadata-key">{{ t('filePath') }}</span>
|
||||
<span class="metadata-key">{{ t('filePathLabel') }}</span>
|
||||
<i class="pi eye-icon" [ngClass]="showFilePath ? 'pi-eye-slash' : 'pi-eye'" (click)="showFilePath = !showFilePath"></i>
|
||||
@if (showFilePath) {
|
||||
<code class="file-path-code">{{ book?.primaryFile?.filePath }}</code>
|
||||
@@ -628,7 +628,7 @@
|
||||
}
|
||||
@if (userState.user!.permissions.canEditMetadata || userState.user!.permissions.admin) {
|
||||
<p-button
|
||||
[label]="isAutoFetching ? t('fetchingMetadata') : t('fetchMetadata')"
|
||||
[label]="isAutoFetching ? t('fetchingBtn') : t('fetchMetadataBtn')"
|
||||
[icon]="isAutoFetching ? 'pi pi-spin pi-spinner' : 'pi pi-bolt'"
|
||||
[outlined]="true"
|
||||
severity="warn"
|
||||
@@ -655,7 +655,7 @@
|
||||
<div class="description-section">
|
||||
<div class="section-header">
|
||||
<i class="pi pi-align-left"></i>
|
||||
<span>{{ t('synopsis') }}</span>
|
||||
<span>{{ t('synopsisTitle') }}</span>
|
||||
</div>
|
||||
<div class="description-body">
|
||||
<div [ngClass]="{ 'line-clamp-7': !isExpanded }" class="description-content">
|
||||
@@ -679,7 +679,7 @@
|
||||
<div class="section-header clickable" (click)="isComicSectionExpanded = !isComicSectionExpanded">
|
||||
<div class="section-header-left">
|
||||
<i class="pi pi-images"></i>
|
||||
<span>{{ t('comicDetails') }}</span>
|
||||
<span>{{ t('comicDetailsTitle') }}</span>
|
||||
</div>
|
||||
<i class="pi section-toggle-icon" [ngClass]="isComicSectionExpanded ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
||||
</div>
|
||||
@@ -690,13 +690,13 @@
|
||||
<div class="comic-info-grid">
|
||||
@if (comic.issueNumber) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('issue') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicIssue') }}</span>
|
||||
<span class="comic-info-value">#{{ comic.issueNumber }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (comic.volumeName) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('volume') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicVolume') }}</span>
|
||||
<span class="comic-info-value">
|
||||
{{ comic.volumeName }}
|
||||
@if (comic.volumeNumber) {
|
||||
@@ -707,7 +707,7 @@
|
||||
}
|
||||
@if (comic.storyArc) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('storyArc') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicStoryArc') }}</span>
|
||||
<span class="comic-info-value">
|
||||
{{ comic.storyArc }}
|
||||
@if (comic.storyArcNumber) {
|
||||
@@ -718,7 +718,7 @@
|
||||
}
|
||||
@if (comic.alternateSeries) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('altSeries') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicAltSeries') }}</span>
|
||||
<span class="comic-info-value">
|
||||
{{ comic.alternateSeries }}
|
||||
@if (comic.alternateIssue) {
|
||||
@@ -729,13 +729,13 @@
|
||||
}
|
||||
@if (comic.format) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('format') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicFormat') }}</span>
|
||||
<span class="comic-info-value">{{ comic.format }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (comic.imprint) {
|
||||
<div class="comic-info-item">
|
||||
<span class="comic-info-label">{{ t('imprint') }}</span>
|
||||
<span class="comic-info-label">{{ t('comicImprint') }}</span>
|
||||
<span class="comic-info-value">{{ comic.imprint }}</span>
|
||||
</div>
|
||||
}
|
||||
@@ -745,7 +745,7 @@
|
||||
<div class="comic-subsection">
|
||||
<div class="comic-subsection-title">
|
||||
<i class="pi pi-users"></i>
|
||||
<span>{{ t('creators') }}</span>
|
||||
<span>{{ t('creatorsTitle') }}</span>
|
||||
</div>
|
||||
<div class="comic-creators-grid">
|
||||
@if (comic.pencillers?.length) {
|
||||
@@ -816,7 +816,7 @@
|
||||
<div class="comic-subsection">
|
||||
<div class="comic-subsection-title">
|
||||
<i class="pi pi-globe"></i>
|
||||
<span>{{ t('universe') }}</span>
|
||||
<span>{{ t('universeTitle') }}</span>
|
||||
</div>
|
||||
<div class="comic-tags-container">
|
||||
@if (comic.characters?.length) {
|
||||
@@ -868,12 +868,12 @@
|
||||
}
|
||||
@if (comic.blackAndWhite) {
|
||||
<span class="comic-property-badge bw">
|
||||
<i class="pi pi-palette"></i> {{ t('bw') }}
|
||||
<i class="pi pi-palette"></i> {{ t('blackAndWhite') }}
|
||||
</span>
|
||||
}
|
||||
@if (comic.readingDirection === 'rtl') {
|
||||
<span class="comic-property-badge rtl">
|
||||
<i class="pi pi-arrow-left"></i> {{ t('rtl') }}
|
||||
<i class="pi pi-arrow-left"></i> {{ t('rightToLeft') }}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
@@ -892,7 +892,7 @@
|
||||
<div class="comic-notes">
|
||||
<div class="comic-notes-label">
|
||||
<i class="pi pi-file-edit"></i>
|
||||
<span>{{ t('comicNotes') }}</span>
|
||||
<span>{{ t('notesLabel') }}</span>
|
||||
</div>
|
||||
<p class="comic-notes-content">{{ comic.notes }}</p>
|
||||
</div>
|
||||
@@ -906,7 +906,7 @@
|
||||
<div class="section-header clickable" (click)="isAudiobookSectionExpanded = !isAudiobookSectionExpanded">
|
||||
<div class="section-header-left">
|
||||
<i class="pi pi-headphones"></i>
|
||||
<span>{{ t('audiobookDetails') }}</span>
|
||||
<span>{{ t('audiobookDetailsTitle') }}</span>
|
||||
</div>
|
||||
<i class="pi section-toggle-icon" [ngClass]="isAudiobookSectionExpanded ? 'pi-chevron-up' : 'pi-chevron-down'"></i>
|
||||
</div>
|
||||
@@ -917,13 +917,13 @@
|
||||
<div class="audiobook-info-grid">
|
||||
@if (audio.durationSeconds) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('duration') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookDuration') }}</span>
|
||||
<span class="audiobook-info-value">{{ formatDuration(audio.durationSeconds) }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (book.metadata?.narrator) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('narrator') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookNarrator') }}</span>
|
||||
<a class="audiobook-info-value audiobook-link" (click)="goToNarrator(book.metadata!.narrator!)">
|
||||
{{ book.metadata?.narrator }}
|
||||
</a>
|
||||
@@ -931,31 +931,31 @@
|
||||
}
|
||||
@if (audio.chapterCount) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('chapters') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookChapters') }}</span>
|
||||
<span class="audiobook-info-value">{{ audio.chapterCount }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (audio.bitrate) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('bitrate') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookBitrate') }}</span>
|
||||
<span class="audiobook-info-value">{{ audio.bitrate }} kbps</span>
|
||||
</div>
|
||||
}
|
||||
@if (audio.sampleRate) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('sampleRate') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookSampleRate') }}</span>
|
||||
<span class="audiobook-info-value">{{ formatSampleRate(audio.sampleRate) }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (audio.channels) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('channels') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookChannels') }}</span>
|
||||
<span class="audiobook-info-value">{{ getChannelLabel(audio.channels) }}</span>
|
||||
</div>
|
||||
}
|
||||
@if (audio.codec) {
|
||||
<div class="audiobook-info-item">
|
||||
<span class="audiobook-info-label">{{ t('codec') }}</span>
|
||||
<span class="audiobook-info-label">{{ t('audiobookCodec') }}</span>
|
||||
<span class="audiobook-info-value">{{ audio.codec.toUpperCase() }}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -78,16 +78,16 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
isEditingDateFinished = false;
|
||||
editDateFinished: Date | null = null;
|
||||
|
||||
readStatusOptions: { value: ReadStatus, label: string }[] = [
|
||||
{value: ReadStatus.UNREAD, label: 'Unread'},
|
||||
{value: ReadStatus.PAUSED, label: 'Paused'},
|
||||
{value: ReadStatus.READING, label: 'Reading'},
|
||||
{value: ReadStatus.RE_READING, label: 'Re-reading'},
|
||||
{value: ReadStatus.READ, label: 'Read'},
|
||||
{value: ReadStatus.PARTIALLY_READ, label: 'Partially Read'},
|
||||
{value: ReadStatus.ABANDONED, label: 'Abandoned'},
|
||||
{value: ReadStatus.WONT_READ, label: 'Won\'t Read'},
|
||||
{value: ReadStatus.UNSET, label: 'Unset'},
|
||||
readStatusOptions: { value: ReadStatus, labelKey: string }[] = [
|
||||
{value: ReadStatus.UNREAD, labelKey: 'metadata.viewer.readStatusUnread'},
|
||||
{value: ReadStatus.PAUSED, labelKey: 'metadata.viewer.readStatusPaused'},
|
||||
{value: ReadStatus.READING, labelKey: 'metadata.viewer.readStatusReading'},
|
||||
{value: ReadStatus.RE_READING, labelKey: 'metadata.viewer.readStatusReReading'},
|
||||
{value: ReadStatus.READ, labelKey: 'metadata.viewer.readStatusRead'},
|
||||
{value: ReadStatus.PARTIALLY_READ, labelKey: 'metadata.viewer.readStatusPartiallyRead'},
|
||||
{value: ReadStatus.ABANDONED, labelKey: 'metadata.viewer.readStatusAbandoned'},
|
||||
{value: ReadStatus.WONT_READ, labelKey: 'metadata.viewer.readStatusWontRead'},
|
||||
{value: ReadStatus.UNSET, labelKey: 'metadata.viewer.readStatusUnset'},
|
||||
];
|
||||
|
||||
private bookNavigationService = inject(BookNavigationService);
|
||||
@@ -105,13 +105,13 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
const primaryType = book.primaryFile?.bookType;
|
||||
if (primaryType === 'PDF') {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.streamingReader'),
|
||||
label: this.t.translate('metadata.viewer.menuStreamingReader'),
|
||||
icon: 'pi pi-play',
|
||||
command: () => this.read(book.id, 'pdf-streaming')
|
||||
});
|
||||
} else if (primaryType === 'EPUB') {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.streamingReader'),
|
||||
label: this.t.translate('metadata.viewer.menuStreamingReader'),
|
||||
icon: 'pi pi-play',
|
||||
command: () => this.read(book.id, 'epub-streaming')
|
||||
});
|
||||
@@ -138,12 +138,12 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
icon: this.getFileIcon(formatType),
|
||||
items: [
|
||||
{
|
||||
label: this.t.translate('metadata.viewer.standardReader'),
|
||||
label: this.t.translate('metadata.viewer.menuStandardReader'),
|
||||
icon: 'pi pi-book',
|
||||
command: () => this.read(book.id, undefined, formatType)
|
||||
},
|
||||
{
|
||||
label: this.t.translate('metadata.viewer.streamingReader'),
|
||||
label: this.t.translate('metadata.viewer.menuStreamingReader'),
|
||||
icon: 'pi pi-play',
|
||||
command: () => this.read(book.id, formatType === 'PDF' ? 'pdf-streaming' : 'epub-streaming', formatType)
|
||||
}
|
||||
@@ -216,7 +216,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
const items: MenuItem[] = [];
|
||||
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.shelf'),
|
||||
label: this.t.translate('metadata.viewer.menuShelf'),
|
||||
icon: 'pi pi-folder',
|
||||
command: () => this.assignShelf(book.id)
|
||||
});
|
||||
@@ -225,7 +225,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
|
||||
if (userState?.user?.permissions.canUpload || userState?.user?.permissions.admin) {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.uploadFile'),
|
||||
label: this.t.translate('metadata.viewer.menuUploadFile'),
|
||||
icon: 'pi pi-upload',
|
||||
command: () => {
|
||||
this.bookDialogHelperService.openAdditionalFileUploaderDialog(book);
|
||||
@@ -237,7 +237,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
|
||||
if (hasFiles && (userState?.user?.permissions.canManageLibrary || userState?.user?.permissions.admin) && appSettings?.diskType === 'LOCAL') {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.organizeFiles'),
|
||||
label: this.t.translate('metadata.viewer.menuOrganizeFiles'),
|
||||
icon: 'pi pi-arrows-h',
|
||||
command: () => {
|
||||
this.openFileMoverDialog(book.id);
|
||||
@@ -247,16 +247,16 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
|
||||
if (hasFiles && (userState?.user?.permissions.canEmailBook || userState?.user?.permissions.admin)) {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.sendBook'),
|
||||
label: this.t.translate('metadata.viewer.menuSendBook'),
|
||||
icon: 'pi pi-send',
|
||||
items: [
|
||||
{
|
||||
label: this.t.translate('metadata.viewer.quickSend'),
|
||||
label: this.t.translate('metadata.viewer.menuQuickSend'),
|
||||
icon: 'pi pi-bolt',
|
||||
command: () => this.quickSend(book.id)
|
||||
},
|
||||
{
|
||||
label: this.t.translate('metadata.viewer.customSend'),
|
||||
label: this.t.translate('metadata.viewer.menuCustomSend'),
|
||||
icon: 'pi pi-cog',
|
||||
command: () => {
|
||||
this.bookDialogHelperService.openCustomSendDialog(book);
|
||||
@@ -270,7 +270,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
const isSingleFileBook = hasFiles && !book.alternativeFormats?.length;
|
||||
if (isSingleFileBook && (userState?.user?.permissions.canManageLibrary || userState?.user?.permissions.admin)) {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.attachToAnotherBook'),
|
||||
label: this.t.translate('metadata.viewer.menuAttachToAnotherBook'),
|
||||
icon: 'pi pi-link',
|
||||
command: () => {
|
||||
this.bookDialogHelperService.openBookFileAttacherDialog(book);
|
||||
@@ -312,7 +312,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
|
||||
if (deleteFormatItems.length > 0) {
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.deleteFileFormats'),
|
||||
label: this.t.translate('metadata.viewer.menuDeleteFileFormats'),
|
||||
icon: 'pi pi-file',
|
||||
items: deleteFormatItems
|
||||
});
|
||||
@@ -333,7 +333,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
});
|
||||
|
||||
items.push({
|
||||
label: this.t.translate('metadata.viewer.deleteSupplementaryFiles'),
|
||||
label: this.t.translate('metadata.viewer.menuDeleteSupplementaryFiles'),
|
||||
icon: 'pi pi-paperclip',
|
||||
items: deleteSupplementaryItems
|
||||
});
|
||||
@@ -356,11 +356,11 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
? `\n\nThe following files will be permanently deleted:\n• ${allFormats.join('\n• ')}`
|
||||
: '';
|
||||
|
||||
const deleteLabel = isPhysical ? this.t.translate('metadata.viewer.deleteBook') : this.t.translate('metadata.viewer.deleteBookAndAllFiles');
|
||||
const deleteLabel = isPhysical ? this.t.translate('metadata.viewer.menuDeleteBook') : this.t.translate('metadata.viewer.menuDeleteBookAllFiles');
|
||||
const deleteMessage = isPhysical
|
||||
? this.t.translate('metadata.viewer.confirm.deleteBookMessage', { title: book.metadata?.title })
|
||||
: this.t.translate('metadata.viewer.confirm.deleteBookAndFilesMessage', { title: book.metadata?.title, fileList: fileListMessage });
|
||||
const deleteAcceptLabel = isPhysical ? this.t.translate('common.delete') : this.t.translate('metadata.viewer.deleteEverything');
|
||||
: this.t.translate('metadata.viewer.confirm.deleteBookAllFilesMessage', { title: book.metadata?.title, fileList: fileListMessage });
|
||||
const deleteAcceptLabel = isPhysical ? this.t.translate('common.delete') : this.t.translate('metadata.viewer.confirm.deleteEverythingBtn');
|
||||
|
||||
items.push({
|
||||
label: deleteLabel,
|
||||
@@ -480,9 +480,9 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
getReadButtonLabel(book: Book): string {
|
||||
const isAudiobook = book.primaryFile?.bookType === 'AUDIOBOOK';
|
||||
if (this.isInProgressStatus()) {
|
||||
return isAudiobook ? this.t.translate('metadata.viewer.continue') : this.t.translate('metadata.viewer.continueReading');
|
||||
return isAudiobook ? this.t.translate('metadata.viewer.continueBtn') : this.t.translate('metadata.viewer.continueReadingBtn');
|
||||
}
|
||||
return isAudiobook ? this.t.translate('metadata.viewer.playAction') : this.t.translate('metadata.viewer.readAction');
|
||||
return isAudiobook ? this.t.translate('metadata.viewer.playBtn') : this.t.translate('metadata.viewer.readBtn');
|
||||
}
|
||||
|
||||
getReadButtonIcon(book: Book): string {
|
||||
@@ -564,8 +564,8 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
message = this.t.translate('metadata.viewer.confirm.deletePrimaryFormatMessage', { fileName });
|
||||
header = this.t.translate('metadata.viewer.confirm.deletePrimaryFormatHeader');
|
||||
} else {
|
||||
message = this.t.translate('metadata.viewer.confirm.deleteAlternativeFormatMessage', { fileName });
|
||||
header = this.t.translate('metadata.viewer.confirm.deleteAlternativeFormatHeader');
|
||||
message = this.t.translate('metadata.viewer.confirm.deleteAltFormatMessage', { fileName });
|
||||
header = this.t.translate('metadata.viewer.confirm.deleteAltFormatHeader');
|
||||
}
|
||||
|
||||
this.confirmationService.confirm({
|
||||
@@ -574,7 +574,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
acceptIcon: 'pi pi-trash',
|
||||
rejectIcon: 'pi pi-times',
|
||||
acceptLabel: this.t.translate('metadata.viewer.confirm.deleteFile'),
|
||||
acceptLabel: this.t.translate('metadata.viewer.confirm.deleteFileBtn'),
|
||||
rejectLabel: this.t.translate('common.cancel'),
|
||||
rejectButtonStyleClass: 'p-button-secondary',
|
||||
acceptButtonStyleClass: 'p-button-danger',
|
||||
@@ -622,7 +622,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
error: (err) => this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: this.t.translate('metadata.viewer.toast.quickSendErrorSummary'),
|
||||
detail: err?.error?.message || this.t.translate('metadata.viewer.toast.quickSendErrorDetailFallback'),
|
||||
detail: err?.error?.message || this.t.translate('metadata.viewer.toast.quickSendErrorDetail'),
|
||||
})
|
||||
});
|
||||
}
|
||||
@@ -1122,12 +1122,13 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
readStatusMenuItems = this.readStatusOptions.map(option => ({
|
||||
label: option.label,
|
||||
label: this.t.translate(option.labelKey),
|
||||
command: () => this.updateReadStatus(option.value)
|
||||
}));
|
||||
|
||||
getStatusLabel(value: string): string {
|
||||
return this.readStatusOptions.find(o => o.value === value)?.label.toUpperCase() ?? 'UNSET';
|
||||
const option = this.readStatusOptions.find(o => o.value === value);
|
||||
return option ? this.t.translate(option.labelKey).toUpperCase() : 'UNSET';
|
||||
}
|
||||
|
||||
|
||||
@@ -1170,8 +1171,8 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
error: () => {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: this.t.translate('metadata.viewer.toast.dateFailedSummary'),
|
||||
detail: this.t.translate('metadata.viewer.toast.dateFailedDetail'),
|
||||
summary: this.t.translate('metadata.viewer.toast.dateUpdateFailedSummary'),
|
||||
detail: this.t.translate('metadata.viewer.toast.dateUpdateFailedDetail'),
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
@@ -1225,7 +1226,7 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
|
||||
getNavigationPosition(): string {
|
||||
const position = this.bookNavigationService.getCurrentPosition();
|
||||
return position ? this.t.translate('metadata.viewer.navigationOf', { current: position.current, total: position.total }) : '';
|
||||
return position ? this.t.translate('metadata.viewer.navigationPosition', { current: position.current, total: position.total }) : '';
|
||||
}
|
||||
|
||||
hasDigitalFile(book: Book): boolean {
|
||||
@@ -1353,11 +1354,11 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
getChannelLabel(channels: number): string {
|
||||
switch (channels) {
|
||||
case 1:
|
||||
return 'Mono';
|
||||
return this.t.translate('metadata.viewer.channelMono');
|
||||
case 2:
|
||||
return 'Stereo';
|
||||
return this.t.translate('metadata.viewer.channelStereo');
|
||||
default:
|
||||
return `${channels} channels`;
|
||||
return this.t.translate('metadata.viewer.channelMultiple', { count: channels });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
} @else {
|
||||
<div class="sidecar-actions">
|
||||
<p-button
|
||||
[label]="t('exportToSidecar')"
|
||||
[label]="t('exportBtn')"
|
||||
icon="pi pi-upload"
|
||||
[loading]="exporting"
|
||||
(onClick)="exportToSidecar()"
|
||||
@@ -34,7 +34,7 @@
|
||||
tooltipPosition="top"
|
||||
/>
|
||||
<p-button
|
||||
[label]="t('importFromSidecar')"
|
||||
[label]="t('importBtn')"
|
||||
icon="pi pi-download"
|
||||
[loading]="importing"
|
||||
[disabled]="syncStatus === 'MISSING'"
|
||||
@@ -49,7 +49,7 @@
|
||||
@if (syncStatus === 'MISSING') {
|
||||
<div class="empty-state">
|
||||
<i class="pi pi-file"></i>
|
||||
<h4>{{ t('noSidecarFile') }}</h4>
|
||||
<h4>{{ t('noSidecarTitle') }}</h4>
|
||||
<p>
|
||||
{{ t('noSidecarDescription') }}
|
||||
</p>
|
||||
@@ -60,15 +60,15 @@
|
||||
<div class="content-meta">
|
||||
<span class="meta-item">
|
||||
<i class="pi pi-clock"></i>
|
||||
{{ t('generated') }} {{ sidecarContent.generatedAt | date:'medium' }}
|
||||
{{ t('generatedLabel') }} {{ sidecarContent.generatedAt | date:'medium' }}
|
||||
</span>
|
||||
<span class="meta-item">
|
||||
<i class="pi pi-tag"></i>
|
||||
{{ t('version') }} {{ sidecarContent.version }}
|
||||
{{ t('versionLabel') }} {{ sidecarContent.version }}
|
||||
</span>
|
||||
<span class="meta-item">
|
||||
<i class="pi pi-cog"></i>
|
||||
{{ t('generatedBy') }} {{ sidecarContent.generatedBy }}
|
||||
{{ t('byLabel') }} {{ sidecarContent.generatedBy }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@
|
||||
@if (sidecarContent.cover) {
|
||||
<div class="cover-info">
|
||||
<i class="pi pi-image"></i>
|
||||
<span>{{ t('coverFile') }} {{ sidecarContent.cover.path }}</span>
|
||||
<span>{{ t('coverFileLabel') }} {{ sidecarContent.cover.path }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -161,17 +161,17 @@ export class SidecarViewerComponent implements OnInit, OnDestroy {
|
||||
getSyncStatusLabel(): string {
|
||||
switch (this.syncStatus) {
|
||||
case 'IN_SYNC':
|
||||
return this.t.translate('metadata.sidecar.syncStatus.inSync');
|
||||
return this.t.translate('metadata.sidecar.syncStatusInSync');
|
||||
case 'OUTDATED':
|
||||
return this.t.translate('metadata.sidecar.syncStatus.outdated');
|
||||
return this.t.translate('metadata.sidecar.syncStatusOutdated');
|
||||
case 'CONFLICT':
|
||||
return this.t.translate('metadata.sidecar.syncStatus.conflict');
|
||||
return this.t.translate('metadata.sidecar.syncStatusConflict');
|
||||
case 'MISSING':
|
||||
return this.t.translate('metadata.sidecar.syncStatus.missing');
|
||||
return this.t.translate('metadata.sidecar.syncStatusMissing');
|
||||
case 'NOT_APPLICABLE':
|
||||
return this.t.translate('metadata.sidecar.syncStatus.notApplicable');
|
||||
return this.t.translate('metadata.sidecar.syncStatusNA');
|
||||
default:
|
||||
return this.t.translate('metadata.sidecar.syncStatus.unknown');
|
||||
return this.t.translate('metadata.sidecar.syncStatusUnknown');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +215,8 @@
|
||||
"playTooltip": "Play",
|
||||
"downloadTooltip": "Download",
|
||||
"deleteTooltip": "Delete",
|
||||
"downloadAllTooltip": "Download all files as a ZIP archive"
|
||||
"downloadAllTooltip": "Download all files as a ZIP archive",
|
||||
"physicalBookHint": "You can upload a digital copy or add metadata manually."
|
||||
},
|
||||
"viewer": {
|
||||
"metadataLocked": "This book metadata is locked.",
|
||||
@@ -288,6 +289,10 @@
|
||||
"continueBtn": "Continue",
|
||||
"fetchMetadataBtn": "Fetch Metadata",
|
||||
"fetchingBtn": "Fetching...",
|
||||
"fetchMetadataTooltip": "Quickly refresh metadata using your default fetch settings",
|
||||
"goToPreviousBook": "Go to Previous Book",
|
||||
"goToNextBook": "Go to Next Book",
|
||||
"personalRating": "Personal Rating",
|
||||
"loadingBookDetails": "Loading book details...",
|
||||
"readStatusUnread": "Unread",
|
||||
"readStatusPaused": "Paused",
|
||||
|
||||
@@ -215,7 +215,8 @@
|
||||
"playTooltip": "Reproducir",
|
||||
"downloadTooltip": "Descargar",
|
||||
"deleteTooltip": "Eliminar",
|
||||
"downloadAllTooltip": "Descargar todos los archivos como archivo ZIP"
|
||||
"downloadAllTooltip": "Descargar todos los archivos como archivo ZIP",
|
||||
"physicalBookHint": "Puede subir una copia digital o agregar metadatos manualmente."
|
||||
},
|
||||
"viewer": {
|
||||
"metadataLocked": "Los metadatos de este libro están bloqueados.",
|
||||
@@ -288,6 +289,10 @@
|
||||
"continueBtn": "Continuar",
|
||||
"fetchMetadataBtn": "Obtener metadatos",
|
||||
"fetchingBtn": "Obteniendo...",
|
||||
"fetchMetadataTooltip": "Actualizar rápidamente los metadatos usando la configuración predeterminada",
|
||||
"goToPreviousBook": "Ir al libro anterior",
|
||||
"goToNextBook": "Ir al siguiente libro",
|
||||
"personalRating": "Calificación personal",
|
||||
"loadingBookDetails": "Cargando detalles del libro...",
|
||||
"readStatusUnread": "No leído",
|
||||
"readStatusPaused": "Pausado",
|
||||
|
||||
Reference in New Issue
Block a user