* Updated readme to have progress bars on localization to help motivate users.

* Fixed a bug where downloads could trigger on lazy loaded module boundaries.

* Updated all packages to latest

* Fixed a bug where remove from on deck would show on all series cards when it shouldn't have.

* Fixed a bug where virtualized reading list page wasn't showing the correct order on the UI

* Localization fixes from shakeout

* Fixed fullscreen mode broken in nightly from localization.

* Fixed a bug where duplicate series add events could show duplicate items in library detail page.

* Translations update from Hosted Weblate (#2184)

* Added translation using Weblate (Kannada)

* Added translation using Weblate (Hindi)

* Added translation using Weblate (German)

* Added translation using Weblate (Russian)

* Added translation using Weblate (Malay)

* Translated using Weblate (Dutch)

Currently translated at 20.8% (296 of 1423 strings)

Translation: Kavita/ui
Translate-URL: https://hosted.weblate.org/projects/kavita/ui/nl/

* Translated using Weblate (Portuguese)

Currently translated at 5.2% (75 of 1423 strings)

Translation: Kavita/ui
Translate-URL: https://hosted.weblate.org/projects/kavita/ui/pt/

* Translated using Weblate (German)

Currently translated at 98.7% (156 of 158 strings)

Translation: Kavita/backend
Translate-URL: https://hosted.weblate.org/projects/kavita/backend/de/

* Translated using Weblate (Japanese)

Currently translated at 1.9% (28 of 1423 strings)

Translation: Kavita/ui
Translate-URL: https://hosted.weblate.org/projects/kavita/ui/ja/

* Translated using Weblate (Spanish)

Currently translated at 1.8% (3 of 158 strings)

Translation: Kavita/backend
Translate-URL: https://hosted.weblate.org/projects/kavita/backend/es/

* Translated using Weblate (Hindi)

Currently translated at 100.0% (158 of 158 strings)

Translation: Kavita/backend
Translate-URL: https://hosted.weblate.org/projects/kavita/backend/hi/

* Translated using Weblate (German)

Currently translated at 7.3% (105 of 1423 strings)

Translation: Kavita/ui
Translate-URL: https://hosted.weblate.org/projects/kavita/ui/de/

* Deleted translation using Weblate (Undetermined)

* Added translation using Weblate (Italian)

---------

Co-authored-by: Shashank Pujari <shashankppujari@gmail.com>
Co-authored-by: Andre <andruecha32@gmail.com>
Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com>
Co-authored-by: Duarte Silva <smallflake@protonmail.com>
Co-authored-by: Andre Smith <andrepsmithjr@gmail.com>
Co-authored-by: ThePromidius <thepromidiusyt@gmail.com>
Co-authored-by: majora2007 <kavitareader@gmail.com>
Co-authored-by: Tomas Battistini <tomas.battistini@gmail.com>

---------

Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: Shashank Pujari <shashankppujari@gmail.com>
Co-authored-by: Andre <andruecha32@gmail.com>
Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com>
Co-authored-by: Duarte Silva <smallflake@protonmail.com>
Co-authored-by: Andre Smith <andrepsmithjr@gmail.com>
Co-authored-by: ThePromidius <thepromidiusyt@gmail.com>
Co-authored-by: majora2007 <kavitareader@gmail.com>
Co-authored-by: Tomas Battistini <tomas.battistini@gmail.com>
This commit is contained in:
Joe Milazzo 2023-08-07 09:14:57 -05:00 committed by GitHub
parent e9f8ecfc27
commit 7358ba7220
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 7838 additions and 771 deletions

View file

@ -41,7 +41,7 @@ export class ErrorInterceptor implements HttpInterceptor {
break;
default:
// Don't throw multiple Something unexpected went wrong
const genericError = this.translocoService.translate('errors.generic');
let genericError = translate('errors.generic');
if (this.toastr.previousToastMessage !== 'Something unexpected went wrong.' && this.toastr.previousToastMessage !== genericError) {
this.toast(genericError);
}

View file

@ -1,5 +1,5 @@
<ng-container *transloco="let t; read: 'book-reader'">
<div class="container-flex {{darkMode ? 'dark-mode' : ''}} reader-container {{ColumnLayout}} {{WritingStyleClass}}" tabindex="0" #reader>
<div class="container-flex {{darkMode ? 'dark-mode' : ''}} reader-container {{ColumnLayout}} {{WritingStyleClass}}" tabindex="0" #reader>
<ng-container *transloco="let t; read: 'book-reader'">
<div class="fixed-top" #stickyTop>
<a class="visually-hidden-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">{{t('skip-header')}}</a>
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
@ -141,8 +141,8 @@
</div>
</ng-container>
<ng-template #showTitle>
<span *ngIf="incognitoMode" (click)="turnOffIncognito()" role="button" [attr.aria-label]="t('incognito-mode-alt')">
(<i class="fa fa-glasses" aria-hidden="true"></i><span class="visually-hidden">{{t('incognito-mode-label')}}</span>)</span>
<span *ngIf="incognitoMode" (click)="turnOffIncognito()" role="button" [attr.aria-label]="t('incognito-mode-alt')">
(<i class="fa fa-glasses" aria-hidden="true"></i><span class="visually-hidden">{{t('incognito-mode-label')}}</span>)</span>
<span class="book-title-text ms-1" [ngbTooltip]="bookTitle">{{bookTitle}}</span>
</ng-template>
</div>
@ -154,6 +154,5 @@
</button>
</div>
</ng-template>
</div>
</ng-container>
</ng-container>
</div>

View file

@ -306,7 +306,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('readingHtml', {static: false}) bookContentElemRef!: ElementRef<HTMLDivElement>;
@ViewChild('readingSection', {static: false}) readingSectionElemRef!: ElementRef<HTMLDivElement>;
@ViewChild('stickyTop', {static: false}) stickyTopElemRef!: ElementRef<HTMLDivElement>;
@ViewChild('reader', {static: true}) reader!: ElementRef;
@ViewChild('reader', {static: false}) reader!: ElementRef;
get BookPageLayoutMode() {
@ -855,7 +855,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
promptForPage() {
const question = 'There are ' + (this.maxPages - 1) + ' pages. What page do you want to go to?';
const question = translate('book-reader.go-to-page-prompt', {totalPages: this.maxPages - 1});
const goToPageNum = window.prompt(question, '');
if (goToPageNum === null || goToPageNum.trim().length === 0) { return null; }
return goToPageNum;
@ -1597,6 +1597,4 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
refreshPersonalToC() {
this.refreshPToC.emit();
}
protected readonly undefined = undefined;
}

View file

@ -24,6 +24,30 @@ import {RelationshipPipe} from "../../pipe/relationship.pipe";
import {Device} from "../../_models/device/device";
import {TranslocoService} from "@ngneat/transloco";
function deepClone(obj: any): any {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Array) {
return obj.map(item => deepClone(item));
}
const clonedObj: any = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (typeof obj[key] === 'object' && obj[key] !== null) {
clonedObj[key] = deepClone(obj[key]);
} else {
clonedObj[key] = obj[key];
}
}
}
return clonedObj;
}
@Component({
selector: 'app-series-card',
standalone: true,
@ -85,11 +109,12 @@ export class SeriesCardComponent implements OnInit, OnChanges {
ngOnChanges(changes: any) {
if (this.data) {
this.actions = this.actionFactoryService.getSeriesActions((action: ActionItem<Series>, series: Series) => this.handleSeriesActionCallback(action, series));
this.actions = [...this.actionFactoryService.getSeriesActions((action: ActionItem<Series>, series: Series) => this.handleSeriesActionCallback(action, series))];
if (this.isOnDeck) {
const othersIndex = this.actions.findIndex(obj => obj.title === 'others');
if (this.actions[othersIndex].children.findIndex(o => o.action === Action.RemoveFromOnDeck) < 0) {
this.actions[othersIndex].children.push({
const othersAction = deepClone(this.actions[othersIndex]) as ActionItem<Series>;
if (othersAction.children.findIndex(o => o.action === Action.RemoveFromOnDeck) < 0) {
othersAction.children.push({
action: Action.RemoveFromOnDeck,
title: 'remove-from-on-deck',
callback: (action: ActionItem<Series>, series: Series) => this.handleSeriesActionCallback(action, series),
@ -97,6 +122,7 @@ export class SeriesCardComponent implements OnInit, OnChanges {
requiresAdmin: false,
children: [],
});
this.actions[othersIndex] = othersAction;
}
}
this.cdRef.markForCheck();

View file

@ -173,6 +173,7 @@ export class LibraryDetailComponent implements OnInit {
return;
}
this.seriesService.getSeries(seriesAdded.seriesId).subscribe(s => {
if (this.series.filter(sObj => s.id === sObj.id).length > 0) return;
this.series = [...this.series, s].sort((s1: Series, s2: Series) => {
if (s1.sortName < s2.sortName) return -1;
if (s1.sortName > s2.sortName) return 1;

View file

@ -1497,7 +1497,8 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
// This is menu only code
promptForPage() {
const goToPageNum = window.prompt('There are ' + this.maxPages + ' pages. What page would you like to go to?', '');
const question = translate('book-reader.go-to-page-prompt', {totalPages: this.maxPages});
const goToPageNum = window.prompt(question, '');
if (goToPageNum === null || goToPageNum.trim().length === 0) { return null; }
return goToPageNum;
}

View file

@ -7,8 +7,8 @@
<div class="d-flex list-container">
<div class="me-3 align-middle">
<div style="padding-top: 40px">
<label for="reorder-{{i}}" class="form-label visually-hidden">{{t('reorder')}}</label>
<input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="i" style="width: 60px"
<label for="reorder-{{i}}" class="form-label visually-hidden">{{t('reorder-label')}}</label>
<input *ngIf="accessibilityMode" id="reorder-{{i}}" class="form-control" type="number" inputmode="numeric" min="0" [max]="items.length - 1" [value]="item.order" style="width: 60px"
(focusout)="updateIndex(i, item)" (keydown.enter)="updateIndex(i, item)" aria-describedby="instructions">
</div>
</div>

View file

@ -1,18 +1,27 @@
import { HttpClient } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import {DestroyRef, inject, Inject, Injectable} from '@angular/core';
import { Series } from 'src/app/_models/series';
import { environment } from 'src/environments/environment';
import { ConfirmService } from '../confirm.service';
import { Chapter } from 'src/app/_models/chapter';
import { Volume } from 'src/app/_models/volume';
import { asyncScheduler, BehaviorSubject, Observable, tap, finalize, of, filter } from 'rxjs';
import {
asyncScheduler,
BehaviorSubject,
Observable,
tap,
finalize,
of,
filter,
} from 'rxjs';
import { SAVER, Saver } from '../_providers/saver.provider';
import { download, Download } from '../_models/download';
import { PageBookmark } from 'src/app/_models/readers/page-bookmark';
import { switchMap, takeWhile, throttleTime } from 'rxjs/operators';
import {switchMap, take, takeWhile, throttleTime} from 'rxjs/operators';
import { AccountService } from 'src/app/_services/account.service';
import { BytesPipe } from 'src/app/pipe/bytes.pipe';
import {translate} from "@ngneat/transloco";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
export const DEBOUNCE_TIME = 100;
@ -42,6 +51,7 @@ export type DownloadEntityType = 'volume' | 'chapter' | 'series' | 'bookmark' |
*/
export type DownloadEntity = Series | Volume | Chapter | PageBookmark[] | undefined;
@Injectable({
providedIn: 'root'
})
@ -56,10 +66,12 @@ export class DownloadService {
private downloadsSource: BehaviorSubject<DownloadEvent[]> = new BehaviorSubject<DownloadEvent[]>([]);
public activeDownloads$ = this.downloadsSource.asObservable();
private readonly destroyRef = inject(DestroyRef);
constructor(private httpClient: HttpClient, private confirmService: ConfirmService,
@Inject(SAVER) private save: Saver, private accountService: AccountService) { }
/**
* Returns the entity subtitle (for the event widget) for a given entity
* @param downloadEntityType
@ -117,7 +129,7 @@ export class DownloadService {
}
this.accountService.currentUser$.pipe(switchMap(user => {
this.accountService.currentUser$.pipe(take(1), switchMap(user => {
if (user && user.preferences.promptForDownloadSize) {
return sizeCheckCall;
}
@ -138,7 +150,8 @@ export class DownloadService {
finalize(() => {
if (callback) callback(undefined);
}))
})).subscribe(() => {});
}), takeUntilDestroyed(this.destroyRef)
).subscribe(() => {});
}
private downloadSeriesSize(seriesId: number) {

View file

@ -15,7 +15,7 @@ export class DevicePlatformPipe implements PipeTransform {
case DevicePlatform.Kindle: return 'Kindle';
case DevicePlatform.Kobo: return 'Kobo';
case DevicePlatform.PocketBook: return 'PocketBook';
case DevicePlatform.Custom: return this.translocoService.translate('device.platform-pipe.custom');
case DevicePlatform.Custom: return this.translocoService.translate('device-platform-pipe.custom');
default: return value + '';
}
}

File diff suppressed because it is too large Load diff

View file

@ -615,8 +615,8 @@
"incognito-mode-alt": "Incognito mode is on. Toggle to turn off.",
"incognito-mode-label": "Incognito Mode",
"next": "Next",
"previous": "Previous"
"previous": "Previous",
"go-to-page-prompt": "There are {{totalPages}} pages. What page do you want to go to?"
},
"personal-table-of-contents": {
@ -1474,7 +1474,8 @@
"layout-mode-switched": "Layout mode switched to Single due to insufficient space to render double layout",
"no-next-chapter": "No Next Chapter",
"no-prev-chapter": "No Previous Chapter",
"user-preferences-updated": "User preferences updated"
"user-preferences-updated": "User preferences updated",
"emulate-comic-book-label": "{{user-preferences.emulate-comic-book-label}}"
},
"metadata-filter": {
@ -1787,7 +1788,8 @@
"details": "Details",
"view-series": "View Series",
"clear": "Clear",
"import-cbl": "Import CBL"
"import-cbl": "Import CBL",
"read": "Read"
},
"preferences": {

View file

@ -405,5 +405,11 @@
"chapter-missing": "{{series}}: Capítulo {{chapter}} no presente en Kavita. Este item será saltado.",
"empty-file": "El archivo CBL está vacío. Ninguna acción realizada.",
"name-conflict": "Una lista de lectura que coincide con el archivo CBL ({{readingListName}}) ya existe en tu cuenta."
},
"library-type-pipe": {
"manga": "Manga"
},
"age-rating-pipe": {
"unknown": "Desconocido"
}
}

File diff suppressed because it is too large Load diff

View file

@ -47,7 +47,7 @@
"chapter-read": "",
"score-updated": "",
"want-to-read-add": "読みたい:追加",
"want-to-read-remove": "",
"want-to-read-remove": "読みたい:消除",
"review": ""
},
"spoiler": {
@ -56,7 +56,7 @@
"review-series-modal": {
"title": "",
"tagline-label": "",
"review-label": "",
"review-label": "レビュー",
"close": "",
"save": ""
},
@ -69,7 +69,7 @@
"review-card": {
"your-review": "",
"external-review": "",
"local-review": "",
"local-review": "レビュー",
"rating-percentage": ""
},
"want-to-read": {
@ -239,7 +239,7 @@
"save": ""
},
"api-key": {
"copy": "",
"copy": "コピー",
"regen-warning": "",
"no-key": "",
"confirm-reset": "",
@ -312,7 +312,7 @@
"path-placeholder": "",
"instructions": "",
"type-header": "",
"name-header": "",
"name-header": "名前",
"cancel": "",
"share": "",
"help": ""
@ -339,13 +339,13 @@
"custom": ""
},
"day-of-week-pipe": {
"monday": "",
"tuesday": "",
"wednesday": "",
"thursday": "",
"friday": "",
"saturday": "",
"sunday": ""
"monday": "月曜日",
"tuesday": "火曜日",
"wednesday": "水曜日",
"thursday": "木曜日",
"friday": "金曜日",
"saturday": "土曜日",
"sunday": "日曜日"
},
"cbl-import-result-pipe": {
"success": "",
@ -388,9 +388,9 @@
"adaptation": "",
"alternative-setting": "",
"alternative-version": "",
"character": "",
"character": "キャラクター",
"contains": "",
"doujinshi": "",
"doujinshi": "同人誌",
"other": "",
"prequel": "",
"sequel": "",
@ -540,7 +540,7 @@
"next-chapter": "",
"skip-header": "",
"virtual-pages": "",
"settings-header": "",
"settings-header": "設定",
"table-of-contents-header": "",
"bookmarks-header": "",
"toc-header": "",
@ -548,7 +548,7 @@
"go-back": "",
"incognito-mode-alt": "",
"incognito-mode-label": "",
"next": "",
"next": "次へ",
"previous": ""
},
"personal-table-of-contents": {
@ -583,7 +583,7 @@
"password-validation": ""
},
"register": {
"title": "",
"title": "登録",
"description": "",
"username-label": "",
"email-label": "",
@ -609,7 +609,7 @@
"add-to-want-to-read": "",
"edit-series-alt": "",
"download-series--tooltip": "",
"downloading-status": "",
"downloading-status": "ダウンロード中。。。",
"user-reviews-alt": "",
"storyline-tab": "",
"books-tab": "",
@ -1472,7 +1472,7 @@
"title": "",
"visualisation-label": "",
"data-table-label": "",
"year-header": "",
"year-header": "",
"count-header": ""
},
"server-stats": {
@ -1601,7 +1601,7 @@
"refresh-covers": "",
"analyze-files": "",
"settings": "",
"edit": "",
"edit": "編集",
"mark-as-read": "",
"mark-as-unread": "",
"scan-series": "",
@ -1613,8 +1613,8 @@
"add-to-reading-list": "",
"add-to-collection": "",
"send-to": "",
"delete": "",
"download": "",
"delete": "削除",
"download": "ダウンロード",
"read-incognito": "",
"details": "",
"view-series": "",
@ -1670,7 +1670,7 @@
"submit": "",
"email": "",
"read": "",
"loading": "",
"loading": "読み込み中。。。",
"username": "",
"password": "",
"promoted": "",

File diff suppressed because it is too large Load diff

View file

@ -140,211 +140,211 @@
"margin-book-label": "Marge",
"margin-book-tooltip": "Hoeveel ruimte aan elke kant van het scherm. Dit overschrijft naar 0 op mobiele apparaten, ongeacht deze instelling.",
"clients-opds-alert": "OPDS is niet ingeschakeld op deze server. Dit heeft geen invloed op Tachiyomi-gebruikers.",
"clients-opds-description": "",
"clients-api-key-tooltip": "",
"clients-opds-url-tooltip": "",
"reset": "",
"save": ""
"clients-opds-description": "Alle externe clients gebruiken de API-sleutel of de onderstaande verbindings-URL. Dit zijn net wachtwoorden, houd het privé.",
"clients-api-key-tooltip": "De API-sleutel is als een wachtwoord. Houd het geheim, houd het veilig.",
"clients-opds-url-tooltip": "OPDS URL",
"reset": "{{common.reset}}",
"save": "{{common.save}}"
},
"user-holds": {
"title": "",
"title": "Scrobble Holds",
"description": ""
},
"theme-manager": {
"title": "",
"looking-for-theme": "",
"looking-for-theme-continued": "",
"scan": "",
"site-themes": "",
"set-default": "",
"apply": "",
"applied": "",
"updated-toastr": "",
"scan-queued": ""
"title": "Thema Beheerder",
"looking-for-theme": "Op zoek naar een licht of e-inkt thema? We hebben enkele aangepaste thema's die u kunt gebruiken ",
"looking-for-theme-continued": "thema github.",
"scan": "Scan",
"site-themes": "Site Thema's",
"set-default": "Stel de standaard in",
"apply": "{{common.apply}}",
"applied": "Toegepast",
"updated-toastr": "Sitestandaard is bijgewerkt naar {{name}}",
"scan-queued": "Er is een sitethema-scan in de wachtrij geplaatst"
},
"restriction-selector": {
"title": "",
"description": "",
"not-applicable-for-admins": "",
"age-rating-label": "",
"no-restriction": "",
"include-unknowns-label": "",
"include-unknowns-tooltip": ""
"title": "Beperking leeftijdsclassificatie",
"description": "Indien geselecteerd, worden alle series en leeslijsten met ten minste één item dat groter is dan de geselecteerde beperking, uit de resultaten verwijderd.",
"not-applicable-for-admins": "Dit is niet van toepassing op beheerders.",
"age-rating-label": "Leeftijdsclassificatie",
"no-restriction": "Geen beperkingen",
"include-unknowns-label": "Inclusief onbekenden",
"include-unknowns-tooltip": "Als dit waar is, zijn onbekenden toegestaan met leeftijdsbeperking. Dit kan ertoe leiden dat niet-gecodeerde media uitlekken naar gebruikers met leeftijdsbeperkingen."
},
"site-theme-provider-pipe": {
"system": "",
"user": ""
"system": "Systeem",
"user": "Gebruiker"
},
"manage-devices": {
"title": "",
"description": "",
"devices-title": "",
"no-devices": "",
"platform-label": "",
"email-label": "",
"add": "",
"title": "Apparaat beheerder",
"description": "Deze sectie is bedoeld voor het instellen van apparaten die geen verbinding kunnen maken met Kavita via een webbrowser en in plaats daarvan een e-mailadres hebben dat bestanden accepteert.",
"devices-title": "Apparaten",
"no-devices": "Er zijn nog geen apparaten ingesteld",
"platform-label": "Platform: ",
"email-label": "Email: ",
"add": "{{common.add}}",
"delete": "{{common.delete}}",
"edit": "{{common.edit}}"
},
"edit-device": {
"device-name-label": "",
"email-label": "",
"email-tooltip": "",
"device-platform-label": "",
"save": "",
"required-field": "",
"valid-email": ""
"device-name-label": "Apparaat naam",
"email-label": "{{common.email}}",
"email-tooltip": "Dit e-mailadres wordt gebruikt om het bestand via Verzenden naar te accepteren",
"device-platform-label": "Apparaatplatform",
"save": "{{common.save}}",
"required-field": "{{validation.required-field}}",
"valid-email": "{{validation.valid-email}}"
},
"change-password": {
"password-label": "",
"current-password-label": "",
"new-password-label": "",
"confirm-password-label": "",
"reset": "",
"edit": "",
"cancel": "",
"save": "",
"required-field": "",
"passwords-must-match": "",
"permission-error": ""
"password-label": "{{common.password}}",
"current-password-label": "Huidig wachtwoord",
"new-password-label": "Nieuw Wachtwoord",
"confirm-password-label": "Bevestig wachtwoord",
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}",
"required-field": "{{validation.required-field}}",
"passwords-must-match": "Wachtwoorden moeten overeenkomen",
"permission-error": "U heeft geen toestemming om uw wachtwoord te wijzigen. Neem contact op met de beheerder van de server."
},
"change-email": {
"email-label": "",
"current-password-label": "",
"email-not-confirmed": "",
"email-updated-title": "",
"email-updated-description": "",
"setup-user-account": "",
"invite-url-label": "",
"invite-url-tooltip": "",
"permission-error": "",
"required-field": "",
"reset": "",
"edit": "",
"cancel": "",
"save": ""
"email-label": "{{common.email}}",
"current-password-label": "Huidig paswoord",
"email-not-confirmed": "Deze e-mail is niet bevestigd",
"email-updated-title": "E-mail bijgewerkt",
"email-updated-description": "U kunt de volgende link hieronder gebruiken om de e-mail voor uw account te bevestigen. Als uw server extern toegankelijk is, is er een e-mail naar de e-mail verzonden en kan de link worden gebruikt om de e-mail te bevestigen.",
"setup-user-account": "Gebruikersaccount instellen",
"invite-url-label": "Uitnodigings-URL",
"invite-url-tooltip": "Kopieer dit en plak in een nieuw tabblad",
"permission-error": "U heeft geen toestemming om uw e-mailadres te wijzigen. Neem contact op met de beheerder van de server.",
"required-field": "{{validation.required-field}}",
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"change-age-restriction": {
"age-restriction-label": "",
"unknowns": "",
"reset": "",
"edit": "",
"cancel": "",
"save": ""
"age-restriction-label": "Leeftijdsbeperking",
"unknowns": "Onbekenden",
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"api-key": {
"copy": "",
"regen-warning": "",
"no-key": "",
"confirm-reset": "",
"key-reset": ""
"copy": "Kopie",
"regen-warning": "Door uw API-sleutel opnieuw te genereren, worden alle bestaande clients ongeldig.",
"no-key": "FOUT - SLEUTEL NIET INGESTELD",
"confirm-reset": "Hierdoor worden alle OPDS-configuraties die u hebt ingesteld, ongeldig. Weet je zeker dat je door wilt gaan?",
"key-reset": "API-sleutel reset"
},
"scrobbling-providers": {
"title": "",
"requires": "",
"token-expired": "",
"no-token-set": "",
"token-set": "",
"generate": "",
"instructions": "",
"token-input-label": "",
"edit": "",
"cancel": "",
"save": ""
"requires": "Voor deze functie is een actieve {{product}} licentie vereist",
"token-expired": "Token verlopen",
"no-token-set": "Geen Token Ingesteld",
"token-set": "Token Ingesteld",
"generate": "Genereer",
"instructions": "Nieuwe gebruikers moeten hieronder op \"{{scrobbling-providers.generate}}\" klikken om Kavita+ toe te staan te praten met {{service}}. Nadat u het programma hebt geautoriseerd, kopieert en plakt u het token in de onderstaande invoer. U kunt uw token op elk moment opnieuw genereren.",
"token-input-label": "{{service}} Token komt hier",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"typeahead": {
"locked-field": "",
"close": "",
"loading": "",
"add-item": "",
"no-data": "",
"add-custom-item": ""
"locked-field": "Veld is vergrendeld",
"close": "{{common.close}}",
"loading": "{{common.loading}}",
"add-item": "{{item}} toevoegen…",
"no-data": "Geen data",
"add-custom-item": ", typ om een gepersonaliseerd item toe te voegen"
},
"generic-list-modal": {
"close": "",
"clear": "",
"filter": "",
"open-filtered-search": ""
"close": "{{common.close}}",
"clear": "Wissen",
"filter": "Filter",
"open-filtered-search": "Open een gefilterde zoekopdracht voor {{item}}"
},
"user-stats-info-cards": {
"total-pages-read-label": "",
"total-pages-read-tooltip": "",
"total-words-read-label": "",
"total-words-read-tooltip": "",
"time-spent-reading-label": "",
"time-spent-reading-tooltip": "",
"chapters-read-label": "",
"chapters-read-tooltip": "",
"avg-reading-per-week-label": "",
"last-active-label": "",
"chapters": ""
"total-pages-read-label": "Totaal pagina's gelezen",
"total-pages-read-tooltip": "{{user-stats-info-cards.total-pages-read-label}}: {{value}}",
"total-words-read-label": "Totaal gelezen woorden",
"total-words-read-tooltip": "{{user-stats-info-cards.total-words-read-label}}: {{value}}",
"time-spent-reading-label": "Tijd besteed aan lezen",
"time-spent-reading-tooltip": "{{user-stats-info-cards.time-spent-reading-label}}: {{value}}",
"chapters-read-label": "Hoofdstukken gelezen",
"chapters-read-tooltip": "{{user-stats-info-cards.chapters-read-label}}: {{value}}",
"avg-reading-per-week-label": "Gemiddelde lezing / week",
"last-active-label": "Laatst actief",
"chapters": "{{value}} hoofdstukken"
},
"user-stats": {
"library-read-progress-title": "",
"read-percentage": ""
"library-read-progress-title": "Leesvoortgang bibliotheek",
"read-percentage": "% gelezen"
},
"top-readers": {
"title": "",
"time-selection-label": "",
"comics-label": "",
"manga-label": "",
"books-label": "",
"this-week": "",
"last-7-days": "",
"last-30-days": "",
"last-90-days": "",
"last-year": "",
"all-time": ""
"title": "Toplezers",
"time-selection-label": "Tijdsbestek",
"comics-label": "Strips: {{value}} uur",
"manga-label": "Manga: {{value}} uur",
"books-label": "Boeken: {{value}} uur",
"this-week": "{{time-periods.this-week}}",
"last-7-days": "{{time-periods.last-7-days}}",
"last-30-days": "{{time-periods.last-30-days}}",
"last-90-days": "{{time-periods.last-90-days}}",
"last-year": "{{time-periods.last-year}}",
"all-time": "{{time-periods.all-time}}"
},
"role-selector": {
"title": ""
"title": "Rollen"
},
"directory-picker": {
"title": "",
"close": "",
"path-label": "",
"path-placeholder": "",
"instructions": "",
"type-header": "",
"name-header": "",
"cancel": "",
"share": "",
"help": ""
"title": "Kies een map",
"close": "{{common.close}}",
"path-label": "Pad",
"path-placeholder": "Begin met typen of selecteer pad",
"instructions": "Selecteer een map om breadcrumb te bekijken. Zie je je directory niet? Probeer eerst / te controleren.",
"type-header": "Type",
"name-header": "Naam",
"cancel": "{{common.cancel}}",
"share": "Deel",
"help": "{{common.help}}"
},
"library-access-modal": {
"select-all": "",
"deselect-all": "",
"title": "",
"close": "",
"reset": "",
"cancel": "",
"save": "",
"no-data": ""
"select-all": "{{common.select-all}}",
"deselect-all": "{{common.deselect-all}}",
"title": "Bibliotheek toegang",
"close": "{{common.close}}",
"reset": "{{common.reset}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}",
"no-data": "Er zijn nog geen bibliotheken ingesteld."
},
"time-periods": {
"this-week": "",
"last-7-days": "",
"last-30-days": "",
"last-90-days": "",
"last-year": "",
"all-time": ""
"this-week": "Deze Week",
"last-7-days": "Laatste 7 dagen",
"last-30-days": "Laatste 30 dagen",
"last-90-days": "Laatste 90 dagen",
"last-year": "Vorig jaar",
"all-time": "Altijd"
},
"device-platform-pipe": {
"custom": ""
"custom": "Op maat"
},
"day-of-week-pipe": {
"monday": "",
"tuesday": "",
"wednesday": "",
"thursday": "",
"friday": "",
"saturday": "",
"sunday": ""
"monday": "Maandag",
"tuesday": "Dinsdag",
"wednesday": "Woensdag",
"thursday": "Donderdag",
"friday": "Vrijdag",
"saturday": "Zaterdag",
"sunday": "Zondag"
},
"cbl-import-result-pipe": {
"success": "",
"partial": "",
"failure": ""
"success": "Succes",
"partial": "Gedeeltelijk",
"failure": "Mislukt"
},
"cbl-conflict-reason-pipe": {
"all-series-missing": "",
@ -1627,5 +1627,11 @@
"issue-num": "",
"chapter-num": "",
"volume-num": ""
},
"theme": {
"theme-dark": "Donker",
"theme-black": "Zwart",
"theme-paper": "Papier",
"theme-white": "Wit"
}
}

View file

@ -12,166 +12,166 @@
"server-settings-link": "Definições do servidor",
"not-granted": "Não lhe foi atribuído acesso a nenhuma biblioteca.",
"on-deck-title": "",
"recently-updated-title": "",
"recently-added-title": ""
"recently-updated-title": "Séries Atualizadas Recentemente",
"recently-added-title": "Séries Adicionadas Recentemente"
},
"edit-user": {
"edit": "",
"close": "",
"username": "",
"required": "",
"email": "",
"not-valid-email": "",
"cancel": "",
"saving": "",
"update": ""
"edit": "{{common.edit}}",
"close": "{{common.close}}",
"username": "{{common.username}}",
"required": "{{validation.required-field}}",
"email": "{{common.email}}",
"not-valid-email": "{{validation.valid-email}}",
"cancel": "{{common.cancel}}",
"saving": "A Guardar…",
"update": "Atualizar"
},
"user-scrobble-history": {
"title": "",
"description": "",
"filter-label": "",
"created-header": "",
"last-modified-header": "",
"type-header": "",
"series-header": "",
"data-header": "",
"is-processed-header": "",
"no-data": "",
"volume-and-chapter-num": "",
"rating": "",
"not-applicable": "",
"processed": "",
"not-processed": ""
"filter-label": "Filtro",
"created-header": "Criado",
"last-modified-header": "Última alteração",
"type-header": "Tipo",
"series-header": "Séries",
"data-header": "Dados",
"is-processed-header": "Processado",
"no-data": "Sem Dados",
"volume-and-chapter-num": "Volume {{v}} Capítulo {{n}}",
"rating": "Classificação {{r}}",
"not-applicable": "Não Aplicável",
"processed": "Processado",
"not-processed": "Não Processado"
},
"scrobble-event-type-pipe": {
"chapter-read": "",
"score-updated": "",
"score-updated": "Atualização de Classificação",
"want-to-read-add": "",
"want-to-read-remove": "",
"review": ""
"review": "Atualização de crítica"
},
"spoiler": {
"click-to-show": ""
},
"review-series-modal": {
"title": "",
"title": "Editar Crítica",
"tagline-label": "",
"review-label": "",
"close": "",
"save": ""
"review-label": "Crítica",
"close": "{{common.close}}",
"save": "{{common.save}}"
},
"review-card-modal": {
"close": "",
"user-review": "",
"external-mod": "",
"go-to-review": ""
"close": "{{common.close}}",
"user-review": "Crítica de {{username}}",
"external-mod": "(externo/a)",
"go-to-review": "Ir Para Crítica"
},
"review-card": {
"your-review": "",
"external-review": "",
"local-review": "",
"rating-percentage": ""
"your-review": "Esta é a sua crítica",
"external-review": "Crítica externa",
"local-review": "Crítica",
"rating-percentage": "Classificação {{r}}%"
},
"want-to-read": {
"title": "",
"series-count": "",
"no-items": "",
"no-items-filtered": ""
"title": "Leituras Futuras",
"series-count": "{{common.series-count}}",
"no-items": "Não existem itens. Tente adicionar uma série.",
"no-items-filtered": "Não existem itens para o filtro atual."
},
"user-preferences": {
"title": "",
"pref-description": "",
"account-tab": "",
"preferences-tab": "",
"3rd-party-clients-tab": "",
"theme-tab": "",
"devices-tab": "",
"stats-tab": "",
"pref-description": "Estas definições globais estão ligadas à sua conta.",
"account-tab": "Conta",
"preferences-tab": "Preferências",
"3rd-party-clients-tab": "Clientes de Terceiros",
"theme-tab": "Tema",
"devices-tab": "Dispositivos",
"stats-tab": "Estatísticas",
"scrobbling-tab": "",
"success-toast": "",
"global-settings-title": "",
"success-toast": "Preferências de utilizador atualizadas",
"global-settings-title": "Definições globais",
"page-layout-mode-label": "",
"page-layout-mode-tooltip": "",
"locale-label": "",
"locale-tooltip": "",
"blur-unread-summaries-label": "",
"blur-unread-summaries-tooltip": "",
"prompt-on-download-label": "",
"prompt-on-download-tooltip": "",
"disable-animations-label": "",
"disable-animations-tooltip": "",
"collapse-series-relationships-label": "",
"locale-tooltip": "O idiota que o Kavita deve usar",
"blur-unread-summaries-label": "Ofuscar sumários não lidos",
"blur-unread-summaries-tooltip": "Ofusca o sumário em volumes ou capítulos que não tenham leitura em curso (para evitar spoilers)",
"prompt-on-download-label": "Aviso nos Downloads",
"prompt-on-download-tooltip": "Aviso quando um download excede {{size}}MB de tamanho",
"disable-animations-label": "Desabilitar animações",
"disable-animations-tooltip": "Desligar animações no site. Útil para leitores e-ink.",
"collapse-series-relationships-label": "Colapsar Relações de Séries",
"collapse-series-relationships-tooltip": "",
"share-series-reviews-label": "",
"share-series-reviews-tooltip": "",
"share-series-reviews-label": "Partilhar Críticas de Séries",
"share-series-reviews-tooltip": "As suas críticas de Séries devem ser incluídas para outros utilizadores pelo Kavita",
"image-reader-settings-title": "",
"reading-direction-label": "",
"reading-direction-label": "Direção de Leitura",
"reading-direction-tooltip": "",
"scaling-option-label": "",
"scaling-option-tooltip": "",
"scaling-option-label": "Opções de Dimensionamento",
"scaling-option-tooltip": "Como adaptar a dimensão da imagem ao seu ecrã.",
"page-splitting-label": "",
"page-splitting-tooltip": "",
"reading-mode-label": "",
"reading-mode-label": "Modo de Leitura",
"layout-mode-label": "",
"layout-mode-tooltip": "",
"background-color-label": "",
"auto-close-menu-label": "",
"background-color-label": "Cor de Fundo",
"auto-close-menu-label": "Fechar Menu Automaticamente",
"show-screen-hints-label": "",
"emulate-comic-book-label": "",
"swipe-to-paginate-label": "",
"book-reader-settings-title": "",
"tap-to-paginate-label": "",
"tap-to-paginate-tooltip": "",
"immersive-mode-label": "",
"immersive-mode-label": "Modo Imersivo",
"immersive-mode-tooltip": "",
"reading-direction-book-label": "",
"reading-direction-book-label": "Direção de Leitura",
"reading-direction-book-tooltip": "",
"font-family-label": "",
"font-family-tooltip": "",
"writing-style-label": "",
"writing-style-tooltip": "",
"writing-style-tooltip": "Muda a direção do texto. Horizontal é da esquerda para direita, vertical é do topo para o fundo.",
"layout-mode-book-label": "",
"layout-mode-book-tooltip": "",
"color-theme-book-label": "",
"color-theme-book-label": "Tema de Cor",
"color-theme-book-tooltip": "",
"font-size-book-label": "",
"line-height-book-label": "",
"line-height-book-tooltip": "",
"margin-book-label": "",
"margin-book-tooltip": "",
"clients-opds-alert": "",
"clients-opds-description": "",
"clients-api-key-tooltip": "",
"clients-opds-url-tooltip": "",
"reset": "",
"save": ""
"line-height-book-label": "Espaçamento Entre Linhas",
"line-height-book-tooltip": "Quanto espaçamento entre as linhas do livro",
"margin-book-label": "Margem",
"margin-book-tooltip": "Espaçamento em cada lado do ecrã. Nos dispositivos móveis o valor desta definição será sempre substituído por 0.",
"clients-opds-alert": "O OPDS não está habilitado neste servidor. Isto não irá afectar os utilizadores do Tachiyomi.",
"clients-opds-description": "Todos os clientes de terceiros utilizarão a chave de API ou URL abaixo. Estes elementos são semelhantes a palavras passe, mantenha-os privados.",
"clients-api-key-tooltip": "A chave de API é como uma palavra passe. Mantenha-a privada e em segurança.",
"clients-opds-url-tooltip": "URL OPDS",
"reset": "{{common.reset}}",
"save": "{{common.save}}"
},
"user-holds": {
"title": "",
"description": ""
},
"theme-manager": {
"title": "",
"looking-for-theme": "",
"looking-for-theme-continued": "",
"title": "Gestor de Temas",
"looking-for-theme": "À procura de um tema 'light' ou e-ink? Pode encontrar alguns temas customizados no nosso ",
"looking-for-theme-continued": "github de temas.",
"scan": "",
"site-themes": "",
"set-default": "",
"apply": "",
"site-themes": "Temas do Site",
"set-default": "Tema Por Defeito",
"apply": "{{common.apply}}",
"applied": "",
"updated-toastr": "",
"updated-toastr": "O tema por defeito do site foi atualizado para {{name}}",
"scan-queued": ""
},
"theme": {
"theme-dark": "",
"theme-black": "",
"theme-paper": "",
"theme-white": ""
"theme-dark": "Escuro",
"theme-black": "Preto",
"theme-paper": "Papel",
"theme-white": "Branco"
},
"restriction-selector": {
"title": "",
"description": "",
"not-applicable-for-admins": "",
"description": "Quando selecionado, todas as séries e listas de leitura, que tenham pelo menos um elemento que seja superior à restrição selecionada, serão removidas dos resultados.",
"not-applicable-for-admins": "Não aplicável a administradores.",
"age-rating-label": "",
"no-restriction": "",
"include-unknowns-label": "",
@ -206,70 +206,70 @@
"current-password-label": "",
"new-password-label": "",
"confirm-password-label": "",
"reset": "",
"edit": "",
"cancel": "",
"save": "",
"required-field": "",
"passwords-must-match": "",
"permission-error": ""
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}",
"required-field": "{{validation.required-field}}",
"passwords-must-match": "As palavras passe têm de ser iguais",
"permission-error": "Não tem permissões para alterar a sua palavra passe. Contacte o administrador do servidor."
},
"change-email": {
"email-label": "",
"current-password-label": "",
"email-not-confirmed": "",
"email-updated-title": "",
"email-updated-description": "",
"setup-user-account": "",
"invite-url-label": "",
"invite-url-tooltip": "",
"permission-error": "",
"required-field": "",
"reset": "",
"edit": "",
"cancel": "",
"save": ""
"email-label": "{{common.email}}",
"current-password-label": "Palavra Passe Atual",
"email-not-confirmed": "Este email não está confirmado",
"email-updated-title": "Email Atualizado",
"email-updated-description": "Pode usar o link abaixo para confirmar o endereço de email da sua conta. Se o seu servidor tiver acesso externo, um email terá sido enviado para o seu endereço e o link pode ser usado para confirmar o endereço.",
"setup-user-account": "Configurar conta de utilizador",
"invite-url-label": "Url de Convite",
"invite-url-tooltip": "Copie e cole o url numa nova aba",
"permission-error": "Não tem permissões para alterar o seu email. Contacte o administrador do servidor.",
"required-field": "{{validation.required-field}}",
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"change-age-restriction": {
"age-restriction-label": "",
"unknowns": "",
"reset": "",
"edit": "",
"cancel": "",
"save": ""
"age-restriction-label": "Restrição Etária",
"unknowns": "Desconhecidos",
"reset": "{{common.reset}}",
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"api-key": {
"copy": "",
"regen-warning": "",
"copy": "Copiar",
"regen-warning": "Se recriar a chave da API, os clientes de terceiros existentes deixarão de ter acesso.",
"no-key": "",
"confirm-reset": "",
"key-reset": ""
"confirm-reset": "Isto irá invalidar todas as configurações OPDS. Tem a certeza que deseja continuar?",
"key-reset": "Repor chave da API"
},
"scrobbling-providers": {
"title": "",
"requires": "",
"token-expired": "",
"no-token-set": "",
"token-set": "",
"generate": "",
"requires": "Esta funcionalidade requer uma licença {{product}} ativa",
"token-expired": "Token Expirado",
"no-token-set": "Token Não Definido",
"token-set": "Token Definido",
"generate": "Gerar",
"instructions": "",
"token-input-label": "",
"edit": "",
"cancel": "",
"save": ""
"edit": "{{common.edit}}",
"cancel": "{{common.cancel}}",
"save": "{{common.save}}"
},
"typeahead": {
"locked-field": "",
"close": "",
"loading": "",
"add-item": "",
"no-data": "",
"locked-field": "Campo bloqueado",
"close": "{{common.close}}",
"loading": "{{common.loading}}",
"add-item": "Adicionar {{item}}…",
"no-data": "Sem dados",
"add-custom-item": ""
},
"generic-list-modal": {
"close": "",
"clear": "",
"filter": "",
"close": "{{common.close}}",
"clear": "Limpar",
"filter": "Filtro",
"open-filtered-search": ""
},
"user-stats-info-cards": {

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@
},
"user-scrobble-history": {
"title": "ประวัติการทำ Scrobble",
"description": "",
"description": "ที่นี่คุณสามารถดูรายการ Scrobble ที่เกิดขึ้นภายใต้บัญชีคุณได้ โดยรายการจะเกิดขึ้นก็ต่อเมื่อคุณได้ตั้งค่า Scrobble เรียบร้อยแล้ว รายการต่างๆ จะถูกลบเมื่อผ่านไปหนึ่งเดือน ถ้ามีรายการที่ยังไม่ถูกประมวลผล นั่นหมายความว่าอาจเกิดปัญหาที่ต้นทาง กรุณาติดต่อผู้ดูแลระบบเพื่อแก้ไขปัญหานี้",
"filter-label": "ตัวกรอง",
"created-header": "สร้างแล้ว",
"last-modified-header": "แก้ไขล่าสุด",
@ -90,42 +90,42 @@
"scrobbling-tab": "การดึงข้อมูลภายนอก",
"success-toast": "อัปเดทการตั้งค่าแล้ว",
"global-settings-title": "ตั้งค่าส่วนกลาง",
"page-layout-mode-label": "",
"page-layout-mode-tooltip": "",
"locale-label": "",
"locale-tooltip": "",
"blur-unread-summaries-label": "",
"blur-unread-summaries-tooltip": "",
"prompt-on-download-label": "",
"prompt-on-download-tooltip": "",
"disable-animations-label": "",
"disable-animations-tooltip": "",
"collapse-series-relationships-label": "",
"collapse-series-relationships-tooltip": "",
"share-series-reviews-label": "",
"share-series-reviews-tooltip": "",
"image-reader-settings-title": "",
"reading-direction-label": "",
"reading-direction-tooltip": "",
"scaling-option-label": "",
"scaling-option-tooltip": "",
"page-splitting-label": "",
"page-splitting-tooltip": "",
"reading-mode-label": "",
"layout-mode-label": "",
"layout-mode-tooltip": "",
"background-color-label": "",
"auto-close-menu-label": "",
"show-screen-hints-label": "",
"emulate-comic-book-label": "",
"swipe-to-paginate-label": "",
"book-reader-settings-title": "",
"tap-to-paginate-label": "",
"tap-to-paginate-tooltip": "",
"immersive-mode-label": "",
"immersive-mode-tooltip": "",
"reading-direction-book-label": "",
"reading-direction-book-tooltip": "",
"page-layout-mode-label": "รูปแบบหน้าจอ",
"page-layout-mode-tooltip": "แสดงหนังสือในรูปแบบการ์ดหรือรายการบนหน้ารายละเอียดซีรีย์",
"locale-label": "ภาษา",
"locale-tooltip": "ภาษาที่ใช้งานบน Kavita",
"blur-unread-summaries-label": "เบลอบทสรุปที่ยังไม่ได้อ่าน",
"blur-unread-summaries-tooltip": "เบลอข้อความสรุปในเล่มหรือบทที่ไม่มีความคืบหน้าในการอ่าน (เพื่อหลีกเลี่ยงการสปอยล์)",
"prompt-on-download-label": "แจ้งเตือนเมื่อดาวน์โหลด",
"prompt-on-download-tooltip": "แจ้งเมื่อการดาวน์โหลดมีขนาดเกิน {{size}} MB",
"disable-animations-label": "ปิดการใช้งานแอนิเมชั่น",
"disable-animations-tooltip": "ปิดภาพเคลื่อนไหว ใช้งานได้ดีสำหรับผู้ใช้เครื่อง e-ink",
"collapse-series-relationships-label": "ยุบความสัมพันธ์ของซีรี่ส์",
"collapse-series-relationships-tooltip": "Kavita ควรแสดงซีรีส์ที่ไม่มีความสัมพันธ์หรือเป็นพาเรนต์/พรีเควล",
"share-series-reviews-label": "แบ่งปันบทวิจารณ์ซีรีส์",
"share-series-reviews-tooltip": "Kavita ควรรวมบทวิจารณ์ซีรี่ส์ของคุณสำหรับผู้ใช้รายอื่นหรือไม่",
"image-reader-settings-title": "โปรแกรมอ่านรูปภาพ",
"reading-direction-label": "ทิศทางการอ่าน",
"reading-direction-tooltip": "ทิศทางการคลิกเพื่อไปยังหน้าถัดไป ขวาไปซ้าย หมายถึงคุณคลิกที่ด้านซ้ายของหน้าจอเพื่อไปยังหน้าถัดไป",
"scaling-option-label": "ตัวเลือกการปรับขนาด",
"scaling-option-tooltip": "วิธีปรับขนาดภาพให้พอดีกับหน้าจอของคุณ",
"page-splitting-label": "การแยกหน้า",
"page-splitting-tooltip": "วิธีแยกภาพเต็มความกว้าง (เช่น รวมภาพซ้ายและขวาเข้าด้วยกัน)",
"reading-mode-label": "โหมดการอ่าน",
"layout-mode-label": "โหมดเค้าโครง",
"layout-mode-tooltip": "เรนเดอร์ภาพเดียวไปที่หน้าจอหรือสองภาพเคียงข้างกัน",
"background-color-label": "สีพื้นหลัง",
"auto-close-menu-label": "ปิดเมนูอัตโนมัติ",
"show-screen-hints-label": "แสดงคำแนะนำบนหน้าจอ",
"emulate-comic-book-label": "เลียนแบบหนังสือการ์ตูน",
"swipe-to-paginate-label": "ปัดเพื่อเปลี่ยนหน้า",
"book-reader-settings-title": "เครื่องอ่านหนังสือ",
"tap-to-paginate-label": "แตะเพื่อเปลี่ยนหน้า",
"tap-to-paginate-tooltip": "อนุญาตให้แตะมุมหนังสือเพื่อเลื่อนไปยังหน้าก่อนหน้า/ถัดไป",
"immersive-mode-label": "โหมดดื่มด่ำ",
"immersive-mode-tooltip": "วิธีนี้จะซ่อนเมนูหลังการคลิกบนเอกสารของผู้อ่านและเปิดการแตะเพื่อแบ่งหน้า",
"reading-direction-book-label": "ทิศทางการอ่าน",
"reading-direction-book-tooltip": "ทิศทางการคลิกเพื่อไปยังหน้าถัดไป ขวาไปซ้าย หมายถึงคุณคลิกที่ด้านซ้ายของหน้าจอเพื่อไปยังหน้าถัดไป",
"font-family-label": "",
"font-family-tooltip": "",
"writing-style-label": "",

View file

@ -1,5 +1,9 @@
/// <reference types="@angular/localize" />
import {APP_INITIALIZER, importProvidersFrom, isDevMode} from '@angular/core';
import {
APP_INITIALIZER, ApplicationConfig,
importProvidersFrom,
isDevMode,
} from '@angular/core';
import { AppComponent } from './app/app.component';
import { NgCircleProgressModule } from 'ng-circle-progress';
import { ToastrModule } from 'ngx-toastr';
@ -9,18 +13,20 @@ import { SAVER, getSaver } from './app/shared/_providers/saver.provider';
import { Title, BrowserModule, bootstrapApplication } from '@angular/platform-browser';
import { JwtInterceptor } from './app/_interceptors/jwt.interceptor';
import { ErrorInterceptor } from './app/_interceptors/error.interceptor';
import {HTTP_INTERCEPTORS, withInterceptorsFromDi, provideHttpClient, HttpClient} from '@angular/common/http';
import {TRANSLOCO_CONFIG, TranslocoConfig, TranslocoModule, TranslocoService} from "@ngneat/transloco";
import {environment} from "./environments/environment";
import {HttpLoader, translocoLoader} from "./httpLoader";
import {HTTP_INTERCEPTORS, withInterceptorsFromDi, provideHttpClient} from '@angular/common/http';
import {
TRANSLOCO_PERSIST_LANG_STORAGE,
TranslocoPersistLangModule,
provideTransloco,
TranslocoService
} from "@ngneat/transloco";
import {environment} from "./environments/environment";
import {HttpLoader} from "./httpLoader";
import {
provideTranslocoPersistLang,
} from '@ngneat/transloco-persist-lang';
import {PERSIST_TRANSLATIONS_STORAGE, TranslocoPersistTranslationsModule} from "@ngneat/transloco-persist-translations";
import {TranslocoLocaleModule} from "@ngneat/transloco-locale";
import {AccountService} from "./app/_services/account.service";
import {switchMap} from "rxjs";
import {provideTranslocoLocale} from "@ngneat/transloco-locale";
import {provideTranslocoPersistTranslations} from "@ngneat/transloco-persist-translations";
const disableAnimations = !('animate' in document.documentElement);
@ -40,6 +46,7 @@ export function preloadUser(userService: AccountService, transloco: TranslocoSer
};
}
export const preLoad = {
provide: APP_INITIALIZER,
multi: true,
@ -74,6 +81,23 @@ const languageCodes = [
'zh-SG', 'zh-TW', 'zu', 'zu-ZA', 'zh_Hans'
];
const translocoOptions = {
config: {
reRenderOnLangChange: true,
availableLangs: languageCodes,
prodMode: environment.production,
defaultLang: 'en',
fallbackLang: 'en',
missingHandler: {
useFallbackTranslation: true,
allowEmpty: false,
},
flatten: {
aot: !isDevMode()
}
}
};
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(BrowserModule,
@ -87,46 +111,26 @@ bootstrapApplication(AppComponent, {
autoDismiss: true
}),
NgCircleProgressModule.forRoot(),
TranslocoModule,
TranslocoPersistLangModule.forRoot({
storage: {
provide: TRANSLOCO_PERSIST_LANG_STORAGE,
useValue: localStorage,
},
}),
TranslocoLocaleModule.forRoot(),
TranslocoPersistTranslationsModule.forRoot({
loader: HttpLoader,
storage: {
provide: PERSIST_TRANSLATIONS_STORAGE,
useValue: sessionStorage
}
})
),
provideTransloco(translocoOptions),
provideTranslocoLocale({
defaultLocale: 'en'
}),
provideTranslocoPersistTranslations({
loader: HttpLoader,
storage: { useValue: localStorage }
}),
provideTranslocoPersistLang({
storage: {
useValue: localStorage,
},
}),
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
{
provide: TRANSLOCO_CONFIG,
useValue: {
reRenderOnLangChange: true,
availableLangs: languageCodes,
prodMode: environment.production,
defaultLang: 'en',
fallbackLang: 'en',
missingHandler: {
useFallbackTranslation: true,
allowEmpty: false,
},
flatten: {
aot: !isDevMode()
}
} as TranslocoConfig
},
preLoad,
Title,
{ provide: SAVER, useFactory: getSaver },
provideHttpClient(withInterceptorsFromDi())
]
})
} as ApplicationConfig)
.catch(err => console.error(err));