Skip to content
Snippets Groups Projects
Commit 63d91c4f authored by Hamza HRAMCHI's avatar Hamza HRAMCHI
Browse files

FEAT #15546 TIME 5:10 language management

parent ed69097f
No related branches found
No related tags found
No related merge requests found
......@@ -371,6 +371,11 @@
"back": "Retour",
"documentsImported": "Document(s) importé(s)",
"onlyPdfAuthorized": "Seul des fichiers pdf sont autorisés",
"mustSetWorkflowBeforeSignPositions": "Veuillez paramétrer votre circuit avant de pouvoir positionner les signatures."
"mustSetWorkflowBeforeSignPositions": "Veuillez paramétrer votre circuit avant de pouvoir positionner les signatures.",
"missingLang": "Langue(s) manquante(s)",
"langChecking": "Vérification de(s) langue(s)",
"generateLangVar": "Génerer les variables de langues",
"generateLangVarIgnoreTranslate": "Génerer les variables de langues (IGNORE __TO_TRANSLATE)",
"close": "Fermer"
}
}
......@@ -11,4 +11,5 @@
<div id="rightContent" style="display: contents;"></div>
</ion-menu>
</ion-split-pane>
</ion-app>
\ No newline at end of file
</ion-app>
<app-dev-tool *ngIf="debugMode && authService.isAuth()"></app-dev-tool>
\ No newline at end of file
......@@ -10,6 +10,7 @@ import { MatIconRegistry } from '@angular/material/icon';
import { AuthService } from './service/auth.service';
import { MenuController } from '@ionic/angular';
import { Router } from '@angular/router';
import { environment } from '../core/environments/environment';
@Component({
selector: 'app-root',
......@@ -19,6 +20,7 @@ import { Router } from '@angular/router';
})
export class AppComponent {
debugMode: boolean = false;
showLeftContent: boolean = false;
showRightContent: boolean = false;
constructor(private translate: TranslateService,
......@@ -41,6 +43,9 @@ export class AppComponent {
this.cookieService.set('maarchParapheurLang', 'fr');
translate.setDefaultLang('fr');
}
if (!environment.production) {
this.debugMode = true;
}
}
test() {
......
......@@ -55,6 +55,8 @@ import { PasswordModificationComponent } from './login/passwordModification/pass
import { VisaWorkflowModelsComponent } from './document/visa-workflow/models/visa-workflow-models.component';
import { SearchComponent } from './search/search.component';
import { SignaturePositionComponent } from './indexation/signature-position/signature-position.component';
import { DevToolComponent } from './service/debug/dev-tool.component';
import { DevLangComponent } from './service/debug/dev-lang.component';
// ADMINISTRATION
......@@ -135,7 +137,9 @@ import { SortPipe } from './plugins/sorting.pipe';
IndexationComponent,
VisaWorkflowModelsComponent,
SearchComponent,
SignaturePositionComponent
SignaturePositionComponent,
DevToolComponent,
DevLangComponent
],
imports: [
FormsModule,
......
<ion-header translucent>
<ion-toolbar color="primary">
<ion-title>{{'lang.langChecking' | translate}}</ion-title>
</ion-toolbar>
<ion-segment>
<span *ngFor="let langName of allLang | keyvalue" >
<ion-segment-button *ngIf="langName.key !== 'fr'" (ionChange)="setActiveLang($event)" [value]="currentLang">
<ion-label>{{langName.key}} <ion-badge color="secondary">{{missingLang[langName.key].length}}</ion-badge></ion-label>
</ion-segment-button>
</span>
</ion-segment>
</ion-header>
<ion-content>
<ng-container>
<ion-list *ngIf="currentLang === 'en'" lines="full">
<ion-item *ngFor="let lang of missingLang[currentLang]">
<ion-label position="stacked">{{lang.id}}</ion-label>
<ion-input type="text" [(ngModel)]="lang.value"></ion-input>
<ion-button slot="end" color="primary" (click)="openTranslation(lang.value)">
<ion-icon name="language-outline"></ion-icon>
</ion-button>
</ion-item>
</ion-list>
</ng-container>
</ion-content>
<ion-footer [translucent]="true">
<ion-button (click)="generateMissingLang(false)" color="primary">{{'lang.generateLangVar' | translate}}</ion-button>
<ion-button (click)="generateMissingLang(true)" color="primary">{{'lang.generateLangVarIgnoreTranslate' | translate}}</ion-button>
<ion-button mat-dialog-close color="secondary">{{'lang.close' | translate}}</ion-button>
</ion-footer>
\ No newline at end of file
.mat-dialog-content {
padding-top: 0px;
}
.lang-container {
::ng-deep.mat-tab-header {
position: sticky;
top: 0px;
z-index: 2;
}
::ng-deep.mat-tab-label-container {
background: white;
}
}
\ No newline at end of file
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { HttpClient } from '@angular/common/http';
import { catchError, tap } from 'rxjs/operators';
import { of } from 'rxjs';
import { NotificationService } from '../notification.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
templateUrl: 'dev-lang.component.html',
styleUrls: ['dev-lang.component.scss'],
})
export class DevLangComponent implements OnInit {
allLang: any;
missingLang: any = {};
currentLang = 'en';
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<DevLangComponent>,
public http: HttpClient,
private notify: NotificationService,
private translate: TranslateService,
) {
}
ngOnInit(): void {
this.getLangs();
}
getLangs() {
this.http.get('../rest/dev/languages').pipe(
tap((data: any) => {
this.allLang = data.languages;
Object.keys(this.allLang).forEach(langName => {
this.missingLang[langName] = Object.keys(this.allLang.fr.lang).filter((keyLang: any) => Object.keys(this.allLang[langName].lang).indexOf(keyLang) === -1).map((keyLang: any) => {
return {
id: keyLang,
value: this.allLang.fr.lang[keyLang] + '__TO_TRANSLATE'
};
});
});
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
openTranslation(text: string) {
window.open('https://translate.google.fr/?hl=fr#view=home&op=translate&sl=fr&tl=' + this.currentLang + '&text=' + text.replace('__TO_TRANSLATE', ''), '_blank');
}
setActiveLang(ev: any) {
this.currentLang = ev.detail.value;
}
generateMissingLang(ignoreToTranslate = false) {
let newLang = {};
let mergedLang = this.allLang[this.currentLang];
const regex = /__TO_TRANSLATE$/g;
this.missingLang[this.currentLang].forEach((element: any) => {
if (element.value.match(regex) === null && ignoreToTranslate) {
newLang[element.id] = element.value;
} else if (!ignoreToTranslate) {
newLang[element.id] = element.value;
}
});
mergedLang = { ...mergedLang, ...newLang };
this.http.put('../rest/dev/languages', { langId: this.currentLang, jsonContent: mergedLang }).pipe(
tap((data: any) => {
Object.keys(newLang).forEach(keyLang => {
delete this.allLang[this.currentLang][keyLang];
this.missingLang[this.currentLang] = this.missingLang[this.currentLang].filter((missLang: any) => missLang.id !== keyLang);
this.data.countMissingLang--;
});
this.dialogRef.close(this.data.countMissingLang);
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
}
<button mat-fab cdkDrag [matBadge]="countMissingLang" [matMenuTriggerFor]="menu" color="warn" style="position: fixed;right: 50px;top: 50px;z-index: 1;">
<mat-icon class="fas fa-toolbox" style="height: auto;font-size: 23px;"></mat-icon>
</button>
<mat-menu #menu="matMenu" [class]="'devToolListMenu'">
<button mat-menu-item (click)="openLangTool()">
<mat-icon color="primary" class="fas fa-language" style="height: auto;"></mat-icon>
<span>{{'lang.missingLang' | translate}}</span>&nbsp;&nbsp;<span [matBadge]="countMissingLang">&nbsp;</span>
</button>
</mat-menu>
\ No newline at end of file
::ng-deep.devToolListMenu {
min-height : auto !important;
width: 250px;
}
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { DevLangComponent } from '../debug/dev-lang.component';
import { HttpClient } from '@angular/common/http';
import { NotificationService } from '../notification.service';
import { of } from 'rxjs';
import { FunctionsService } from '../functions.service';
import { catchError, filter, tap } from 'rxjs/operators';
@Component({
selector: 'app-dev-tool',
templateUrl: 'dev-tool.component.html',
styleUrls: ['dev-tool.component.scss'],
})
export class DevToolComponent implements OnInit {
allLang: any;
countMissingLang: number = 0;
constructor(
private notify: NotificationService,
public dialog: MatDialog,
public http: HttpClient,
private functionsService: FunctionsService
) { }
ngOnInit(): void {
this.getLangs();
}
openLangTool() {
const dialogRef = this.dialog.open(DevLangComponent, {
panelClass: 'maarch-modal',
height: '99%',
width: '80%',
data: {
countMissingLang : this.countMissingLang
}
});
dialogRef.afterClosed().pipe(
filter((data: string) => !this.functionsService.empty(data)),
tap((data: any) => {
this.countMissingLang = data;
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
getLangs() {
this.http.get('../rest/dev/languages').pipe(
tap((data: any) => {
this.allLang = data.languages;
Object.keys(this.allLang).forEach(langName => {
this.countMissingLang += Object.keys(this.allLang.fr.lang).filter((keyLang: any) => Object.keys(this.allLang[langName].lang).indexOf(keyLang) === -1).length;
});
}),
catchError((err: any) => {
this.notify.handleErrors(err);
return of(false);
})
).subscribe();
}
}
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LatinisePipe } from 'ngx-pipes';
@Injectable({
providedIn: 'root'
})
export class FunctionsService {
constructor(
public translate: TranslateService,
private latinisePipe: LatinisePipe,
) { }
empty(value: any) {
if (value === null || value === undefined) {
return true;
} else if (Array.isArray(value)) {
if (value.length > 0) {
return false;
} else {
return true;
}
} else if (String(value) !== '') {
return false;
} else {
return true;
}
}
isDate(value: any) {
return value instanceof Date && !isNaN(value.valueOf());
}
formatFrenchDateToTechnicalDate(date: string) {
if (!this.empty(date)) {
let arrDate = date.split('-');
arrDate = arrDate.concat(arrDate[arrDate.length - 1].split(' '));
arrDate.splice(2, 1);
if (this.empty(arrDate[3])) {
arrDate[3] = '00:00:00';
}
const formatDate = `${arrDate[2]}-${arrDate[1]}-${arrDate[0]} ${arrDate[3]}`;
return formatDate;
} else {
return date;
}
}
formatFrenchDateToObjectDate(date: string, delimiter: string = '-') {
if (!this.empty(date)) {
let arrDate = date.split(delimiter);
arrDate = arrDate.concat(arrDate[arrDate.length - 1].split(' '));
arrDate.splice(2, 1);
if (this.empty(arrDate[3])) {
arrDate[3] = '00:00:00';
}
const formatDate = `${arrDate[2]}-${arrDate[1]}-${arrDate[0]} ${arrDate[3]}`;
return new Date(formatDate);
} else {
return date;
}
}
formatDateObjectToDateString(date: Date, limitMode: boolean = false, format: string = 'dd-mm-yyyy') {
if (date !== null) {
let formatDate: any[] = [];
format.split('-').forEach((element: any) => {
if (element === 'dd') {
let day: any = date.getDate();
day = ('00' + day).slice(-2);
formatDate.push(day);
} else if (element === 'mm') {
let month: any = date.getMonth() + 1;
month = ('00' + month).slice(-2);
formatDate.push(month);
} else if (element === 'yyyy') {
let year: any = date.getFullYear();
formatDate.push(year);
}
});
let limit = '';
if (limitMode) {
limit = ' 23:59:59';
}
return `${formatDate.join('-')}${limit}`;
} else {
return date;
}
}
formatSerializedDateToDateString(date: string) {
return this.formatDateObjectToDateString(new Date(date));
}
listSortingDataAccessor(data: any, sortHeaderId: any) {
if (typeof data[sortHeaderId] === 'string') {
return data[sortHeaderId].toLowerCase();
}
return data[sortHeaderId];
}
filterUnSensitive(template: any, filter: string, filteredColumns: any) {
let filterReturn = false;
filter = this.latinisePipe.transform(filter);
filteredColumns.forEach((column: any) => {
let val = template[column];
if (typeof template[column] !== 'string') {
val = val === undefined || null ? '' : JSON.stringify(val);
}
filterReturn = filterReturn || this.latinisePipe.transform(val.toLowerCase()).includes(filter);
});
return filterReturn;
}
formatBytes(bytes: number, decimals = 2) {
if (typeof bytes === 'number') {
if (bytes === 0) { return '0 Octet'; }
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Octets', 'KO', 'MO', 'GO', 'TO', 'PO', 'EO', 'ZO', 'YO'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
} else {
return bytes;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment