mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-04 22:25:36 -04:00
v0.8.3.2 - A Small Hotfix (#3194)
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com> Co-authored-by: Weblate (bot) <hosted@weblate.org> Co-authored-by: Havokdan <havokdan@yahoo.com.br> Co-authored-by: daydreamrabbit <devrabbit90@gmail.com> Co-authored-by: 無情天 <kofzhanganguo@126.com>
This commit is contained in:
parent
77de5ccce3
commit
894b49bb76
@ -549,12 +549,15 @@ public class OpdsController : BaseApiController
|
|||||||
Id = readingListDto.Id.ToString(),
|
Id = readingListDto.Id.ToString(),
|
||||||
Title = readingListDto.Title,
|
Title = readingListDto.Title,
|
||||||
Summary = readingListDto.Summary,
|
Summary = readingListDto.Summary,
|
||||||
Links = new List<FeedLink>()
|
Links =
|
||||||
{
|
[
|
||||||
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation, $"{prefix}{apiKey}/reading-list/{readingListDto.Id}"),
|
CreateLink(FeedLinkRelation.SubSection, FeedLinkType.AtomNavigation,
|
||||||
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image, $"{baseUrl}api/image/readinglist-cover?readingListId={readingListDto.Id}&apiKey={apiKey}"),
|
$"{prefix}{apiKey}/reading-list/{readingListDto.Id}"),
|
||||||
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image, $"{baseUrl}api/image/readinglist-cover?readingListId={readingListDto.Id}&apiKey={apiKey}")
|
CreateLink(FeedLinkRelation.Image, FeedLinkType.Image,
|
||||||
}
|
$"{baseUrl}api/image/readinglist-cover?readingListId={readingListDto.Id}&apiKey={apiKey}"),
|
||||||
|
CreateLink(FeedLinkRelation.Thumbnail, FeedLinkType.Image,
|
||||||
|
$"{baseUrl}api/image/readinglist-cover?readingListId={readingListDto.Id}&apiKey={apiKey}")
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,7 +576,7 @@ public class OpdsController : BaseApiController
|
|||||||
|
|
||||||
[HttpGet("{apiKey}/reading-list/{readingListId}")]
|
[HttpGet("{apiKey}/reading-list/{readingListId}")]
|
||||||
[Produces("application/xml")]
|
[Produces("application/xml")]
|
||||||
public async Task<IActionResult> GetReadingListItems(int readingListId, string apiKey)
|
public async Task<IActionResult> GetReadingListItems(int readingListId, string apiKey, [FromQuery] int pageNumber = 0)
|
||||||
{
|
{
|
||||||
var userId = await GetUser(apiKey);
|
var userId = await GetUser(apiKey);
|
||||||
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
|
||||||
@ -592,7 +595,7 @@ public class OpdsController : BaseApiController
|
|||||||
var feed = CreateFeed(readingList.Title + " " + await _localizationService.Translate(userId, "reading-list"), $"{apiKey}/reading-list/{readingListId}", apiKey, prefix);
|
var feed = CreateFeed(readingList.Title + " " + await _localizationService.Translate(userId, "reading-list"), $"{apiKey}/reading-list/{readingListId}", apiKey, prefix);
|
||||||
SetFeedId(feed, $"reading-list-{readingListId}");
|
SetFeedId(feed, $"reading-list-{readingListId}");
|
||||||
|
|
||||||
var items = (await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId)).ToList();
|
var items = await _unitOfWork.ReadingListRepository.GetReadingListItemDtosByIdAsync(readingListId, userId);
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
var chapterDto = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(item.ChapterId);
|
var chapterDto = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(item.ChapterId);
|
||||||
|
@ -345,7 +345,7 @@ public class SettingsController : BaseApiController
|
|||||||
|
|
||||||
if (updateBookmarks)
|
if (updateBookmarks)
|
||||||
{
|
{
|
||||||
BackgroundJob.Enqueue(() => UpdateBookmarkDirectory(originalBookmarkDirectory, bookmarkDirectory));
|
UpdateBookmarkDirectory(originalBookmarkDirectory, bookmarkDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateSettingsDto.EnableFolderWatching)
|
if (updateSettingsDto.EnableFolderWatching)
|
||||||
@ -371,6 +371,7 @@ public class SettingsController : BaseApiController
|
|||||||
return Ok(updateSettingsDto);
|
return Ok(updateSettingsDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void UpdateBookmarkDirectory(string originalBookmarkDirectory, string bookmarkDirectory)
|
private void UpdateBookmarkDirectory(string originalBookmarkDirectory, string bookmarkDirectory)
|
||||||
{
|
{
|
||||||
_directoryService.ExistOrCreate(bookmarkDirectory);
|
_directoryService.ExistOrCreate(bookmarkDirectory);
|
||||||
|
@ -9,7 +9,7 @@ public class ConfirmEmailDto
|
|||||||
[Required]
|
[Required]
|
||||||
public string Token { get; set; } = default!;
|
public string Token { get; set; } = default!;
|
||||||
[Required]
|
[Required]
|
||||||
[StringLength(32, MinimumLength = 6)]
|
[StringLength(256, MinimumLength = 6)]
|
||||||
public string Password { get; set; } = default!;
|
public string Password { get; set; } = default!;
|
||||||
[Required]
|
[Required]
|
||||||
public string Username { get; set; } = default!;
|
public string Username { get; set; } = default!;
|
||||||
|
@ -9,6 +9,6 @@ public class ConfirmPasswordResetDto
|
|||||||
[Required]
|
[Required]
|
||||||
public string Token { get; set; } = default!;
|
public string Token { get; set; } = default!;
|
||||||
[Required]
|
[Required]
|
||||||
[StringLength(32, MinimumLength = 6)]
|
[StringLength(256, MinimumLength = 6)]
|
||||||
public string Password { get; set; } = default!;
|
public string Password { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public class ResetPasswordDto
|
|||||||
/// The new password
|
/// The new password
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required]
|
[Required]
|
||||||
[StringLength(32, MinimumLength = 6)]
|
[StringLength(256, MinimumLength = 6)]
|
||||||
public string Password { get; init; } = default!;
|
public string Password { get; init; } = default!;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The old, existing password. If an admin is performing the change, this is not required. Otherwise, it is.
|
/// The old, existing password. If an admin is performing the change, this is not required. Otherwise, it is.
|
||||||
|
@ -11,6 +11,6 @@ public class RegisterDto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Email { get; init; } = default!;
|
public string Email { get; init; } = default!;
|
||||||
[Required]
|
[Required]
|
||||||
[StringLength(32, MinimumLength = 6)]
|
[StringLength(256, MinimumLength = 6)]
|
||||||
public string Password { get; set; } = default!;
|
public string Password { get; set; } = default!;
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,7 @@ public class CacheService : ICacheService
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("File Dimensions call for {Length} images took {Time}ms", dimensions.Count, sw.ElapsedMilliseconds);
|
_logger.LogDebug("File Dimensions call for {Length} images took {Time}ms", dimensions.Count, sw.ElapsedMilliseconds);
|
||||||
|
|
||||||
return dimensions;
|
return dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Company>kavitareader.com</Company>
|
<Company>kavitareader.com</Company>
|
||||||
<Product>Kavita</Product>
|
<Product>Kavita</Product>
|
||||||
<AssemblyVersion>0.8.3.1</AssemblyVersion>
|
<AssemblyVersion>0.8.3.2</AssemblyVersion>
|
||||||
<NeutralLanguage>en</NeutralLanguage>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
<TieredPGO>true</TieredPGO>
|
<TieredPGO>true</TieredPGO>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -168,7 +168,7 @@ $image-width: 160px;
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 110px;
|
max-width: 98px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
padding: var(--bs-dropdown-item-padding-y) 0;
|
padding: var(--bs-dropdown-item-padding-y) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
// Robbie added this but it broke most of the uses
|
// Robbie added this but it broke most of the uses
|
||||||
//.dropdown-toggle {
|
//.dropdown-toggle {
|
||||||
// padding-top: 0;
|
// padding-top: 0;
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
<ng-container *transloco="let t; read: 'details-tab'">
|
<ng-container *transloco="let t; read: 'details-tab'">
|
||||||
<div class="details pb-3">
|
<div class="details pb-3">
|
||||||
<div class="mb-3">
|
<div class="mb-3 ms-1">
|
||||||
<h4 class="header">{{t('genres-title')}}</h4>
|
<h4 class="header">{{t('genres-title')}}</h4>
|
||||||
|
<div class="ms-3">
|
||||||
<app-badge-expander [includeComma]="true" [items]="genres" [itemsTillExpander]="3">
|
<app-badge-expander [includeComma]="true" [items]="genres" [itemsTillExpander]="3">
|
||||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openGeneric(FilterField.Genres, item.id)">{{item.title}}</a>
|
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openGeneric(FilterField.Genres, item.id)">{{item.title}}</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-badge-expander>
|
</app-badge-expander>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3 ms-1">
|
||||||
<h4 class="header">{{t('tags-title')}}</h4>
|
<h4 class="header">{{t('tags-title')}}</h4>
|
||||||
|
<div class="ms-3">
|
||||||
<app-badge-expander [includeComma]="true" [items]="tags" [itemsTillExpander]="3">
|
<app-badge-expander [includeComma]="true" [items]="tags" [itemsTillExpander]="3">
|
||||||
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
<ng-template #badgeExpanderItem let-item let-position="idx" let-last="last">
|
||||||
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openGeneric(FilterField.Tags, item.id)">{{item.title}}</a>
|
<a href="javascript:void(0)" class="dark-exempt btn-icon" (click)="openGeneric(FilterField.Tags, item.id)">{{item.title}}</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</app-badge-expander>
|
</app-badge-expander>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<app-carousel-reel [items]="webLinks" [title]="t('weblinks-title')">
|
<app-carousel-reel [items]="webLinks" [title]="t('weblinks-title')">
|
||||||
@ -29,7 +33,7 @@
|
|||||||
</app-carousel-reel>
|
</app-carousel-reel>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (genres.length > 0 || tags.length > 0) {
|
@if (genres.length > 0 || tags.length > 0 || webLinks.length > 0) {
|
||||||
<div class="setting-section-break" aria-hidden="true"></div>
|
<div class="setting-section-break" aria-hidden="true"></div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
<p>{{t('description')}}</p>
|
<p>{{t('description')}}</p>
|
||||||
|
|
||||||
<form [formGroup]="settingsForm">
|
<form [formGroup]="settingsForm">
|
||||||
<p class="alert alert-warning">{{t('setting-description')}}</p>
|
<p class="alert alert-warning">{{t('setting-description')}} {{t('test-warning')}}</p>
|
||||||
|
|
||||||
@if (settingsForm.dirty) {
|
|
||||||
<div class="alert alert-warning">{{t('test-warning')}}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="row g-0 mt-2">
|
<div class="row g-0 mt-2">
|
||||||
@if (settingsForm.get('hostName'); as formControl) {
|
@if (settingsForm.get('hostName'); as formControl) {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, OnInit} from '@angular/core';
|
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, OnInit} from '@angular/core';
|
||||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||||
import {ToastrService} from 'ngx-toastr';
|
import {ToastrService} from 'ngx-toastr';
|
||||||
import {debounceTime, distinctUntilChanged, filter, switchMap, take, tap} from 'rxjs';
|
import {debounceTime, distinctUntilChanged, filter, map, switchMap, take, tap} from 'rxjs';
|
||||||
import {SettingsService} from '../settings.service';
|
import {SettingsService} from '../settings.service';
|
||||||
import {ServerSettings} from '../_models/server-settings';
|
import {ServerSettings} from '../_models/server-settings';
|
||||||
import {
|
import {
|
||||||
NgbAlert,
|
NgbAlert,
|
||||||
NgbTooltip
|
NgbTooltip
|
||||||
} from '@ng-bootstrap/ng-bootstrap';
|
} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {NgIf, NgTemplateOutlet, TitleCasePipe} from '@angular/common';
|
import {AsyncPipe, NgIf, NgTemplateOutlet, TitleCasePipe} from '@angular/common';
|
||||||
import {translate, TranslocoModule} from "@jsverse/transloco";
|
import {translate, TranslocoModule} from "@jsverse/transloco";
|
||||||
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
|
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
|
||||||
import {ManageMediaIssuesComponent} from "../manage-media-issues/manage-media-issues.component";
|
import {ManageMediaIssuesComponent} from "../manage-media-issues/manage-media-issues.component";
|
||||||
@ -25,7 +25,7 @@ import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
imports: [NgIf, ReactiveFormsModule, NgbTooltip, NgTemplateOutlet, TranslocoModule, SafeHtmlPipe,
|
imports: [NgIf, ReactiveFormsModule, NgbTooltip, NgTemplateOutlet, TranslocoModule, SafeHtmlPipe,
|
||||||
ManageMediaIssuesComponent, TitleCasePipe, NgbAlert, SettingItemComponent, SettingSwitchComponent, DefaultValuePipe, BytesPipe]
|
ManageMediaIssuesComponent, TitleCasePipe, NgbAlert, SettingItemComponent, SettingSwitchComponent, DefaultValuePipe, BytesPipe, AsyncPipe]
|
||||||
})
|
})
|
||||||
export class ManageEmailSettingsComponent implements OnInit {
|
export class ManageEmailSettingsComponent implements OnInit {
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import {allEncodeFormats} from '../_models/encode-format';
|
|||||||
import {ManageMediaIssuesComponent} from '../manage-media-issues/manage-media-issues.component';
|
import {ManageMediaIssuesComponent} from '../manage-media-issues/manage-media-issues.component';
|
||||||
import {NgFor, NgIf, NgTemplateOutlet} from '@angular/common';
|
import {NgFor, NgIf, NgTemplateOutlet} from '@angular/common';
|
||||||
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
|
import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
|
||||||
import {allCoverImageSizes} from '../_models/cover-image-size';
|
import {allCoverImageSizes, CoverImageSize} from '../_models/cover-image-size';
|
||||||
import {pageLayoutModes} from "../../_models/preferences/preferences";
|
import {pageLayoutModes} from "../../_models/preferences/preferences";
|
||||||
import {PageLayoutModePipe} from "../../_pipes/page-layout-mode.pipe";
|
import {PageLayoutModePipe} from "../../_pipes/page-layout-mode.pipe";
|
||||||
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
|
import {SettingItemComponent} from "../../settings/_components/setting-item/setting-item.component";
|
||||||
@ -62,7 +62,7 @@ export class ManageMediaSettingsComponent implements OnInit {
|
|||||||
this.serverSettings = settings;
|
this.serverSettings = settings;
|
||||||
this.settingsForm.addControl('encodeMediaAs', new FormControl(this.serverSettings.encodeMediaAs, [Validators.required]));
|
this.settingsForm.addControl('encodeMediaAs', new FormControl(this.serverSettings.encodeMediaAs, [Validators.required]));
|
||||||
this.settingsForm.addControl('bookmarksDirectory', new FormControl(this.serverSettings.bookmarksDirectory, [Validators.required]));
|
this.settingsForm.addControl('bookmarksDirectory', new FormControl(this.serverSettings.bookmarksDirectory, [Validators.required]));
|
||||||
this.settingsForm.addControl('coverImageSize', new FormControl(this.serverSettings.coverImageSize, [Validators.required]));
|
this.settingsForm.addControl('coverImageSize', new FormControl(this.serverSettings.coverImageSize || CoverImageSize.Default, [Validators.required]));
|
||||||
|
|
||||||
// Automatically save settings as we edit them
|
// Automatically save settings as we edit them
|
||||||
this.settingsForm.valueChanges.pipe(
|
this.settingsForm.valueChanges.pipe(
|
||||||
|
@ -107,7 +107,7 @@ export class ManageTasksSettingsComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'sync-themes-task',
|
name: 'sync-themes-task',
|
||||||
description: 'sync-themes-desc',
|
description: 'sync-themes-task-desc',
|
||||||
api: this.serverService.syncThemes(),
|
api: this.serverService.syncThemes(),
|
||||||
successMessage: 'sync-themes-success'
|
successMessage: 'sync-themes-success'
|
||||||
},
|
},
|
||||||
@ -143,72 +143,20 @@ export class ManageTasksSettingsComponent implements OnInit {
|
|||||||
this.logLevels = result.levels;
|
this.logLevels = result.levels;
|
||||||
this.serverSettings = result.settings;
|
this.serverSettings = result.settings;
|
||||||
|
|
||||||
|
// Create base controls for taskScan, taskBackup, taskCleanup
|
||||||
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskCleanup', new FormControl(this.serverSettings.taskCleanup, [Validators.required]));
|
this.settingsForm.addControl('taskCleanup', new FormControl(this.serverSettings.taskCleanup, [Validators.required]));
|
||||||
|
|
||||||
if (!this.taskFrequencies.includes(this.serverSettings.taskScan)) {
|
|
||||||
this.settingsForm.get('taskScan')?.setValue(this.customOption);
|
|
||||||
this.settingsForm.addControl('taskScanCustom', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
|
||||||
} else {
|
|
||||||
this.settingsForm.addControl('taskScanCustom', new FormControl('', [Validators.required]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.taskFrequencies.includes(this.serverSettings.taskBackup)) {
|
this.updateCustomFields('taskScan', 'taskScanCustom', this.taskFrequencies, this.serverSettings.taskScan);
|
||||||
this.settingsForm.get('taskBackup')?.setValue(this.customOption);
|
this.updateCustomFields('taskBackup', 'taskBackupCustom', this.taskFrequencies, this.serverSettings.taskBackup);
|
||||||
this.settingsForm.addControl('taskBackupCustom', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
this.updateCustomFields('taskCleanup', 'taskCleanupCustom', this.taskFrequenciesForCleanup, this.serverSettings.taskCleanup);
|
||||||
} else {
|
|
||||||
this.settingsForm.addControl('taskBackupCustom', new FormControl('', [Validators.required]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.taskFrequenciesForCleanup.includes(this.serverSettings.taskCleanup)) {
|
// Call the validation method for each custom control
|
||||||
this.settingsForm.get('taskCleanup')?.setValue(this.customOption);
|
this.validateCronExpression('taskScanCustom');
|
||||||
this.settingsForm.addControl('taskCleanupCustom', new FormControl(this.serverSettings.taskCleanup, [Validators.required]));
|
this.validateCronExpression('taskBackupCustom');
|
||||||
} else {
|
this.validateCronExpression('taskCleanupCustom');
|
||||||
this.settingsForm.addControl('taskCleanupCustom', new FormControl('', [Validators.required]));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.settingsForm.get('taskScanCustom')?.valueChanges.pipe(
|
|
||||||
debounceTime(100),
|
|
||||||
switchMap(val => this.settingsService.isValidCronExpression(val)),
|
|
||||||
tap(isValid => {
|
|
||||||
if (isValid) {
|
|
||||||
this.settingsForm.get('taskScanCustom')?.setErrors(null);
|
|
||||||
} else {
|
|
||||||
this.settingsForm.get('taskScanCustom')?.setErrors({invalidCron: true})
|
|
||||||
}
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
}),
|
|
||||||
takeUntilDestroyed(this.destroyRef)
|
|
||||||
).subscribe();
|
|
||||||
|
|
||||||
this.settingsForm.get('taskBackupCustom')?.valueChanges.pipe(
|
|
||||||
debounceTime(100),
|
|
||||||
switchMap(val => this.settingsService.isValidCronExpression(val)),
|
|
||||||
tap(isValid => {
|
|
||||||
if (isValid) {
|
|
||||||
this.settingsForm.get('taskBackupCustom')?.setErrors(null);
|
|
||||||
} else {
|
|
||||||
this.settingsForm.get('taskBackupCustom')?.setErrors({invalidCron: true})
|
|
||||||
}
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
}),
|
|
||||||
takeUntilDestroyed(this.destroyRef)
|
|
||||||
).subscribe();
|
|
||||||
|
|
||||||
this.settingsForm.get('taskCleanupCustom')?.valueChanges.pipe(
|
|
||||||
debounceTime(100),
|
|
||||||
switchMap(val => this.settingsService.isValidCronExpression(val)),
|
|
||||||
tap(isValid => {
|
|
||||||
if (isValid) {
|
|
||||||
this.settingsForm.get('taskCleanupCustom')?.setErrors(null);
|
|
||||||
} else {
|
|
||||||
this.settingsForm.get('taskCleanupCustom')?.setErrors({invalidCron: true})
|
|
||||||
}
|
|
||||||
this.cdRef.markForCheck();
|
|
||||||
}),
|
|
||||||
takeUntilDestroyed(this.destroyRef)
|
|
||||||
).subscribe();
|
|
||||||
|
|
||||||
// Automatically save settings as we edit them
|
// Automatically save settings as we edit them
|
||||||
this.settingsForm.valueChanges.pipe(
|
this.settingsForm.valueChanges.pipe(
|
||||||
@ -235,6 +183,35 @@ export class ManageTasksSettingsComponent implements OnInit {
|
|||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom logic to dynamically handle custom fields and validators
|
||||||
|
updateCustomFields(controlName: string, customControlName: string, frequencyList: string[], currentSetting: string) {
|
||||||
|
if (!frequencyList.includes(currentSetting)) {
|
||||||
|
// If the setting is not in the predefined list, it's a custom value
|
||||||
|
this.settingsForm.get(controlName)?.setValue(this.customOption);
|
||||||
|
this.settingsForm.addControl(customControlName, new FormControl(currentSetting, [Validators.required]));
|
||||||
|
} else {
|
||||||
|
// Otherwise, reset the custom control (no need for Validators.required here)
|
||||||
|
this.settingsForm.addControl(customControlName, new FormControl(''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the custom fields for cron expressions
|
||||||
|
validateCronExpression(controlName: string) {
|
||||||
|
this.settingsForm.get(controlName)?.valueChanges.pipe(
|
||||||
|
debounceTime(100),
|
||||||
|
switchMap(val => this.settingsService.isValidCronExpression(val)),
|
||||||
|
tap(isValid => {
|
||||||
|
if (isValid) {
|
||||||
|
this.settingsForm.get(controlName)?.setErrors(null);
|
||||||
|
} else {
|
||||||
|
this.settingsForm.get(controlName)?.setErrors({ invalidCron: true });
|
||||||
|
}
|
||||||
|
this.cdRef.markForCheck();
|
||||||
|
}),
|
||||||
|
takeUntilDestroyed(this.destroyRef)
|
||||||
|
).subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.settingsForm.get('taskScan')?.setValue(this.serverSettings.taskScan, {onlySelf: true, emitEvent: false});
|
this.settingsForm.get('taskScan')?.setValue(this.serverSettings.taskScan, {onlySelf: true, emitEvent: false});
|
||||||
|
@ -112,6 +112,7 @@ export class AllSeriesComponent implements OnInit {
|
|||||||
private readonly cdRef: ChangeDetectorRef) {
|
private readonly cdRef: ChangeDetectorRef) {
|
||||||
|
|
||||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||||
|
console.log('url: ', this.route.snapshot);
|
||||||
|
|
||||||
this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => {
|
this.filterUtilityService.filterPresetsFromUrl(this.route.snapshot).subscribe(filter => {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
@ -22,7 +22,7 @@ import {ServerService} from "./_services/server.service";
|
|||||||
import {OutOfDateModalComponent} from "./announcements/_components/out-of-date-modal/out-of-date-modal.component";
|
import {OutOfDateModalComponent} from "./announcements/_components/out-of-date-modal/out-of-date-modal.component";
|
||||||
import {PreferenceNavComponent} from "./sidenav/preference-nav/preference-nav.component";
|
import {PreferenceNavComponent} from "./sidenav/preference-nav/preference-nav.component";
|
||||||
import {Breakpoint, UtilityService} from "./shared/_services/utility.service";
|
import {Breakpoint, UtilityService} from "./shared/_services/utility.service";
|
||||||
import {translate} from "@jsverse/transloco";
|
import {TranslocoService} from "@jsverse/transloco";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -47,6 +47,7 @@ export class AppComponent implements OnInit {
|
|||||||
private readonly router = inject(Router);
|
private readonly router = inject(Router);
|
||||||
private readonly themeService = inject(ThemeService);
|
private readonly themeService = inject(ThemeService);
|
||||||
private readonly document = inject(DOCUMENT);
|
private readonly document = inject(DOCUMENT);
|
||||||
|
private readonly translocoService = inject(TranslocoService);
|
||||||
|
|
||||||
protected readonly Breakpoint = Breakpoint;
|
protected readonly Breakpoint = Breakpoint;
|
||||||
|
|
||||||
@ -126,6 +127,9 @@ export class AppComponent implements OnInit {
|
|||||||
// Bust locale cache
|
// Bust locale cache
|
||||||
localStorage.removeItem('@transloco/translations/timestamp');
|
localStorage.removeItem('@transloco/translations/timestamp');
|
||||||
localStorage.removeItem('@transloco/translations');
|
localStorage.removeItem('@transloco/translations');
|
||||||
|
(this.translocoService as any).cache.delete(localStorage.getItem('kavita-locale') || 'en');
|
||||||
|
(this.translocoService as any).cache.clear();
|
||||||
|
localStorage.setItem('kavita--version', version);
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
localStorage.setItem('kavita--version', version);
|
localStorage.setItem('kavita--version', version);
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
@if (chapter.isSpecial) {
|
@if (chapter.isSpecial) {
|
||||||
{{chapter.title || chapter.range}}
|
{{chapter.title || chapter.range}}
|
||||||
} @else {
|
} @else {
|
||||||
<app-entity-title [entity]="chapter" [prioritizeTitleName]="false"></app-entity-title>
|
<app-entity-title [entity]="chapter" [prioritizeTitleName]="false" [libraryType]="libraryType"></app-entity-title>
|
||||||
}
|
}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -33,31 +33,50 @@
|
|||||||
@case (LibraryType.Manga) {
|
@case (LibraryType.Manga) {
|
||||||
@if (titleName !== '' && prioritizeTitleName) {
|
@if (titleName !== '' && prioritizeTitleName) {
|
||||||
@if (isChapter && includeChapter) {
|
@if (isChapter && includeChapter) {
|
||||||
|
@if (number === LooseLeafOrSpecial) {
|
||||||
|
{{t('chapter') + ' - ' }}
|
||||||
|
} @else {
|
||||||
{{t('chapter') + ' ' + number + ' - ' }}
|
{{t('chapter') + ' ' + number + ' - ' }}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
{{titleName}}
|
{{titleName}}
|
||||||
} @else {
|
} @else {
|
||||||
@if (includeVolume && volumeTitle !== '') {
|
@if (includeVolume && volumeTitle !== '') {
|
||||||
{{number !== LooseLeafOrSpecial ? (isChapter && includeVolume ? volumeTitle : '') : ''}}
|
@if (number !== LooseLeafOrSpecial && isChapter && includeVolume) {
|
||||||
|
{{volumeTitle}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{{number !== LooseLeafOrSpecial ? (isChapter ? (t('chapter') + ' ') + number : volumeTitle) : t('special')}}
|
@if (number !== LooseLeafOrSpecial) {
|
||||||
|
@if (isChapter) {
|
||||||
|
{{t('chapter') + ' ' + number}}
|
||||||
|
} @else {
|
||||||
|
{{volumeTitle}}
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
{{t('special')}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@case (LibraryType.Book) {
|
@case (LibraryType.Book) {
|
||||||
@if (titleName !== '' && prioritizeTitleName) {
|
@if (titleName !== '' && prioritizeTitleName) {
|
||||||
{{titleName}}
|
{{titleName}}
|
||||||
|
} @else if (number === LooseLeafOrSpecial) {
|
||||||
|
{{null | defaultValue}}
|
||||||
} @else {
|
} @else {
|
||||||
{{volumeTitle}}
|
{{t('book-num', {num: volumeTitle})}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@case (LibraryType.LightNovel) {
|
@case (LibraryType.LightNovel) {
|
||||||
@if (titleName !== '' && prioritizeTitleName) {
|
@if (titleName !== '' && prioritizeTitleName) {
|
||||||
{{titleName}}
|
{{titleName}}
|
||||||
|
} @else if (number === LooseLeafOrSpecial) {
|
||||||
|
{{null | defaultValue}}
|
||||||
} @else {
|
} @else {
|
||||||
{{volumeTitle}}
|
{{t('book-num', {num: (isChapter ? number : volumeTitle)})}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { Chapter, LooseLeafOrDefaultNumber } from 'src/app/_models/chapter';
|
|||||||
import { LibraryType } from 'src/app/_models/library/library';
|
import { LibraryType } from 'src/app/_models/library/library';
|
||||||
import { Volume } from 'src/app/_models/volume';
|
import { Volume } from 'src/app/_models/volume';
|
||||||
import {TranslocoModule} from "@jsverse/transloco";
|
import {TranslocoModule} from "@jsverse/transloco";
|
||||||
|
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is primarily used for list item
|
* This is primarily used for list item
|
||||||
@ -12,7 +13,8 @@ import {TranslocoModule} from "@jsverse/transloco";
|
|||||||
selector: 'app-entity-title',
|
selector: 'app-entity-title',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
TranslocoModule
|
TranslocoModule,
|
||||||
|
DefaultValuePipe
|
||||||
],
|
],
|
||||||
templateUrl: './entity-title.component.html',
|
templateUrl: './entity-title.component.html',
|
||||||
styleUrls: ['./entity-title.component.scss'],
|
styleUrls: ['./entity-title.component.scss'],
|
||||||
@ -20,7 +22,6 @@ import {TranslocoModule} from "@jsverse/transloco";
|
|||||||
})
|
})
|
||||||
export class EntityTitleComponent implements OnInit {
|
export class EntityTitleComponent implements OnInit {
|
||||||
|
|
||||||
protected readonly LooseLeafOrSpecialNumber = LooseLeafOrDefaultNumber;
|
|
||||||
protected readonly LooseLeafOrSpecial = LooseLeafOrDefaultNumber + "";
|
protected readonly LooseLeafOrSpecial = LooseLeafOrDefaultNumber + "";
|
||||||
protected readonly LibraryType = LibraryType;
|
protected readonly LibraryType = LibraryType;
|
||||||
|
|
||||||
@ -59,6 +60,7 @@ export class EntityTitleComponent implements OnInit {
|
|||||||
this.volumeTitle = c.volumeTitle || '';
|
this.volumeTitle = c.volumeTitle || '';
|
||||||
this.titleName = c.titleName || '';
|
this.titleName = c.titleName || '';
|
||||||
this.number = c.range;
|
this.number = c.range;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const v = this.utilityService.asVolume(this.entity);
|
const v = this.utilityService.asVolume(this.entity);
|
||||||
this.volumeTitle = v.name || '';
|
this.volumeTitle = v.name || '';
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {BulkOperationsComponent} from "../cards/bulk-operations/bulk-operations.component";
|
import {BulkOperationsComponent} from "../cards/bulk-operations/bulk-operations.component";
|
||||||
import {TagBadgeComponent} from "../shared/tag-badge/tag-badge.component";
|
import {TagBadgeComponent} from "../shared/tag-badge/tag-badge.component";
|
||||||
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle, NgClass, DatePipe} from "@angular/common";
|
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle, NgClass, DatePipe, Location} from "@angular/common";
|
||||||
import {CardActionablesComponent} from "../_single-module/card-actionables/card-actionables.component";
|
import {CardActionablesComponent} from "../_single-module/card-actionables/card-actionables.component";
|
||||||
import {CarouselReelComponent} from "../carousel/_components/carousel-reel/carousel-reel.component";
|
import {CarouselReelComponent} from "../carousel/_components/carousel-reel/carousel-reel.component";
|
||||||
import {ExternalSeriesCardComponent} from "../cards/external-series-card/external-series-card.component";
|
import {ExternalSeriesCardComponent} from "../cards/external-series-card/external-series-card.component";
|
||||||
@ -171,6 +171,7 @@ export class ChapterDetailComponent implements OnInit {
|
|||||||
private readonly messageHub = inject(MessageHubService);
|
private readonly messageHub = inject(MessageHubService);
|
||||||
private readonly actionFactoryService = inject(ActionFactoryService);
|
private readonly actionFactoryService = inject(ActionFactoryService);
|
||||||
private readonly actionService = inject(ActionService);
|
private readonly actionService = inject(ActionService);
|
||||||
|
private readonly location = inject(Location);
|
||||||
|
|
||||||
protected readonly AgeRating = AgeRating;
|
protected readonly AgeRating = AgeRating;
|
||||||
protected readonly TabID = TabID;
|
protected readonly TabID = TabID;
|
||||||
@ -331,8 +332,9 @@ export class ChapterDetailComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateUrl(activeTab: TabID) {
|
updateUrl(activeTab: TabID) {
|
||||||
const newUrl = `${this.router.url.split('#')[0]}#${activeTab}`;
|
const tokens = this.location.path().split('#');
|
||||||
window.history.replaceState({}, '', newUrl);
|
const newUrl = `${tokens[0]}#${activeTab}`;
|
||||||
|
this.location.replaceState(newUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
openPerson(field: FilterField, value: number) {
|
openPerson(field: FilterField, value: number) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
DecimalPipe,
|
DecimalPipe,
|
||||||
DOCUMENT, JsonPipe,
|
DOCUMENT, JsonPipe, Location,
|
||||||
NgClass,
|
NgClass,
|
||||||
NgOptimizedImage,
|
NgOptimizedImage,
|
||||||
NgStyle,
|
NgStyle,
|
||||||
@ -211,6 +211,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||||||
protected readonly themeService = inject(ThemeService);
|
protected readonly themeService = inject(ThemeService);
|
||||||
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
private readonly filterUtilityService = inject(FilterUtilitiesService);
|
||||||
private readonly scrobbleService = inject(ScrobblingService);
|
private readonly scrobbleService = inject(ScrobblingService);
|
||||||
|
private readonly location = inject(Location);
|
||||||
|
|
||||||
protected readonly LibraryType = LibraryType;
|
protected readonly LibraryType = LibraryType;
|
||||||
protected readonly TabID = TabID;
|
protected readonly TabID = TabID;
|
||||||
@ -523,6 +524,8 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.route.fragment.pipe(tap(frag => {
|
this.route.fragment.pipe(tap(frag => {
|
||||||
if (frag !== null && this.activeTabId !== (frag as TabID)) {
|
if (frag !== null && this.activeTabId !== (frag as TabID)) {
|
||||||
this.activeTabId = frag as TabID;
|
this.activeTabId = frag as TabID;
|
||||||
@ -561,9 +564,9 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateUrl(activeTab: TabID) {
|
updateUrl(activeTab: TabID) {
|
||||||
var tokens = this.router.url.split('#');
|
const tokens = this.location.path().split('#');
|
||||||
const newUrl = `${tokens[0]}#${activeTab}`;
|
const newUrl = `${tokens[0]}#${activeTab}`;
|
||||||
window.history.replaceState({}, '', newUrl);
|
this.location.replaceState(newUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSeriesActionCallback(action: ActionItem<Series>, series: Series) {
|
handleSeriesActionCallback(action: ActionItem<Series>, series: Series) {
|
||||||
|
@ -69,7 +69,9 @@ export class SettingItemComponent {
|
|||||||
if (!this.toggleOnViewClick) return false;
|
if (!this.toggleOnViewClick) return false;
|
||||||
|
|
||||||
const mouseEvent = event as MouseEvent;
|
const mouseEvent = event as MouseEvent;
|
||||||
return !elementRef.nativeElement.contains(mouseEvent.target)
|
const selection = window.getSelection();
|
||||||
|
const hasSelection = selection !== null && selection.toString().trim() === '';
|
||||||
|
return !elementRef.nativeElement.contains(mouseEvent.target) && hasSelection;
|
||||||
}),
|
}),
|
||||||
tap(() => {
|
tap(() => {
|
||||||
this.isEditMode = false;
|
this.isEditMode = false;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {inject, Injectable} from '@angular/core';
|
||||||
import {ActivatedRouteSnapshot, Params, Router} from '@angular/router';
|
import {ActivatedRouteSnapshot, Params, Router} from '@angular/router';
|
||||||
import {SortField, SortOptions} from 'src/app/_models/metadata/series-filter';
|
import {SortField, SortOptions} from 'src/app/_models/metadata/series-filter';
|
||||||
import {MetadataService} from "../../_services/metadata.service";
|
import {MetadataService} from "../../_services/metadata.service";
|
||||||
@ -12,6 +12,7 @@ import {TextResonse} from "../../_types/text-response";
|
|||||||
import {environment} from "../../../environments/environment";
|
import {environment} from "../../../environments/environment";
|
||||||
import {map, tap} from "rxjs/operators";
|
import {map, tap} from "rxjs/operators";
|
||||||
import {of, switchMap} from "rxjs";
|
import {of, switchMap} from "rxjs";
|
||||||
|
import {Location} from "@angular/common";
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -19,9 +20,12 @@ import {of, switchMap} from "rxjs";
|
|||||||
})
|
})
|
||||||
export class FilterUtilitiesService {
|
export class FilterUtilitiesService {
|
||||||
|
|
||||||
private apiUrl = environment.apiUrl;
|
private readonly location = inject(Location);
|
||||||
|
private readonly router = inject(Router);
|
||||||
|
private readonly metadataService = inject(MetadataService);
|
||||||
|
private readonly http = inject(HttpClient);
|
||||||
|
|
||||||
constructor(private metadataService: MetadataService, private router: Router, private http: HttpClient) {}
|
private apiUrl = environment.apiUrl;
|
||||||
|
|
||||||
encodeFilter(filter: SeriesFilterV2 | undefined) {
|
encodeFilter(filter: SeriesFilterV2 | undefined) {
|
||||||
return this.http.post<string>(this.apiUrl + 'filter/encode', filter, TextResonse);
|
return this.http.post<string>(this.apiUrl + 'filter/encode', filter, TextResonse);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@if (!item.isProvided) {
|
@if (!item.isProvided) {
|
||||||
<div class="ps-1">
|
<div class="ps-1">
|
||||||
<a [href]="'/all-series?' + this.item.smartFilterEncoded" target="_blank">{{t('load-filter')}}</a>
|
<a [href]="baseUrl + 'all-series?' + this.item.smartFilterEncoded" target="_blank">{{t('load-filter')}}</a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
Component,
|
Component,
|
||||||
EventEmitter,
|
EventEmitter, inject,
|
||||||
Input,
|
Input,
|
||||||
Output
|
Output
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {CommonModule, NgClass} from '@angular/common';
|
import {APP_BASE_HREF, CommonModule, NgClass} from '@angular/common';
|
||||||
import {ImageComponent} from "../../../shared/image/image.component";
|
import {ImageComponent} from "../../../shared/image/image.component";
|
||||||
import {MangaFormatIconPipe} from "../../../_pipes/manga-format-icon.pipe";
|
import {MangaFormatIconPipe} from "../../../_pipes/manga-format-icon.pipe";
|
||||||
import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
|
import {MangaFormatPipe} from "../../../_pipes/manga-format.pipe";
|
||||||
@ -13,11 +13,12 @@ import {NgbProgressbar} from "@ng-bootstrap/ng-bootstrap";
|
|||||||
import {TranslocoDirective} from "@jsverse/transloco";
|
import {TranslocoDirective} from "@jsverse/transloco";
|
||||||
import {DashboardStream} from "../../../_models/dashboard/dashboard-stream";
|
import {DashboardStream} from "../../../_models/dashboard/dashboard-stream";
|
||||||
import {StreamNamePipe} from "../../../_pipes/stream-name.pipe";
|
import {StreamNamePipe} from "../../../_pipes/stream-name.pipe";
|
||||||
|
import {RouterLink} from "@angular/router";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-stream-list-item',
|
selector: 'app-dashboard-stream-list-item',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ImageComponent, MangaFormatIconPipe, MangaFormatPipe, NgbProgressbar, TranslocoDirective, StreamNamePipe, NgClass],
|
imports: [ImageComponent, MangaFormatIconPipe, MangaFormatPipe, NgbProgressbar, TranslocoDirective, StreamNamePipe, NgClass, RouterLink],
|
||||||
templateUrl: './dashboard-stream-list-item.component.html',
|
templateUrl: './dashboard-stream-list-item.component.html',
|
||||||
styleUrls: ['./dashboard-stream-list-item.component.scss'],
|
styleUrls: ['./dashboard-stream-list-item.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
@ -26,4 +27,5 @@ export class DashboardStreamListItemComponent {
|
|||||||
@Input({required: true}) item!: DashboardStream;
|
@Input({required: true}) item!: DashboardStream;
|
||||||
@Input({required: true}) position: number = 0;
|
@Input({required: true}) position: number = 0;
|
||||||
@Output() hide: EventEmitter<DashboardStream> = new EventEmitter<DashboardStream>();
|
@Output() hide: EventEmitter<DashboardStream> = new EventEmitter<DashboardStream>();
|
||||||
|
protected readonly baseUrl = inject(APP_BASE_HREF);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<i class="fa-solid fa-triangle-exclamation red me-2" [ngbTooltip]="t('errored')"></i>
|
<i class="fa-solid fa-triangle-exclamation red me-2" [ngbTooltip]="t('errored')"></i>
|
||||||
<span class="visually-hidden">{{t('errored')}}</span>
|
<span class="visually-hidden">{{t('errored')}}</span>
|
||||||
}
|
}
|
||||||
<a [href]="'/all-series?' + f.filter" target="_blank">{{f.name}}</a>
|
<a [href]="baseUrl + 'all-series?' + f.filter" target="_blank">{{f.name}}</a>
|
||||||
</span>
|
</span>
|
||||||
<button class="btn btn-danger float-end" (click)="deleteFilter(f)">
|
<button class="btn btn-danger float-end" (click)="deleteFilter(f)">
|
||||||
<i class="fa-solid fa-trash" aria-hidden="true"></i>
|
<i class="fa-solid fa-trash" aria-hidden="true"></i>
|
||||||
|
@ -6,11 +6,13 @@ import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";
|
|||||||
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
||||||
import {ActionService} from "../../../_services/action.service";
|
import {ActionService} from "../../../_services/action.service";
|
||||||
import {NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
|
import {NgbTooltip} from "@ng-bootstrap/ng-bootstrap";
|
||||||
|
import {RouterLink} from "@angular/router";
|
||||||
|
import {APP_BASE_HREF} from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-manage-smart-filters',
|
selector: 'app-manage-smart-filters',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ReactiveFormsModule, TranslocoDirective, FilterPipe, NgbTooltip],
|
imports: [ReactiveFormsModule, TranslocoDirective, FilterPipe, NgbTooltip, RouterLink],
|
||||||
templateUrl: './manage-smart-filters.component.html',
|
templateUrl: './manage-smart-filters.component.html',
|
||||||
styleUrls: ['./manage-smart-filters.component.scss'],
|
styleUrls: ['./manage-smart-filters.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
@ -20,6 +22,7 @@ export class ManageSmartFiltersComponent {
|
|||||||
private readonly filterService = inject(FilterService);
|
private readonly filterService = inject(FilterService);
|
||||||
private readonly cdRef = inject(ChangeDetectorRef);
|
private readonly cdRef = inject(ChangeDetectorRef);
|
||||||
private readonly actionService = inject(ActionService);
|
private readonly actionService = inject(ActionService);
|
||||||
|
protected readonly baseUrl = inject(APP_BASE_HREF);
|
||||||
|
|
||||||
filters: Array<SmartFilter> = [];
|
filters: Array<SmartFilter> = [];
|
||||||
listForm: FormGroup = new FormGroup({
|
listForm: FormGroup = new FormGroup({
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
<div class="row pt-2 g-0 list-item">
|
<div class="row pt-2 g-0 list-item">
|
||||||
<div class="g-0">
|
<div class="g-0">
|
||||||
<h5 class="mb-1 pb-0" id="item.id--{{position}}">
|
<h5 class="mb-1 pb-0" id="item.id--{{position}}">
|
||||||
<span *ngIf="item.isProvided; else nonProvidedTitle">
|
@if (item.isProvided) {
|
||||||
{{item.name | streamName }}
|
{{item.name | streamName }}
|
||||||
</span>
|
} @else {
|
||||||
<ng-template #nonProvidedTitle>
|
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</ng-template>
|
}
|
||||||
|
|
||||||
<span class="float-end">
|
<span class="float-end">
|
||||||
<button class="btn btn-icon p-0" (click)="hide.emit(item)">
|
<button class="btn btn-icon p-0" (click)="hide.emit(item)">
|
||||||
<i class="me-1" [ngClass]="{'fas fa-eye': item.visible, 'fa-solid fa-eye-slash': !item.visible}" aria-hidden="true"></i>
|
<i class="me-1" [ngClass]="{'fas fa-eye': item.visible, 'fa-solid fa-eye-slash': !item.visible}" aria-hidden="true"></i>
|
||||||
@ -29,10 +29,10 @@
|
|||||||
<div class="ps-1" *ngIf="!item.isProvided">
|
<div class="ps-1" *ngIf="!item.isProvided">
|
||||||
<ng-container [ngSwitch]="item.streamType">
|
<ng-container [ngSwitch]="item.streamType">
|
||||||
<ng-container *ngSwitchCase="SideNavStreamType.Library">
|
<ng-container *ngSwitchCase="SideNavStreamType.Library">
|
||||||
<a [href]="'/library/' + this.item.libraryId" target="_blank">{{item.library?.name}}</a>
|
<a [href]="baseUrl + 'library/' + this.item.libraryId" target="_blank">{{item.library?.name}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngSwitchCase="SideNavStreamType.SmartFilter">
|
<ng-container *ngSwitchCase="SideNavStreamType.SmartFilter">
|
||||||
<a [href]="'/all-series?' + this.item.smartFilterEncoded" target="_blank">{{t('load-filter')}}</a>
|
<a [href]="baseUrl + 'all-series?' + this.item.smartFilterEncoded">{{t('load-filter')}}</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngSwitchCase="SideNavStreamType.ExternalSource">
|
<ng-container *ngSwitchCase="SideNavStreamType.ExternalSource">
|
||||||
<a [href]="item.externalSource!.host! + 'login?apiKey=' + item.externalSource!.apiKey" target="_blank" rel="noopener noreferrer">{{item.externalSource!.host!}}</a>
|
<a [href]="item.externalSource!.host! + 'login?apiKey=' + item.externalSource!.apiKey" target="_blank" rel="noopener noreferrer">{{item.externalSource!.host!}}</a>
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core';
|
import {ChangeDetectionStrategy, Component, EventEmitter, inject, Input, Output} from '@angular/core';
|
||||||
import {CommonModule} from '@angular/common';
|
import {APP_BASE_HREF, CommonModule} from '@angular/common';
|
||||||
import {SideNavStream} from "../../../_models/sidenav/sidenav-stream";
|
import {SideNavStream} from "../../../_models/sidenav/sidenav-stream";
|
||||||
import {StreamNamePipe} from "../../../_pipes/stream-name.pipe";
|
import {StreamNamePipe} from "../../../_pipes/stream-name.pipe";
|
||||||
import {TranslocoDirective} from "@jsverse/transloco";
|
import {TranslocoDirective} from "@jsverse/transloco";
|
||||||
import {SideNavStreamType} from "../../../_models/sidenav/sidenav-stream-type.enum";
|
import {SideNavStreamType} from "../../../_models/sidenav/sidenav-stream-type.enum";
|
||||||
|
import {RouterLink} from "@angular/router";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sidenav-stream-list-item',
|
selector: 'app-sidenav-stream-list-item',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, StreamNamePipe, TranslocoDirective],
|
imports: [CommonModule, StreamNamePipe, TranslocoDirective, RouterLink],
|
||||||
templateUrl: './sidenav-stream-list-item.component.html',
|
templateUrl: './sidenav-stream-list-item.component.html',
|
||||||
styleUrls: ['./sidenav-stream-list-item.component.scss'],
|
styleUrls: ['./sidenav-stream-list-item.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
@ -18,4 +19,10 @@ export class SidenavStreamListItemComponent {
|
|||||||
@Input({required: true}) position: number = 0;
|
@Input({required: true}) position: number = 0;
|
||||||
@Output() hide: EventEmitter<SideNavStream> = new EventEmitter<SideNavStream>();
|
@Output() hide: EventEmitter<SideNavStream> = new EventEmitter<SideNavStream>();
|
||||||
protected readonly SideNavStreamType = SideNavStreamType;
|
protected readonly SideNavStreamType = SideNavStreamType;
|
||||||
|
protected readonly baseUrl = inject(APP_BASE_HREF);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
console.log('baseUrl', this.baseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
OnInit,
|
OnInit,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle, NgClass, DatePipe} from "@angular/common";
|
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle, NgClass, DatePipe, Location} from "@angular/common";
|
||||||
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
|
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
|
||||||
import {ImageService} from "../_services/image.service";
|
import {ImageService} from "../_services/image.service";
|
||||||
import {SeriesService} from "../_services/series.service";
|
import {SeriesService} from "../_services/series.service";
|
||||||
@ -198,6 +198,7 @@ export class VolumeDetailComponent implements OnInit {
|
|||||||
protected readonly utilityService = inject(UtilityService);
|
protected readonly utilityService = inject(UtilityService);
|
||||||
private readonly readingListService = inject(ReadingListService);
|
private readonly readingListService = inject(ReadingListService);
|
||||||
private readonly messageHub = inject(MessageHubService);
|
private readonly messageHub = inject(MessageHubService);
|
||||||
|
private readonly location = inject(Location);
|
||||||
|
|
||||||
|
|
||||||
protected readonly AgeRating = AgeRating;
|
protected readonly AgeRating = AgeRating;
|
||||||
@ -555,8 +556,9 @@ export class VolumeDetailComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateUrl(activeTab: TabID) {
|
updateUrl(activeTab: TabID) {
|
||||||
const newUrl = `${this.router.url.split('#')[0]}#${activeTab}`;
|
const tokens = this.location.path().split('#');
|
||||||
window.history.replaceState({}, '', newUrl);
|
const newUrl = `${tokens[0]}#${activeTab}`;
|
||||||
|
this.location.replaceState(newUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
openPerson(field: FilterField, value: number) {
|
openPerson(field: FilterField, value: number) {
|
||||||
|
@ -625,7 +625,7 @@
|
|||||||
"continue-incognito": "Unsichtbar fortsetzen",
|
"continue-incognito": "Unsichtbar fortsetzen",
|
||||||
"incognito": "Unsichtbar",
|
"incognito": "Unsichtbar",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"edit-series-alt": "Bearbeite die Serieninformationen",
|
"edit-series-alt": "Informationen bearbeiten",
|
||||||
"user-reviews-local": "Lokale Bewertungen",
|
"user-reviews-local": "Lokale Bewertungen",
|
||||||
"user-reviews-plus": "Externe Bewertungen",
|
"user-reviews-plus": "Externe Bewertungen",
|
||||||
"cover-artists-title": "{{metadata-fields.cover-artists-title}}",
|
"cover-artists-title": "{{metadata-fields.cover-artists-title}}",
|
||||||
@ -832,8 +832,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Spezial",
|
"special": "Spezial",
|
||||||
"issue-num": "Ausgabe #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "Kapitel"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "Extern öffnen"
|
"open-external": "Extern öffnen"
|
||||||
@ -867,7 +868,7 @@
|
|||||||
"email-settings-title": "E-Mail-Einstellungen",
|
"email-settings-title": "E-Mail-Einstellungen",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"setting-description": "Sie müssen sowohl den Hostnamen als auch die SMTP-Einstellungen ausfüllen, um die E-Mail-basierten Funktionen von Kavita nutzen zu können.",
|
"setting-description": "Sie müssen sowohl den Hostnamen als auch die SMTP-Einstellungen ausfüllen, um die E-Mail-basierten Funktionen von Kavita nutzen zu können.",
|
||||||
"test-warning": "Sie müssen speichern, bevor Sie die Schaltfläche Test verwenden.",
|
"test-warning": "Sie müssen über gültige Einstellungen verfügen, bevor Sie auf „Testen“ klicken.",
|
||||||
"size-limit-tooltip": "Wie viele Bytes kann der E-Mail-Server für Anhänge verarbeiten",
|
"size-limit-tooltip": "Wie viele Bytes kann der E-Mail-Server für Anhänge verarbeiten",
|
||||||
"customized-templates-label": "Angepasste Templates"
|
"customized-templates-label": "Angepasste Templates"
|
||||||
},
|
},
|
||||||
@ -1135,7 +1136,7 @@
|
|||||||
},
|
},
|
||||||
"filter-field-pipe": {
|
"filter-field-pipe": {
|
||||||
"want-to-read": "Möchte ich lesen",
|
"want-to-read": "Möchte ich lesen",
|
||||||
"cover-artist": "Cover Künstler",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"read-time": "Lesezeit",
|
"read-time": "Lesezeit",
|
||||||
"location": "Standort",
|
"location": "Standort",
|
||||||
"file-path": "Datei-Pfad",
|
"file-path": "Datei-Pfad",
|
||||||
@ -1251,7 +1252,7 @@
|
|||||||
"character": "Charakter",
|
"character": "Charakter",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"publisher": "Herausgeber",
|
"publisher": "Herausgeber",
|
||||||
"cover-artist": "Cover Künstler",
|
"cover-artist": "{{artist}}",
|
||||||
"translator": "Übersetzer",
|
"translator": "Übersetzer",
|
||||||
"colorist": "Kolorist",
|
"colorist": "Kolorist",
|
||||||
"imprint": "Impressum",
|
"imprint": "Impressum",
|
||||||
|
@ -527,7 +527,7 @@
|
|||||||
"artist": "Artist",
|
"artist": "Artist",
|
||||||
"character": "Character",
|
"character": "Character",
|
||||||
"colorist": "Colorist",
|
"colorist": "Colorist",
|
||||||
"cover-artist": "Cover Artist",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"inker": "Inker",
|
"inker": "Inker",
|
||||||
"letterer": "Letterer",
|
"letterer": "Letterer",
|
||||||
@ -788,7 +788,7 @@
|
|||||||
"incognito": "Incognito",
|
"incognito": "Incognito",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "Edit Series Information",
|
"edit-series-alt": "Edit Information",
|
||||||
"reviews-tab": "{{tabs.reviews-tab}}",
|
"reviews-tab": "{{tabs.reviews-tab}}",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"books-tab": "{{tabs.books-tab}}",
|
"books-tab": "{{tabs.books-tab}}",
|
||||||
@ -1109,8 +1109,9 @@
|
|||||||
|
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Special",
|
"special": "Special",
|
||||||
"issue-num": "Issue #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "Chapter"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
|
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
@ -1132,7 +1133,7 @@
|
|||||||
"manage-email-settings": {
|
"manage-email-settings": {
|
||||||
"description": "In order to use some functions of Kavita like Send To Device an email provider must be setup. Other features like Forgot Password require admin intervention without Email setup.",
|
"description": "In order to use some functions of Kavita like Send To Device an email provider must be setup. Other features like Forgot Password require admin intervention without Email setup.",
|
||||||
"setting-description": "You must fill out both Host Name and SMTP settings to use email-based functionality within Kavita.",
|
"setting-description": "You must fill out both Host Name and SMTP settings to use email-based functionality within Kavita.",
|
||||||
"test-warning": "You must save before using Test button.",
|
"test-warning": "You must have valid settings before hitting Test.",
|
||||||
"send-to-warning": "If you want Send to Device to work you must setup your email settings",
|
"send-to-warning": "If you want Send to Device to work you must setup your email settings",
|
||||||
"email-url-label": "Email Service URL",
|
"email-url-label": "Email Service URL",
|
||||||
"email-url-tooltip": "Use fully qualified URL of the email service. Do not include ending slash.",
|
"email-url-tooltip": "Use fully qualified URL of the email service. Do not include ending slash.",
|
||||||
@ -2188,7 +2189,7 @@
|
|||||||
"characters": "{{metadata-fields.characters-title}}",
|
"characters": "{{metadata-fields.characters-title}}",
|
||||||
"collection-tags": "Collection Tags",
|
"collection-tags": "Collection Tags",
|
||||||
"colorist": "Colorist",
|
"colorist": "Colorist",
|
||||||
"cover-artist": "Cover Artist",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"formats": "Formats",
|
"formats": "Formats",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
|
@ -614,7 +614,7 @@
|
|||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"incognito": "Incógnito",
|
"incognito": "Incógnito",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "Editar informacion de la serie",
|
"edit-series-alt": "Editar información",
|
||||||
"volumes-tab": "{{tabs.volumes-tab}}",
|
"volumes-tab": "{{tabs.volumes-tab}}",
|
||||||
"specials-tab": "{{tabs.specials-tab}}",
|
"specials-tab": "{{tabs.specials-tab}}",
|
||||||
"related-tab": "{{tabs.related-tab}}",
|
"related-tab": "{{tabs.related-tab}}",
|
||||||
@ -895,7 +895,7 @@
|
|||||||
"artist": "Artista",
|
"artist": "Artista",
|
||||||
"writer": "Escritor",
|
"writer": "Escritor",
|
||||||
"character": "Personaje",
|
"character": "Personaje",
|
||||||
"cover-artist": "Artista de portada",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"other": "Otro",
|
"other": "Otro",
|
||||||
"publisher": "Editorial",
|
"publisher": "Editorial",
|
||||||
@ -1469,8 +1469,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Especial",
|
"special": "Especial",
|
||||||
"chapter": "Capítulo",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"issue-num": "Número #"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "Abrir externamente"
|
"open-external": "Abrir externamente"
|
||||||
@ -1506,7 +1507,7 @@
|
|||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"setting-description": "Para poder utilizar las funciones de correo electrónico de Kavita, debes rellenar los campos nombre del host y SMTP.",
|
"setting-description": "Para poder utilizar las funciones de correo electrónico de Kavita, debes rellenar los campos nombre del host y SMTP.",
|
||||||
"test-warning": "Debes guardar antes de utilizar el botón Probar."
|
"test-warning": "Debe tener configuraciones válidas antes de presionar Probar."
|
||||||
},
|
},
|
||||||
"cover-image-size": {
|
"cover-image-size": {
|
||||||
"xlarge": "Extragrande (1265x1795)",
|
"xlarge": "Extragrande (1265x1795)",
|
||||||
@ -1658,7 +1659,7 @@
|
|||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
"release-year": "{{sort-field-pipe.release-year}}",
|
"release-year": "{{sort-field-pipe.release-year}}",
|
||||||
"writers": "{{metadata-fields.writers-title}}",
|
"writers": "{{metadata-fields.writers-title}}",
|
||||||
"cover-artist": "Artista de la portada",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"read-progress": "Progreso de la lectura",
|
"read-progress": "Progreso de la lectura",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"read-time": "Tiempo de lectura",
|
"read-time": "Tiempo de lectura",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"username": "{{common.username}}",
|
"username": "{{common.username}}",
|
||||||
"password": "{{common.password}}",
|
"password": "{{common.password}}",
|
||||||
"password-validation": "{{validation.password-validation}}",
|
"password-validation": "{{validation.password-validation}}",
|
||||||
"forgot-password": "Mot de passe oublié ?",
|
"forgot-password": "Mot de passe oublié?",
|
||||||
"submit": "Se connecter"
|
"submit": "Se connecter"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
@ -416,7 +416,7 @@
|
|||||||
"other": "Autre",
|
"other": "Autre",
|
||||||
"penciller": "Crayonneur",
|
"penciller": "Crayonneur",
|
||||||
"letterer": "Lettreur",
|
"letterer": "Lettreur",
|
||||||
"cover-artist": "Artiste de la couverture",
|
"cover-artist": "{{artist}}",
|
||||||
"character": "Personnage",
|
"character": "Personnage",
|
||||||
"artist": "Artiste",
|
"artist": "Artiste",
|
||||||
"inker": "Encreur",
|
"inker": "Encreur",
|
||||||
@ -668,7 +668,7 @@
|
|||||||
"collection-tags": "Étiquettes de la collection",
|
"collection-tags": "Étiquettes de la collection",
|
||||||
"characters": "{{metadata-fields.characters-title}}",
|
"characters": "{{metadata-fields.characters-title}}",
|
||||||
"languages": "Langues",
|
"languages": "Langues",
|
||||||
"cover-artist": "Artiste de couverture",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"writers": "{{metadata-fields.writers-title}}",
|
"writers": "{{metadata-fields.writers-title}}",
|
||||||
"release-year": "{{sort-field-pipe.release-year}}",
|
"release-year": "{{sort-field-pipe.release-year}}",
|
||||||
"read-progress": "Progrès de lecture",
|
"read-progress": "Progrès de lecture",
|
||||||
@ -987,7 +987,7 @@
|
|||||||
"read-incognito": "Lire en mode privé",
|
"read-incognito": "Lire en mode privé",
|
||||||
"specials-tab": "{{tabs.specials-tab}}",
|
"specials-tab": "{{tabs.specials-tab}}",
|
||||||
"recommendations-tab": "{{tabs.recommendations-tab}}",
|
"recommendations-tab": "{{tabs.recommendations-tab}}",
|
||||||
"edit-series-alt": "Modifier les informations sur la série",
|
"edit-series-alt": "Modifier les informations",
|
||||||
"layout-mode-option-list": "Liste",
|
"layout-mode-option-list": "Liste",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"no-pages": "{{toasts.no-pages}}",
|
"no-pages": "{{toasts.no-pages}}",
|
||||||
@ -1317,7 +1317,7 @@
|
|||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"setting-description": "Vous devez remplir les paramètres Nom d'hôte et SMTP pour utiliser les fonctionnalités de messagerie électronique dans Kavita.",
|
"setting-description": "Vous devez remplir les paramètres Nom d'hôte et SMTP pour utiliser les fonctionnalités de messagerie électronique dans Kavita.",
|
||||||
"test-warning": "Vous devez enregistrer avant d'utiliser le bouton Test."
|
"test-warning": "Vous devez avoir des paramètres valides avant de cliquer sur Test."
|
||||||
},
|
},
|
||||||
"bulk-add-to-collection": {
|
"bulk-add-to-collection": {
|
||||||
"collection-label": "Collection",
|
"collection-label": "Collection",
|
||||||
@ -1332,8 +1332,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Spécial",
|
"special": "Spécial",
|
||||||
"chapter": "Chapitre",
|
"chapter": "{{common.chapter-num}}",
|
||||||
"issue-num": "Numéro #"
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"manage-library": {
|
"manage-library": {
|
||||||
"add-library": "Ajouter une bibliothèque",
|
"add-library": "Ajouter une bibliothèque",
|
||||||
|
@ -345,7 +345,7 @@
|
|||||||
"read-options-alt": "Léigh roghanna",
|
"read-options-alt": "Léigh roghanna",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "Cuir Eolas faoin tSraith in Eagar",
|
"edit-series-alt": "Cuir Eolas in Eagar",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"books-tab": "{{tabs.books-tab}}",
|
"books-tab": "{{tabs.books-tab}}",
|
||||||
"volumes-tab": "{{tabs.volumes-tab}}",
|
"volumes-tab": "{{tabs.volumes-tab}}",
|
||||||
@ -524,7 +524,7 @@
|
|||||||
"gmail-label": "GmailName",
|
"gmail-label": "GmailName",
|
||||||
"description": "Chun úsáid a bhaint as roinnt feidhmeanna de chuid Kavita cosúil le Send To Device ní mór soláthraí ríomhphoist a shocrú. Teastaíonn idirghabháil riaracháin ó ghnéithe eile cosúil le Forgot Password gan socrú Ríomhphost.",
|
"description": "Chun úsáid a bhaint as roinnt feidhmeanna de chuid Kavita cosúil le Send To Device ní mór soláthraí ríomhphoist a shocrú. Teastaíonn idirghabháil riaracháin ó ghnéithe eile cosúil le Forgot Password gan socrú Ríomhphost.",
|
||||||
"setting-description": "Ní mór duit socruithe Ainm Óstach agus SMTP araon a líonadh chun feidhmiúlacht ríomhphost-bhunaithe a úsáid laistigh de Kavita.",
|
"setting-description": "Ní mór duit socruithe Ainm Óstach agus SMTP araon a líonadh chun feidhmiúlacht ríomhphost-bhunaithe a úsáid laistigh de Kavita.",
|
||||||
"test-warning": "Ní mór duit sábháil sula n-úsáideann tú cnaipe Tástála.",
|
"test-warning": "Ní mór socruithe bailí a bheith agat sula mbuaileann tú Tástáil.",
|
||||||
"send-to-warning": "Más mian leat Seol chuig gléas a bheith ag obair ní mór duit do shocruithe ríomhphoist a shocrú",
|
"send-to-warning": "Más mian leat Seol chuig gléas a bheith ag obair ní mór duit do shocruithe ríomhphoist a shocrú",
|
||||||
"email-url-label": "URL na Seirbhíse Ríomhphoist",
|
"email-url-label": "URL na Seirbhíse Ríomhphoist",
|
||||||
"email-url-tooltip": "Úsáid URL láncháilithe na seirbhíse ríomhphoist. Ná cuir deireadh le slais.",
|
"email-url-tooltip": "Úsáid URL láncháilithe na seirbhíse ríomhphoist. Ná cuir deireadh le slais.",
|
||||||
@ -1134,7 +1134,7 @@
|
|||||||
"characters": "{{metadata-fields.characters-title}}",
|
"characters": "{{metadata-fields.characters-title}}",
|
||||||
"collection-tags": "Clibeanna Bailiúcháin",
|
"collection-tags": "Clibeanna Bailiúcháin",
|
||||||
"colorist": "Dathóir",
|
"colorist": "Dathóir",
|
||||||
"cover-artist": "Ealaíontóir Clúdaigh",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"editor": "Eagarthóir",
|
"editor": "Eagarthóir",
|
||||||
"formats": "Formáidí",
|
"formats": "Formáidí",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
@ -1849,8 +1849,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Speisialta",
|
"special": "Speisialta",
|
||||||
"issue-num": "Eisiúint #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "Caibidil 1009"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "Oscail Seachtrach"
|
"open-external": "Oscail Seachtrach"
|
||||||
|
@ -693,11 +693,11 @@
|
|||||||
"annual": "연간"
|
"annual": "연간"
|
||||||
},
|
},
|
||||||
"publication-status-pipe": {
|
"publication-status-pipe": {
|
||||||
"ended": "종료",
|
"ended": "누락",
|
||||||
"ongoing": "진행중",
|
"ongoing": "연재중",
|
||||||
"hiatus": "중단",
|
"hiatus": "휴재",
|
||||||
"completed": "완결",
|
"completed": "완결",
|
||||||
"cancelled": "취소"
|
"cancelled": "연재중단"
|
||||||
},
|
},
|
||||||
"person-role-pipe": {
|
"person-role-pipe": {
|
||||||
"character": "캐릭터",
|
"character": "캐릭터",
|
||||||
@ -705,7 +705,7 @@
|
|||||||
"writer": "작가",
|
"writer": "작가",
|
||||||
"other": "그 외",
|
"other": "그 외",
|
||||||
"artist": "작가",
|
"artist": "작가",
|
||||||
"cover-artist": "표지 작가",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "편집자",
|
"editor": "편집자",
|
||||||
"inker": "잉커",
|
"inker": "잉커",
|
||||||
"letterer": "레터러",
|
"letterer": "레터러",
|
||||||
@ -825,7 +825,7 @@
|
|||||||
"series-detail": {
|
"series-detail": {
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "시리즈 정보 편집",
|
"edit-series-alt": "정보 편집",
|
||||||
"no-pages": "{{toasts.no-pages}}",
|
"no-pages": "{{toasts.no-pages}}",
|
||||||
"no-chapters": "이 볼륨에는 챕터가 없습니다. 읽을 수 없습니다.",
|
"no-chapters": "이 볼륨에는 챕터가 없습니다. 읽을 수 없습니다.",
|
||||||
"cover-change": "브라우저에서 이미지를 새로 고치는 데 최대 1분이 걸릴 수 있습니다. 그때까지는 일부 페이지에 이전 이미지가 표시될 수 있습니다.",
|
"cover-change": "브라우저에서 이미지를 새로 고치는 데 최대 1분이 걸릴 수 있습니다. 그때까지는 일부 페이지에 이전 이미지가 표시될 수 있습니다.",
|
||||||
@ -982,8 +982,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "스페셜",
|
"special": "스페셜",
|
||||||
"issue-num": "이슈 #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "챕터"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"manage-email-settings": {
|
"manage-email-settings": {
|
||||||
"reset": "{{common.reset}}",
|
"reset": "{{common.reset}}",
|
||||||
@ -1016,7 +1017,7 @@
|
|||||||
"username-tooltip": "호스트에 대해 인증하는 데 사용되는 사용자 이름",
|
"username-tooltip": "호스트에 대해 인증하는 데 사용되는 사용자 이름",
|
||||||
"host-tooltip": "이메일 서버의 발신/SMTP 주소",
|
"host-tooltip": "이메일 서버의 발신/SMTP 주소",
|
||||||
"setting-description": "Kavita 내에서 이메일 기반 기능을 사용하려면 호스트 이름과 SMTP 설정을 모두 입력해야 합니다.",
|
"setting-description": "Kavita 내에서 이메일 기반 기능을 사용하려면 호스트 이름과 SMTP 설정을 모두 입력해야 합니다.",
|
||||||
"test-warning": "테스트 버튼을 사용하기 전에 반드시 저장해야 합니다."
|
"test-warning": "테스트를 누르기 전에 설정이 유효해야 합니다."
|
||||||
},
|
},
|
||||||
"manage-scrobble-errors": {
|
"manage-scrobble-errors": {
|
||||||
"edit-item-alt": "편집 {{seriesName}}",
|
"edit-item-alt": "편집 {{seriesName}}",
|
||||||
@ -1885,7 +1886,7 @@
|
|||||||
"filter-field-pipe": {
|
"filter-field-pipe": {
|
||||||
"collection-tags": "컬렉션 태그",
|
"collection-tags": "컬렉션 태그",
|
||||||
"colorist": "컬러리스트",
|
"colorist": "컬러리스트",
|
||||||
"cover-artist": "커버 아티스트",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"editor": "편집자",
|
"editor": "편집자",
|
||||||
"summary": "요약",
|
"summary": "요약",
|
||||||
"tags": "{{metadata-fields.tags-title}}",
|
"tags": "{{metadata-fields.tags-title}}",
|
||||||
|
@ -622,7 +622,7 @@
|
|||||||
},
|
},
|
||||||
"series-detail": {
|
"series-detail": {
|
||||||
"continue": "Kontynuuj",
|
"continue": "Kontynuuj",
|
||||||
"edit-series-alt": "Edytuj informacje o serii",
|
"edit-series-alt": "Edytuj informacje",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"recommendations-tab": "{{tabs.recommendations-tab}}",
|
"recommendations-tab": "{{tabs.recommendations-tab}}",
|
||||||
"send-to": "Plik wysłany e-mailem do {{deviceName}}",
|
"send-to": "Plik wysłany e-mailem do {{deviceName}}",
|
||||||
@ -1199,7 +1199,7 @@
|
|||||||
"size-limit-tooltip": "Ile bajtów może obsłużyć serwer poczty e-mail dla załączników",
|
"size-limit-tooltip": "Ile bajtów może obsłużyć serwer poczty e-mail dla załączników",
|
||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"test-warning": "Musisz zapisać przed użyciem przycisku Test.",
|
"test-warning": "Przed naciśnięciem przycisku Test wprowadź prawidłowe ustawienia.",
|
||||||
"setting-description": "Aby korzystać z funkcji poczty e-mail w Kavita, należy wypełnić zarówno ustawienia nazwy hosta, jak i SMTP."
|
"setting-description": "Aby korzystać z funkcji poczty e-mail w Kavita, należy wypełnić zarówno ustawienia nazwy hosta, jak i SMTP."
|
||||||
},
|
},
|
||||||
"manage-media-settings": {
|
"manage-media-settings": {
|
||||||
@ -1403,8 +1403,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Special",
|
"special": "Special",
|
||||||
"chapter": "Rozdział",
|
"chapter": "{{common.chapter-num}}",
|
||||||
"issue-num": "Wydanie #"
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"card-detail-layout": {
|
"card-detail-layout": {
|
||||||
"jumpkey-count": "{{count}} Serii",
|
"jumpkey-count": "{{count}} Serii",
|
||||||
|
@ -462,7 +462,7 @@
|
|||||||
"artist": "Artista",
|
"artist": "Artista",
|
||||||
"character": "Personagem",
|
"character": "Personagem",
|
||||||
"colorist": "Colorista",
|
"colorist": "Colorista",
|
||||||
"cover-artist": "Artista de Capa",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"inker": "Arte-Finalista",
|
"inker": "Arte-Finalista",
|
||||||
"letterer": "Letrista",
|
"letterer": "Letrista",
|
||||||
@ -682,7 +682,7 @@
|
|||||||
"incognito": "Incógnito",
|
"incognito": "Incógnito",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "Editar Informação da Série",
|
"edit-series-alt": "Editar informações",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"books-tab": "{{tabs.books-tab}}",
|
"books-tab": "{{tabs.books-tab}}",
|
||||||
"volumes-tab": "{{tabs.volumes-tab}}",
|
"volumes-tab": "{{tabs.volumes-tab}}",
|
||||||
@ -917,8 +917,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Especial",
|
"special": "Especial",
|
||||||
"issue-num": "Número #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "Capítulo"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "Abrir Externo"
|
"open-external": "Abrir Externo"
|
||||||
@ -953,7 +954,7 @@
|
|||||||
"username-tooltip": "O nome de utilizador usado para autenticar no host",
|
"username-tooltip": "O nome de utilizador usado para autenticar no host",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"test-warning": "Tem de gravar antes de usar o botão Teste.",
|
"test-warning": "Deve ter definições válidas antes de clicar em Teste.",
|
||||||
"setting-description": "Tem de preencher o nome do Host e as definições de SMTP para poder usar as funcionalidades do Kavita baseadas em email."
|
"setting-description": "Tem de preencher o nome do Host e as definições de SMTP para poder usar as funcionalidades do Kavita baseadas em email."
|
||||||
},
|
},
|
||||||
"manage-library": {
|
"manage-library": {
|
||||||
@ -1890,7 +1891,7 @@
|
|||||||
},
|
},
|
||||||
"filter-field-pipe": {
|
"filter-field-pipe": {
|
||||||
"age-rating": "{{metadata-fields.age-rating-title}}",
|
"age-rating": "{{metadata-fields.age-rating-title}}",
|
||||||
"cover-artist": "Artista de Capa",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"formats": "Formatos",
|
"formats": "Formatos",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
"libraries": "Bibliotecas",
|
"libraries": "Bibliotecas",
|
||||||
|
@ -462,7 +462,7 @@
|
|||||||
"artist": "Artista",
|
"artist": "Artista",
|
||||||
"character": "Personagem",
|
"character": "Personagem",
|
||||||
"colorist": "Colorista",
|
"colorist": "Colorista",
|
||||||
"cover-artist": "Artista da Capa",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"inker": "Arte-finalista",
|
"inker": "Arte-finalista",
|
||||||
"letterer": "Letrista",
|
"letterer": "Letrista",
|
||||||
@ -682,7 +682,7 @@
|
|||||||
"incognito": "Incógnito",
|
"incognito": "Incógnito",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "Editar Informações da Série",
|
"edit-series-alt": "Editar informações",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"books-tab": "{{tabs.books-tab}}",
|
"books-tab": "{{tabs.books-tab}}",
|
||||||
"volumes-tab": "{{tabs.volumes-tab}}",
|
"volumes-tab": "{{tabs.volumes-tab}}",
|
||||||
@ -917,8 +917,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "Especial",
|
"special": "Especial",
|
||||||
"issue-num": "Número #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "Capítulo"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "Abrir Externamente"
|
"open-external": "Abrir Externamente"
|
||||||
@ -953,7 +954,7 @@
|
|||||||
"username-tooltip": "O nome de usuário usado para autenticação no host",
|
"username-tooltip": "O nome de usuário usado para autenticação no host",
|
||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"test-warning": "Você deve salvar antes de usar o botão Teste.",
|
"test-warning": "Você deve ter configurações válidas antes de clicar em Testar.",
|
||||||
"setting-description": "Você deve preencher as configurações de nome do host e SMTP para usar a funcionalidade baseada em e-mail no Kavita."
|
"setting-description": "Você deve preencher as configurações de nome do host e SMTP para usar a funcionalidade baseada em e-mail no Kavita."
|
||||||
},
|
},
|
||||||
"manage-library": {
|
"manage-library": {
|
||||||
@ -1171,8 +1172,8 @@
|
|||||||
"series-tab": "{{tabs.series-tab}}",
|
"series-tab": "{{tabs.series-tab}}",
|
||||||
"name-label": "Nome",
|
"name-label": "Nome",
|
||||||
"name-validation": "Nome deve ser único",
|
"name-validation": "Nome deve ser único",
|
||||||
"promote-label": "Promoção",
|
"promote-label": "Divulgar",
|
||||||
"promote-tooltip": "Promoção significa que a tag pode ser vista em todo o servidor, não apenas para usuários administrativos. Todas as séries que possuem essa tag ainda terão restrições de acesso do usuário.",
|
"promote-tooltip": "Divulgação significa que a etiqueta pode ser vista em todo o servidor, não apenas para usuários administrativos. Todas as séries que possuem essa etiqueta ainda terão restrições de acesso do usuário.",
|
||||||
"summary-label": "Sumário",
|
"summary-label": "Sumário",
|
||||||
"deselect-all": "{{common.deselect-all}}",
|
"deselect-all": "{{common.deselect-all}}",
|
||||||
"select-all": "{{common.select-all}}",
|
"select-all": "{{common.select-all}}",
|
||||||
@ -1319,8 +1320,8 @@
|
|||||||
"month-label": "Mês",
|
"month-label": "Mês",
|
||||||
"ending-title": "Terminando",
|
"ending-title": "Terminando",
|
||||||
"starting-title": "Começando",
|
"starting-title": "Começando",
|
||||||
"promote-label": "Promover",
|
"promote-label": "Divulgar",
|
||||||
"promote-tooltip": "Promoção significa que a coleção pode ser vista em todo o servidor, não apenas para você. Todas as séries desta coleção ainda terão restrições de acesso do usuário."
|
"promote-tooltip": "Divulgação significa que a coleção pode ser vista em todo o servidor, não apenas para você. Todas as séries desta coleção ainda terão restrições de acesso do usuário."
|
||||||
},
|
},
|
||||||
"import-cbl-modal": {
|
"import-cbl-modal": {
|
||||||
"close": "{{common.close}}",
|
"close": "{{common.close}}",
|
||||||
@ -1705,8 +1706,8 @@
|
|||||||
"confirm-download-size-ios": "O iOS tem problemas para baixar arquivos maiores que 200 MB; esse download pode não ser concluído.",
|
"confirm-download-size-ios": "O iOS tem problemas para baixar arquivos maiores que 200 MB; esse download pode não ser concluído.",
|
||||||
"confirm-delete-collections": "Tem certeza de que deseja excluir várias coleções?",
|
"confirm-delete-collections": "Tem certeza de que deseja excluir várias coleções?",
|
||||||
"collection-not-owned": "Você não possui esta coleção",
|
"collection-not-owned": "Você não possui esta coleção",
|
||||||
"collections-promoted": "Coleções promovidas",
|
"collections-promoted": "Coleções divulgadas",
|
||||||
"collections-unpromoted": "Coleções não promovidas",
|
"collections-unpromoted": "Coleções não divulgadas",
|
||||||
"collections-deleted": "Coleções excluídas",
|
"collections-deleted": "Coleções excluídas",
|
||||||
"pdf-book-mode-screen-size": "Tela muito pequena para o modo Livro",
|
"pdf-book-mode-screen-size": "Tela muito pequena para o modo Livro",
|
||||||
"stack-imported": "Pilha Importada",
|
"stack-imported": "Pilha Importada",
|
||||||
@ -1714,11 +1715,11 @@
|
|||||||
"mal-token-required": "O token MAL é obrigatório, definido nas Configurações do Usuário",
|
"mal-token-required": "O token MAL é obrigatório, definido nas Configurações do Usuário",
|
||||||
"reading-lists-deleted": "Listas de leitura excluídas",
|
"reading-lists-deleted": "Listas de leitura excluídas",
|
||||||
"confirm-delete-reading-lists": "Tem certeza de que deseja excluir as listas de leitura? Isto não pode ser desfeito.",
|
"confirm-delete-reading-lists": "Tem certeza de que deseja excluir as listas de leitura? Isto não pode ser desfeito.",
|
||||||
"reading-lists-unpromoted": "Listas de leitura não promovidas",
|
"reading-lists-unpromoted": "Listas de leitura não divulgadas",
|
||||||
"reading-lists-promoted": "Listas de leitura promovidas",
|
"reading-lists-promoted": "Listas de leitura divulgadas",
|
||||||
"reading-list-promoted": "Lista de Leitura promovida",
|
"reading-list-promoted": "Lista de Leitura divulgadas",
|
||||||
"confirm-reset-server-settings": "Isso redefinirá suas configurações para os valores da primeira instalação. Tem certeza de que deseja continuar?",
|
"confirm-reset-server-settings": "Isso redefinirá suas configurações para os valores da primeira instalação. Tem certeza de que deseja continuar?",
|
||||||
"reading-list-unpromoted": "Lista de Leitura não promovida",
|
"reading-list-unpromoted": "Lista de Leitura não divulgadas",
|
||||||
"generate-colorscape-queued": "Gerar colorscape na fila para {{name}}",
|
"generate-colorscape-queued": "Gerar colorscape na fila para {{name}}",
|
||||||
"chapter-deleted": "Capítulo excluído",
|
"chapter-deleted": "Capítulo excluído",
|
||||||
"confirm-delete-chapter": "Tem certeza de que deseja excluir este capítulo? Não modificará arquivos no disco.",
|
"confirm-delete-chapter": "Tem certeza de que deseja excluir este capítulo? Não modificará arquivos no disco.",
|
||||||
@ -1754,8 +1755,8 @@
|
|||||||
"mark-invisible": "Marcar como Invisível",
|
"mark-invisible": "Marcar como Invisível",
|
||||||
"mark-visible": "Marcar como Visível",
|
"mark-visible": "Marcar como Visível",
|
||||||
"import-mal-stack": "Importar Pilha do Mal",
|
"import-mal-stack": "Importar Pilha do Mal",
|
||||||
"unpromote": "Não Promover",
|
"unpromote": "Não Divulgar",
|
||||||
"promote": "Promover",
|
"promote": "Divulgar",
|
||||||
"generate-colorscape": "Gerar ColorScape",
|
"generate-colorscape": "Gerar ColorScape",
|
||||||
"new-collection": "Nova Coleção",
|
"new-collection": "Nova Coleção",
|
||||||
"multiple-selections": "Múltiplas Seleções",
|
"multiple-selections": "Múltiplas Seleções",
|
||||||
@ -1765,7 +1766,7 @@
|
|||||||
"mark-as-read-tooltip": "Marcar o progresso como totalmente lido",
|
"mark-as-read-tooltip": "Marcar o progresso como totalmente lido",
|
||||||
"scan-library-tooltip": "Escanear a biblioteca em busca de alterações. Use o escaneamento forçado para forçar a verificação de todas as pastas",
|
"scan-library-tooltip": "Escanear a biblioteca em busca de alterações. Use o escaneamento forçado para forçar a verificação de todas as pastas",
|
||||||
"analyze-files-tooltip": "Analisar Arquivos quanto ao tipo e tamanho da extensão",
|
"analyze-files-tooltip": "Analisar Arquivos quanto ao tipo e tamanho da extensão",
|
||||||
"unpromote-tooltip": "Restringir a visibilidade apenas à sua conta",
|
"unpromote-tooltip": "Restringi a visibilidade apenas à sua conta",
|
||||||
"generate-colorscape-tooltip": "Gerar colorscapes e quaisquer capas ausentes",
|
"generate-colorscape-tooltip": "Gerar colorscapes e quaisquer capas ausentes",
|
||||||
"edit-tooltip": "Editar configurações ou detalhes",
|
"edit-tooltip": "Editar configurações ou detalhes",
|
||||||
"remove-from-on-deck-tooltip": "Remover séries da exibição no Na Estante",
|
"remove-from-on-deck-tooltip": "Remover séries da exibição no Na Estante",
|
||||||
@ -1854,7 +1855,7 @@
|
|||||||
"loading": "Carregando…",
|
"loading": "Carregando…",
|
||||||
"username": "Nome do usuário",
|
"username": "Nome do usuário",
|
||||||
"password": "Senha",
|
"password": "Senha",
|
||||||
"promoted": "Promovido",
|
"promoted": "Divulgado",
|
||||||
"select-all": "Selecionar Tudo",
|
"select-all": "Selecionar Tudo",
|
||||||
"deselect-all": "Deselecionar Todos",
|
"deselect-all": "Deselecionar Todos",
|
||||||
"series-count": "{{num}} Séries",
|
"series-count": "{{num}} Séries",
|
||||||
@ -1893,7 +1894,7 @@
|
|||||||
"characters": "{{metadata-fields.characters-title}}",
|
"characters": "{{metadata-fields.characters-title}}",
|
||||||
"collection-tags": "Coleção de Tags",
|
"collection-tags": "Coleção de Tags",
|
||||||
"colorist": "Colorista",
|
"colorist": "Colorista",
|
||||||
"cover-artist": "Artista da Capa",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"editor": "Editor",
|
"editor": "Editor",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
"inker": "Arte-finalista",
|
"inker": "Arte-finalista",
|
||||||
|
@ -158,7 +158,7 @@
|
|||||||
"pdf-theme-label": "主题",
|
"pdf-theme-label": "主题",
|
||||||
"pdf-scroll-mode-label": "滚动模式",
|
"pdf-scroll-mode-label": "滚动模式",
|
||||||
"pdf-scroll-mode-tooltip": "您如何滚动页面。垂直/水平和点击翻页(无滚动)",
|
"pdf-scroll-mode-tooltip": "您如何滚动页面。垂直/水平和点击翻页(无滚动)",
|
||||||
"pdf-spread-mode-label": "页面传播模式",
|
"pdf-spread-mode-label": "页面阅读模式",
|
||||||
"background-color-tooltip": "图像阅读器的背景颜色",
|
"background-color-tooltip": "图像阅读器的背景颜色",
|
||||||
"auto-close-menu-tooltip": "菜单应该自动关闭",
|
"auto-close-menu-tooltip": "菜单应该自动关闭",
|
||||||
"show-screen-hints-tooltip": "显示覆盖以帮助了解分页区域和方向",
|
"show-screen-hints-tooltip": "显示覆盖以帮助了解分页区域和方向",
|
||||||
@ -206,7 +206,7 @@
|
|||||||
},
|
},
|
||||||
"restriction-selector": {
|
"restriction-selector": {
|
||||||
"title": "年龄分级限制",
|
"title": "年龄分级限制",
|
||||||
"description": "选中后,全部系列和至少存在一个条目的阅读清单,其年龄限制大于下面选择的,将从结果中移除。",
|
"description": "选中后,全部系列和至少存在一个条目的阅读列表,其年龄限制大于下面选择的,将从结果中移除。",
|
||||||
"not-applicable-for-admins": "不适用于管理员。",
|
"not-applicable-for-admins": "不适用于管理员。",
|
||||||
"age-rating-label": "{{metadata-fields.age-rating-title}}",
|
"age-rating-label": "{{metadata-fields.age-rating-title}}",
|
||||||
"no-restriction": "无限制",
|
"no-restriction": "无限制",
|
||||||
@ -405,7 +405,7 @@
|
|||||||
"cbl-conflict-reason-pipe": {
|
"cbl-conflict-reason-pipe": {
|
||||||
"all-series-missing": "您的账户无法访问列表中的所有系列,或者Kavita在列表中没有任何内容。",
|
"all-series-missing": "您的账户无法访问列表中的所有系列,或者Kavita在列表中没有任何内容。",
|
||||||
"chapter-missing": "{{series}}: Kavita缺少第{{chapter}}章节。此项目将被跳过。",
|
"chapter-missing": "{{series}}: Kavita缺少第{{chapter}}章节。此项目将被跳过。",
|
||||||
"empty-file": "cbl文件为空,没有任何操作可以进行。",
|
"empty-file": "cbl 文件为空,没有任何操作可以进行。",
|
||||||
"name-conflict": "您的账户已经存在一个与cbl文件匹配的阅读列表({{readingListName}})。",
|
"name-conflict": "您的账户已经存在一个与cbl文件匹配的阅读列表({{readingListName}})。",
|
||||||
"series-collision": "系列{{seriesLink}}与另一个资料库中同名的系列发生冲突。",
|
"series-collision": "系列{{seriesLink}}与另一个资料库中同名的系列发生冲突。",
|
||||||
"series-missing": "系列{{series}}在Kavita中缺失,或者您的账户没有权限。所有带有此系列的项目将在导入时被跳过。",
|
"series-missing": "系列{{series}}在Kavita中缺失,或者您的账户没有权限。所有带有此系列的项目将在导入时被跳过。",
|
||||||
@ -462,7 +462,7 @@
|
|||||||
"artist": "设计师",
|
"artist": "设计师",
|
||||||
"character": "角色",
|
"character": "角色",
|
||||||
"colorist": "上色师",
|
"colorist": "上色师",
|
||||||
"cover-artist": "封面设计",
|
"cover-artist": "{{artist}}",
|
||||||
"editor": "编辑",
|
"editor": "编辑",
|
||||||
"inker": "上墨师",
|
"inker": "上墨师",
|
||||||
"letterer": "嵌字师",
|
"letterer": "嵌字师",
|
||||||
@ -682,7 +682,7 @@
|
|||||||
"incognito": "隐身模式",
|
"incognito": "隐身模式",
|
||||||
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
"remove-from-want-to-read": "{{actionable.remove-from-want-to-read}}",
|
||||||
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
"add-to-want-to-read": "{{actionable.add-to-want-to-read}}",
|
||||||
"edit-series-alt": "编辑系列信息",
|
"edit-series-alt": "編輯訊息",
|
||||||
"storyline-tab": "{{tabs.storyline-tab}}",
|
"storyline-tab": "{{tabs.storyline-tab}}",
|
||||||
"books-tab": "{{tabs.books-tab}}",
|
"books-tab": "{{tabs.books-tab}}",
|
||||||
"volumes-tab": "{{tabs.volumes-tab}}",
|
"volumes-tab": "{{tabs.volumes-tab}}",
|
||||||
@ -752,7 +752,7 @@
|
|||||||
"home": "主页",
|
"home": "主页",
|
||||||
"want-to-read": "想读",
|
"want-to-read": "想读",
|
||||||
"collections": "收藏",
|
"collections": "收藏",
|
||||||
"reading-lists": "阅读清单",
|
"reading-lists": "阅读列表",
|
||||||
"bookmarks": "书签",
|
"bookmarks": "书签",
|
||||||
"filter-label": "{{common.filter}}",
|
"filter-label": "{{common.filter}}",
|
||||||
"all-series": "所有系列",
|
"all-series": "所有系列",
|
||||||
@ -789,7 +789,7 @@
|
|||||||
"manage-collection-label": "管理收藏",
|
"manage-collection-label": "管理收藏",
|
||||||
"manage-collection-tooltip": "是否允许Kavita根据ComicInfo.xml/opf文件中的SeriesGroup标签创建收藏",
|
"manage-collection-tooltip": "是否允许Kavita根据ComicInfo.xml/opf文件中的SeriesGroup标签创建收藏",
|
||||||
"manage-reading-list-label": "管理阅读列表",
|
"manage-reading-list-label": "管理阅读列表",
|
||||||
"manage-reading-list-tooltip": "是否允许Kavita根据ComicInfo.xml/opf文件中的StoryArc/StoryArcNumber和AlternativeSeries/AlternativeCount标签创建阅读清单",
|
"manage-reading-list-tooltip": "是否允许Kavita根据ComicInfo.xml/opf文件中的StoryArc/StoryArcNumber和AlternativeSeries/AlternativeCount标签创建阅读列表",
|
||||||
"allow-scrobbling-label": "允许Scrobbling",
|
"allow-scrobbling-label": "允许Scrobbling",
|
||||||
"allow-scrobbling-tooltip": "是否允许Kavita将阅读事件、想读状态、评分和评论记录至已配置的Scrobble服务提供商?本功能仅在激活服务器的Kavita+订阅后才会生效。",
|
"allow-scrobbling-tooltip": "是否允许Kavita将阅读事件、想读状态、评分和评论记录至已配置的Scrobble服务提供商?本功能仅在激活服务器的Kavita+订阅后才会生效。",
|
||||||
"folder-watching-label": "监控文件夹",
|
"folder-watching-label": "监控文件夹",
|
||||||
@ -917,8 +917,9 @@
|
|||||||
},
|
},
|
||||||
"entity-title": {
|
"entity-title": {
|
||||||
"special": "特刊",
|
"special": "特刊",
|
||||||
"issue-num": "期 #",
|
"issue-num": "{{common.issue-hash-num}}",
|
||||||
"chapter": "章节"
|
"chapter": "{{common.chapter-num}}",
|
||||||
|
"book-num": "{{common.book-num-shorthand}}"
|
||||||
},
|
},
|
||||||
"external-series-card": {
|
"external-series-card": {
|
||||||
"open-external": "打开外部链接"
|
"open-external": "打开外部链接"
|
||||||
@ -954,7 +955,7 @@
|
|||||||
"gmail-label": "Gmail",
|
"gmail-label": "Gmail",
|
||||||
"outlook-label": "Outlook",
|
"outlook-label": "Outlook",
|
||||||
"setting-description": "您必须填写主机名和 SMTP 设置才能使用 Kavita 中的基于电子邮件的功能。",
|
"setting-description": "您必须填写主机名和 SMTP 设置才能使用 Kavita 中的基于电子邮件的功能。",
|
||||||
"test-warning": "使用测试按钮之前必须保存。"
|
"test-warning": "在點擊“測試”之前,您必須具有有效的設定。"
|
||||||
},
|
},
|
||||||
"manage-library": {
|
"manage-library": {
|
||||||
"title": "资料库",
|
"title": "资料库",
|
||||||
@ -1219,9 +1220,9 @@
|
|||||||
"bulk-select-label": "批量选择项目"
|
"bulk-select-label": "批量选择项目"
|
||||||
},
|
},
|
||||||
"reading-lists": {
|
"reading-lists": {
|
||||||
"title": "阅读清单",
|
"title": "阅读列表",
|
||||||
"item-count": "{{common.item-count}}",
|
"item-count": "{{common.item-count}}",
|
||||||
"no-data": "没有阅读清单。",
|
"no-data": "没有阅读列表。",
|
||||||
"create-one-part-1": "尝试创建",
|
"create-one-part-1": "尝试创建",
|
||||||
"create-one-part-2": "一个"
|
"create-one-part-2": "一个"
|
||||||
},
|
},
|
||||||
@ -1272,7 +1273,7 @@
|
|||||||
"tags": "标签",
|
"tags": "标签",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
"libraries": "资料库",
|
"libraries": "资料库",
|
||||||
"reading-lists": "阅读清单",
|
"reading-lists": "阅读列表",
|
||||||
"collections": "收藏",
|
"collections": "收藏",
|
||||||
"close": "{{common.close}}",
|
"close": "{{common.close}}",
|
||||||
"loading": "{{common.loading}}",
|
"loading": "{{common.loading}}",
|
||||||
@ -1295,17 +1296,17 @@
|
|||||||
"close": "{{common.close}}"
|
"close": "{{common.close}}"
|
||||||
},
|
},
|
||||||
"add-to-list-modal": {
|
"add-to-list-modal": {
|
||||||
"title": "添加到阅读清单",
|
"title": "添加到阅读列表",
|
||||||
"close": "{{common.close}}",
|
"close": "{{common.close}}",
|
||||||
"filter-label": "{{common.filter}}",
|
"filter-label": "{{common.filter}}",
|
||||||
"promoted-alt": "{{common.promoted}}",
|
"promoted-alt": "{{common.promoted}}",
|
||||||
"no-data": "尚未创建任何清单",
|
"no-data": "尚未创建任何列表",
|
||||||
"loading": "{{common.loading}}",
|
"loading": "{{common.loading}}",
|
||||||
"reading-list-label": "阅读清单",
|
"reading-list-label": "阅读列表",
|
||||||
"create": "{{common.create}}"
|
"create": "{{common.create}}"
|
||||||
},
|
},
|
||||||
"edit-reading-list-modal": {
|
"edit-reading-list-modal": {
|
||||||
"title": "编辑阅读清单: {{name}}",
|
"title": "编辑阅读列表: {{name}}",
|
||||||
"general-tab": "{{tabs.general-tab}}",
|
"general-tab": "{{tabs.general-tab}}",
|
||||||
"cover-image-tab": "{{tabs.cover-tab}}",
|
"cover-image-tab": "{{tabs.cover-tab}}",
|
||||||
"close": "{{common.close}}",
|
"close": "{{common.close}}",
|
||||||
@ -1645,7 +1646,7 @@
|
|||||||
"email-service-reset": "电子邮件服务已重置",
|
"email-service-reset": "电子邮件服务已重置",
|
||||||
"email-service-reachable": "Kavita电子邮件服务连接成功",
|
"email-service-reachable": "Kavita电子邮件服务连接成功",
|
||||||
"email-service-unresponsive": "电子邮件服务的网址没有响应。",
|
"email-service-unresponsive": "电子邮件服务的网址没有响应。",
|
||||||
"refresh-covers-queued": "已为{{name}}排队刷新封面",
|
"refresh-covers-queued": "刷新 {{name}} 队列中的封面",
|
||||||
"library-file-analysis-queued": "已为{{name}}排队进行资料库文件分析",
|
"library-file-analysis-queued": "已为{{name}}排队进行资料库文件分析",
|
||||||
"entity-read": "{{name}}已标记为已读",
|
"entity-read": "{{name}}已标记为已读",
|
||||||
"entity-unread": "{{name}}已标记为未读",
|
"entity-unread": "{{name}}已标记为未读",
|
||||||
@ -1713,13 +1714,13 @@
|
|||||||
"confirm-delete-theme": "删除该主题将从磁盘中删除它。您可以在删除之前从临时目录中获取它",
|
"confirm-delete-theme": "删除该主题将从磁盘中删除它。您可以在删除之前从临时目录中获取它",
|
||||||
"mal-token-required": "需要 MAL 令牌,在用户设置中设置",
|
"mal-token-required": "需要 MAL 令牌,在用户设置中设置",
|
||||||
"reading-lists-deleted": "阅读列表已删除",
|
"reading-lists-deleted": "阅读列表已删除",
|
||||||
"reading-lists-unpromoted": "未推广的阅读清单",
|
"reading-lists-unpromoted": "未推广的阅读列表",
|
||||||
"confirm-delete-reading-lists": "您确定要删除阅读列表吗?此操作无法撤消。",
|
"confirm-delete-reading-lists": "您确定要删除阅读列表吗?此操作无法撤消。",
|
||||||
"reading-lists-promoted": "推广阅读清单",
|
"reading-lists-promoted": "推广阅读列表",
|
||||||
"reading-list-promoted": "提升阅读清单",
|
"reading-list-promoted": "提升阅读列表",
|
||||||
"reading-list-unpromoted": "阅读清单未推广",
|
"reading-list-unpromoted": "阅读列表未推广",
|
||||||
"confirm-reset-server-settings": "这会将您的设置重置为首次安装值。您确定要继续吗?",
|
"confirm-reset-server-settings": "这会将您的设置重置为首次安装值。您确定要继续吗?",
|
||||||
"generate-colorscape-queued": "为 {{name}} 生成排队的彩色图案",
|
"generate-colorscape-queued": "为 {{name}} 生成排队的色彩主题",
|
||||||
"volume-deleted": "卷已删除",
|
"volume-deleted": "卷已删除",
|
||||||
"confirm-delete-chapter": "您确定要删除此章节吗?它不会修改磁盘上的文件。",
|
"confirm-delete-chapter": "您确定要删除此章节吗?它不会修改磁盘上的文件。",
|
||||||
"confirm-delete-volume": "您确定要删除此卷吗?它不会修改磁盘上的文件。",
|
"confirm-delete-volume": "您确定要删除此卷吗?它不会修改磁盘上的文件。",
|
||||||
@ -1739,7 +1740,7 @@
|
|||||||
"remove-from-want-to-read": "从想读中移除",
|
"remove-from-want-to-read": "从想读中移除",
|
||||||
"remove-from-on-deck": "从最近阅读中移除",
|
"remove-from-on-deck": "从最近阅读中移除",
|
||||||
"others": "其他",
|
"others": "其他",
|
||||||
"add-to-reading-list": "添加到阅读清单",
|
"add-to-reading-list": "添加到阅读列表",
|
||||||
"add-to-collection": "添加到收藏",
|
"add-to-collection": "添加到收藏",
|
||||||
"send-to": "发送到",
|
"send-to": "发送到",
|
||||||
"delete": "删除",
|
"delete": "删除",
|
||||||
@ -1757,7 +1758,7 @@
|
|||||||
"promote": "推广",
|
"promote": "推广",
|
||||||
"unpromote": "取消推广",
|
"unpromote": "取消推广",
|
||||||
"new-collection": "新收藏",
|
"new-collection": "新收藏",
|
||||||
"generate-colorscape": "生成彩色图案",
|
"generate-colorscape": "生成色彩主题",
|
||||||
"multiple-selections": "多项选择",
|
"multiple-selections": "多项选择",
|
||||||
"scan-library-tooltip": "扫描库以查看是否有更改。使用强制扫描检查每个文件夹",
|
"scan-library-tooltip": "扫描库以查看是否有更改。使用强制扫描检查每个文件夹",
|
||||||
"edit-tooltip": "编辑设置或详细信息",
|
"edit-tooltip": "编辑设置或详细信息",
|
||||||
@ -1777,7 +1778,7 @@
|
|||||||
"promote-tooltip": "使项目对所有用户可见",
|
"promote-tooltip": "使项目对所有用户可见",
|
||||||
"settings-tooltip": "查看设置或详细信息",
|
"settings-tooltip": "查看设置或详细信息",
|
||||||
"analyze-files-tooltip": "分析文件的扩展类型和大小",
|
"analyze-files-tooltip": "分析文件的扩展类型和大小",
|
||||||
"generate-colorscape-tooltip": "生成色彩图案和任何缺失的封面",
|
"generate-colorscape-tooltip": "生成色彩主题和任何缺失的封面",
|
||||||
"refresh-covers-tooltip": "重新生成所有封面",
|
"refresh-covers-tooltip": "重新生成所有封面",
|
||||||
"mark-as-unread-tooltip": "将进度标记为未读",
|
"mark-as-unread-tooltip": "将进度标记为未读",
|
||||||
"add-to-want-to-read-tooltip": "添加系列到想读",
|
"add-to-want-to-read-tooltip": "添加系列到想读",
|
||||||
@ -1814,7 +1815,7 @@
|
|||||||
"pdf-vertical": "垂直滚动",
|
"pdf-vertical": "垂直滚动",
|
||||||
"pdf-horizontal": "水平滚动",
|
"pdf-horizontal": "水平滚动",
|
||||||
"pdf-page": "点击翻页",
|
"pdf-page": "点击翻页",
|
||||||
"pdf-none": "没有",
|
"pdf-none": "无",
|
||||||
"pdf-light": "明亮",
|
"pdf-light": "明亮",
|
||||||
"pdf-multiple": "默认",
|
"pdf-multiple": "默认",
|
||||||
"pdf-dark": "黑暗",
|
"pdf-dark": "黑暗",
|
||||||
@ -1892,7 +1893,7 @@
|
|||||||
"characters": "{{metadata-fields.characters-title}}",
|
"characters": "{{metadata-fields.characters-title}}",
|
||||||
"collection-tags": "收藏标签",
|
"collection-tags": "收藏标签",
|
||||||
"colorist": "上色师",
|
"colorist": "上色师",
|
||||||
"cover-artist": "封面设计",
|
"cover-artist": "{{person-role-pipe.cover-artist}}",
|
||||||
"editor": "编辑",
|
"editor": "编辑",
|
||||||
"formats": "格式",
|
"formats": "格式",
|
||||||
"genres": "{{metadata-fields.genres-title}}",
|
"genres": "{{metadata-fields.genres-title}}",
|
||||||
@ -2164,7 +2165,7 @@
|
|||||||
"user-stats": "状态",
|
"user-stats": "状态",
|
||||||
"theme": "主题",
|
"theme": "主题",
|
||||||
"customize": "自定义",
|
"customize": "自定义",
|
||||||
"cbl-import": "CBL 阅读清单",
|
"cbl-import": "CBL 阅读列表",
|
||||||
"mal-stack-import": "MAL Stack",
|
"mal-stack-import": "MAL Stack",
|
||||||
"info-section-title": "信息"
|
"info-section-title": "信息"
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,7 @@ import {provideTranslocoPersistTranslations} from "@jsverse/transloco-persist-tr
|
|||||||
import {LazyLoadImageModule} from "ng-lazyload-image";
|
import {LazyLoadImageModule} from "ng-lazyload-image";
|
||||||
import {getSaver, SAVER} from "./app/_providers/saver.provider";
|
import {getSaver, SAVER} from "./app/_providers/saver.provider";
|
||||||
import {distinctUntilChanged} from "rxjs/operators";
|
import {distinctUntilChanged} from "rxjs/operators";
|
||||||
|
import {APP_BASE_HREF, PlatformLocation} from "@angular/common";
|
||||||
|
|
||||||
const disableAnimations = !('animate' in document.documentElement);
|
const disableAnimations = !('animate' in document.documentElement);
|
||||||
|
|
||||||
@ -115,6 +116,10 @@ const translocoOptions = {
|
|||||||
} as TranslocoConfig
|
} as TranslocoConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getBaseHref(platformLocation: PlatformLocation): string {
|
||||||
|
return platformLocation.getBaseHrefFromDOM();
|
||||||
|
}
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, {
|
bootstrapApplication(AppComponent, {
|
||||||
providers: [
|
providers: [
|
||||||
importProvidersFrom(BrowserModule,
|
importProvidersFrom(BrowserModule,
|
||||||
@ -149,6 +154,11 @@ bootstrapApplication(AppComponent, {
|
|||||||
preLoad,
|
preLoad,
|
||||||
Title,
|
Title,
|
||||||
{ provide: SAVER, useFactory: getSaver },
|
{ provide: SAVER, useFactory: getSaver },
|
||||||
|
{
|
||||||
|
provide: APP_BASE_HREF,
|
||||||
|
useFactory: getBaseHref,
|
||||||
|
deps: [PlatformLocation]
|
||||||
|
},
|
||||||
provideHttpClient(withInterceptorsFromDi())
|
provideHttpClient(withInterceptorsFromDi())
|
||||||
]
|
]
|
||||||
} as ApplicationConfig)
|
} as ApplicationConfig)
|
||||||
|
19
openapi.json
19
openapi.json
@ -2,7 +2,7 @@
|
|||||||
"openapi": "3.0.1",
|
"openapi": "3.0.1",
|
||||||
"info": {
|
"info": {
|
||||||
"title": "Kavita",
|
"title": "Kavita",
|
||||||
"description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.2.12",
|
"description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.3.2",
|
||||||
"license": {
|
"license": {
|
||||||
"name": "GPL-3.0",
|
"name": "GPL-3.0",
|
||||||
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
||||||
@ -4383,6 +4383,15 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pageNumber",
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -16084,7 +16093,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"maxLength": 32,
|
"maxLength": 256,
|
||||||
"minLength": 6,
|
"minLength": 6,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -16144,7 +16153,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"maxLength": 32,
|
"maxLength": 256,
|
||||||
"minLength": 6,
|
"minLength": 6,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -19134,7 +19143,7 @@
|
|||||||
"nullable": true
|
"nullable": true
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"maxLength": 32,
|
"maxLength": 256,
|
||||||
"minLength": 6,
|
"minLength": 6,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -19273,7 +19282,7 @@
|
|||||||
"description": "The Username of the User"
|
"description": "The Username of the User"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"maxLength": 32,
|
"maxLength": 256,
|
||||||
"minLength": 6,
|
"minLength": 6,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The new password"
|
"description": "The new password"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user