Localization - Part 2 (#2178)
* Changed language codes in the UI to be a list of all codes we will ever support. * Converted actionables * Fixed the GetLocales not using Intersect, but Union. * Fixed some localization strings in backend when user doesn't exist. Removed AllowAnonymous from reset-password, since it is a protected API * Fixed all instances of anonymous APIs where Claim wouldn't work * Keyed preference options and mixed misc localization issues * Translations update from Hosted Weblate (#2177) * Bump versions by dotnet-bump-version. * Added translation using Weblate (Dutch) * Bump versions by dotnet-bump-version. * Translated using Weblate (Dutch) Currently translated at 20.8% (33 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Translated using Weblate (Spanish) Currently translated at 1.4% (20 of 1371 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/es/ * Translated using Weblate (Dutch) Currently translated at 60.1% (95 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Translated using Weblate (Dutch) Currently translated at 60.1% (95 of 158 strings) Translation: Kavita/backend Translate-URL: https://hosted.weblate.org/projects/kavita/backend/nl/ * Added translation using Weblate (Dutch) --------- Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com> Co-authored-by: Javier Barbero <javier.agustin.barbero@gmail.com> Co-authored-by: Stijn <stijn.biemans@gmail.com> --------- Co-authored-by: Weblate (bot) <hosted@weblate.org> Co-authored-by: Hans Kalisvaart <hans.kalisvaart@gmail.com> Co-authored-by: Javier Barbero <javier.agustin.barbero@gmail.com> Co-authored-by: Stijn <stijn.biemans@gmail.com>
This commit is contained in:
parent
c7701bc729
commit
69532d45ac
26 changed files with 2035 additions and 195 deletions
|
|
@ -45,11 +45,11 @@ export interface Preferences {
|
|||
locale: string;
|
||||
}
|
||||
|
||||
export const readingDirections = [{text: 'Left to Right', value: ReadingDirection.LeftToRight}, {text: 'Right to Left', value: ReadingDirection.RightToLeft}];
|
||||
export const bookWritingStyles = [{text: 'Horizontal', value: WritingStyle.Horizontal}, {text: 'Vertical', value: WritingStyle.Vertical}];
|
||||
export const scalingOptions = [{text: 'Automatic', value: ScalingOption.Automatic}, {text: 'Fit to Height', value: ScalingOption.FitToHeight}, {text: 'Fit to Width', value: ScalingOption.FitToWidth}, {text: 'Original', value: ScalingOption.Original}];
|
||||
export const pageSplitOptions = [{text: 'Fit to Screen', value: PageSplitOption.FitSplit}, {text: 'Right to Left', value: PageSplitOption.SplitRightToLeft}, {text: 'Left to Right', value: PageSplitOption.SplitLeftToRight}, {text: 'No Split', value: PageSplitOption.NoSplit}];
|
||||
export const readingModes = [{text: 'Left to Right', value: ReaderMode.LeftRight}, {text: 'Up to Down', value: ReaderMode.UpDown}, {text: 'Webtoon', value: ReaderMode.Webtoon}];
|
||||
export const layoutModes = [{text: 'Single', value: LayoutMode.Single}, {text: 'Double', value: LayoutMode.Double}, {text: 'Double (Manga)', value: LayoutMode.DoubleReversed}]; // , {text: 'Double (No Cover)', value: LayoutMode.DoubleNoCover}
|
||||
export const bookLayoutModes = [{text: 'Scroll', value: BookPageLayoutMode.Default}, {text: '1 Column', value: BookPageLayoutMode.Column1}, {text: '2 Column', value: BookPageLayoutMode.Column2}];
|
||||
export const pageLayoutModes = [{text: 'Cards', value: PageLayoutMode.Cards}, {text: 'List', value: PageLayoutMode.List}];
|
||||
export const readingDirections = [{text: 'left-to-right', value: ReadingDirection.LeftToRight}, {text: 'right-to-left', value: ReadingDirection.RightToLeft}];
|
||||
export const bookWritingStyles = [{text: 'horizontal', value: WritingStyle.Horizontal}, {text: 'vertical', value: WritingStyle.Vertical}];
|
||||
export const scalingOptions = [{text: 'automatic', value: ScalingOption.Automatic}, {text: 'fit-to-height', value: ScalingOption.FitToHeight}, {text: 'fit-to-width', value: ScalingOption.FitToWidth}, {text: 'original', value: ScalingOption.Original}];
|
||||
export const pageSplitOptions = [{text: 'fit-to-screen', value: PageSplitOption.FitSplit}, {text: 'right-to-left', value: PageSplitOption.SplitRightToLeft}, {text: 'left-to-right', value: PageSplitOption.SplitLeftToRight}, {text: 'no-split', value: PageSplitOption.NoSplit}];
|
||||
export const readingModes = [{text: 'left-to-right', value: ReaderMode.LeftRight}, {text: 'up-to-down', value: ReaderMode.UpDown}, {text: 'webtoon', value: ReaderMode.Webtoon}];
|
||||
export const layoutModes = [{text: 'single', value: LayoutMode.Single}, {text: 'double', value: LayoutMode.Double}, {text: 'double-manga', value: LayoutMode.DoubleReversed}]; // , {text: 'Double (No Cover)', value: LayoutMode.DoubleNoCover}
|
||||
export const bookLayoutModes = [{text: 'scroll', value: BookPageLayoutMode.Default}, {text: '1-column', value: BookPageLayoutMode.Column1}, {text: '2-column', value: BookPageLayoutMode.Column2}];
|
||||
export const pageLayoutModes = [{text: 'cards', value: PageLayoutMode.Cards}, {text: 'list', value: PageLayoutMode.List}];
|
||||
|
|
|
|||
|
|
@ -192,27 +192,27 @@ export class ActionFactoryService {
|
|||
this.libraryActions = [
|
||||
{
|
||||
action: Action.Scan,
|
||||
title: 'Scan Library',
|
||||
title: 'scan-library',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Others',
|
||||
title: 'others',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [
|
||||
{
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
title: 'refresh-covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
title: 'analyze-files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
|
|
@ -221,7 +221,7 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Settings',
|
||||
title: 'settings',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
|
|
@ -231,7 +231,7 @@ export class ActionFactoryService {
|
|||
this.collectionTagActions = [
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
title: 'edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
|
|
@ -241,55 +241,55 @@ export class ActionFactoryService {
|
|||
this.seriesActions = [
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
title: 'mark-as-read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
title: 'mark-as-unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Scan,
|
||||
title: 'Scan Series',
|
||||
title: 'scan-series',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Add to',
|
||||
title: 'add-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToWantToReadList,
|
||||
title: 'Add to Want to Read',
|
||||
title: 'add-to-want-to-read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.RemoveFromWantToReadList,
|
||||
title: 'Remove from Want to Read',
|
||||
title: 'remove-from-want-to-read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
title: 'add-to-reading-list',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddToCollection,
|
||||
title: 'Add to Collection',
|
||||
title: 'add-to-collection',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
|
|
@ -298,7 +298,7 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Send To',
|
||||
title: 'send-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
|
|
@ -316,27 +316,27 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Others',
|
||||
title: 'others',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [
|
||||
{
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
title: 'refresh-covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
title: 'analyze-files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Delete',
|
||||
title: 'delete',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
class: 'danger',
|
||||
|
|
@ -346,14 +346,14 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
title: 'download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
title: 'edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
|
|
@ -363,34 +363,34 @@ export class ActionFactoryService {
|
|||
this.volumeActions = [
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
title: 'read-incognito',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
title: 'mark-as-read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
title: 'mark-as-unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Add to',
|
||||
title: 'add-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
title: 'add-to-reading-list',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
|
|
@ -399,7 +399,7 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Send To',
|
||||
title: 'send-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
|
|
@ -417,14 +417,14 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
title: 'download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Details',
|
||||
title: 'details',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
|
|
@ -434,34 +434,34 @@ export class ActionFactoryService {
|
|||
this.chapterActions = [
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
title: 'read-incognito',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
title: 'mark-as-read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
title: 'mark-as-unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Add to',
|
||||
title: 'add-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
title: 'add-to-reading-list',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
|
|
@ -470,7 +470,7 @@ export class ActionFactoryService {
|
|||
},
|
||||
{
|
||||
action: Action.Submenu,
|
||||
title: 'Send To',
|
||||
title: 'send-to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
|
|
@ -489,14 +489,14 @@ export class ActionFactoryService {
|
|||
// RBS will handle rendering this, so non-admins with download are appicable
|
||||
{
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
title: 'download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Details',
|
||||
title: 'details',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
|
|
@ -506,14 +506,14 @@ export class ActionFactoryService {
|
|||
this.readingListActions = [
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
title: 'edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Delete',
|
||||
title: 'delete',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
class: 'danger',
|
||||
|
|
@ -524,21 +524,21 @@ export class ActionFactoryService {
|
|||
this.bookmarkActions = [
|
||||
{
|
||||
action: Action.ViewSeries,
|
||||
title: 'View Series',
|
||||
title: 'view-series',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.DownloadBookmark,
|
||||
title: 'Download',
|
||||
title: 'download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Clear',
|
||||
title: 'clear',
|
||||
callback: this.dummyCallback,
|
||||
class: 'danger',
|
||||
requiresAdmin: false,
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@
|
|||
<ng-container *ngFor="let theme of themes">
|
||||
<button class="btn btn-icon color" (click)="setTheme(theme.name)" [ngClass]="{'active': activeTheme?.name === theme.name}">
|
||||
<div class="dot" [ngStyle]="{'background-color': theme.colorHash}"></div>
|
||||
{{t('theme.translationKey')}}
|
||||
{{t(theme.translationKey)}}
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,40 @@
|
|||
<ng-container *ngIf="actions.length > 0">
|
||||
<ng-container *transloco="let t; read: 'actionable'">
|
||||
<ng-container *ngIf="actions.length > 0">
|
||||
<div ngbDropdown container="body" class="d-inline-block">
|
||||
<button [disabled]="disabled" class="btn {{btnClass}}" id="actions-{{labelBy}}" ngbDropdownToggle
|
||||
(click)="preventEvent($event)"><i class="fa {{iconClass}}" aria-hidden="true"></i></button>
|
||||
(click)="preventEvent($event)"><i class="fa {{iconClass}}" aria-hidden="true"></i></button>
|
||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{labelBy}}">
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: actions }"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: actions }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #submenu let-list="list">
|
||||
<ng-container *ngFor="let action of list">
|
||||
<!-- Non Submenu items -->
|
||||
<ng-container *ngIf="action.children === undefined || action?.children?.length === 0 || action.dynamicList !== undefined ; else submenuDropdown">
|
||||
<ng-template #submenu let-list="list">
|
||||
<ng-container *ngFor="let action of list">
|
||||
<!-- Non Submenu items -->
|
||||
<ng-container *ngIf="action.children === undefined || action?.children?.length === 0 || action.dynamicList !== undefined ; else submenuDropdown">
|
||||
|
||||
<ng-container *ngIf="action.dynamicList !== undefined && (action.dynamicList | async | dynamicList) as dList; else justItem">
|
||||
<ng-container *ngFor="let dynamicItem of dList">
|
||||
<button ngbDropdownItem (click)="performDynamicClick($event, action, dynamicItem)">{{dynamicItem.title}}</button>
|
||||
<ng-container *ngIf="action.dynamicList !== undefined && (action.dynamicList | async | dynamicList) as dList; else justItem">
|
||||
<ng-container *ngFor="let dynamicItem of dList">
|
||||
<button ngbDropdownItem (click)="performDynamicClick($event, action, dynamicItem)">{{dynamicItem.title}}</button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #justItem>
|
||||
<button ngbDropdownItem *ngIf="willRenderAction(action)" (click)="performAction($event, action)" (mouseover)="closeAllSubmenus()">{{action.title}}</button>
|
||||
<ng-template #justItem>
|
||||
<button ngbDropdownItem *ngIf="willRenderAction(action)" (click)="performAction($event, action)" (mouseover)="closeAllSubmenus()">{{t(action.title)}}</button>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-template #submenuDropdown>
|
||||
<!-- Submenu items -->
|
||||
<ng-container *ngIf="shouldRenderSubMenu(action, action.children?.[0].dynamicList | async)">
|
||||
<div ngbDropdown #subMenuHover="ngbDropdown" placement="right left" (click)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseover)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseleave)="preventEvent($event)">
|
||||
<button *ngIf="willRenderAction(action)" id="actions-{{action.title}}" class="submenu-toggle" ngbDropdownToggle>{{t(action.title)}} <i class="fa-solid fa-angle-right submenu-icon"></i></button>
|
||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{action.title}}">
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: action.children }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<ng-template #submenuDropdown>
|
||||
<!-- Submenu items -->
|
||||
<ng-container *ngIf="shouldRenderSubMenu(action, action.children?.[0].dynamicList | async)">
|
||||
<div ngbDropdown #subMenuHover="ngbDropdown" placement="right left" (click)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseover)="preventEvent($event); openSubmenu(action.title, subMenuHover)" (mouseleave)="preventEvent($event)">
|
||||
<button *ngIf="willRenderAction(action)" id="actions-{{action.title}}" class="submenu-toggle" ngbDropdownToggle>{{action.title}} <i class="fa-solid fa-angle-right submenu-icon"></i></button>
|
||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{action.title}}">
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: action.children }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import { AccountService } from 'src/app/_services/account.service';
|
|||
import { Action, ActionItem } from 'src/app/_services/action-factory.service';
|
||||
import {CommonModule} from "@angular/common";
|
||||
import {DynamicListPipe} from "../../dynamic-list.pipe";
|
||||
import {TranslocoModule} from "@ngneat/transloco";
|
||||
|
||||
@Component({
|
||||
selector: 'app-card-actionables',
|
||||
standalone: true,
|
||||
imports: [CommonModule, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem, DynamicListPipe],
|
||||
imports: [CommonModule, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbDropdownItem, DynamicListPipe, TranslocoModule],
|
||||
templateUrl: './card-actionables.component.html',
|
||||
styleUrls: ['./card-actionables.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
|
|
|
|||
|
|
@ -87,8 +87,7 @@ export class SeriesCardComponent implements OnInit, OnChanges {
|
|||
if (this.data) {
|
||||
this.actions = this.actionFactoryService.getSeriesActions((action: ActionItem<Series>, series: Series) => this.handleSeriesActionCallback(action, series));
|
||||
if (this.isOnDeck) {
|
||||
const otherStr = this.translocoService.translate('actionable.others');
|
||||
const othersIndex = this.actions.findIndex(obj => obj.title === otherStr);
|
||||
const othersIndex = this.actions.findIndex(obj => obj.title === 'others');
|
||||
if (this.actions[othersIndex].children.findIndex(o => o.action === Action.RemoveFromOnDeck) < 0) {
|
||||
this.actions[othersIndex].children.push({
|
||||
action: Action.RemoveFromOnDeck,
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@
|
|||
<div class="{{SplitIconClass}}"></div>
|
||||
</div>
|
||||
<select class="form-control" id="page-splitting" formControlName="pageSplitOption">
|
||||
<option *ngFor="let opt of pageSplitOptions" [value]="opt.value">{{opt.text}}</option>
|
||||
<option *ngFor="let opt of pageSplitOptionsTranslated" [value]="opt.value">{{opt.text}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -223,7 +223,7 @@
|
|||
</ng-container>
|
||||
</ng-container>
|
||||
<select class="form-control" id="layout-mode" formControlName="layoutMode">
|
||||
<option [value]="opt.value" *ngFor="let opt of layoutModes">{{opt.text}}</option>
|
||||
<option [value]="opt.value" *ngFor="let opt of layoutModesTranslated">{{opt.text}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-12">
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
pagingDirection$: Observable<PAGING_DIRECTION> = this.pagingDirectionSubject.asObservable();
|
||||
|
||||
|
||||
pageSplitOptions = pageSplitOptions;
|
||||
layoutModes = layoutModes;
|
||||
pageSplitOptionsTranslated = pageSplitOptions.map(this.translatePrefOptions);
|
||||
layoutModesTranslated = layoutModes.map(this.translatePrefOptions);
|
||||
|
||||
isLoading = true;
|
||||
hasBookmarkRights: boolean = false; // TODO: This can be an observable
|
||||
|
|
@ -458,9 +458,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
public utilityService: UtilityService, @Inject(DOCUMENT) private document: Document,
|
||||
private modalService: NgbModal, private readonly cdRef: ChangeDetectorRef,
|
||||
public mangaReaderService: ManagaReaderService) {
|
||||
this.navService.hideNavBar();
|
||||
this.navService.hideSideNav();
|
||||
this.cdRef.markForCheck();
|
||||
this.navService.hideNavBar();
|
||||
this.navService.hideSideNav();
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
@ -1652,4 +1652,10 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
})
|
||||
});
|
||||
}
|
||||
|
||||
translatePrefOptions(o: {text: string, value: any}) {
|
||||
const d = {...o};
|
||||
d.text = translate('preferences.' + o.text);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export class ManagaReaderService {
|
|||
});
|
||||
this.pairs = chapterInfo.doublePairs!;
|
||||
}
|
||||
|
||||
|
||||
adjustForDoubleReader(page: number) {
|
||||
if (!this.pairs.hasOwnProperty(page)) return page;
|
||||
return this.pairs[page];
|
||||
|
|
@ -61,10 +61,10 @@ export class ManagaReaderService {
|
|||
|
||||
|
||||
/**
|
||||
* If pagenumber is 0 aka first page, which on double page rendering should always render as a single.
|
||||
*
|
||||
* If pageNumber is 0 aka first page, which on double page rendering should always render as a single.
|
||||
*
|
||||
* @param pageNumber current page number
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
isCoverImage(pageNumber: number) {
|
||||
return pageNumber === 0;
|
||||
|
|
@ -104,9 +104,9 @@ export class ManagaReaderService {
|
|||
|
||||
/**
|
||||
* Should Canvas Renderer be used
|
||||
* @param img
|
||||
* @param pageSplitOption
|
||||
* @returns
|
||||
* @param img
|
||||
* @param pageSplitOption
|
||||
* @returns
|
||||
*/
|
||||
shouldSplit(img: HTMLImageElement, pageSplitOption: PageSplitOption) {
|
||||
const needsSplitting = this.isWidePage(this.readerService.imageUrlToPageNum(img?.src));
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export class SideNavComponent implements OnInit {
|
|||
|
||||
libraries: Library[] = [];
|
||||
actions: ActionItem<Library>[] = [];
|
||||
readingListActions = [{action: Action.Import, title: 'Import CBL', children: [], requiresAdmin: true, callback: this.importCbl.bind(this)}];
|
||||
readingListActions = [{action: Action.Import, title: 'import-cbl', children: [], requiresAdmin: true, callback: this.importCbl.bind(this)}];
|
||||
filterQuery: string = '';
|
||||
filterLibrary = (library: Library) => {
|
||||
return library.name.toLowerCase().indexOf((this.filterQuery || '').toLowerCase()) >= 0;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
<ng-container [ngTemplateOutlet]="layoutModeTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="globalPageLayoutMode" id="settings-global-layoutmode">
|
||||
<option *ngFor="let opt of pageLayoutModes" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of pageLayoutModesTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
<ng-container [ngTemplateOutlet]="readingDirectionTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="readingDirection" id="settings-reading-direction">
|
||||
<option *ngFor="let opt of readingDirections" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of readingDirectionsTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
<ng-container [ngTemplateOutlet]="scalingOptionTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="scalingOption" id="settings-scaling-option">
|
||||
<option *ngFor="let opt of scalingOptions" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of scalingOptionsTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -182,13 +182,13 @@
|
|||
<ng-container [ngTemplateOutlet]="pageSplitOptionTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="pageSplitOption" id="settings-pagesplit-option">
|
||||
<option *ngFor="let opt of pageSplitOptions" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of pageSplitOptionsTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12 pe-2 mb-2">
|
||||
<label for="settings-readingmode-option" class="form-label">{{t('reading-mode-label')}}</label>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="readerMode" id="settings-readingmode-option">
|
||||
<option *ngFor="let opt of readingModes" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of readingModesTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
<ng-container [ngTemplateOutlet]="layoutModeTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="manga-header" formControlName="layoutMode" id="settings-layoutmode-option">
|
||||
<option *ngFor="let opt of layoutModes" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of layoutModesTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12 pe-2 mb-2">
|
||||
|
|
@ -309,7 +309,7 @@
|
|||
<ng-container [ngTemplateOutlet]="bookReadingDirectionTooltip"></ng-container>
|
||||
</span>
|
||||
<select id="settings-book-reading-direction" class="form-select" aria-describedby="settings-book-reading-direction-help" formControlName="bookReaderReadingDirection">
|
||||
<option *ngFor="let opt of readingDirections" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of readingDirectionsTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -334,7 +334,7 @@
|
|||
<ng-container [ngTemplateOutlet]="bookWritingStyleToolTip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="settings-book-writing-style-help" formControlName="bookReaderWritingStyle" id="settings-book-writing-style" >
|
||||
<option *ngFor="let opt of bookWritingStyles" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of bookWritingStylesTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -345,7 +345,7 @@
|
|||
<ng-container [ngTemplateOutlet]="bookLayoutModeTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="settings-book-layout-mode-help" formControlName="bookReaderLayoutMode" id="settings-book-layout-mode">
|
||||
<option *ngFor="let opt of bookLayoutModes" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
<option *ngFor="let opt of bookLayoutModesTranslated" [value]="opt.value">{{opt.text | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -359,7 +359,7 @@
|
|||
<ng-container [ngTemplateOutlet]="bookColorThemeTooltip"></ng-container>
|
||||
</span>
|
||||
<select class="form-select" aria-describedby="settings-color-theme-option-help" formControlName="bookReaderThemeName" id="settings-color-theme-option">
|
||||
<option *ngFor="let opt of bookColorThemes" [value]="opt.name">{{opt.name | titlecase}}</option>
|
||||
<option *ngFor="let opt of bookColorThemesTranslated" [value]="opt.name">{{opt.name | titlecase}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import { NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavContent, NgbAccor
|
|||
import { SideNavCompanionBarComponent } from '../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
|
||||
import {LocalizationService} from "../../_services/localization.service";
|
||||
import {Language} from "../../_models/metadata/language";
|
||||
import {TranslocoModule, TranslocoService} from "@ngneat/transloco";
|
||||
import {translate, TranslocoModule, TranslocoService} from "@ngneat/transloco";
|
||||
|
||||
enum AccordionPanelID {
|
||||
ImageReader = 'image-reader',
|
||||
|
|
@ -80,15 +80,20 @@ enum FragmentID {
|
|||
})
|
||||
export class UserPreferencesComponent implements OnInit, OnDestroy {
|
||||
|
||||
readingDirections = readingDirections;
|
||||
scalingOptions = scalingOptions;
|
||||
pageSplitOptions = pageSplitOptions;
|
||||
readingModes = readingModes;
|
||||
layoutModes = layoutModes;
|
||||
bookLayoutModes = bookLayoutModes;
|
||||
bookColorThemes = bookColorThemes;
|
||||
pageLayoutModes = pageLayoutModes;
|
||||
bookWritingStyles = bookWritingStyles;
|
||||
readingDirectionsTranslated = readingDirections.map(this.translatePrefOptions);
|
||||
scalingOptionsTranslated = scalingOptions.map(this.translatePrefOptions);
|
||||
pageSplitOptionsTranslated = pageSplitOptions.map(this.translatePrefOptions);
|
||||
readingModesTranslated = readingModes.map(this.translatePrefOptions);
|
||||
layoutModesTranslated = layoutModes.map(this.translatePrefOptions);
|
||||
bookLayoutModesTranslated = bookLayoutModes.map(this.translatePrefOptions);
|
||||
bookColorThemesTranslated = bookColorThemes.map(o => {
|
||||
const d = {...o};
|
||||
d.name = translate('theme.' + d.translationKey);
|
||||
return d;
|
||||
});
|
||||
|
||||
pageLayoutModesTranslated = pageLayoutModes.map(this.translatePrefOptions);
|
||||
bookWritingStylesTranslated = bookWritingStyles.map(this.translatePrefOptions);
|
||||
|
||||
settingsForm: FormGroup = new FormGroup({});
|
||||
user: User | undefined = undefined;
|
||||
|
|
@ -314,4 +319,10 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
this.settingsForm.markAsTouched();
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
translatePrefOptions(o: {text: string, value: any}) {
|
||||
const d = {...o};
|
||||
d.text = translate('preferences.' + o.text);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue