Localization - First Pass (#2174)
* Started designing the backend localization service * Worked in Transloco for initial PoC * Worked in Transloco for initial PoC * Translated the login screen * translated dashboard screen * Started work on the backend * Fixed a logic bug * translated edit-user screen * Hooked up the backend for having a locale property. * Hooked up the ability to view the available locales and switch to them. * Made the localization service languages be derived from what's in langs/ directory. * Fixed up localization switching * Switched when we check for a license on UI bootstrap * Tweaked some code * Fixed the bug where dashboard wasn't loading and made it so language switching is working. * Fixed a bug on dashboard with languagePath * Converted user-scrobble-history.component.html * Converted spoiler.component.html * Converted review-series-modal.component.html * Converted review-card-modal.component.html * Updated the readme * Translated using Weblate (English) Currently translated at 100.0% (54 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/en/ * Converted review-card.component.html * Deleted dead component * Converted want-to-read.component.html * Added translation using Weblate (Korean) * Translated using Weblate (Spanish) Currently translated at 40.7% (22 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/es/ * Translated using Weblate (Korean) Currently translated at 62.9% (34 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/ko/ * Converted user-preferences.component.html * Translated using Weblate (Korean) Currently translated at 92.5% (50 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/ko/ * Converted user-holds.component.html * Converted theme-manager.component.html * Converted restriction-selector.component.html * Converted manage-devices.component.html * Converted edit-device.component.html * Converted change-password.component.html * Converted change-email.component.html * Converted change-age-restriction.component.html * Converted api-key.component.html * Converted anilist-key.component.html * Converted typeahead.component.html * Converted user-stats-info-cards.component.html * Converted user-stats.component.html * Converted top-readers.component.html * Converted some pipes and ensure translation is loaded before the app. * Finished all but one pipe for localization * Converted directory-picker.component.html * Converted library-access-modal.component.html * Converted a few components * Converted a few components * Converted a few components * Converted a few components * Converted a few components * Merged weblate in * ... -> … update * Updated the readme * Updateded all fonts to be woff2 * Cleaned up some strings to increase re-use * Removed an old flow (that doesn't exist in backend any longer) from when we introduced emails on Kavita. * Converted Series detail * Lots more converted * Lots more converted & hooked up the ability to flatten during prod build the language files. * Lots more converted * Lots more converted & fixed a bunch of broken pipes due to inject() * Lots more converted * Lots more converted * Lots more converted & fixed some bad keys * Lots more converted * Fixed some bugs with admin dasbhoard nested tabs not rendering on first load due to not using onpush change detection * Fixed up some localization errors and fixed forgot password error when the user doesn't have change password permission * Fixed a stupid build issue again * Started adding errors for interceptor and backend. * Finished off manga-reader * More translations * Few fixes * Fixed a bug where character tag badges weren't showing the name on chapter info * All components are translated * All toasts are translated * All confirm/alerts are translated * Trying something new for the backend * Migrated the localization strings for the backend into a new file. * Updated the localization service to be able to do backend localization with fallback to english. * Cleaned up some external reviews code to reduce looping * Localized AccountController.cs * 60% done with controllers * All controllers are done * All KavitaExceptions are covered * Some shakeout fixes * Prep for initial merge * Everything is done except options and basic shakeout proves response times are good. Unit tests are broken. * Fixed up the unit tests * All unit tests are now working * Removed some quantifier * I'm not sure I can support localization for some Volume/Chapter/Book strings within the codebase. --------- Co-authored-by: Robbie Davis <robbie@therobbiedavis.com> Co-authored-by: majora2007 <kavitareader@gmail.com> Co-authored-by: expertjun <jtrobin@naver.com> Co-authored-by: ThePromidius <thepromidiusyt@gmail.com>
This commit is contained in:
parent
670bf82c38
commit
3b23d63234
389 changed files with 13652 additions and 7925 deletions
|
|
@ -1,93 +1,97 @@
|
|||
<div class="{{theme}}" *ngIf="accountService.currentUser$ | async as user">
|
||||
<ng-container *transloco="let t; read: 'pdf-reader'">
|
||||
<div class="{{theme}}" *ngIf="accountService.currentUser$ | async as user">
|
||||
|
||||
<ng-container *ngIf="isLoading">
|
||||
<div class="loading mx-auto" style="min-width: 200px; width: 600px;">
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
Loading...PDFs may take longer than expected
|
||||
</div>
|
||||
<div class="progress-container row g-0 align-items-center">
|
||||
<div class="progress" style="height: 5px;">
|
||||
<div class="progress-bar" role="progressbar" [ngStyle]="{'width': loadPrecent + '%'}" [attr.aria-valuenow]="loadPrecent" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<div class="loading mx-auto" style="min-width: 200px; width: 600px;">
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
{{t('loading-message')}}
|
||||
</div>
|
||||
<div class="progress-container row g-0 align-items-center">
|
||||
<div class="progress" style="height: 5px;">
|
||||
<div class="progress-bar" role="progressbar" [ngStyle]="{'width': loadPercent + '%'}" [attr.aria-valuenow]="loadPercent" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ngx-extended-pdf-viewer
|
||||
#pdfViewer
|
||||
[src]="readerService.downloadPdf(this.chapterId)"
|
||||
[authorization]="'Bearer ' + user.token"
|
||||
height="100vh"
|
||||
[(page)]="currentPage"
|
||||
[textLayer]="true"
|
||||
[useBrowserLocale]="false"
|
||||
[showHandToolButton]="true"
|
||||
[showOpenFileButton]="false"
|
||||
[showPrintButton]="false"
|
||||
[showRotateButton]="false"
|
||||
[showDownloadButton]="false"
|
||||
[showPropertiesButton]="false"
|
||||
[(zoom)]="zoomSetting"
|
||||
[showSecondaryToolbarButton]="true"
|
||||
[showBorders]="true"
|
||||
[theme]="theme"
|
||||
[formTheme]="theme"
|
||||
[backgroundColor]="backgroundColor"
|
||||
[customToolbar]="multiToolbar"
|
||||
#pdfViewer
|
||||
[src]="readerService.downloadPdf(this.chapterId)"
|
||||
[authorization]="'Bearer ' + user.token"
|
||||
height="100vh"
|
||||
[(page)]="currentPage"
|
||||
[textLayer]="true"
|
||||
[useBrowserLocale]="false"
|
||||
[showHandToolButton]="true"
|
||||
[showOpenFileButton]="false"
|
||||
[showPrintButton]="false"
|
||||
[showRotateButton]="false"
|
||||
[showDownloadButton]="false"
|
||||
[showPropertiesButton]="false"
|
||||
[(zoom)]="zoomSetting"
|
||||
[showSecondaryToolbarButton]="true"
|
||||
[showBorders]="true"
|
||||
[theme]="theme"
|
||||
[formTheme]="theme"
|
||||
[backgroundColor]="backgroundColor"
|
||||
[customToolbar]="multiToolbar"
|
||||
[language]="user.preferences.locale"
|
||||
|
||||
(pageChange)="saveProgress()"
|
||||
(pdfLoadingStarts)="updateLoading(true)"
|
||||
(pdfLoaded)="updateLoading(false)"
|
||||
(progress)="updateLoadProgress($event)"
|
||||
(pageChange)="saveProgress()"
|
||||
(pdfLoadingStarts)="updateLoading(true)"
|
||||
(pdfLoaded)="updateLoading(false)"
|
||||
(progress)="updateLoadProgress($event)"
|
||||
>
|
||||
|
||||
</ngx-extended-pdf-viewer>
|
||||
|
||||
<ng-template #multiToolbar>
|
||||
<div style="min-height: 36px" id="toolbarViewer" [ngStyle]="{'background-color': backgroundColor, 'color': fontColor}"> <!--action-bar row g-0 justify-content-between-->
|
||||
<div id="toolbarViewerLeft">
|
||||
<pdf-toggle-sidebar></pdf-toggle-sidebar>
|
||||
<pdf-find-button></pdf-find-button>
|
||||
<pdf-paging-area></pdf-paging-area>
|
||||
</div>
|
||||
|
||||
<div id="toolbarViewerRight">
|
||||
<pdf-hand-tool></pdf-hand-tool>
|
||||
<pdf-select-tool></pdf-select-tool>
|
||||
<pdf-presentation-mode></pdf-presentation-mode>
|
||||
|
||||
|
||||
<!-- This is not yet supported by the underlying library
|
||||
<button (click)="toggleBookPageMode()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa-solid {{this.bookMode !== 'book' ? 'fa-book' : 'fa-book-open'}}" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{this.bookMode !== 'book' ? 'Book Mode' : 'Normal Mode'}}</span>
|
||||
</button> -->
|
||||
|
||||
<button class="btn btn-icon toolbarButton" [ngbTooltip]="bookTitle">
|
||||
<i class="toolbar-icon fa-solid fa-info" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">
|
||||
{{bookTitle}}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button *ngIf="incognitoMode" (click)="turnOffIncognito()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa fa-glasses" [ngStyle]="{color: fontColor}" aria-hidden="true"></i><span class="visually-hidden">Incognito Mode</span>
|
||||
</button>
|
||||
|
||||
<!-- This is pretty experimental, so it might not work perfectly -->
|
||||
<button (click)="toggleTheme()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa-solid {{this.theme === 'light' ? 'fa-sun' : 'fa-moon'}}" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{this.theme === 'light' ? 'Light Theme' : 'Dark Theme'}}</span>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-icon col-2 col-xs-1 toolbarButton" (click)="closeReader()">
|
||||
<i class="toolbar-icon fa fa-times-circle" aria-hidden="true" [ngStyle]="{color: fontColor}"></i>
|
||||
<span class="visually-hidden">Close Reader</span>
|
||||
</button>
|
||||
|
||||
<div class="verticalToolbarSeparator hiddenSmallView"></div>
|
||||
<pdf-toggle-secondary-toolbar></pdf-toggle-secondary-toolbar>
|
||||
</div>
|
||||
<pdf-zoom-toolbar ></pdf-zoom-toolbar>
|
||||
<div style="min-height: 36px" id="toolbarViewer" [ngStyle]="{'background-color': backgroundColor, 'color': fontColor}"> <!--action-bar row g-0 justify-content-between-->
|
||||
<div id="toolbarViewerLeft">
|
||||
<pdf-toggle-sidebar></pdf-toggle-sidebar>
|
||||
<pdf-find-button></pdf-find-button>
|
||||
<pdf-paging-area></pdf-paging-area>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
</div>
|
||||
<div id="toolbarViewerRight">
|
||||
<pdf-hand-tool></pdf-hand-tool>
|
||||
<pdf-select-tool></pdf-select-tool>
|
||||
<pdf-presentation-mode></pdf-presentation-mode>
|
||||
|
||||
|
||||
<!-- This is not yet supported by the underlying library
|
||||
<button (click)="toggleBookPageMode()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa-solid {{this.bookMode !== 'book' ? 'fa-book' : 'fa-book-open'}}" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{this.bookMode !== 'book' ? 'Book Mode' : 'Normal Mode'}}</span>
|
||||
</button> -->
|
||||
|
||||
<button class="btn btn-icon toolbarButton" [ngbTooltip]="bookTitle">
|
||||
<i class="toolbar-icon fa-solid fa-info" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">
|
||||
{{bookTitle}}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button *ngIf="incognitoMode" (click)="turnOffIncognito()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa fa-glasses" [ngStyle]="{color: fontColor}" aria-hidden="true"></i><span class="visually-hidden">{{t('incognito-mode')}}</span>
|
||||
</button>
|
||||
|
||||
<!-- This is pretty experimental, so it might not work perfectly -->
|
||||
<button (click)="toggleTheme()" class="btn btn-icon toolbarButton">
|
||||
<i class="toolbar-icon fa-solid {{this.theme === 'light' ? 'fa-sun' : 'fa-moon'}}" [ngStyle]="{color: fontColor}" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{this.theme === 'light' ? t('light-theme-alt') : t('dark-theme-alt')}}</span>
|
||||
</button>
|
||||
|
||||
<button class="btn btn-icon col-2 col-xs-1 toolbarButton" (click)="closeReader()">
|
||||
<i class="toolbar-icon fa fa-times-circle" aria-hidden="true" [ngStyle]="{color: fontColor}"></i>
|
||||
<span class="visually-hidden">{{t('close-reader-alt')}}</span>
|
||||
</button>
|
||||
|
||||
<div class="verticalToolbarSeparator hiddenSmallView"></div>
|
||||
<pdf-toggle-secondary-toolbar></pdf-toggle-secondary-toolbar>
|
||||
</div>
|
||||
<pdf-zoom-toolbar ></pdf-zoom-toolbar>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
HostListener,
|
||||
inject, OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NgxExtendedPdfViewerService, PageViewModeType, ProgressBarEvent, NgxExtendedPdfViewerModule } from 'ngx-extended-pdf-viewer';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
|
@ -14,6 +21,7 @@ import { SeriesService } from 'src/app/_services/series.service';
|
|||
import { ThemeService } from 'src/app/_services/theme.service';
|
||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NgIf, NgStyle, AsyncPipe } from '@angular/common';
|
||||
import {TranslocoModule, TranslocoService} from "@ngneat/transloco";
|
||||
|
||||
@Component({
|
||||
selector: 'app-pdf-reader',
|
||||
|
|
@ -21,7 +29,7 @@ import { NgIf, NgStyle, AsyncPipe } from '@angular/common';
|
|||
styleUrls: ['./pdf-reader.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [NgIf, NgStyle, NgxExtendedPdfViewerModule, NgbTooltip, AsyncPipe]
|
||||
imports: [NgIf, NgStyle, NgxExtendedPdfViewerModule, NgbTooltip, AsyncPipe, TranslocoModule]
|
||||
})
|
||||
export class PdfReaderComponent implements OnInit, OnDestroy {
|
||||
|
||||
|
|
@ -71,20 +79,20 @@ export class PdfReaderComponent implements OnInit, OnDestroy {
|
|||
/**
|
||||
* How much of the current document is loaded
|
||||
*/
|
||||
loadPrecent: number = 0;
|
||||
loadPercent: number = 0;
|
||||
|
||||
/**
|
||||
* This can't be updated dynamically:
|
||||
* This can't be updated dynamically:
|
||||
* https://github.com/stephanrauh/ngx-extended-pdf-viewer/issues/1415
|
||||
*/
|
||||
bookMode: PageViewModeType = 'multiple';
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
private readonly translocoService = inject(TranslocoService);
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router, public accountService: AccountService,
|
||||
private seriesService: SeriesService, public readerService: ReaderService,
|
||||
private navService: NavService, private toastr: ToastrService,
|
||||
private bookService: BookService, private themeService: ThemeService,
|
||||
private bookService: BookService, private themeService: ThemeService,
|
||||
private readonly cdRef: ChangeDetectorRef, private pdfViewerService: NgxExtendedPdfViewerService) {
|
||||
this.navService.hideNavBar();
|
||||
this.themeService.clearThemes();
|
||||
|
|
@ -105,9 +113,6 @@ export class PdfReaderComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.navService.showNavBar();
|
||||
this.navService.showSideNav();
|
||||
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
@ -124,7 +129,7 @@ export class PdfReaderComponent implements OnInit, OnDestroy {
|
|||
this.seriesId = parseInt(seriesId, 10);
|
||||
this.chapterId = parseInt(chapterId, 10);
|
||||
this.incognitoMode = this.route.snapshot.queryParamMap.get('incognitoMode') === 'true';
|
||||
|
||||
|
||||
|
||||
const readingListId = this.route.snapshot.queryParamMap.get('readingListId');
|
||||
if (readingListId != null) {
|
||||
|
|
@ -173,7 +178,7 @@ export class PdfReaderComponent implements OnInit, OnDestroy {
|
|||
this.incognitoMode = false;
|
||||
const newRoute = this.readerService.getNextChapterUrl(this.router.url, this.chapterId, this.incognitoMode, this.readingListMode, this.readingListId);
|
||||
window.history.replaceState({}, '', newRoute);
|
||||
this.toastr.info('Incognito mode is off. Progress will now start being tracked.');
|
||||
this.toastr.info(this.translocoService.translate('toasts.incognito-off'));
|
||||
this.saveProgress();
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
|
@ -213,7 +218,7 @@ export class PdfReaderComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
updateLoadProgress(event: ProgressBarEvent) {
|
||||
this.loadPrecent = event.percent;
|
||||
this.loadPercent = event.percent;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue