From 4108c009fb198de0475a42543c25a8015741f1e3 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Fri, 11 Oct 2024 08:06:05 +0000
Subject: [PATCH 01/16] fix: init translation fr/en Refs #6

---
 package-lock.json          | 29 ++++++++++++++++++++++++
 package.json               |  2 ++
 src/app/app.component.html | 45 +++++++++++++++++++++++---------------
 src/app/app.component.ts   | 11 +++++++---
 src/app/app.config.ts      | 20 +++++++++++++++--
 src/assets/i18n/en.json    | 25 +++++++++++++++++++++
 src/assets/i18n/fr.json    | 25 +++++++++++++++++++++
 7 files changed, 134 insertions(+), 23 deletions(-)
 create mode 100644 src/assets/i18n/en.json
 create mode 100644 src/assets/i18n/fr.json

diff --git a/package-lock.json b/package-lock.json
index 9b7fde0..b55cac4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,6 +20,8 @@
         "@angular/platform-server": "^17.3.0",
         "@angular/router": "^17.3.0",
         "@angular/ssr": "^17.3.3",
+        "@ngx-translate/core": "^15.0.0",
+        "@ngx-translate/http-loader": "^8.0.0",
         "base64-js": "^1.5.1",
         "chart.js": "^4.4.4",
         "express": "^4.18.2",
@@ -4051,6 +4053,33 @@
         "webpack": "^5.54.0"
       }
     },
+    "node_modules/@ngx-translate/core": {
+      "version": "15.0.0",
+      "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-15.0.0.tgz",
+      "integrity": "sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==",
+      "engines": {
+        "node": "^16.13.0 || >=18.10.0"
+      },
+      "peerDependencies": {
+        "@angular/common": ">=16.0.0",
+        "@angular/core": ">=16.0.0",
+        "rxjs": "^6.5.5 || ^7.4.0"
+      }
+    },
+    "node_modules/@ngx-translate/http-loader": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz",
+      "integrity": "sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==",
+      "engines": {
+        "node": "^16.13.0 || >=18.10.0"
+      },
+      "peerDependencies": {
+        "@angular/common": ">=16.0.0",
+        "@angular/core": ">=16.0.0",
+        "@ngx-translate/core": ">=15.0.0",
+        "rxjs": "^6.5.5 || ^7.4.0"
+      }
+    },
     "node_modules/@nodelib/fs.scandir": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
diff --git a/package.json b/package.json
index 6779e75..72b7e54 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,8 @@
     "@angular/platform-server": "^17.3.0",
     "@angular/router": "^17.3.0",
     "@angular/ssr": "^17.3.3",
+    "@ngx-translate/core": "^15.0.0",
+    "@ngx-translate/http-loader": "^8.0.0",
     "base64-js": "^1.5.1",
     "chart.js": "^4.4.4",
     "express": "^4.18.2",
diff --git a/src/app/app.component.html b/src/app/app.component.html
index e142919..ccd3108 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,13 +1,13 @@
 <mat-toolbar>
-  <button mat-icon-button class="app-sidenav-toggle-button" (click)="sidenav.toggle()" matTooltip="Menu">
+  <button mat-icon-button class="app-sidenav-toggle-button" (click)="sidenav.toggle()" matTooltip="{{ 'TOOLBAR.MENU' | translate }}">
       <mat-icon>menu</mat-icon>
   </button>
-  <span>Moulinet</span>
+  <span>{{ 'TOOLBAR.TITLE' | translate }}</span>
   <span class="toolbar-item-spacer"></span>
-  <button mat-icon-button matTooltip="Search">
+  <button mat-icon-button matTooltip="{{ 'TOOLBAR.SEARCH' | translate }}">
     <mat-icon>search</mat-icon>
   </button>
-  <button mat-icon-button matTooltip="Help">
+  <button mat-icon-button matTooltip="{{ 'TOOLBAR.HELP' | translate }}">
     <mat-icon>help</mat-icon>
   </button>
 </mat-toolbar>
@@ -16,37 +16,46 @@
   <mat-sidenav #sidenav mode="over" [class.mat-elevation-z4]="true" class="app-sidenav">
     <mat-nav-list>
       <mat-list-item routerLink="equipment" (click)="sidenav.close()">
-        <mat-icon class="icon-list-item">construction</mat-icon><span>Matériel</span>
+        <mat-icon class="icon-list-item">construction</mat-icon>
+        <span>{{ 'SIDENAV.MATERIAL' | translate }}</span>
       </mat-list-item>
       <mat-list-item routerLink="list" (click)="sidenav.close()">
-        <mat-icon class="icon-list-item">waves icon</mat-icon><span>Liste des jaugeages</span>
+        <mat-icon class="icon-list-item">waves</mat-icon>
+        <span>{{ 'SIDENAV.GAUGING_LIST' | translate }}</span>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <button (click)="createNewGauging()"> <mat-icon
-          class="icon-list-item">waves icon</mat-icon><span>Nouveau jaugeage</span>
+        <button (click)="createNewGauging()">
+          <mat-icon class="icon-list-item">waves</mat-icon>
+          <span>{{ 'SIDENAV.NEW_GAUGING' | translate }}</span>
         </button>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()"> <mat-icon
-            class="icon-list-item">insert_drive_file</mat-icon><span>Réinitialiser la session</span></button>
+        <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()">
+          <mat-icon class="icon-list-item">insert_drive_file</mat-icon>
+          <span>{{ 'SIDENAV.RESET_SESSION' | translate }}</span>
+        </button>
       </mat-list-item>
       <mat-list-item (click)="loadSession(); sidenav.close()">
-        <mat-icon class="icon-list-item">folder_open</mat-icon><span>Charger une session</span>
+        <mat-icon class="icon-list-item">folder_open</mat-icon>
+        <span>{{ 'SIDENAV.LOAD_SESSION' | translate }}</span>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="saveSession()"> <mat-icon
-            class="icon-list-item">file_download</mat-icon><span>Enregistrer la session</span></button>
+        <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="saveSession()">
+          <mat-icon class="icon-list-item">file_download</mat-icon>
+          <span>{{ 'SIDENAV.SAVE_SESSION' | translate }}</span>
+        </button>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <mat-icon class="icon-list-item">settings</mat-icon><span>Configuration</span>
+        <mat-icon class="icon-list-item">settings</mat-icon>
+        <span>{{ 'SIDENAV.CONFIGURATION' | translate }}</span>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <mat-icon class="icon-list-item">help</mat-icon><span>Documentation</span>
+        <mat-icon class="icon-list-item">help</mat-icon>
+        <span>{{ 'SIDENAV.DOCUMENTATION' | translate }}</span>
       </mat-list-item>
     </mat-nav-list>
   </mat-sidenav>
   <mat-sidenav-content>
-    <router-outlet>
-    </router-outlet>
+    <router-outlet></router-outlet>
   </mat-sidenav-content>
-</mat-sidenav-container>
\ No newline at end of file
+</mat-sidenav-container>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 5afb4af..234d7d0 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -22,11 +22,14 @@ import { GaugingService } from './services/gauging.service';
 import { Gauging } from './models/gauging';
 import { DialogConfirmNewGaugingComponent } from './components/dialog/dialog-confirm-new-gauging/dialog-confirm-new-gauging.component';
 import { GaugingFormService } from './services/forms/gauging-form.service';
+import { TranslateModule, TranslateService } from '@ngx-translate/core';
+import { MatTooltipModule } from '@angular/material/tooltip';
+
 
 @Component({
   selector: 'app-root',
   standalone: true,
-  imports: [AsyncPipe, RouterOutlet, RouterModule, RouterLink, MatButtonModule, MatToolbarModule, MatSidenavModule, MatListModule, MatExpansionModule, MatIconModule, MatMenuModule],
+  imports: [MatTooltipModule,AsyncPipe, RouterOutlet, RouterModule, RouterLink, MatButtonModule, MatToolbarModule, MatSidenavModule, MatListModule, MatExpansionModule, MatIconModule, MatMenuModule, TranslateModule],
   templateUrl: './app.component.html',
   styleUrl: './app.component.scss'
 })
@@ -38,15 +41,17 @@ export class AppComponent {
   gaugingList$: Observable<Gauging[]>;
   materialList: Material[] = [];
 
-  constructor(private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
+  constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
     this.materialList$ = this.equipmentService.materialList$;
     this.gaugingList$ = this.gaugingService.gaugingList$;
+    this.translate.addLangs(['fr', 'en']);
+    this.translate.setDefaultLang('fr');
+    this.translate.use('fr');
   }
 
   ngOnInit(): void {
     // Charger les données de session depuis le localStorage
     this.session.loadFromLocalStorage();
-    // localStorage.removeItem("currentSessionMoulinet")
     if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') {
       const wasPageRefreshed = sessionStorage.getItem('pageRefreshed');
       if (wasPageRefreshed) {
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index cfa828c..495ff54 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -1,11 +1,27 @@
-import { ApplicationConfig } from '@angular/core';
+import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
 import { provideRouter, PreloadAllModules, withPreloading } from '@angular/router';
 import { routes } from './app.routes';
 import { provideClientHydration } from '@angular/platform-browser';
 import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
 import { MAT_DATE_LOCALE } from '@angular/material/core';
+import { HttpClient, provideHttpClient } from '@angular/common/http';
+import { TranslateHttpLoader } from '@ngx-translate/http-loader';
+import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
+
+const httpLoaderFactory: (http: HttpClient) => TranslateHttpLoader = (http: HttpClient) =>
+    new TranslateHttpLoader(http, './assets/i18n/', '.json');
 
 export const appConfig: ApplicationConfig = {
   providers: [
-    provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'}]
+    provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'},
+    provideZoneChangeDetection({ eventCoalescing: true }),
+    provideHttpClient(),
+    importProvidersFrom([TranslateModule.forRoot({
+      loader: {
+        provide: TranslateLoader,
+        useFactory: httpLoaderFactory,
+        deps: [HttpClient],
+      },
+    })])
+  ]
 };
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
new file mode 100644
index 0000000..e085fa2
--- /dev/null
+++ b/src/assets/i18n/en.json
@@ -0,0 +1,25 @@
+{
+    "TOOLBAR": {
+      "MENU": "Menu",
+      "TITLE": "Moulinet",
+      "SEARCH": "Search",
+      "HELP": "Help"
+    },
+    "SIDENAV": {
+      "MATERIAL": "Equipment",
+      "GAUGING_LIST": "List of Gaugings",
+      "NEW_GAUGING": "New Gauging",
+      "RESET_SESSION": "Reset Session",
+      "LOAD_SESSION": "Load Session",
+      "SAVE_SESSION": "Save Session",
+      "CONFIGURATION": "Configuration",
+      "DOCUMENTATION": "Documentation"
+    },
+    "BUTTONS": {
+      "CREATE_NEW_GAUGING": "Create New Gauging",
+      "RESET_SESSION": "Reset Session",
+      "LOAD_SESSION": "Load Session",
+      "SAVE_SESSION": "Save Session"
+    }
+  }
+  
\ No newline at end of file
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
new file mode 100644
index 0000000..c97906d
--- /dev/null
+++ b/src/assets/i18n/fr.json
@@ -0,0 +1,25 @@
+{
+    "TOOLBAR": {
+      "MENU": "Menu",
+      "TITLE": "Moulinet",
+      "SEARCH": "Rechercher",
+      "HELP": "Aide"
+    },
+    "SIDENAV": {
+      "MATERIAL": "Matériel",
+      "GAUGING_LIST": "Liste des jaugeages",
+      "NEW_GAUGING": "Nouveau jaugeage",
+      "RESET_SESSION": "Réinitialiser la session",
+      "LOAD_SESSION": "Charger une session",
+      "SAVE_SESSION": "Enregistrer la session",
+      "CONFIGURATION": "Configuration",
+      "DOCUMENTATION": "Documentation"
+    },
+    "BUTTONS": {
+      "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage",
+      "RESET_SESSION": "Réinitialiser la session",
+      "LOAD_SESSION": "Charger une session",
+      "SAVE_SESSION": "Enregistrer la session"
+    }
+  }
+  
\ No newline at end of file
-- 
GitLab


From 38a3c6aa6fb43699b9898c4b7e25444ef83a1c74 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Fri, 11 Oct 2024 08:15:57 +0000
Subject: [PATCH 02/16] fix: translate gauging list component Refs #6

---
 src/app/app.component.ts                      |  2 +-
 .../gauging-list/gauging-list.component.html  | 34 ++++++++++---------
 .../gauging-list/gauging-list.component.ts    |  3 +-
 src/assets/i18n/en.json                       | 15 ++++++++
 src/assets/i18n/fr.json                       | 15 ++++++++
 5 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 234d7d0..a51cede 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -46,7 +46,7 @@ export class AppComponent {
     this.gaugingList$ = this.gaugingService.gaugingList$;
     this.translate.addLangs(['fr', 'en']);
     this.translate.setDefaultLang('fr');
-    this.translate.use('fr');
+    this.translate.use('en');
   }
 
   ngOnInit(): void {
diff --git a/src/app/views/gauging-list/gauging-list.component.html b/src/app/views/gauging-list/gauging-list.component.html
index baa0574..a4dd044 100644
--- a/src/app/views/gauging-list/gauging-list.component.html
+++ b/src/app/views/gauging-list/gauging-list.component.html
@@ -1,53 +1,54 @@
-<!-- template.html -->
 <div class="container">
   <div class="gauging-list-container">
     <div class="gauging-list">
       @if((gaugingsList$ | async)?.length! > 0){ 
       <div class="gauging-list-title">
-        <h1>Liste des Jaugeages</h1>
-        <button mat-raised-button color="primary" (click)="addGauging()" class="gauging-list-title-add">Ajouter un jaugeage</button>
+        <h1>{{ 'GAUGING.LIST_TITLE' | translate }}</h1>
+        <button mat-raised-button color="primary" (click)="addGauging()" class="gauging-list-title-add">
+          {{ 'GAUGING.ADD_GAUGING' | translate }}
+        </button>
       </div>
       <table mat-table [dataSource]="(gaugingsList$ | async)!"  cdkDropList>
        
         <!-- Watercourse Column -->
        <ng-container matColumnDef="watercourse">
-        <th mat-header-cell *matHeaderCellDef> Cours d'eau </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.WATERCOURSE' | translate }} </th>
         <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)" > {{ gauging.watercourse || '-' }} </td>
       </ng-container>
 
        <!-- Department Column -->
        <ng-container matColumnDef="department">
-        <th mat-header-cell *matHeaderCellDef> Département </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DEPARTMENT' | translate }} </th>
         <td mat-cell *matCellDef="let gauging"(click)="editGauging(gauging)" > {{ gauging.department || '-' }} </td>
       </ng-container>
 
       <!-- Municipality Column -->
       <ng-container matColumnDef="municipality">
-          <th mat-header-cell *matHeaderCellDef> Commune </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.MUNICIPALITY' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.municipality || '-' }} </td>
       </ng-container>
 
       <!-- Locality Column -->
       <ng-container matColumnDef="locality">
-          <th mat-header-cell *matHeaderCellDef> Lieu-dit </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.LOCALITY' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.locality || '-' }} </td>
       </ng-container>
 
       <!-- Date Column -->
       <ng-container matColumnDef="date">
-          <th mat-header-cell *matHeaderCellDef> Date </th>
-          <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)">  {{ gauging.date | date: 'dd/MM/yyyy' }}</td>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DATE' | translate }} </th>
+          <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.date | date: 'dd/MM/yyyy' }}</td>
       </ng-container>
 
       <!-- State Column -->
       <ng-container matColumnDef="state">
-          <th mat-header-cell *matHeaderCellDef> Etat </th>
-          <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> Validé </td>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.STATE' | translate }} </th>
+          <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ 'GAUGING.VALIDATED' | translate }} </td>
       </ng-container>
 
       <!-- Actions Column -->
       <ng-container matColumnDef="actions">
-        <th mat-header-cell *matHeaderCellDef> Actions </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.ACTIONS' | translate }} </th>
         <td mat-cell *matCellDef="let gauging, , let i =index">
           <button mat-icon-button color="primary" (click)="editGauging(gauging)">
               <mat-icon class="edit-button">edit</mat-icon>
@@ -67,12 +68,13 @@
     @else{
       <!-- if no created gauging  -->
       <div class="no-gauging-title">
-        <h1>Liste des jaugeages</h1>
-        <p>Aucun jaugeage réalisé ou en cours de réalisation.</p>
-        <button mat-raised-button color="primary" (click)="addGauging()" class="add-button">Ajouter</button>
+        <h1>{{ 'GAUGING.LIST_TITLE' | translate }}</h1>
+        <p>{{ 'GAUGING.NO_GAUGING' | translate }}</p>
+        <button mat-raised-button color="primary" (click)="addGauging()" class="add-button">
+          {{ 'GAUGING.ADD_GAUGING' | translate }}
+        </button>
       </div>
       }
     </div>
     </div>
   </div>
- 
\ No newline at end of file
diff --git a/src/app/views/gauging-list/gauging-list.component.ts b/src/app/views/gauging-list/gauging-list.component.ts
index 33056f1..1a9f622 100644
--- a/src/app/views/gauging-list/gauging-list.component.ts
+++ b/src/app/views/gauging-list/gauging-list.component.ts
@@ -13,11 +13,12 @@ import { Router} from '@angular/router';
 import { subscribeOnce } from '../../tools/ObservableHelper';
 import { DialogConfirmDeleteGaugingComponent } from '../../components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component';
 import { MatDialog } from '@angular/material/dialog';
+import { TranslateModule } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-gauging-list',
   standalone: true,
-  imports: [ReactiveFormsModule, FormsModule, CommonModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent],
+  imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent],
   templateUrl: './gauging-list.component.html',
   styleUrl: './gauging-list.component.scss',
   providers: [DatePipe]
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index e085fa2..89561fa 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -20,6 +20,21 @@
       "RESET_SESSION": "Reset Session",
       "LOAD_SESSION": "Load Session",
       "SAVE_SESSION": "Save Session"
+    },
+    "GAUGING": {
+      "LIST_TITLE": "Gauging List",
+      "ADD_GAUGING": "Add Gauging",
+      "COLUMNS": {
+        "WATERCOURSE": "Watercourse",
+        "DEPARTMENT": "Department",
+        "MUNICIPALITY": "Municipality",
+        "LOCALITY": "Locality",
+        "DATE": "Date",
+        "STATE": "State",
+        "ACTIONS": "Actions"
+      },
+      "VALIDATED": "Validated",
+      "NO_GAUGING": "No gauging has been carried out or is in progress."
     }
   }
   
\ No newline at end of file
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index c97906d..1997953 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -20,6 +20,21 @@
       "RESET_SESSION": "Réinitialiser la session",
       "LOAD_SESSION": "Charger une session",
       "SAVE_SESSION": "Enregistrer la session"
+    },
+    "GAUGING": {
+      "LIST_TITLE": "Liste des Jaugeages",
+      "ADD_GAUGING": "Ajouter un jaugeage",
+      "COLUMNS": {
+        "WATERCOURSE": "Cours d'eau",
+        "DEPARTMENT": "Département",
+        "MUNICIPALITY": "Commune",
+        "LOCALITY": "Lieu-dit",
+        "DATE": "Date",
+        "STATE": "État",
+        "ACTIONS": "Actions"
+      },
+      "VALIDATED": "Validé",
+      "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation."
     }
   }
   
\ No newline at end of file
-- 
GitLab


From f32ee41f3ac9b838d0c1b68cfc039abdbc94ce80 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Fri, 11 Oct 2024 10:09:29 +0000
Subject: [PATCH 03/16] fix: translate equipment component Refs #6

---
 src/app/models/equipment.model.ts             |   7 +-
 src/app/services/equipment.service.ts         |  19 +-
 .../views/equipment/equipment.component.html  | 238 +++++++++---------
 .../views/equipment/equipment.component.ts    |   3 +-
 src/assets/i18n/en.json                       | 108 +++++---
 src/assets/i18n/fr.json                       | 108 +++++---
 6 files changed, 278 insertions(+), 205 deletions(-)

diff --git a/src/app/models/equipment.model.ts b/src/app/models/equipment.model.ts
index 26d5b16..d71f899 100644
--- a/src/app/models/equipment.model.ts
+++ b/src/app/models/equipment.model.ts
@@ -1,5 +1,6 @@
 export enum MaterialType {
-    ElectromagneticFlowMeter = 'courantomètre électromagnétique',
-    PropellerFlowMeter = 'moulinet',
-    VelocityHeadRod = 'perche à charge dynamique transparente'
+    ElectromagneticFlowMeter = 'EQUIPMENT.materialTypes.ElectromagneticFlowMeter',
+    PropellerFlowMeter = 'EQUIPMENT.materialTypes.PropellerFlowMeter',
+    VelocityHeadRod = 'EQUIPMENT.materialTypes.VelocityHeadRod'
 }
+
diff --git a/src/app/services/equipment.service.ts b/src/app/services/equipment.service.ts
index 7784394..f28e9f3 100644
--- a/src/app/services/equipment.service.ts
+++ b/src/app/services/equipment.service.ts
@@ -6,6 +6,7 @@ import { MaterialPropeller } from '../models/material_propeller';
 import { MaterialHeadRod } from '../models/material_headRod';
 import { Gauging } from '../models/gauging';
 import { GaugingService } from './gauging.service';
+import { MaterialType } from '../models/equipment.model';
 
 @Injectable({
   providedIn: 'root'
@@ -66,18 +67,18 @@ export class EquipmentService {
 
   public createInstanceofMaterial(materialType: string, ...args: any[]): any {
     const MaterialTypeDictionary: { [key: string]: any } = {
-      'courantomètre électromagnétique': MaterialCouranto,
-      'moulinet': MaterialPropeller,
-      'perche à charge dynamique transparente': MaterialHeadRod
+      [MaterialType.ElectromagneticFlowMeter]: MaterialCouranto,
+      [MaterialType.PropellerFlowMeter]: MaterialPropeller,
+      [MaterialType.VelocityHeadRod]: MaterialHeadRod
     };
 
-    const SelectedMaterialTypeClass = MaterialTypeDictionary[materialType];
-    if (SelectedMaterialTypeClass) {
-      return new SelectedMaterialTypeClass(...args);
-    } else {
-      throw new Error(`La classe ${materialType} n'existe pas.`);
+    const MaterialClass = MaterialTypeDictionary[materialType];
+    if (MaterialClass) {
+        return new MaterialClass(...args);
     }
-  }
+    throw new Error(`Unknown material type: ${materialType}`);
+}
+
 
   // Nouvelle méthode pour vérifier si un matériel est associé à un gauging
   isMaterialAssociatedWithGauging(materialId: string): boolean {
diff --git a/src/app/views/equipment/equipment.component.html b/src/app/views/equipment/equipment.component.html
index 80366f6..2e0d6b4 100644
--- a/src/app/views/equipment/equipment.component.html
+++ b/src/app/views/equipment/equipment.component.html
@@ -4,17 +4,19 @@
     <div class="equipment-list">
       @if((materialList$ | async)?.length! > 0){
       <div class="equipment-list-title">
-        <h1>Liste du Matériel</h1>
+        <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1>
         <button mat-raised-button color="primary" [disabled]="showEditMaterialForm" class="equipment-list-title-add"
-          [disabled]="needMaterial" (click)="addMaterial()"><span>Ajouter</span><mat-icon
-            class="icon-list-item">add</mat-icon></button>
+          [disabled]="needMaterial" (click)="addMaterial()">
+          <span>{{ 'EQUIPMENT.addMaterialButton' | translate }}</span>
+          <mat-icon class="icon-list-item">add</mat-icon>
+        </button>
       </div>
       <table mat-table [dataSource]="(materialList$ | async)!" cdkDropList
         [cdkDropListDisabled]="!enableDragFunctionality" (cdkDropListDropped)="dropTable($event)"
         [cdkDropListLockAxis]="'y'">
         <!-- Reorder column -->
         <ng-container matColumnDef="reorder">
-          <th mat-header-cell *matHeaderCellDef style="width:5%"></th>> <th>
+          <th mat-header-cell *matHeaderCellDef style="width:5%"></th>
           <td mat-cell *matCellDef="let material" style="text-overflow: unset !important;">
             <!-- draggable button -->
             <mat-icon (click)="toggleDragFunctionality()" class="drag-icon">drag_indicator</mat-icon>
@@ -23,7 +25,7 @@
 
         <!-- Name Column -->
         <ng-container matColumnDef="name">
-          <th mat-header-cell *matHeaderCellDef>Nom</th>
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.nameColumn' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)" id="name-row">{{
             materiel.name }}
           </td>
@@ -31,27 +33,27 @@
 
         <!-- Type Column -->
         <ng-container matColumnDef="type">
-          <th mat-header-cell *matHeaderCellDef>Type</th>
-          <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type }}
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.typeColumn' | translate }}</th>
+          <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type | translate}}
           </td>
         </ng-container>
 
         <!-- Serial Number Column -->
         <ng-container matColumnDef="serialNumber">
-          <th mat-header-cell *matHeaderCellDef>Numéro de série</th>
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.serialNumberColumn' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{
             materiel.serialNumber || '-' }}</td>
         </ng-container>
         <!-- Description Column -->
         <ng-container matColumnDef="description">
-          <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>Description</th>
+          <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.descriptionColumn' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{
             materiel.description || '-' }}</td>
         </ng-container>
 
         <!-- Edit/Remove Column -->
         <ng-container matColumnDef="edit">
-          <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">Actions</th>
+          <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.actionsColumn' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i =index" style="text-overflow: unset; text-align: center;">
             <button mat-icon-button color="primary" (click)="editMaterial(materiel, i)"
               [disabled]="needMaterial || showEditMaterialForm" id="edit">
@@ -75,10 +77,10 @@
       @else{
       <!-- if no created material  -->
       <div class="equipment-form-title">
-        <h1>Liste du Matériel</h1>
-        <p>Aucun matériel disponible.</p>
+        <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1>
+        <p>{{ 'EQUIPMENT.noMaterialAvailable' | translate }}</p>
         @if(!needMaterial) {
-        <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">Ajouter</button>
+        <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.addMaterialButton' | translate }}</button>
         }
       </div>
       }
@@ -86,112 +88,108 @@
   </div>
   <!-- Creation/Edition form -->
   @if(needMaterial || showEditMaterialForm ){
-  <div class="equipment-form-container">
-    <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()">
-      <h1 class="equipment-form-title">{{needMaterial ? 'Nouveau matériel' : 'Modifier le matériel'}}</h1>
-      <!-- Material Type Section -->
-      <section class="form-section">
-        <h2>Type de matériel</h2>
-        <mat-form-field appearance="outline">
-          <mat-label>Type de matériel</mat-label>
-          <mat-select formControlName="type" placeholder="Type" (selectionChange)="onMaterialTypeChange()">
-            @for (type of materielTypes; track type) {
-            <mat-option [value]="type">
-              {{type}}
-            </mat-option>
-            }
-          </mat-select>
-        </mat-form-field>
-      </section>
-
-      <!-- Model Section -->
-      <section class="form-section">
-        <h2>Modèle</h2>
-        <mat-form-field appearance="outline">
-          <mat-label>Nom</mat-label>
-          <input matInput placeholder="Nom" formControlName="name" autocomplete="name">
-        </mat-form-field>
-        @if(hasError('name', 'required')){
-        <app-error-message [displayed]="hasError('name', 'required')">Le nom est
-          requis</app-error-message>
-        }
-        <mat-form-field appearance="outline">
-          <mat-label>Numéro de série
-          </mat-label>
-          <input matInput placeholder="Numéro de série" formControlName="serialNumber" autocomplete="off">
-        </mat-form-field>
-        @if(isPropeller) {
-        <!-- Numéro de l'hélice -->
-        <mat-form-field appearance="outline">
-          <mat-label>Numéro de l'hélice</mat-label>
-          <input matInput placeholder="Numéro de l'hélice" formControlName="propellerNumber" autocomplete="off">
-        </mat-form-field>
-
-        <!-- Numéro de série de l'hélice -->
-        <mat-form-field appearance="outline">
-          <mat-label>Numéro de série de l'hélice</mat-label>
-          <input matInput placeholder="Numéro de série de l'hélice" formControlName="propellerSerialNumber"
-            autocomplete="off">
-        </mat-form-field>
-
-        <!-- Nombre de formules de vitesse -->
-        <mat-form-field appearance="outline">
-          <mat-label>Nombre de formules de vitesse</mat-label>
-          <mat-select formControlName="velocityFormulaCount" placeholder="Nombre de formules de vitesse"
-            (selectionChange)="onVelocityFormulaCountChange($event.value)">
-            <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count">
-              {{count}}
-            </mat-option>
-          </mat-select>
-        </mat-form-field>
-        <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}">
-          @for(formula of velocityFormulas.controls; track formula; let i = $index ) {
-          <div [formGroupName]="i">
-            <h3>Formule de vitesse n°{{ i + 1 }}</h3>
-            <div class="form-field-row">
-              <mat-form-field appearance="outline" class="form-field-inline">
-                <mat-label>Borne inférieure</mat-label>
-                <input matInput placeholder="n >" formControlName="lowerBound">
-              </mat-form-field>
-              <!-- Message d'erreur -->
-              <mat-form-field appearance="outline" class="form-field-inline">
-                <mat-label>Borne supérieure</mat-label>
-                <input matInput placeholder="n &lt;" formControlName="upperBound">
-              </mat-form-field>
-            </div>
-            @if(formula.errors?.invalidBounds) {
-            <mat-error>Les bornes spécifiées ne sont pas correctes. La borne inférieure doit être strictement inférieure
-              à la borne supérieure.</mat-error>
-            }
-
-            <!-- Deuxième ligne : Coef a et Coef b -->
-            <div class="form-field-row">
-              <mat-form-field appearance="outline" class="form-field-inline">
-                <mat-label>Coefficient A</mat-label>
-                <input matInput placeholder="Coef a" formControlName="coefA">
-              </mat-form-field>
-              <mat-form-field appearance="outline" class="form-field-inline">
-                <mat-label>Constante B</mat-label>
-                <input matInput placeholder="Constante b" formControlName="constantB">
-              </mat-form-field>
+    <div class="equipment-form-container">
+      <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()">
+        <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.newMaterialTitle' | translate) : ('EQUIPMENT.editMaterialTitle' | translate)}}</h1>
+        
+        <!-- Material Type Section -->
+        <section class="form-section">
+          <h2>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</h2>
+          <mat-form-field appearance="outline">
+            <mat-label>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</mat-label>
+            <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.materialTypeLabel' | translate }}" (selectionChange)="onMaterialTypeChange()">
+              @for (type of materielTypes; track type) {
+                <mat-option [value]="type">
+                  {{ type | translate }}
+                </mat-option>
+              }
+            </mat-select>
+          </mat-form-field>
+        </section>
+  
+        <!-- Model Section -->
+        <section class="form-section">
+          <h2>{{ 'EQUIPMENT.modelSectionTitle' | translate }}</h2>
+          <mat-form-field appearance="outline">
+            <mat-label>{{ 'EQUIPMENT.nameLabel' | translate }}</mat-label>
+            <input matInput placeholder="{{ 'EQUIPMENT.nameLabel' | translate }}" formControlName="name" autocomplete="name">
+          </mat-form-field>
+          @if(hasError('name', 'required')){
+            <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.requiredNameError' | translate }}</app-error-message>
+          }
+          <mat-form-field appearance="outline">
+            <mat-label>{{ 'EQUIPMENT.serialNumberLabel' | translate }}</mat-label>
+            <input matInput placeholder="{{ 'EQUIPMENT.serialNumberLabel' | translate }}" formControlName="serialNumber" autocomplete="off">
+          </mat-form-field>
+          @if(isPropeller) {
+            <!-- Propeller Number -->
+            <mat-form-field appearance="outline">
+              <mat-label>{{ 'EQUIPMENT.propellerNumberLabel' | translate }}</mat-label>
+              <input matInput placeholder="{{ 'EQUIPMENT.propellerNumberLabel' | translate }}" formControlName="propellerNumber" autocomplete="off">
+            </mat-form-field>
+  
+            <!-- Propeller Serial Number -->
+            <mat-form-field appearance="outline">
+              <mat-label>{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}</mat-label>
+              <input matInput placeholder="{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}" formControlName="propellerSerialNumber" autocomplete="off">
+            </mat-form-field>
+  
+            <!-- Number of Velocity Formulas -->
+            <mat-form-field appearance="outline">
+              <mat-label>{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}</mat-label>
+              <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)">
+                <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count">
+                  {{count}}
+                </mat-option>
+              </mat-select>
+            </mat-form-field>
+            <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}">
+              @for(formula of velocityFormulas.controls; track formula; let i = $index ) {
+                <div [formGroupName]="i">
+                  <h3>{{ 'EQUIPMENT.velocityFormulaTitle' | translate }} {{ i + 1 }}</h3>
+                  <div class="form-field-row">
+                    <mat-form-field appearance="outline" class="form-field-inline">
+                      <mat-label>{{ 'EQUIPMENT.lowerBoundLabel' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.lowerBoundLabel' | translate }}" formControlName="lowerBound">
+                    </mat-form-field>
+                    <!-- Error Message -->
+                    <mat-form-field appearance="outline" class="form-field-inline">
+                      <mat-label>{{ 'EQUIPMENT.upperBoundLabel' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.upperBoundLabel' | translate }}" formControlName="upperBound">
+                    </mat-form-field>
+                  </div>
+                  @if(formula.errors?.invalidBounds) {
+                    <mat-error>{{ 'EQUIPMENT.invalidBoundsError' | translate }}</mat-error>
+                  }
+  
+                  <!-- Second row: Coefficient A and B -->
+                  <div class="form-field-row">
+                    <mat-form-field appearance="outline" class="form-field-inline">
+                      <mat-label>{{ 'EQUIPMENT.coefALabel' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.coefALabel' | translate }}" formControlName="coefA">
+                    </mat-form-field>
+                    <mat-form-field appearance="outline" class="form-field-inline">
+                      <mat-label>{{ 'EQUIPMENT.constantBLabel' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.constantBLabel' | translate }}" formControlName="constantB">
+                    </mat-form-field>
+                  </div>
+                </div>
+              }
             </div>
-          </div>
           }
-        </div>
-        }
-      </section>
-      <section class="form-section">
-        <h2>Infomations complémentaires</h2>
-        <mat-form-field class="equipment-description" appearance="outline">
-          <mat-label>Description</mat-label>
-          <textarea matInput placeholder="Description" formControlName="description" rows="4"
-            autocomplete="off"></textarea>
-        </mat-form-field>
-      </section>
-
-      <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button"
-        [disabled]="!form.valid">Valider</button>
-      <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">Annuler</button>
-    </form>
-  </div>
-  }
\ No newline at end of file
+        </section>
+  
+        <section class="form-section">
+          <h2>{{ 'EQUIPMENT.additionalInfoTitle' | translate }}</h2>
+          <mat-form-field class="equipment-description" appearance="outline">
+            <mat-label>{{ 'EQUIPMENT.descriptionLabel' | translate }}</mat-label>
+            <textarea matInput placeholder="{{ 'EQUIPMENT.descriptionLabel' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea>
+          </mat-form-field>
+        </section>
+  
+        <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.submitButton' | translate }}</button>
+        <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.cancelButton' | translate }}</button>
+      </form>
+    </div>
+  }
+  
\ No newline at end of file
diff --git a/src/app/views/equipment/equipment.component.ts b/src/app/views/equipment/equipment.component.ts
index c944ab1..ee043ab 100644
--- a/src/app/views/equipment/equipment.component.ts
+++ b/src/app/views/equipment/equipment.component.ts
@@ -25,13 +25,14 @@ import { boundsValidator } from '../../tools/Vallidators/propellerFormulaBoundsV
 import { ActivatedRoute, Router } from '@angular/router';
 import { Session } from '../../models/session';
 import { DialogWarningMaterialAssociatedToGaugingComponent } from '../../components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component';
+import { TranslateModule } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-equipment',
   standalone: true,
   templateUrl: './equipment.component.html',
   styleUrl: './equipment.component.scss',
-  imports: [ReactiveFormsModule, FormsModule, CommonModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent]
+  imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, DragDropModule, MatIconModule, ErrorMessageComponent]
 })
 
 export class EquipmentComponent extends AbstractFormComponent {
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 89561fa..97b37ed 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -1,40 +1,76 @@
 {
-    "TOOLBAR": {
-      "MENU": "Menu",
-      "TITLE": "Moulinet",
-      "SEARCH": "Search",
-      "HELP": "Help"
+  "TOOLBAR": {
+    "MENU": "Menu",
+    "TITLE": "Moulinet",
+    "SEARCH": "Search",
+    "HELP": "Help"
+  },
+  "SIDENAV": {
+    "MATERIAL": "Equipment",
+    "GAUGING_LIST": "List of Gaugings",
+    "NEW_GAUGING": "New Gauging",
+    "RESET_SESSION": "Reset Session",
+    "LOAD_SESSION": "Load Session",
+    "SAVE_SESSION": "Save Session",
+    "CONFIGURATION": "Configuration",
+    "DOCUMENTATION": "Documentation"
+  },
+  "BUTTONS": {
+    "CREATE_NEW_GAUGING": "Create New Gauging",
+    "RESET_SESSION": "Reset Session",
+    "LOAD_SESSION": "Load Session",
+    "SAVE_SESSION": "Save Session"
+  },
+  "GAUGING": {
+    "LIST_TITLE": "Gauging List",
+    "ADD_GAUGING": "Add Gauging",
+    "COLUMNS": {
+      "WATERCOURSE": "Watercourse",
+      "DEPARTMENT": "Department",
+      "MUNICIPALITY": "Municipality",
+      "LOCALITY": "Locality",
+      "DATE": "Date",
+      "STATE": "State",
+      "ACTIONS": "Actions"
     },
-    "SIDENAV": {
-      "MATERIAL": "Equipment",
-      "GAUGING_LIST": "List of Gaugings",
-      "NEW_GAUGING": "New Gauging",
-      "RESET_SESSION": "Reset Session",
-      "LOAD_SESSION": "Load Session",
-      "SAVE_SESSION": "Save Session",
-      "CONFIGURATION": "Configuration",
-      "DOCUMENTATION": "Documentation"
+    "VALIDATED": "Validated",
+    "NO_GAUGING": "No gauging has been carried out or is in progress."
+  },
+  "EQUIPMENT": {
+    "materialListTitle": "Material List",
+    "addMaterialButton": "Add",
+    "noMaterialAvailable": "No material available.",
+    "actionsColumn": "Actions",
+    "nameColumn": "Name",
+    "typeColumn": "Type",
+    "serialNumberColumn": "Serial Number",
+    "descriptionColumn": "Description",
+    "editButton": "Edit",
+    "deleteButton": "Delete",
+    "newMaterialTitle": "New Material",
+    "editMaterialTitle": "Edit Material",
+    "materialTypeLabel": "Material Type",
+    "materialTypes": {
+      "ElectromagneticFlowMeter": "Electromagnetic Flow Meter",
+      "PropellerFlowMeter": "Propeller Flow Meter",
+      "VelocityHeadRod": "Velocity Head Rod"
     },
-    "BUTTONS": {
-      "CREATE_NEW_GAUGING": "Create New Gauging",
-      "RESET_SESSION": "Reset Session",
-      "LOAD_SESSION": "Load Session",
-      "SAVE_SESSION": "Save Session"
-    },
-    "GAUGING": {
-      "LIST_TITLE": "Gauging List",
-      "ADD_GAUGING": "Add Gauging",
-      "COLUMNS": {
-        "WATERCOURSE": "Watercourse",
-        "DEPARTMENT": "Department",
-        "MUNICIPALITY": "Municipality",
-        "LOCALITY": "Locality",
-        "DATE": "Date",
-        "STATE": "State",
-        "ACTIONS": "Actions"
-      },
-      "VALIDATED": "Validated",
-      "NO_GAUGING": "No gauging has been carried out or is in progress."
-    }
+    "modelSectionTitle": "Model",
+    "nameLabel": "Name",
+    "serialNumberLabel": "Serial Number",
+    "propellerNumberLabel": "Propeller Number",
+    "propellerSerialNumberLabel": "Propeller Serial Number",
+    "velocityFormulaCountLabel": "Number of Velocity Formulas",
+    "velocityFormulaTitle": "Velocity Formula n°",
+    "lowerBoundLabel": "Lower Bound",
+    "upperBoundLabel": "Upper Bound",
+    "coefALabel": "Coefficient A",
+    "constantBLabel": "Constant B",
+    "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.",
+    "requiredNameError": "The name is required.",
+    "additionalInfoTitle": "Additional information",
+    "descriptionLabel": "Description",
+    "submitButton": "Submit",
+    "cancelButton": "Cancel"
   }
-  
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 1997953..ea92bc4 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -1,40 +1,76 @@
 {
-    "TOOLBAR": {
-      "MENU": "Menu",
-      "TITLE": "Moulinet",
-      "SEARCH": "Rechercher",
-      "HELP": "Aide"
+  "TOOLBAR": {
+    "MENU": "Menu",
+    "TITLE": "Moulinet",
+    "SEARCH": "Rechercher",
+    "HELP": "Aide"
+  },
+  "SIDENAV": {
+    "MATERIAL": "Matériel",
+    "GAUGING_LIST": "Liste des jaugeages",
+    "NEW_GAUGING": "Nouveau jaugeage",
+    "RESET_SESSION": "Réinitialiser la session",
+    "LOAD_SESSION": "Charger une session",
+    "SAVE_SESSION": "Enregistrer la session",
+    "CONFIGURATION": "Configuration",
+    "DOCUMENTATION": "Documentation"
+  },
+  "BUTTONS": {
+    "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage",
+    "RESET_SESSION": "Réinitialiser la session",
+    "LOAD_SESSION": "Charger une session",
+    "SAVE_SESSION": "Enregistrer la session"
+  },
+  "GAUGING": {
+    "LIST_TITLE": "Liste des Jaugeages",
+    "ADD_GAUGING": "Ajouter un jaugeage",
+    "COLUMNS": {
+      "WATERCOURSE": "Cours d'eau",
+      "DEPARTMENT": "Département",
+      "MUNICIPALITY": "Commune",
+      "LOCALITY": "Lieu-dit",
+      "DATE": "Date",
+      "STATE": "État",
+      "ACTIONS": "Actions"
     },
-    "SIDENAV": {
-      "MATERIAL": "Matériel",
-      "GAUGING_LIST": "Liste des jaugeages",
-      "NEW_GAUGING": "Nouveau jaugeage",
-      "RESET_SESSION": "Réinitialiser la session",
-      "LOAD_SESSION": "Charger une session",
-      "SAVE_SESSION": "Enregistrer la session",
-      "CONFIGURATION": "Configuration",
-      "DOCUMENTATION": "Documentation"
+    "VALIDATED": "Validé",
+    "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation."
+  },
+  "EQUIPMENT": {
+    "materialListTitle": "Liste de Matériel",
+    "addMaterialButton": "Ajouter",
+    "noMaterialAvailable": "Aucun matériel disponible.",
+    "actionsColumn": "Actions",
+    "nameColumn": "Nom",
+    "typeColumn": "Type",
+    "serialNumberColumn": "Numéro de Série",
+    "descriptionColumn": "Description",
+    "editButton": "Modifier",
+    "deleteButton": "Supprimer",
+    "newMaterialTitle": "Nouveau Matériel",
+    "editMaterialTitle": "Modifier Matériel",
+    "materialTypeLabel": "Type de Matériel",
+    "materialTypes": {
+      "ElectromagneticFlowMeter": "Courantomètre Électromagnétique",
+      "PropellerFlowMeter": "Moulinet",
+      "VelocityHeadRod": "Perche à Charge Dynamique Transparente"
     },
-    "BUTTONS": {
-      "CREATE_NEW_GAUGING": "Créer un nouveau jaugeage",
-      "RESET_SESSION": "Réinitialiser la session",
-      "LOAD_SESSION": "Charger une session",
-      "SAVE_SESSION": "Enregistrer la session"
-    },
-    "GAUGING": {
-      "LIST_TITLE": "Liste des Jaugeages",
-      "ADD_GAUGING": "Ajouter un jaugeage",
-      "COLUMNS": {
-        "WATERCOURSE": "Cours d'eau",
-        "DEPARTMENT": "Département",
-        "MUNICIPALITY": "Commune",
-        "LOCALITY": "Lieu-dit",
-        "DATE": "Date",
-        "STATE": "État",
-        "ACTIONS": "Actions"
-      },
-      "VALIDATED": "Validé",
-      "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation."
-    }
+    "modelSectionTitle": "Modèle",
+    "nameLabel": "Nom",
+    "serialNumberLabel": "Numéro de Série",
+    "propellerNumberLabel": "Numéro de Moulinet",
+    "propellerSerialNumberLabel": "Numéro de Série du Moulinet",
+    "velocityFormulaCountLabel": "Nombre de Formules de Vitesse",
+    "velocityFormulaTitle": "Formule de Vitesse n°",
+    "lowerBoundLabel": "Limite Inférieure",
+    "upperBoundLabel": "Limite Supérieure",
+    "coefALabel": "Coefficient A",
+    "constantBLabel": "Constante B",
+    "invalidBoundsError": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.",
+    "requiredNameError": "Le nom est requis.",
+    "additionalInfoTitle": "Informations complémentaires",
+    "descriptionLabel": "Description",
+    "submitButton": "Valider",
+    "cancelButton": "Annuler"
   }
-  
\ No newline at end of file
+}
\ No newline at end of file
-- 
GitLab


From 81c76ac1df27c882f7f25ba5ea681defd7ed95ff Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Fri, 11 Oct 2024 15:37:33 +0000
Subject: [PATCH 04/16] fix: translate gauging component in progress Refs #6

---
 src/app/app.component.ts                      |   2 +-
 .../gauging-list/gauging-list.component.html  |  14 +-
 src/app/views/gauging/gauging.component.html  | 143 +++++++++---------
 src/app/views/gauging/gauging.component.ts    |   3 +-
 src/assets/i18n/en.json                       | 143 ++++++++++++------
 src/assets/i18n/fr.json                       |  70 +++++++--
 6 files changed, 236 insertions(+), 139 deletions(-)

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index a51cede..234d7d0 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -46,7 +46,7 @@ export class AppComponent {
     this.gaugingList$ = this.gaugingService.gaugingList$;
     this.translate.addLangs(['fr', 'en']);
     this.translate.setDefaultLang('fr');
-    this.translate.use('en');
+    this.translate.use('fr');
   }
 
   ngOnInit(): void {
diff --git a/src/app/views/gauging-list/gauging-list.component.html b/src/app/views/gauging-list/gauging-list.component.html
index a4dd044..1b55a0b 100644
--- a/src/app/views/gauging-list/gauging-list.component.html
+++ b/src/app/views/gauging-list/gauging-list.component.html
@@ -12,43 +12,43 @@
        
         <!-- Watercourse Column -->
        <ng-container matColumnDef="watercourse">
-        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.WATERCOURSE' | translate }} </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.WATERCOURSE' | translate }} </th>
         <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)" > {{ gauging.watercourse || '-' }} </td>
       </ng-container>
 
        <!-- Department Column -->
        <ng-container matColumnDef="department">
-        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DEPARTMENT' | translate }} </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPARTMENT' | translate }} </th>
         <td mat-cell *matCellDef="let gauging"(click)="editGauging(gauging)" > {{ gauging.department || '-' }} </td>
       </ng-container>
 
       <!-- Municipality Column -->
       <ng-container matColumnDef="municipality">
-          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.MUNICIPALITY' | translate }} </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.MUNICIPALITY' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.municipality || '-' }} </td>
       </ng-container>
 
       <!-- Locality Column -->
       <ng-container matColumnDef="locality">
-          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.LOCALITY' | translate }} </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.LOCALITY' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.locality || '-' }} </td>
       </ng-container>
 
       <!-- Date Column -->
       <ng-container matColumnDef="date">
-          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.DATE' | translate }} </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DATE' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ gauging.date | date: 'dd/MM/yyyy' }}</td>
       </ng-container>
 
       <!-- State Column -->
       <ng-container matColumnDef="state">
-          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.STATE' | translate }} </th>
+          <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.STATE' | translate }} </th>
           <td mat-cell *matCellDef="let gauging" (click)="editGauging(gauging)"> {{ 'GAUGING.VALIDATED' | translate }} </td>
       </ng-container>
 
       <!-- Actions Column -->
       <ng-container matColumnDef="actions">
-        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.COLUMNS.ACTIONS' | translate }} </th>
+        <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ACTIONS' | translate }} </th>
         <td mat-cell *matCellDef="let gauging, , let i =index">
           <button mat-icon-button color="primary" (click)="editGauging(gauging)">
               <mat-icon class="edit-button">edit</mat-icon>
diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html
index 5d00a06..0c016fe 100644
--- a/src/app/views/gauging/gauging.component.html
+++ b/src/app/views/gauging/gauging.component.html
@@ -1,31 +1,31 @@
 <mat-tab-group #tabGroup animationDuration="0ms">
 
   <!-- Tab1: Création/édition d'un jaugeage -->
-  <mat-tab label="Description du jaugeage">
+  <mat-tab label="{{ 'GAUGING.DESCRIPTION' | translate }}">
     <div class="tab-content">
-      <h2>Description du jaugeage</h2>
+      <h2><mat-label>{{ 'GAUGING.DESCRIPTION' | translate }}</mat-label></h2>
       <form [formGroup]="descriptionForm">
         <!-- Localisation Section -->
         <mat-card class="form-section">
-          <mat-card-title class="card-title"><mat-icon>location_on</mat-icon>Localisation</mat-card-title>
+          <mat-card-title class="card-title"><mat-icon>location_on</mat-icon>{{ 'GAUGING.LOCATION' | translate }}</mat-card-title>
           <mat-card-content>
             <div class="form-row">
               <mat-form-field appearance="outline">
-                <mat-label>Cours d'eau</mat-label>
+                <mat-label>{{ 'GAUGING.WATERCOURSE' | translate }}</mat-label>
                 <input matInput formControlName="watercourse">
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Lieu-dit</mat-label>
+                <mat-label>{{ 'GAUGING.LOCALITY' | translate }}</mat-label>
                 <input matInput formControlName="locality">
               </mat-form-field>
             </div>
             <div class="form-row">
               <mat-form-field appearance="outline">
-                <mat-label>Commune</mat-label>
+                <mat-label>{{ 'GAUGING.MUNICIPALITY' | translate }}</mat-label>
                 <input matInput formControlName="municipality">
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Département</mat-label>
+                <mat-label>{{ 'GAUGING.DEPARTMENT' | translate }}</mat-label>
                 <input matInput formControlName="department">
               </mat-form-field>
             </div>
@@ -34,7 +34,7 @@
 
         <!-- Géolocalisation Section -->
         <mat-card class="form-section">
-          <mat-card-title class="card-title"><mat-icon>my_location</mat-icon>Géolocalisation</mat-card-title>
+          <mat-card-title class="card-title"><mat-icon>my_location</mat-icon>{{ 'GAUGING.GEOLOCATION' | translate }}</mat-card-title>
           <mat-card-content>
             <div class="form-row">
               <mat-form-field appearance="outline">
@@ -47,11 +47,11 @@
                 </mat-select>
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Point X</mat-label>
+                <mat-label>{{ 'GAUGING.X_LOCATION' | translate }}</mat-label>
                 <input matInput formControlName="locationX" type="number" step="0.01">
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Point Y</mat-label>
+                <mat-label>{{ 'GAUGING.Y_LOCATION' | translate }}</mat-label>
                 <input matInput formControlName="locationY" type="number" step="0.01">
               </mat-form-field>
             </div>
@@ -61,24 +61,24 @@
         <!-- Date/time section -->
         <mat-card class="form-section">
           <mat-card-title class="card-title">
-            <mat-icon>access_time</mat-icon> Date/Heure
+            <mat-icon>access_time</mat-icon> {{ 'GAUGING.DATE_TIME' | translate }}
           </mat-card-title>
           <mat-card-content>
             <div class="form-row">
               <mat-form-field appearance="outline">
-                <mat-label>Date</mat-label>
+                <mat-label>{{ 'GAUGING.DATE' | translate }}</mat-label>
                 <input matInput [matDatepicker]="picker" formControlName="date">
                 <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                 <mat-datepicker #picker></mat-datepicker>
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Heure de début</mat-label>
+                <mat-label>{{ 'GAUGING.START_TIME' | translate }}</mat-label>
                 <input matInput formControlName="timeStart" [format]="24" [max]="getMaxTimeStart()"
                   [ngxTimepicker]="startTimePicker">
                 <ngx-material-timepicker #startTimePicker></ngx-material-timepicker>
               </mat-form-field>
               <mat-form-field appearance="outline">
-                <mat-label>Heure de fin</mat-label>
+                <mat-label>{{ 'GAUGING.END_TIME' | translate }}</mat-label>
                 <input matInput formControlName="timeEnd" [format]="24" [min]="descriptionForm.get('timeStart')?.value"
                   [ngxTimepicker]="endTimePicker">
                 <ngx-material-timepicker #endTimePicker></ngx-material-timepicker>
@@ -91,7 +91,7 @@
         <mat-card class="form-section">
           <mat-card-title class="card-title">
             <div class="card-title-with-button">
-              <mat-icon>person</mat-icon> Opérateurs
+              <mat-icon>person</mat-icon> {{ 'GAUGING.OPERATORS' | translate }}
               <button mat-mini-fab color="primary" (click)="addOperatorField()"
                 class="add-button"><mat-icon>add</mat-icon></button>
               @if(operatorNames.length > 2) {
@@ -106,7 +106,7 @@
               @for (operator of operatorNames.controls; track operator; let i = $index) {
               <div [formGroupName]="i" class="operator-form-field">
                 <mat-form-field appearance="outline">
-                  <mat-label>Opérateur {{i + 1}}</mat-label>
+                  <mat-label>{{ 'GAUGING.OPERATOR' | translate }} {{i + 1}}</mat-label>
                   <input matInput formControlName="name">
                 </mat-form-field>
               </div>
@@ -118,12 +118,12 @@
         <!-- Observations section -->
         <mat-card class="form-section">
           <mat-card-title class="card-title">
-            <mat-icon>book</mat-icon> Observations
+            <mat-icon>book</mat-icon> {{ 'GAUGING.OBSERVATIONS' | translate }}
           </mat-card-title>
           <mat-card-content>
             <div class="form-row">
               <mat-form-field appearance="outline" class="full-width">
-                <mat-label>Observation</mat-label>
+                <mat-label>{{ 'GAUGING.OBSERVATION' | translate }}</mat-label>
                 <textarea matInput formControlName="observations" rows="4"></textarea>
               </mat-form-field>
             </div>
@@ -134,7 +134,7 @@
         <mat-card class="form-section">
           <mat-card-title class="card-title">
             <div class="card-title-with-button">
-              <mat-icon>brightness_1</mat-icon> Granulométrie Représentative
+              <mat-icon>brightness_1</mat-icon> {{ 'GAUGING.REPRESENTATIVE_GRAIN_SIZE' | translate }}
               <button mat-mini-fab color="primary" (click)="addGrainSizeField()"
                 class="add-button"><mat-icon>add</mat-icon>
               </button>
@@ -149,8 +149,8 @@
             <div class="grainSize-container">
               @for (grainsize of grainSizesArray.controls; track grainsize; let i = $index) {
               <div [formGroupName]="i" class="grainSize-form-field">
-                <mat-form-field appearance="outline" class="full-width" placeholder="Granulométrie">
-                  <mat-label>{{ i === 0 ? 'Dominante' : 'Accessoire ' + i }}</mat-label>
+                <mat-form-field appearance="outline" class="full-width">
+                  <mat-label>{{ i === 0 ? ('GAUGING.DOMINANT_GRAIN_SIZE' | translate) : ('GAUGING.ACCESSORY_GRAIN_SIZE' | translate) + ' ' + i }}</mat-label>
                   <mat-select formControlName="size" disableRipple>
                     @for (size of grainSizes; track size) {
                     <mat-option [value]="size">
@@ -167,25 +167,24 @@
 
         <!-- Boutons Précédent et Suivant -->
         <div class="form-buttons">
-          <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">Suivant</button>
+          <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">{{ 'NEXT' | translate }}</button>
         </div>
       </form>
     </div>
   </mat-tab>
 
   <!-- Paramètres -->
-  <mat-tab label="Paramètres du jaugeage">
+  <mat-tab label="{{ 'GAUGING.PARAMETERS' | translate }}">
     <div class="tab-content">
-      <h2>Paramètres du jaugeage</h2>
+      <h2>{{ 'GAUGING.PARAMETERS' | translate }}</h2>
       <form [formGroup]="parametersForm">
 
         <!-- Largeur de la section -->
         <mat-card class="form-section">
-          <mat-card-title class="card-title"><mat-icon>aspect_ratio</mat-icon>Largeur de la
-            section</mat-card-title>
+          <mat-card-title class="card-title"><mat-icon>aspect_ratio</mat-icon>{{ 'GAUGING.SECTION_WIDTH' | translate }}</mat-card-title>
           <mat-card-content class="form-row">
             <mat-form-field appearance="outline">
-              <mat-label>Largeur (m)</mat-label>
+              <mat-label>{{ 'GAUGING.WIDTH' | translate }}(m)</mat-label>
               <input matInput formControlName="sectionWidth" type="number" step="0.01">
             </mat-form-field>
           </mat-card-content>
@@ -193,14 +192,14 @@
 
         <!-- Hauteur d'eau en rive -->
         <mat-card class="form-section">
-          <mat-card-title class="card-title"><mat-icon>waves</mat-icon>Hauteur d'eau en rive</mat-card-title>
+          <mat-card-title class="card-title"><mat-icon>waves</mat-icon>{{ 'GAUGING.HEIGHT_BANK_WATER' | translate }}</mat-card-title>
           <mat-card-content class="form-row">
             <mat-form-field appearance="outline">
-              <mat-label>Hauteur d'eau rive gauche (m)</mat-label>
+              <mat-label>{{ 'GAUGING.HEIGHT_BANK_LEFT' | translate }} (m)</mat-label>
               <input matInput formControlName="heightBankLeft" type="number" step="0.01">
             </mat-form-field>
             <mat-form-field appearance="outline">
-              <mat-label>Hauteur d'eau rive droite (m)</mat-label>
+              <mat-label>{{ 'GAUGING.HEIGHT_BANK_RIGHT' | translate }} (m)</mat-label>
               <input matInput formControlName="heightBankRight" type="number" step="0.01">
             </mat-form-field>
           </mat-card-content>
@@ -208,8 +207,7 @@
 
         <!-- Origine des mesures -->
         <mat-card class="form-section">
-          <mat-card-title class="card-title"><mat-icon>gps_fixed</mat-icon>Origine des
-            mesures</mat-card-title>
+          <mat-card-title class="card-title"><mat-icon>gps_fixed</mat-icon>{{ 'GAUGING.ORIGIN_MEASURES' | translate }}</mat-card-title>
           <mat-card-content class="form-row">
             <div>
               <mat-radio-group formControlName="originMeasures">
@@ -226,19 +224,19 @@
         <!-- Type de matériel -->
         <mat-card class="form-section">
           <mat-card-title class="card-title"><mat-icon>construction</mat-icon>
-            Type de matériel</mat-card-title>
+            {{ 'GAUGING.ORIGIN_MEASURES' | translate }}</mat-card-title>
           <mat-card-content class="form-row">
             @if((materialList$ | async)?.length! > 0){
             <mat-radio-group formControlName="materialType" (change)="onChangeMaterialType()" style="width: 50%;">
               @for (type of materielTypes; track type) {
               <mat-radio-button [value]="type" color="primary">
-                {{type}}
+                {{type | translate}}
               </mat-radio-button>
               }
             </mat-radio-group>
             @if(filteredMaterials?.length) {
             <mat-form-field appearance="outline" class="full-width">
-              <mat-label>Choix du matériel</mat-label>
+              <mat-label>{{ 'GAUGING.MATERIAL_CHOICE' | translate }}</mat-label>
               <mat-select formControlName="materialId" (selectionChange)="onChangeMaterial()">
                 @for (material of filteredMaterials ; track material.id) {
                 <mat-option [value]="material.id">{{material.name}} ( n°{{material.serialNumber}} )</mat-option>
@@ -249,14 +247,14 @@
             }
             @else {
             <div class="no-material-message" (click)="openMaterialForm()">
-              <p>Aucun matériel de ce type</p>
+              <p>{{ 'NO_AVALAIBLE_MATERIAL' | translate }}</p>
               <button mat-mini-fab color="primary"><mat-icon>add</mat-icon></button>
             </div>
             }
             }
             @else {
             <div class="no-material-message" (click)="openMaterialForm()">
-              <p>Veuillez ajouter d'abord le matériel</p>
+              <p>{{ 'NEED_MATERIAL' | translate }}</p>
               <button mat-mini-fab color="primary"><mat-icon>add</mat-icon></button>
             </div>
             }
@@ -266,23 +264,23 @@
 
 
         <div class="form-buttons">
-          <button mat-raised-button color="primary" type="button" (click)="selectPreviousTab()">Précédent</button>
-          <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">Suivant</button>
+          <button mat-raised-button color="primary" type="button" (click)="selectPreviousTab()">{{ 'PREVIOUS' | translate }}</button>
+          <button mat-raised-button color="primary" type="button" (click)="selectNextTab()">{{ 'NEXT' | translate }}</button>
         </div>
       </form>
     </div>
   </mat-tab>
 
   <!-- Saisies des mesures -->
-  <mat-tab label="Saisie des mesures" ngSkipHydration [disabled]="!this.selectedMaterialId">
+  <mat-tab label="{{ 'GAUGING.TAB_MEASUREMENTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId">
     <div class="tab-content">
-      <h2>Saisie des mesures</h2>
+      <h2>{{ 'GAUGING.TAB_MEASUREMENTS' | translate }}</h2>
       <div class="vertical-section-container">
         <!-- Verticales -->
         <mat-card class="form-section">
           <mat-card-title class="vertical-card-title">
             <mat-icon> vertical_align_bottom</mat-icon>
-            Verticales
+            {{ 'GAUGING.VERTICALS' | translate }}
             <button mat-mini-fab color="primary" (click)="addVertical()" class="add-button">
               <mat-icon>add</mat-icon>
             </button>
@@ -291,7 +289,8 @@
             <div formArrayName="verticals">
               <table mat-table [dataSource]="verticals.controls" #verticalsTable class="mat-elevation-z2">
                 <ng-container matColumnDef="verticalNumber">
-                  <th mat-header-cell *matHeaderCellDef class="vertical-number"> Verticales n° </th>
+                  <th mat-header-cell *matHeaderCellDef class="vertical-number"> {{ 'GAUGING.VERTICAL_NUMBER' | translate }}
+                  </th>
                   <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)"
                     class="vertical-number" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
@@ -303,17 +302,17 @@
 
                 <!-- Repeat for other columns -->
                 <ng-container matColumnDef="distanceFromBank">
-                  <th mat-header-cell *matHeaderCellDef> Distance à la rive (m) </th>
+                  <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BANK' | translate }} </th>
                   <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
                                       'deleting': i === deletingRowIndex
                                     }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)">
                     <div [formGroupName]="i">
                       <mat-form-field appearance="outline" class="vertical-table-field">
-                        <input matInput formControlName="distanceFromBank" placeholder="Distance" type="number"
+                        <input matInput formControlName="distanceFromBank" placeholder="{{ 'GAUGING.DISTANCE' | translate }}" type="number"
                        min="0">
                         @if(vertical.get('distanceFromBank')?.hasError('invalidDistanceFromBank')) {
-                        <mat-error>Distance invalide</mat-error>
+                        <mat-error>{{ 'GAUGING.INVALID_DISTANCE' | translate }}</mat-error>
                         }
                       </mat-form-field>
 
@@ -323,14 +322,14 @@
 
                 <!-- Repeat for other columns -->
                 <ng-container matColumnDef="depth">
-                  <th mat-header-cell *matHeaderCellDef> Profondeur (m) </th>
+                  <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPTH' | translate }}</th>
                   <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
                                       'deleting': i === deletingRowIndex 
                                     }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)">
                     <div [formGroupName]="i">
                       <mat-form-field appearance="outline" class="vertical-table-field">
-                        <input matInput formControlName="depth" placeholder="Profondeur" type="number" step="1" min="0">
+                        <input matInput formControlName="depth" placeholder="{{ 'GAUGING.DEPTH' | translate }}" type="number" step="1" min="0">
                       </mat-form-field>
                     </div>
                   </td>
@@ -338,14 +337,14 @@
 
                 <!-- Repeat for other columns -->
                 <ng-container matColumnDef="duration">
-                  <th mat-header-cell *matHeaderCellDef> Durée(s) </th>
+                  <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DURATION' | translate }} </th>
                   <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
                                       'deleting': i === deletingRowIndex
                                     }" (focusin)="onRowFocusIn(i)" (focusout)="onRowFocusOut(i)">
                     <div [formGroupName]="i">
                       <mat-form-field appearance="outline" class="vertical-table-field">
-                        <input matInput formControlName="duration" placeholder="Durée" type="number" step="1" min="0">
+                        <input matInput formControlName="duration" placeholder="{{ 'GAUGING.DURATION' | translate }}" type="number" step="1" min="0">
                       </mat-form-field>
                     </div>
                   </td>
@@ -353,7 +352,7 @@
 
                 <!-- Repeat for other columns -->
                 <ng-container matColumnDef="numberOfPoint">
-                  <th mat-header-cell *matHeaderCellDef> Nombre de points </th>
+                  <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.NUMBER_OF_POINTS' | translate }} </th>
                   <td mat-cell *matCellDef="let vertical; let i = index" (click)="onVerticalUpdate(i)" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
                                       'deleting': i === deletingRowIndex
@@ -368,7 +367,7 @@
                 </ng-container>
 
                 <ng-container matColumnDef="delete">
-                  <th mat-header-cell *matHeaderCellDef> Actions </th>
+                  <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ACTIONS' | translate }} </th>
                   <td mat-cell *matCellDef="let vertical; let i = index" [ngClass]="{
                                       'selected-vertical': i === selectedVerticalIndex && i !== deletingRowIndex,
                                       'deleting': i === deletingRowIndex
@@ -397,7 +396,7 @@
         <mat-card class="form-section">
           <mat-card-title class="vertical-card-title">
             <mat-icon>gps_fixed</mat-icon>
-            Mesures sur la verticale n°{{ selectedVerticalIndex + 1 }}
+            {{ 'GAUGING.MEASUREMENTS_ON_VERTICAL' | translate }} {{ selectedVerticalIndex + 1 }}
           </mat-card-title>
           <mat-card-content [formGroup]="verticalsForm">
             <div formArrayName="verticals">
@@ -407,12 +406,12 @@
                     class="mat-elevation-z2" #verticalMeasurementsTable>
                     <!-- Distance From Bottom Column -->
                     <ng-container matColumnDef="distanceFromBottom">
-                      <th mat-header-cell *matHeaderCellDef> Distance du fond (m) </th>
+                      <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BOTTOM' | translate }} </th>
                       <td mat-cell *matCellDef="let measurement; let i = index"
                         (click)="onVerticalMeasurementUpdate(i)">
                         <div [formGroupName]="i">
                           <mat-form-field appearance="outline" class="vertical-table-field">
-                            <input matInput formControlName="distanceFromBottom" placeholder="Distance" min="0"
+                            <input matInput formControlName="distanceFromBottom" placeholder="{{ 'GAUGING.DISTANCE' | translate }}" min="0"
                               readonly="readonly">
                           </mat-form-field>
                         </div>
@@ -421,12 +420,12 @@
 
                     <!-- Speed Column -->
                     <ng-container matColumnDef="speed">
-                      <th mat-header-cell *matHeaderCellDef> Vitesse (m/s) </th>
+                      <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.SPEED' | translate }} </th>
                       <td mat-cell *matCellDef="let measurement; let i = index"
                         (click)="onVerticalMeasurementUpdate(i)">
                         <div [formGroupName]="i">
                           <mat-form-field appearance="outline" class="vertical-table-field">
-                            <input matInput formControlName="speed" placeholder="Vitesse" type="number" step="0.01"
+                            <input matInput formControlName="speed" placeholder="{{ 'GAUGING.SPEED' | translate }}" type="number" step="0.01"
                               min="0">
                           </mat-form-field>
                         </div>
@@ -435,7 +434,7 @@
 
                     <!-- Rotation Column (Conditionnelle) -->
                     <ng-container matColumnDef="rotations">
-                      <th mat-header-cell *matHeaderCellDef> Rotations </th>
+                      <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.ROTATIONS' | translate }} </th>
                       <td mat-cell *matCellDef="let measurement; let i = index"
                         (click)="onVerticalMeasurementUpdate(i)">
                         <div [formGroupName]="i">
@@ -463,18 +462,18 @@
 
 
   <!-- Résultats -->
-  <mat-tab label="Résultats" ngSkipHydration [disabled]="!this.selectedMaterialId">
+  <mat-tab label="{{ 'GAUGING.TAB_RESULTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId">
     <div class="tab-content">
-      <h2>Résultats</h2>
+      <h2>{{ 'RESULTS.TAB_RESULTS' | translate }}</h2>
       <!-- Résultats par verticale -->
       <mat-card class="form-section">
         <mat-card-title class="vertical-card-title">
-          <mat-icon>equalizer</mat-icon> Résultats par verticale
+          <mat-icon>equalizer</mat-icon> {{ 'GAUGING.RESULTS_PER_VERTICAL' | translate }}
         </mat-card-title>
         <mat-card-content>
           <table mat-table [dataSource]="verticalResults" class="mat-elevation-z2">
             <ng-container matColumnDef="verticalNumber">
-              <th mat-header-cell *matHeaderCellDef class="vertical-number"> Verticales n° </th>
+              <th mat-header-cell *matHeaderCellDef class="vertical-number"> {{ 'GAUGING.VERTICAL_NUMBER' | translate }} </th>
               <td mat-cell *matCellDef="let vertical; let i = index" class="vertical-number">
                 {{i+1}}
               </td>
@@ -482,33 +481,33 @@
 
             <!-- Distance from Bank Column -->
             <ng-container matColumnDef="distanceFromBank">
-              <th mat-header-cell *matHeaderCellDef> Distance à la rive (m) </th>
+              <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DISTANCE_FROM_BANK' | translate }} </th>
               <td mat-cell *matCellDef="let vertical"> {{vertical.distanceFromBank}} </td>
             </ng-container>
 
             <!-- Depth Column -->
             <ng-container matColumnDef="depth">
-              <th mat-header-cell *matHeaderCellDef> Profondeur (m) </th>
+              <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.DEPTH' | translate }} </th>
               <td mat-cell *matCellDef="let vertical"> {{vertical.depth}} </td>
             </ng-container>
 
             <!-- Speed Column -->
             <ng-container matColumnDef="speed">
-              <th mat-header-cell *matHeaderCellDef> Vitesse moyenne (m/s) </th>
+              <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.AVERAGE_SPEED' | translate }} </th>
               <td mat-cell *matCellDef="let vertical" style="font-weight: bold; color:#735fff ">
                 {{vertical.averageSpeed.toFixed(3)}} </td>
             </ng-container>
 
             <!-- Surface Column -->
             <ng-container matColumnDef="surface">
-              <th mat-header-cell *matHeaderCellDef> Surface (m²) </th>
+              <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.SURFACE' | translate }} </th>
               <td mat-cell *matCellDef="let vertical; let i = index" class="surface-cell"
                 style="font-weight: bold; color:#00a3a6;"> {{ vertical.surface.toFixed(3) }}</td>
             </ng-container>
 
             <!-- Flow Column -->
             <ng-container matColumnDef="flow">
-              <th mat-header-cell *matHeaderCellDef> Débit (m³/s) </th>
+              <th mat-header-cell *matHeaderCellDef> {{ 'GAUGING.FLOW' | translate }}  </th>
               <td mat-cell *matCellDef="let vertical; let i = index" style="font-weight: bold; color:#ff6347;">
                 {{vertical.flow.toFixed(3)}}</td>
             </ng-container>
@@ -525,23 +524,23 @@
       <!-- Résultats globaux -->
       <mat-card class="form-section">
         <mat-card-title class="vertical-card-title">
-          <mat-icon>assessment</mat-icon> Résultats globaux du jaugeage
+          <mat-icon>assessment</mat-icon>{{ 'GAUGING.OVERALL_GAUGING_RESULTS' | translate }}
         </mat-card-title>
         <mat-card-content>
           <div class="global-results-grid">
             <div class="global-result-card">
               <mat-icon class="result-icon">crop_square</mat-icon>
-              <h3>Surface totale</h3>
+              <h3>{{ 'GAUGING.TOTAL_SURFACE' | translate }}</h3>
               <div class="result-value">{{ calculateTotalSurface(verticalResults).toFixed(3) }} m²</div>
             </div>
             <div class="global-result-card">
               <mat-icon class="result-icon">speed</mat-icon>
-              <h3>Vitesse moyenne</h3>
+              <h3>{{ 'GAUGING.AVERAGE_SPEED' | translate }}</h3>
               <div class="result-value">{{calculateAverageSpeedSection().toFixed(3)}} m/s</div>
             </div>
             <div class="global-result-card">
               <mat-icon class="result-icon">waves</mat-icon>
-              <h3>Débit total</h3>
+              <h3>{{ 'GAUGING.TOTAL_FLOW' | translate }}</h3>
               <div class="result-value">{{ calculateTotalFlow(verticalResults).toFixed(3) }} m³/s</div>
             </div>
           </div>
@@ -551,7 +550,7 @@
       <!-- Représentation graphique des champs de vitesse -->
       <mat-card class="form-section">
         <mat-card-title class="vertical-card-title">
-          <mat-icon>show_chart</mat-icon> Représentation des champs de vitesse
+          <mat-icon>show_chart</mat-icon> {{ 'GAUGING.GRAPHICAL_REPRESENTATION' | translate }}
         </mat-card-title>
         <mat-card-content>
           <!-- Placeholder for the graph -->
diff --git a/src/app/views/gauging/gauging.component.ts b/src/app/views/gauging/gauging.component.ts
index 9ef2c47..27b952e 100644
--- a/src/app/views/gauging/gauging.component.ts
+++ b/src/app/views/gauging/gauging.component.ts
@@ -34,12 +34,13 @@ import { Vertical } from '../../models/vertical';
 import { MaterialPropeller } from '../../models/material_propeller';
 import { rowsAnimation } from '../../tools/Animations/table-row-animation';
 import { animate, state, style, transition, trigger } from '@angular/animations';
+import { TranslateModule } from '@ngx-translate/core';
 Chart.register(...registerables)
 
 @Component({
   selector: 'app-gauging',
   standalone: true,
-  imports: [MatNativeDateModule, MatDatepickerModule, NgxMaterialTimepickerModule, MatTabsModule, ReactiveFormsModule, FormsModule, CommonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, MatIconModule, ErrorMessageComponent, BaseChartDirective,],
+  imports: [TranslateModule, MatNativeDateModule, MatDatepickerModule, NgxMaterialTimepickerModule, MatTabsModule, ReactiveFormsModule, FormsModule, CommonModule, MatCardModule, MatFormFieldModule, MatSelectModule, MatRadioModule, MatInputModule, MatButtonModule, MatTableModule, MatIconModule, ErrorMessageComponent, BaseChartDirective,],
   templateUrl: './gauging.component.html',
   styleUrls: ['./gauging.component.scss'],
   providers: [DatePipe],
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 97b37ed..75b1c9f 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -24,53 +24,102 @@
   "GAUGING": {
     "LIST_TITLE": "Gauging List",
     "ADD_GAUGING": "Add Gauging",
-    "COLUMNS": {
-      "WATERCOURSE": "Watercourse",
-      "DEPARTMENT": "Department",
-      "MUNICIPALITY": "Municipality",
-      "LOCALITY": "Locality",
-      "DATE": "Date",
-      "STATE": "State",
-      "ACTIONS": "Actions"
-    },
+    "WATERCOURSE": "Watercourse",
+    "DEPARTMENT": "Department",
+    "MUNICIPALITY": "Municipality",
+    "LOCALITY": "Locality",
+    "DATE": "Date",
+    "STATE": "State",
+    "ACTIONS": "Actions",
     "VALIDATED": "Validated",
-    "NO_GAUGING": "No gauging has been carried out or is in progress."
+    "NO_GAUGING": "No gauging has been carried out or is in progress.",
+    "DESCRIPTION": "Gauging description",
+    "LOCATION": "Location",
+    "GEOLOCATION": "Geolocation",
+    "X_LOCATION": "Point X",
+    "Y_LOCATION": "Point Y",
+    "DATE_TIME": "Date/Time",
+    "START_TIME": "Start time",
+    "END_TIME": "End time",
+    "OPERATORS": "Operators",
+    "OPERATOR": "Operator",
+    "OBSERVATIONS": "Observations",
+    "OBSERVATION": "Observation",
+    "REPRESENTATIVE_GRAIN_SIZE": "Representative grain size",
+    "DOMINANT_GRAIN_SIZE": "Dominant",
+    "ACCESSORY_GRAIN_SIZE": "Accessory",
+    "PARAMETERS": "Gauging parameters",
+    "SECTION_WIDTH": "Section width",
+    "WIDTH": "Width",
+    "HEIGHT_BANK_WATER": "Height of water on bank",
+    "HEIGHT_BANK_LEFT": "Height bank left",
+    "HEIGHT_BANK_RIGHT": "Height bank right",
+    "ORIGIN_MEASURES": "Origin of measures",
+    "MATERIAL_CHOICE": "Material choice",
+    "TAB_MEASUREMENTS": "Measurement entries",
+    "VERTICALS": "Verticals",
+    "VERTICAL_NUMBER": "Vertical n°",
+    "DISTANCE_FROM_BANK": "Distance from bank (m)",
+    "DEPTH": "Depth (m)",
+    "DURATION": "Duration (s)",
+    "NUMBER_OF_POINTS": "Number of points",
+    "INVALID_DISTANCE": "Distance from bank must be less than or equal to section width",
+    "MEASUREMENTS_ON_VERTICAL": "Measurements on vertical n°",
+    "DISTANCE_FROM_BOTTOM": "Distance from bottom (m)",
+    "SPEED": "Speed (m/s)",
+    "ROTATIONS": "Number of rotations",
+    "ROTATION_NUMBER": "Rotations",
+    "DISTANCE": "Distance",
+    "TAB_RESULTS": "Results",
+    "RESULTS_PER_VERTICAL": "Results by Vertical",
+    "AVERAGE_SPEED": "Average Speed (m/s)",
+    "SURFACE": "Surface Area (m²)",
+    "FLOW": "Flow Rate (m³/s)",
+    "OVERALL_GAUGING_RESULTS": "Overall gauging results",
+    "TOTAL_SURFACE": "Total Surface (m²)",
+    "AVERAGE_SPEED_GLOBAL": "Average Speed",
+    "TOTAL_FLOW": "Total Flow Rate (m³/s)",
+    "GRAPHICAL_REPRESENTATION": "Graphical representation"
+},
+"EQUIPMENT": {
+  "materialListTitle": "Material List",
+  "addMaterialButton": "Add",
+  "noMaterialAvailable": "No material available.",
+  "actionsColumn": "Actions",
+  "nameColumn": "Name",
+  "typeColumn": "Type",
+  "serialNumberColumn": "Serial Number",
+  "descriptionColumn": "Description",
+  "editButton": "Edit",
+  "deleteButton": "Delete",
+  "newMaterialTitle": "New Material",
+  "editMaterialTitle": "Edit Material",
+  "materialTypeLabel": "Material Type",
+  "materialTypes": {
+    "ElectromagneticFlowMeter": "Electromagnetic Flow Meter",
+    "PropellerFlowMeter": "Propeller Flow Meter",
+    "VelocityHeadRod": "Velocity Head Rod"
   },
-  "EQUIPMENT": {
-    "materialListTitle": "Material List",
-    "addMaterialButton": "Add",
-    "noMaterialAvailable": "No material available.",
-    "actionsColumn": "Actions",
-    "nameColumn": "Name",
-    "typeColumn": "Type",
-    "serialNumberColumn": "Serial Number",
-    "descriptionColumn": "Description",
-    "editButton": "Edit",
-    "deleteButton": "Delete",
-    "newMaterialTitle": "New Material",
-    "editMaterialTitle": "Edit Material",
-    "materialTypeLabel": "Material Type",
-    "materialTypes": {
-      "ElectromagneticFlowMeter": "Electromagnetic Flow Meter",
-      "PropellerFlowMeter": "Propeller Flow Meter",
-      "VelocityHeadRod": "Velocity Head Rod"
-    },
-    "modelSectionTitle": "Model",
-    "nameLabel": "Name",
-    "serialNumberLabel": "Serial Number",
-    "propellerNumberLabel": "Propeller Number",
-    "propellerSerialNumberLabel": "Propeller Serial Number",
-    "velocityFormulaCountLabel": "Number of Velocity Formulas",
-    "velocityFormulaTitle": "Velocity Formula n°",
-    "lowerBoundLabel": "Lower Bound",
-    "upperBoundLabel": "Upper Bound",
-    "coefALabel": "Coefficient A",
-    "constantBLabel": "Constant B",
-    "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.",
-    "requiredNameError": "The name is required.",
-    "additionalInfoTitle": "Additional information",
-    "descriptionLabel": "Description",
-    "submitButton": "Submit",
-    "cancelButton": "Cancel"
-  }
+  "modelSectionTitle": "Model",
+  "nameLabel": "Name",
+  "serialNumberLabel": "Serial Number",
+  "propellerNumberLabel": "Propeller Number",
+  "propellerSerialNumberLabel": "Propeller Serial Number",
+  "velocityFormulaCountLabel": "Number of Velocity Formulas",
+  "velocityFormulaTitle": "Velocity Formula n°",
+  "lowerBoundLabel": "Lower Bound",
+  "upperBoundLabel": "Upper Bound",
+  "coefALabel": "Coefficient A",
+  "constantBLabel": "Constant B",
+  "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.",
+  "requiredNameError": "The name is required.",
+  "additionalInfoTitle": "Additional information",
+  "descriptionLabel": "Description",
+  "submitButton": "Submit",
+  "cancelButton": "Cancel"
+},
+"NEXT": "Next",
+"PREVIOUS": "Previous",
+"NO_AVALAIBLE_MATERIAL": "No material of this type",
+"NEED_MATERIAL": "Please add the equipment first"
 }
\ No newline at end of file
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index ea92bc4..13a20fd 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -24,17 +24,61 @@
   "GAUGING": {
     "LIST_TITLE": "Liste des Jaugeages",
     "ADD_GAUGING": "Ajouter un jaugeage",
-    "COLUMNS": {
-      "WATERCOURSE": "Cours d'eau",
-      "DEPARTMENT": "Département",
-      "MUNICIPALITY": "Commune",
-      "LOCALITY": "Lieu-dit",
-      "DATE": "Date",
-      "STATE": "État",
-      "ACTIONS": "Actions"
-    },
+    "WATERCOURSE": "Cours d'eau",
+    "DEPARTMENT": "Département",
+    "MUNICIPALITY": "Commune",
+    "LOCALITY": "Lieu-dit",
+    "DATE": "Date",
+    "STATE": "État",
+    "ACTIONS": "Actions",
     "VALIDATED": "Validé",
-    "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation."
+    "NO_GAUGING": "Aucun jaugeage réalisé ou en cours de réalisation.",
+    "DESCRIPTION": "Description du jaugeage",
+    "LOCATION": "Localisation",
+    "GEOLOCATION": "Géolcalisation",
+    "X_LOCATION": "Point X",
+    "Y_LOCATION": "Point Y",
+    "DATE_TIME": "Date/Heure",
+    "START_TIME": "Heure de début",
+    "END_TIME": "End time",
+    "OPERATORS": "Operators",
+    "OPERATOR": "Operator",
+    "OBSERVATIONS": "Observations",
+    "OBSERVATION": "Observation",
+    "DOMINANT_GRAIN_SIZE": "Dominante",
+    "ACCESSORY_GRAIN_SIZE": "Accessoire",
+    "PARAMETERS": "Paramètres du jaugeage",
+    "SECTION_WIDTH": "Largeur de la section",
+    "WIDTH": "Largeur",
+    "HEIGHT_BANK_WATER": "Hauteur d'eau en rive",
+    "HEIGHT_BANK_LEFT": "Hauteur rive gauche",
+    "HEIGHT_BANK_RIGHT": "Hauteur rive droite",
+    "ORIGIN_MEASURES": "Origine des mesures",
+    "MATERIAL_TYPE": "Type de matériel",
+    "MATERIAL_CHOICE": "Choix du matériel",
+    "TAB_MEASUREMENTS": "Saisies des mesures",
+    "VERTICALS": "Verticales",
+    "VERTICAL_NUMBER": "Verticale n°",
+    "DISTANCE_FROM_BANK": "Distance à la rive (m)",
+    "DEPTH": "Profondeur (m)",
+    "DURATION": "Durée (s)",
+    "NUMBER_OF_POINTS": "Nombre de points",
+    "INVALID_DISTANCE": "La distance à la rive doit être inférieure ou égale à la largeur de la section",
+    "MEASUREMENTS_ON_VERTICAL": "Mesures sur la verticale n°",
+    "DISTANCE_FROM_BOTTOM": "Distance au fond (m)",
+    "SPEED": "Vitesse (m/s)",
+    "ROTATIONS": "Rotations",
+    "ROTATION_NUMBER": "Tours",
+    "DISTANCE": "Distance",
+    "TAB_RESULTS": "Résultats",
+    "RESULTS_PER_VERTICAL": "Résultats par verticale",
+    "AVERAGE_SPEED": "Vitesse moyenne (m/s)",
+    "SURFACE": "Surface (m²)",
+    "FLOW": "Débit (m³/s)",
+    "OVERALL_GAUGING_RESULTS": "Résultats globaux du jaugeage",
+    "TOTAL_SURFACE": "Surface totale (m²)",
+    "TOTAL_FLOW": "Débit total (m³/s)",
+    "GRAPHICAL_REPRESENTATION": "Représentation graphique"
   },
   "EQUIPMENT": {
     "materialListTitle": "Liste de Matériel",
@@ -72,5 +116,9 @@
     "descriptionLabel": "Description",
     "submitButton": "Valider",
     "cancelButton": "Annuler"
-  }
+  },
+  "NEXT": "Suivant",
+  "PREVIOUS": "Précédent",
+  "NO_AVALAIBLE_MATERIAL": "Aucun matériel de ce type",
+  "NEED_MATERIAL": "Veuillez ajouter d'abord le matériel"
 }
\ No newline at end of file
-- 
GitLab


From e4f6661429a4bd02abb71dae48baebdf9c7bb414 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 07:48:27 +0000
Subject: [PATCH 05/16] fix: translate dialog new session Refs #6

---
 src/app/app.component.ts                      |  2 +-
 .../dialog-new-session.component.html         | 25 +++++++++++--------
 .../dialog-new-session.component.ts           |  3 ++-
 src/assets/i18n/en.json                       |  6 +++++
 src/assets/i18n/fr.json                       |  6 +++++
 5 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 234d7d0..a51cede 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -46,7 +46,7 @@ export class AppComponent {
     this.gaugingList$ = this.gaugingService.gaugingList$;
     this.translate.addLangs(['fr', 'en']);
     this.translate.setDefaultLang('fr');
-    this.translate.use('fr');
+    this.translate.use('en');
   }
 
   ngOnInit(): void {
diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html
index b2fdb62..5b6aa91 100644
--- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html
+++ b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.html
@@ -1,11 +1,14 @@
-<h2 mat-dialog-title class="dialog-title"><mat-icon color="warn">warning</mat-icon> Réinitialiser la session</h2>
-  <mat-dialog-content>
-    Attention! La session actuelle sera perdue.
-  <mat-dialog-actions>
-    <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>Confirmer</button>
-    <button mat-raised-button mat-dialog-close color="warn">Annuler</button>
-  </mat-dialog-actions>
-  
-  
-
-
+<h2 mat-dialog-title class="dialog-title">
+  <mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.RESET_SESSION_TITLE' | translate }}
+</h2>
+<mat-dialog-content>
+  {{ 'DIALOG.RESET_SESSION_WARNING' | translate }}
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>
+    {{ 'DIALOG.CONFIRM_BUTTON' | translate }}
+  </button>
+  <button mat-raised-button mat-dialog-close color="warn">
+    {{ 'DIALOG.CANCEL_BUTTON' | translate }}
+  </button>
+</mat-dialog-actions>
diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts
index dd42cd6..c09f03b 100644
--- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts
+++ b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.ts
@@ -2,11 +2,12 @@ import { Component } from '@angular/core';
 import { MatButtonModule } from '@angular/material/button';
 import { MatDialogActions, MatDialogClose, MatDialogContent } from '@angular/material/dialog';
 import { MatIcon } from '@angular/material/icon';
+import { TranslateModule } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-dialog-new-session',
   standalone: true,
-  imports: [MatIcon, MatDialogActions, MatDialogClose, MatDialogContent, MatButtonModule],
+  imports: [MatIcon, MatDialogActions, MatDialogClose, MatDialogContent, MatButtonModule, TranslateModule],
   templateUrl: './dialog-new-session.component.html',
   styleUrl: './dialog-new-session.component.scss'
 })
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 75b1c9f..b45d645 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -21,6 +21,12 @@
     "LOAD_SESSION": "Load Session",
     "SAVE_SESSION": "Save Session"
   },
+  "DIALOG": {
+    "RESET_SESSION_TITLE": "Reset Session",
+    "RESET_SESSION_WARNING": "Warning! The current session will be lost.",
+    "CONFIRM_BUTTON": "Confirm",
+    "CANCEL_BUTTON": "Cancel"
+  },
   "GAUGING": {
     "LIST_TITLE": "Gauging List",
     "ADD_GAUGING": "Add Gauging",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 13a20fd..155f488 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -21,6 +21,12 @@
     "LOAD_SESSION": "Charger une session",
     "SAVE_SESSION": "Enregistrer la session"
   },
+  "DIALOG": {
+    "RESET_SESSION_TITLE": "Réinitialiser la session",
+    "RESET_SESSION_WARNING": "Attention! La session actuelle sera perdue.",
+    "CONFIRM_BUTTON": "Confirmer",
+    "CANCEL_BUTTON": "Annuler"
+  },
   "GAUGING": {
     "LIST_TITLE": "Liste des Jaugeages",
     "ADD_GAUGING": "Ajouter un jaugeage",
-- 
GitLab


From 7c6e3b0f0f4dbc1cdce5e04ea7eef2914de53f9f Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 08:57:07 +0000
Subject: [PATCH 06/16] fix: translate dialog load session and
 mat-expanson-panel Refs #6

---
 .../dialog-load-session.component.html        | 20 +++++++++----------
 .../dialog-load-session.component.ts          |  3 ++-
 .../mat-expansion-panel.component.ts          | 12 +++++++----
 src/assets/i18n/en.json                       | 14 ++++++++++++-
 src/assets/i18n/fr.json                       | 14 ++++++++++++-
 5 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html
index 6c3ff1f..c180176 100644
--- a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html
+++ b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.html
@@ -1,7 +1,7 @@
-<h2 mat-dialog-title class="dialog-title">Charger une session</h2>
+<h2 mat-dialog-title class="dialog-title">{{ 'DIALOG.LOAD_SESSION_TITLE' | translate }}</h2>
 <mat-dialog-content>
   <mat-form-field class="file-input-field" [formGroup]="loadingForm" appearance="outline">
-    <mat-label>Choisir un fichier</mat-label>
+    <mat-label>{{ 'DIALOG.CHOOSE_FILE_LABEL' | translate }}</mat-label>
     <ngx-mat-file-input id="session-file-input" formControlName="file" (change)="onFileSelected($event)" #sessionFile>
     </ngx-mat-file-input>
     @if(!sessionFile.empty) {
@@ -12,31 +12,31 @@
   </mat-form-field>
   @if(!sessionFile.empty) {
     @if(materialList.length > 0 && !notJSONfile && !invalidJSONFile) {
-      <app-mat-expansion-panel [panelTitle]="panelEquipmentTitle" [panelItems]="materialList" [panelItems]="materialList"></app-mat-expansion-panel>
+      <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_EQUIPMENT_TITLE' | translate" [panelItems]="materialList" [panelItems]="materialList"></app-mat-expansion-panel>
     }
     @if(gaugingsList.length > 0 && !notJSONfile && !invalidJSONFile) {
-      <app-mat-expansion-panel [panelTitle]="panelGaugingTitle" [panelItems]="gaugingsList"></app-mat-expansion-panel>
+      <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_GAUGING_TITLE' | translate" [panelItems]="gaugingsList"></app-mat-expansion-panel>
     }
   @if(notJSONfile) {
-  <p><mat-icon color="warn">error_outline</mat-icon>Le fichier téléchargé est invalide</p>
+  <p><mat-icon color="warn">error_outline</mat-icon>{{ 'DIALOG.INVALID_FILE' | translate }}</p>
   }
   @if(invalidJSONFile) {
-  <p><mat-icon color="warn">error_outline</mat-icon>Le fichier JSON contient des données incorrectes</p>
+  <p><mat-icon color="warn">error_outline</mat-icon>{{ 'DIALOG.INVALID_JSON_FILE' | translate }}</p>
   }
   <!-- @if(duplicatedEquipment) {
     <p><mat-icon color="warn">error_outline</mat-icon>Impossible d'ajouter un équipement déjà existant</p>
     } -->
   }
   @else {
-  <p style="color: red">Veuillez télécharger un fichier</p>
+  <p style="color: red">{{ 'DIALOG.UPLOAD_PROMPT' | translate }}</p>
   }
   @if(equipmentService.getAllEquipment().length || gaugingService.getAllGauging().length) {
     <mat-checkbox color="primary" [(ngModel)]="clearCurrentSession" (ngModelChange)="onClearCurrentSessionChange($event)">
-      <span>Vider la session en cours</span>
+      <span>{{ 'DIALOG.CLEAR_SESSION_CHECKBOX' | translate }}</span>
     </mat-checkbox>
   }
   <mat-dialog-actions>
     <button mat-raised-button mat-dialog-close color="primary" (click)="loadSession()"
-      [disabled]="sessionFile.empty||notJSONfile || invalidJSONFile" [mat-dialog-close]="'confirm'">Confirmer</button>
-    <button mat-raised-button  color="warn" cdkFocusInitial mat-dialog-close>Annuler</button>
+      [disabled]="sessionFile.empty||notJSONfile || invalidJSONFile" [mat-dialog-close]="'confirm'">{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button>
+    <button mat-raised-button  color="warn" cdkFocusInitial mat-dialog-close>{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
   </mat-dialog-actions>
\ No newline at end of file
diff --git a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts
index 57cb7d0..e6827fe 100644
--- a/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts
+++ b/src/app/components/dialog/dialog-load-session/dialog-load-session/dialog-load-session.component.ts
@@ -18,12 +18,13 @@ import { Session } from '../../../../models/session';
 import { Gauging } from '../../../../models/gauging';
 import { GaugingService } from '../../../../services/gauging.service';
 import { MaterialPropeller } from '../../../../models/material_propeller';
+import { TranslateModule, TranslateService } from '@ngx-translate/core';
 @Component({
   selector: 'app-dialog-load-session',
   standalone: true,
   templateUrl: './dialog-load-session.component.html',
   styleUrl: './dialog-load-session.component.scss',
-  imports: [MatExpansionPanelComponent, MatListModule, MatCheckboxModule, MatExpansionModule, MaterialFileInputModule, MatDialogClose, MatDialogActions, MatDialogContent, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatIconModule, MatButtonModule, ErrorMessageComponent]
+  imports: [MatExpansionPanelComponent, MatListModule, MatCheckboxModule, MatExpansionModule, MaterialFileInputModule, MatDialogClose, MatDialogActions, MatDialogContent, ReactiveFormsModule, FormsModule, MatFormFieldModule, MatIconModule, MatButtonModule, ErrorMessageComponent, TranslateModule]
 })
 export class DialogLoadSessionComponent {
   private fileReader = new FileReader();
diff --git a/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts b/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts
index ce9cac3..18f75da 100644
--- a/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts
+++ b/src/app/components/mat-expansion-panel/mat-expansion-panel.component.ts
@@ -4,18 +4,22 @@ import { MatButtonModule } from '@angular/material/button';
 import { MatCheckboxModule } from '@angular/material/checkbox';
 import { MatExpansionModule } from '@angular/material/expansion';
 import { MatDividerModule } from '@angular/material/divider';
+import { TranslateModule } from '@ngx-translate/core';
+import { TranslateService } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-mat-expansion-panel',
   standalone: true,
-  imports: [MatCheckboxModule, MatExpansionModule, FormsModule, MatButtonModule, MatDividerModule],
+  imports: [MatCheckboxModule, MatExpansionModule, FormsModule, MatButtonModule, MatDividerModule, TranslateModule,],
   templateUrl: './mat-expansion-panel.component.html',
   styleUrl: './mat-expansion-panel.component.scss'
 })
 export class MatExpansionPanelComponent {
   @Input() panelTitle: string = "";
   @Input() panelItems: any[] = [];
-  selectButtonTitle: string = 'Aucun';
+  selectButtonTitle: string = this.translate.instant('PANEL.SELECT_NONE');
+
+  constructor(private translate: TranslateService) { } 
 
   ngOnInit(): void {
     this.selectAll();
@@ -45,9 +49,9 @@ export class MatExpansionPanelComponent {
   }
 
   selectNoneOrAll() {
-    this.selectButtonTitle = (this.selectButtonTitle === 'Aucun') ? 'Tous' : 'Aucun';
+    this.selectButtonTitle = (this.selectButtonTitle === this.translate.instant('PANEL.SELECT_NONE')) ? this.translate.instant('PANEL.SELECT_ALL') : this.translate.instant('PANEL.SELECT_NONE');
 
-    if (this.selectButtonTitle === 'Aucun') {
+    if (this.selectButtonTitle === this.translate.instant('PANEL.SELECT_NONE')) {
       this.panelItems.forEach(item => item.selected = true);
     } else {
       this.panelItems.forEach(item => item.selected = false);
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index b45d645..aab61b3 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -25,7 +25,19 @@
     "RESET_SESSION_TITLE": "Reset Session",
     "RESET_SESSION_WARNING": "Warning! The current session will be lost.",
     "CONFIRM_BUTTON": "Confirm",
-    "CANCEL_BUTTON": "Cancel"
+    "CANCEL_BUTTON": "Cancel",
+    "LOAD_SESSION_TITLE": "Load a session",
+    "CHOOSE_FILE_LABEL": "Choose a file",
+    "INVALID_FILE": "The uploaded file is invalid",
+    "INVALID_JSON_FILE": "The JSON file contains incorrect data",
+    "UPLOAD_PROMPT": "Please upload a file",
+    "CLEAR_SESSION_CHECKBOX": "Clear current session",
+    "PANEL_GAUGING_TITLE": "Gaugings",
+    "PANEL_EQUIPMENT_TITLE": "Equipment"
+  },
+  "PANEL": {
+    "SELECT_ALL": "All",
+    "SELECT_NONE": "None"
   },
   "GAUGING": {
     "LIST_TITLE": "Gauging List",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 155f488..a9e61b0 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -25,7 +25,19 @@
     "RESET_SESSION_TITLE": "Réinitialiser la session",
     "RESET_SESSION_WARNING": "Attention! La session actuelle sera perdue.",
     "CONFIRM_BUTTON": "Confirmer",
-    "CANCEL_BUTTON": "Annuler"
+    "CANCEL_BUTTON": "Annuler",
+    "LOAD_SESSION_TITLE": "Charger une session",
+    "CHOOSE_FILE_LABEL": "Choisir un fichier",
+    "INVALID_FILE": "Le fichier téléchargé est invalide",
+    "INVALID_JSON_FILE": "Le fichier JSON contient des données incorrectes",
+    "UPLOAD_PROMPT": "Veuillez télécharger un fichier",
+    "CLEAR_SESSION_CHECKBOX": "Vider la session en cours",
+    "PANEL_GAUGING_TITLE": "Jaugeages",
+    "PANEL_EQUIPMENT_TITLE": "Matériel"
+  },
+  "PANEL": {
+    "SELECT_ALL": "Tous",
+    "SELECT_NONE": "Aucun"
   },
   "GAUGING": {
     "LIST_TITLE": "Liste des Jaugeages",
-- 
GitLab


From 7fd42a3900839f1f89a5fee0e29cea3ffcc64aeb Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 09:25:51 +0000
Subject: [PATCH 07/16] fix: translate dialog save session Refs #6

---
 .../dialog-new-session.component.spec.ts      | 23 -------------------
 .../dialog-save-session.component.html        | 10 ++++----
 .../dialog-save-session.component.ts          |  3 ++-
 src/assets/i18n/en.json                       |  5 +++-
 src/assets/i18n/fr.json                       |  5 +++-
 5 files changed, 15 insertions(+), 31 deletions(-)
 delete mode 100644 src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts

diff --git a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts b/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts
deleted file mode 100644
index 0dc2581..0000000
--- a/src/app/components/dialog/dialog-new-session/dialog-new-session/dialog-new-session.component.spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { DialogNewSessionComponent } from './dialog-new-session.component';
-
-describe('DialogNewSessionComponent', () => {
-  let component: DialogNewSessionComponent;
-  let fixture: ComponentFixture<DialogNewSessionComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      imports: [DialogNewSessionComponent]
-    })
-    .compileComponents();
-    
-    fixture = TestBed.createComponent(DialogNewSessionComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
index e4569cb..5eb9f5f 100644
--- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
+++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
@@ -1,13 +1,13 @@
-<h2 mat-dialog-title class="dialog-title">Sauvegarder la session</h2>
+<h2 mat-dialog-title class="dialog-title">{{ 'DIALOG.SAVE_TITLE' | translate }}</h2>
 <mat-dialog-content>
   @if(equipment.length > 0){
-    <app-mat-expansion-panel [panelTitle]="panelEquipmentTitle" [panelItems]="equipment"></app-mat-expansion-panel>
+    <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_EQUIPMENT_TITLE' | translate" [panelItems]="equipment"></app-mat-expansion-panel>
   }
   @if(gaugings.length > 0 ){
-    <app-mat-expansion-panel [panelTitle]="panelGaugingTitle" [panelItems]="gaugings"></app-mat-expansion-panel>
+    <app-mat-expansion-panel [panelTitle]="'DIALOG.PANEL_GAUGING_TITLE' | translate" [panelItems]="gaugings"></app-mat-expansion-panel>
   }
 <mat-form-field class="file-input-field" appearance="outline">
-  <mat-label>Nom du fichier</mat-label>
+  <mat-label>{{ 'DIALOG.FILE_NAME_LABEL' | translate }}</mat-label>
   <input matInput [(ngModel)]="fileName" #sessionFile>
   @if(fileName !== "") {
   <button mat-icon-button matSuffix (click)="fileName = ''" class="clear-button">
@@ -16,7 +16,7 @@
   }
 </mat-form-field>
 @if(fileName === "") { 
-  <p style="color: red">Veuillez nommer le fichier</p>
+  <p style="color: red">{{ 'DIALOG.NO_FILE_NAME_ERROR' | translate }}</p>
 }
 <mat-dialog-actions>
   <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">Confirmer</button>
diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts
index 8cb7f61..16b5363 100644
--- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts
+++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.ts
@@ -14,6 +14,7 @@ import { Material } from '../../../../models/material';
 import { GaugingService } from '../../../../services/gauging.service';
 import { Gauging } from '../../../../models/gauging';
 import { MaterialType } from '../../../../models/equipment.model';
+import { TranslateModule } from '@ngx-translate/core';
 
 interface SelectableMaterial extends Material {
   selected?: boolean;
@@ -26,7 +27,7 @@ interface SelectableGauging extends Gauging {
 @Component({
   selector: 'app-dialog-save-session',
   standalone: true,
-  imports: [MatExpansionPanelComponent, MatIconModule, MatCheckboxModule, MatExpansionModule, MatFormField, MatInputModule, MatDialogClose, FormsModule, MatButtonModule, MatDialogContent, MatDialogActions],
+  imports: [MatExpansionPanelComponent, MatIconModule, MatCheckboxModule, MatExpansionModule, MatFormField, MatInputModule, MatDialogClose, FormsModule, MatButtonModule, MatDialogContent, MatDialogActions, TranslateModule],
   templateUrl: './dialog-save-session.component.html',
   styleUrl: './dialog-save-session.component.scss'
 })
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index aab61b3..47dce71 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -32,6 +32,9 @@
     "INVALID_JSON_FILE": "The JSON file contains incorrect data",
     "UPLOAD_PROMPT": "Please upload a file",
     "CLEAR_SESSION_CHECKBOX": "Clear current session",
+    "SAVE_TITLE": "Save session",
+    "FILE_NAME_LABEL": "File name",
+    "NO_FILE_NAME_ERROR": "Please name the file",
     "PANEL_GAUGING_TITLE": "Gaugings",
     "PANEL_EQUIPMENT_TITLE": "Equipment"
   },
@@ -81,7 +84,7 @@
     "DEPTH": "Depth (m)",
     "DURATION": "Duration (s)",
     "NUMBER_OF_POINTS": "Number of points",
-    "INVALID_DISTANCE": "Distance from bank must be less than or equal to section width",
+    "INVALID_DISTANCE": "Invalid distance",
     "MEASUREMENTS_ON_VERTICAL": "Measurements on vertical n°",
     "DISTANCE_FROM_BOTTOM": "Distance from bottom (m)",
     "SPEED": "Speed (m/s)",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index a9e61b0..37e80d3 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -32,6 +32,9 @@
     "INVALID_JSON_FILE": "Le fichier JSON contient des données incorrectes",
     "UPLOAD_PROMPT": "Veuillez télécharger un fichier",
     "CLEAR_SESSION_CHECKBOX": "Vider la session en cours",
+    "SAVE_TITLE": "Sauvegarder la session",
+    "FILE_NAME_LABEL": "Nom du fichier",
+    "NO_FILE_NAME_ERROR": "Veuillez nommer le fichier",
     "PANEL_GAUGING_TITLE": "Jaugeages",
     "PANEL_EQUIPMENT_TITLE": "Matériel"
   },
@@ -81,7 +84,7 @@
     "DEPTH": "Profondeur (m)",
     "DURATION": "Durée (s)",
     "NUMBER_OF_POINTS": "Nombre de points",
-    "INVALID_DISTANCE": "La distance à la rive doit être inférieure ou égale à la largeur de la section",
+    "INVALID_DISTANCE": "Distance invalide",
     "MEASUREMENTS_ON_VERTICAL": "Mesures sur la verticale n°",
     "DISTANCE_FROM_BOTTOM": "Distance au fond (m)",
     "SPEED": "Vitesse (m/s)",
-- 
GitLab


From 5874659039d12983fbbe20956c2a9ab79fca0a68 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 10:10:30 +0000
Subject: [PATCH 08/16] fix: translate dialog confirm delete equipment Refs #6

---
 .../dialog-confirm-delete-equipment.component.html        | 8 ++++----
 .../dialog-confirm-delete-equipment.component.ts          | 8 +++++---
 src/assets/i18n/en.json                                   | 4 +++-
 src/assets/i18n/fr.json                                   | 4 +++-
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html
index f872405..5c29c4f 100644
--- a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html
+++ b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.html
@@ -1,10 +1,10 @@
-<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2>
+<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_MATERIAL_TITLE' | translate }}</h2>
   <mat-dialog-content>
-    Attention! Le <strong>{{ data.materialType }} {{ data.materialName }}</strong> sera supprimé de la liste.
+    <span [innerHTML]="'DIALOG.WARNING_DELETE_MATERIAL_MESSAGE' | translate: { materialType: translate.instant(data.materialType), materialName: data.materialName }"></span>
   </mat-dialog-content>
   <mat-dialog-actions>
-    <button mat-raised-button mat-dialog-close color="primary">Annuler</button>
-    <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button>
+    <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
+    <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button>
   </mat-dialog-actions>
   
   
diff --git a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts
index 01c4c0b..0a450eb 100644
--- a/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts
+++ b/src/app/components/dialog/dialog-confirm-delete-equipment/dialog-confirm-delete-equipment.component.ts
@@ -8,16 +8,18 @@ import {
 import { MatIconModule } from '@angular/material/icon';
 import {MatButtonModule} from '@angular/material/button'
 import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { TranslateModule, TranslateService } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-dialog-confirm-delete-equipment',
   standalone: true,
-  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule],
+  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule],
   templateUrl: './dialog-confirm-delete-equipment.component.html',
   styleUrl: './dialog-confirm-delete-equipment.component.scss'
 })
 export class DialogConfirmDeleteEquipmentComponent {
 
-  constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
-
+  constructor(@Inject(MAT_DIALOG_DATA) public data: any, protected translate: TranslateService) {
+  }
+  
 }
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 47dce71..637bfe2 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -36,7 +36,9 @@
     "FILE_NAME_LABEL": "File name",
     "NO_FILE_NAME_ERROR": "Please name the file",
     "PANEL_GAUGING_TITLE": "Gaugings",
-    "PANEL_EQUIPMENT_TITLE": "Equipment"
+    "PANEL_EQUIPMENT_TITLE": "Equipment",
+    "DELETE_MATERIAL_TITLE": "Delete material",
+    "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list."
   },
   "PANEL": {
     "SELECT_ALL": "All",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 37e80d3..da35c8f 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -36,7 +36,9 @@
     "FILE_NAME_LABEL": "Nom du fichier",
     "NO_FILE_NAME_ERROR": "Veuillez nommer le fichier",
     "PANEL_GAUGING_TITLE": "Jaugeages",
-    "PANEL_EQUIPMENT_TITLE": "Matériel"
+    "PANEL_EQUIPMENT_TITLE": "Matériel",
+    "DELETE_MATERIAL_TITLE": "Suppression du matériel",
+    "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste."
   },
   "PANEL": {
     "SELECT_ALL": "Tous",
-- 
GitLab


From 356a16ed814043498e2a0f1900840c66401110df Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 10:31:24 +0000
Subject: [PATCH 09/16] fix: translate dialog warning material associated to
 jauging Refs #6

---
 ...alog-confirm-delete-gauging.component.html |  2 +-
 ...erial-associated-to-gauging.component.html | 21 ++++++++-----------
 ...aterial-associated-to-gauging.component.ts |  5 +++--
 src/assets/i18n/en.json                       |  6 +++++-
 src/assets/i18n/fr.json                       |  6 +++++-
 5 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
index 36ff451..455657d 100644
--- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
+++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
@@ -1,4 +1,4 @@
-<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2>
+<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression d'un jaugeage</h2>
   <mat-dialog-content>
     Attention! Le jaugeage réalisé sur le <strong>{{ data.watercourse }}</strong> à la date du <strong>{{ data.date | date: 'dd/MM/yyyy'  }}</strong> sera supprimé de la liste.
   </mat-dialog-content>
diff --git a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html
index a9487a9..f894a63 100644
--- a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html
+++ b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.html
@@ -1,12 +1,9 @@
-<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel impossible</h2>
-  <mat-dialog-content>
-    Attention! Le <strong>{{ data.materialType }} {{ data.materialName }}</strong> est associé à un ou plusieurs jaugeages existants.<br>
-    Supprimer d'abord le ou les jaugeages associés pour supprimer ce matériel. 
-  </mat-dialog-content>
-  <mat-dialog-actions>
-    <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>Liste des jaugeages </button>
-    <button mat-raised-button mat-dialog-close color="warn">Annuler</button>
-  </mat-dialog-actions>
-  
-  
-
+<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_IMPOSSIBLE_TITLE' | translate }}</h2>
+<mat-dialog-content>
+  <span [innerHTML]="'DIALOG.DELETE_IMPOSSIBLE_MESSAGE' | translate: { materialType: translate.instant(data.materialType), materialName: data.materialName }"></span><br>
+  {{ 'DIALOG.DELETE_IMPOSSIBLE_INSTRUCTION' | translate }}
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button mat-raised-button [mat-dialog-close]="'confirm'" color="primary" cdkFocusInitial>{{ 'DIALOG.GAUGING_LIST_BUTTON' | translate }}</button>
+  <button mat-raised-button mat-dialog-close color="warn">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
+</mat-dialog-actions>
diff --git a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts
index 9ec31f9..f77c33b 100644
--- a/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts
+++ b/src/app/components/dialog/dialog-warning-material-associated-to-gauging/dialog-warning-material-associated-to-gauging.component.ts
@@ -2,16 +2,17 @@ import { Component, Inject } from '@angular/core';
 import { MatButtonModule } from '@angular/material/button';
 import { MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { MatIconModule } from '@angular/material/icon';
+import { TranslateModule, TranslateService } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-dialog-warning-material-associated-to-gauging',
   standalone: true,
-  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule],
+  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule],
   templateUrl: './dialog-warning-material-associated-to-gauging.component.html',
   styleUrl: './dialog-warning-material-associated-to-gauging.component.scss'
 })
 export class DialogWarningMaterialAssociatedToGaugingComponent {
-  constructor(@Inject(MAT_DIALOG_DATA) public data: any) {
+  constructor(@Inject(MAT_DIALOG_DATA) public data: any, protected translate: TranslateService) {
     
   }
 }
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 637bfe2..8fc9f00 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -38,7 +38,11 @@
     "PANEL_GAUGING_TITLE": "Gaugings",
     "PANEL_EQUIPMENT_TITLE": "Equipment",
     "DELETE_MATERIAL_TITLE": "Delete material",
-    "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list."
+    "WARNING_DELETE_MATERIAL_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> will be removed from the list.",
+    "DELETE_IMPOSSIBLE_TITLE": "Unable to delete material",
+    "DELETE_IMPOSSIBLE_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> is associated with one or more existing gaugings.",
+    "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.",
+    "GAUGING_LIST_BUTTON": "Gaugings list"
   },
   "PANEL": {
     "SELECT_ALL": "All",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index da35c8f..68e3ddb 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -38,7 +38,11 @@
     "PANEL_GAUGING_TITLE": "Jaugeages",
     "PANEL_EQUIPMENT_TITLE": "Matériel",
     "DELETE_MATERIAL_TITLE": "Suppression du matériel",
-    "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste."
+    "WARNING_DELETE_MATERIAL_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> sera supprimé de la liste.",
+    "DELETE_IMPOSSIBLE_TITLE": "Suppression du matériel impossible",
+    "DELETE_IMPOSSIBLE_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> est associé à un ou plusieurs jaugeages existants.",
+    "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.",
+    "GAUGING_LIST_BUTTON": "Liste des jaugeages"
   },
   "PANEL": {
     "SELECT_ALL": "Tous",
-- 
GitLab


From 7504321809f5a5077d89682abc0c5a91b5d9db16 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 10:38:53 +0000
Subject: [PATCH 10/16] fix: translate dialog confirm delete gauging Refs #6

---
 ...alog-confirm-delete-gauging.component.html | 19 ++++++++-----------
 ...alog-confirm-delete-gauging.component.scss |  5 +++++
 ...dialog-confirm-delete-gauging.component.ts |  3 ++-
 src/assets/i18n/en.json                       |  4 +++-
 src/assets/i18n/fr.json                       |  4 +++-
 5 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
index 455657d..c2eb050 100644
--- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
+++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.html
@@ -1,11 +1,8 @@
-<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression d'un jaugeage</h2>
-  <mat-dialog-content>
-    Attention! Le jaugeage réalisé sur le <strong>{{ data.watercourse }}</strong> à la date du <strong>{{ data.date | date: 'dd/MM/yyyy'  }}</strong> sera supprimé de la liste.
-  </mat-dialog-content>
-  <mat-dialog-actions>
-    <button mat-raised-button mat-dialog-close color="primary">Annuler</button>
-    <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button>
-  </mat-dialog-actions>
-  
-  
-
+<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_GAUGING_TITLE' | translate }}</h2>
+<mat-dialog-content>
+  <span [innerHTML]="'DIALOG.DELETE_GAUGING_MESSAGE' | translate: { watercourse: data.watercourse, date: (data.date | date: 'dd/MM/yyyy') }"></span>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
+  <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button>
+</mat-dialog-actions>
diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss
index e69de29..72fee1c 100644
--- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss
+++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.scss
@@ -0,0 +1,5 @@
+mat-icon {
+    margin-right: 1%;
+    font-size: 25px;
+    vertical-align: middle;
+}
\ No newline at end of file
diff --git a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts
index 8ecb641..7c38ccb 100644
--- a/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts
+++ b/src/app/components/dialog/dialog-confirm-delete-gauging/dialog-confirm-delete-gauging.component.ts
@@ -9,11 +9,12 @@ import { MatIconModule } from '@angular/material/icon';
 import {MatButtonModule} from '@angular/material/button'
 import { MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { DatePipe } from '@angular/common';
+import { TranslateModule } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-dialog-confirm-delete-gauging',
   standalone: true,
-  imports: [DatePipe,MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule],
+  imports: [DatePipe,MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule],
   templateUrl: './dialog-confirm-delete-gauging.component.html',
   styleUrl: './dialog-confirm-delete-gauging.component.scss',
 })
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 8fc9f00..584784f 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -42,7 +42,9 @@
     "DELETE_IMPOSSIBLE_TITLE": "Unable to delete material",
     "DELETE_IMPOSSIBLE_MESSAGE": "Warning! The <strong>{{ materialType }} {{ materialName }}</strong> is associated with one or more existing gaugings.",
     "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.",
-    "GAUGING_LIST_BUTTON": "Gaugings list"
+    "GAUGING_LIST_BUTTON": "Gaugings list",
+    "DELETE_GAUGING_TITLE": "Delete Gauging",
+    "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list."
   },
   "PANEL": {
     "SELECT_ALL": "All",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 68e3ddb..e41ce9d 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -42,7 +42,9 @@
     "DELETE_IMPOSSIBLE_TITLE": "Suppression du matériel impossible",
     "DELETE_IMPOSSIBLE_MESSAGE": "Attention! Le <strong>{{ materialType }} {{ materialName }}</strong> est associé à un ou plusieurs jaugeages existants.",
     "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.",
-    "GAUGING_LIST_BUTTON": "Liste des jaugeages"
+    "GAUGING_LIST_BUTTON": "Liste des jaugeages",
+    "DELETE_GAUGING_TITLE": "Suppression d'un jaugeage",
+    "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste."
   },
   "PANEL": {
     "SELECT_ALL": "Tous",
-- 
GitLab


From d3366cc6abaa7e98697e30c1a369077660949949 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 12:27:29 +0000
Subject: [PATCH 11/16] fix: translate dialog confirm delete vertical Refs #6

---
 src/app/app.component.html                    |  2 +-
 src/app/app.component.ts                      |  1 +
 ...log-confirm-delete-vertical.component.html | 19 ++++++++-----------
 ...ialog-confirm-delete-vertical.component.ts |  3 ++-
 .../dialog-save-session.component.html        |  4 ++--
 src/app/views/gauging/gauging.component.html  |  2 +-
 src/assets/i18n/en.json                       |  4 +++-
 src/assets/i18n/fr.json                       |  4 +++-
 8 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/app/app.component.html b/src/app/app.component.html
index ccd3108..2683604 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -30,7 +30,7 @@
         </button>
       </mat-list-item>
       <mat-list-item (click)="sidenav.close()">
-        <button [disabled]="(materialList$ | async)?.length! === 0" (click)="newSession()">
+        <button [disabled]="(materialList$ | async)?.length! === 0 && (gaugingList$ | async)?.length! === 0" (click)="newSession()">
           <mat-icon class="icon-list-item">insert_drive_file</mat-icon>
           <span>{{ 'SIDENAV.RESET_SESSION' | translate }}</span>
         </button>
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index a51cede..40580c6 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -44,6 +44,7 @@ export class AppComponent {
   constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
     this.materialList$ = this.equipmentService.materialList$;
     this.gaugingList$ = this.gaugingService.gaugingList$;
+    console.log("gauging list", this.gaugingList$ )
     this.translate.addLangs(['fr', 'en']);
     this.translate.setDefaultLang('fr');
     this.translate.use('en');
diff --git a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html
index c6b072c..c1b8a6a 100644
--- a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html
+++ b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.html
@@ -1,11 +1,8 @@
-<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> Suppression du matériel</h2>
-  <mat-dialog-content>
-    Attention! La verticale <strong> n°{{ data.selectedVerticalIndex}}</strong> sera supprimée de la liste.
-  </mat-dialog-content>
-  <mat-dialog-actions>
-    <button mat-raised-button mat-dialog-close color="primary">Annuler</button>
-    <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>Supprimer</button>
-  </mat-dialog-actions>
-  
-  
-
+<h2 mat-dialog-title><mat-icon color="warn">warning</mat-icon> {{ 'DIALOG.DELETE_VERTICAL_TITLE' | translate }}</h2>
+<mat-dialog-content>
+  <span [innerHTML]="'DIALOG.DELETE_VERTICAL_MESSAGE' | translate: { verticalIndex: data.selectedVerticalIndex }"></span>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button mat-raised-button mat-dialog-close color="primary">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
+  <button mat-raised-button [mat-dialog-close]="'confirm'" color="warn" cdkFocusInitial>{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button>
+</mat-dialog-actions>
diff --git a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts
index 884280d..bb3ea09 100644
--- a/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts
+++ b/src/app/components/dialog/dialog-confirm-delete-vertical/dialog-confirm-delete-vertical.component.ts
@@ -8,11 +8,12 @@ import {
 import { MatIconModule } from '@angular/material/icon';
 import {MatButtonModule} from '@angular/material/button'
 import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { TranslateModule } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-dialog-confirm-delete-vertical',
   standalone: true,
-  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule],
+  imports: [MatButtonModule, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatIconModule, TranslateModule],
   templateUrl: './dialog-confirm-delete-vertical.component.html',
   styleUrl: './dialog-confirm-delete-vertical.component.scss'
 })
diff --git a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
index 5eb9f5f..e3c24fd 100644
--- a/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
+++ b/src/app/components/dialog/dialog-save-session/dialog-save-session/dialog-save-session.component.html
@@ -19,7 +19,7 @@
   <p style="color: red">{{ 'DIALOG.NO_FILE_NAME_ERROR' | translate }}</p>
 }
 <mat-dialog-actions>
-  <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">Confirmer</button>
-  <button mat-raised-button color="warn" cdkFocusInitial [mat-dialog-close]="'confirm'">Annuler</button>
+  <button mat-raised-button mat-dialog-close color="primary" [disabled]="fileName === ''" (click)="saveSession()">{{ 'DIALOG.CONFIRM_BUTTON' | translate }}</button>
+  <button mat-raised-button color="warn" cdkFocusInitial [mat-dialog-close]="'confirm'">{{ 'DIALOG.CANCEL_BUTTON' | translate }}</button>
 </mat-dialog-actions>
 
diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html
index 0c016fe..c69c14d 100644
--- a/src/app/views/gauging/gauging.component.html
+++ b/src/app/views/gauging/gauging.component.html
@@ -464,7 +464,7 @@
   <!-- Résultats -->
   <mat-tab label="{{ 'GAUGING.TAB_RESULTS' | translate }}" ngSkipHydration [disabled]="!this.selectedMaterialId">
     <div class="tab-content">
-      <h2>{{ 'RESULTS.TAB_RESULTS' | translate }}</h2>
+      <h2>{{ 'GAUGING.TAB_RESULTS' | translate }}</h2>
       <!-- Résultats par verticale -->
       <mat-card class="form-section">
         <mat-card-title class="vertical-card-title">
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 584784f..3174697 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -44,7 +44,9 @@
     "DELETE_IMPOSSIBLE_INSTRUCTION": "Delete the associated gauging(s) first to remove this material.",
     "GAUGING_LIST_BUTTON": "Gaugings list",
     "DELETE_GAUGING_TITLE": "Delete Gauging",
-    "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list."
+    "DELETE_GAUGING_MESSAGE": "Warning! The gauging performed on the <strong>{{ watercourse }}</strong> on <strong>{{ date }}</strong> will be removed from the list.",
+    "DELETE_VERTICAL_TITLE": "Delete Vertical",
+    "DELETE_VERTICAL_MESSAGE": "Warning! The vertical <strong>number {{ verticalIndex }}</strong> will be removed from the list."
   },
   "PANEL": {
     "SELECT_ALL": "All",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index e41ce9d..f01bc2b 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -44,7 +44,9 @@
     "DELETE_IMPOSSIBLE_INSTRUCTION": "Supprimez d'abord le ou les jaugeages associés pour supprimer ce matériel.",
     "GAUGING_LIST_BUTTON": "Liste des jaugeages",
     "DELETE_GAUGING_TITLE": "Suppression d'un jaugeage",
-    "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste."
+    "DELETE__GAUGING_MESSAGE": "Attention! Le jaugeage réalisé sur le <strong>{{ watercourse }}</strong> à la date du <strong>{{ date }}</strong> sera supprimé de la liste.",
+    "DELETE_VERTICAL_TITLE": "Suppression de la verticale",
+    "DELETE_VERTICAL_MESSAGE": "Attention! La verticale <strong>n°{{ verticalIndex }}</strong> sera supprimée de la liste."
   },
   "PANEL": {
     "SELECT_ALL": "Tous",
-- 
GitLab


From 85d534175cb043a7a7a62ec4feb00f09deabc120 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 12:46:12 +0000
Subject: [PATCH 12/16] fix: translate origin measures enum and grain size type
 enum Refs #6

---
 src/app/app.component.ts                     |  1 -
 src/app/models/grain_size.ts                 | 26 ++++++++++----------
 src/app/models/origin_measures.ts            |  7 +++---
 src/app/views/gauging/gauging.component.html |  4 +--
 src/assets/i18n/en.json                      | 16 ++++++++++++
 src/assets/i18n/fr.json                      | 17 +++++++++++++
 6 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 40580c6..a51cede 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -44,7 +44,6 @@ export class AppComponent {
   constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
     this.materialList$ = this.equipmentService.materialList$;
     this.gaugingList$ = this.gaugingService.gaugingList$;
-    console.log("gauging list", this.gaugingList$ )
     this.translate.addLangs(['fr', 'en']);
     this.translate.setDefaultLang('fr');
     this.translate.use('en');
diff --git a/src/app/models/grain_size.ts b/src/app/models/grain_size.ts
index 0038b8b..7952a90 100644
--- a/src/app/models/grain_size.ts
+++ b/src/app/models/grain_size.ts
@@ -1,14 +1,14 @@
 export enum GrainSize {
-  CONCRETE = 'Béton',
-  ROCKS = 'Rochers',
-  BLOCSS = 'Blocs',
-  LARGE_STONES = 'Pierres grossières',
-  LARGE_PEBBLES = 'Cailloux grossiers',
-  FINE_PEBBLES = 'Cailloux fins',
-  LARGE_GRAVELS= 'Graviers grossiers',
-  FINE_GRAVELS = 'Graviers fins',
-  LARGE_SAND = 'Sable grossier',
-  FINE_SAND = 'Sable fin',
-  SILT = 'Limon',
-  CLAY = 'Argile'
-}
\ No newline at end of file
+  CONCRETE = 'GAUGING.GRAIN_SIZE.CONCRETE',
+  ROCKS = 'GAUGING.GRAIN_SIZE.ROCKS',
+  BLOCSS = 'GAUGING.GRAIN_SIZE.BLOCSS',
+  LARGE_STONES = 'GAUGING.GRAIN_SIZE.LARGE_STONES',
+  LARGE_PEBBLES = 'GAUGING.GRAIN_SIZE.LARGE_PEBBLES',
+  FINE_PEBBLES = 'GAUGING.GRAIN_SIZE.FINE_PEBBLES',
+  LARGE_GRAVELS = 'GAUGING.GRAIN_SIZE.LARGE_GRAVELS',
+  FINE_GRAVELS = 'GAUGING.GRAIN_SIZE.FINE_GRAVELS',
+  LARGE_SAND = 'GAUGING.GRAIN_SIZE.LARGE_SAND',
+  FINE_SAND = 'GAUGING.GRAIN_SIZE.FINE_SAND',
+  SILT = 'GAUGING.GRAIN_SIZE.SILT',
+  CLAY = 'GAUGING.GRAIN_SIZE.CLAY'
+}
diff --git a/src/app/models/origin_measures.ts b/src/app/models/origin_measures.ts
index d75899e..5d51baf 100644
--- a/src/app/models/origin_measures.ts
+++ b/src/app/models/origin_measures.ts
@@ -1,7 +1,8 @@
 export enum OriginMeasures {
-    BANK_LEFT = 'Rive gauche',
-    BANK_RIGHT = 'Rive droite'
-  }
+  BANK_LEFT = 'GAUGING.BANK_LEFT',
+  BANK_RIGHT = 'GAUGING.BANK_RIGHT'
+}
+
 
   // BOTTOM = 'Fond',
   // SURFACE = 'Surface',
\ No newline at end of file
diff --git a/src/app/views/gauging/gauging.component.html b/src/app/views/gauging/gauging.component.html
index c69c14d..c91018d 100644
--- a/src/app/views/gauging/gauging.component.html
+++ b/src/app/views/gauging/gauging.component.html
@@ -154,7 +154,7 @@
                   <mat-select formControlName="size" disableRipple>
                     @for (size of grainSizes; track size) {
                     <mat-option [value]="size">
-                      {{size}}
+                      {{size | translate}}
                     </mat-option>
                     }
                   </mat-select>
@@ -213,7 +213,7 @@
               <mat-radio-group formControlName="originMeasures">
                 @for (origin of originMeasures; track origin) {
                 <mat-radio-button color="primary" [value]="origin">
-                  {{origin}}
+                  {{origin | translate}}
                 </mat-radio-button>
                 }
               </mat-radio-group>
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 3174697..0c16df3 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -77,6 +77,20 @@
     "OBSERVATIONS": "Observations",
     "OBSERVATION": "Observation",
     "REPRESENTATIVE_GRAIN_SIZE": "Representative grain size",
+    "GRAIN_SIZE": {
+      "CONCRETE": "Concrete",
+      "ROCKS": "Rocks",
+      "BLOCSS": "Blocks",
+      "LARGE_STONES": "Large stones",
+      "LARGE_PEBBLES": "Large pebbles",
+      "FINE_PEBBLES": "Fine pebbles",
+      "LARGE_GRAVELS": "Large gravels",
+      "FINE_GRAVELS": "Fine gravels",
+      "LARGE_SAND": "Coarse sand",
+      "FINE_SAND": "Fine sand",
+      "SILT": "Silt",
+      "CLAY": "Clay"
+    },
     "DOMINANT_GRAIN_SIZE": "Dominant",
     "ACCESSORY_GRAIN_SIZE": "Accessory",
     "PARAMETERS": "Gauging parameters",
@@ -86,6 +100,8 @@
     "HEIGHT_BANK_LEFT": "Height bank left",
     "HEIGHT_BANK_RIGHT": "Height bank right",
     "ORIGIN_MEASURES": "Origin of measures",
+    "BANK_LEFT": "Left bank",
+    "BANK_RIGHT": "Right bank",
     "MATERIAL_CHOICE": "Material choice",
     "TAB_MEASUREMENTS": "Measurement entries",
     "VERTICALS": "Verticals",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index f01bc2b..817f5c3 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -76,6 +76,21 @@
     "OPERATOR": "Operator",
     "OBSERVATIONS": "Observations",
     "OBSERVATION": "Observation",
+    "REPRESENTATIVE_GRAIN_SIZE": "Garunulométrie représentative",
+    "GRAIN_SIZE": {
+      "CONCRETE": "Béton",
+      "ROCKS": "Rochers",
+      "BLOCSS": "Blocs",
+      "LARGE_STONES": "Pierres grossières",
+      "LARGE_PEBBLES": "Cailloux grossiers",
+      "FINE_PEBBLES": "Cailloux fins",
+      "LARGE_GRAVELS": "Graviers grossiers",
+      "FINE_GRAVELS": "Graviers fins",
+      "LARGE_SAND": "Sable grossier",
+      "FINE_SAND": "Sable fin",
+      "SILT": "Limon",
+      "CLAY": "Argile"
+    },
     "DOMINANT_GRAIN_SIZE": "Dominante",
     "ACCESSORY_GRAIN_SIZE": "Accessoire",
     "PARAMETERS": "Paramètres du jaugeage",
@@ -85,6 +100,8 @@
     "HEIGHT_BANK_LEFT": "Hauteur rive gauche",
     "HEIGHT_BANK_RIGHT": "Hauteur rive droite",
     "ORIGIN_MEASURES": "Origine des mesures",
+    "BANK_LEFT": "Rive gauche",
+    "BANK_RIGHT": "Rive droite",
     "MATERIAL_TYPE": "Type de matériel",
     "MATERIAL_CHOICE": "Choix du matériel",
     "TAB_MEASUREMENTS": "Saisies des mesures",
-- 
GitLab


From daf1c3418b858f871a16d73aff59b7d15260d518 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 14:33:10 +0000
Subject: [PATCH 13/16] fix:  avoid trigering of beforeunload event when
 material form is opened from gauging component Refs #6

---
 src/app/app.config.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index 495ff54..2115cd0 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -14,7 +14,6 @@ const httpLoaderFactory: (http: HttpClient) => TranslateHttpLoader = (http: Http
 export const appConfig: ApplicationConfig = {
   providers: [
     provideRouter(routes, withPreloading(PreloadAllModules)), provideClientHydration(), provideAnimationsAsync(), {provide: MAT_DATE_LOCALE, useValue: 'en-GB'},
-    provideZoneChangeDetection({ eventCoalescing: true }),
     provideHttpClient(),
     importProvidersFrom([TranslateModule.forRoot({
       loader: {
-- 
GitLab


From edb5ec59255d2fffcebc5e25d58124a8988a7ded Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 15:07:55 +0000
Subject: [PATCH 14/16] fix: add settings component for language selection Refs
 #6

---
 src/app/app.component.html                    |  2 +-
 src/app/app.routes.ts                         |  1 +
 .../views/settings/settings.component.html    | 20 +++++++++++++
 .../views/settings/settings.component.scss    | 15 ++++++++++
 src/app/views/settings/settings.component.ts  | 30 +++++++++++++++++++
 5 files changed, 67 insertions(+), 1 deletion(-)
 create mode 100644 src/app/views/settings/settings.component.html
 create mode 100644 src/app/views/settings/settings.component.scss
 create mode 100644 src/app/views/settings/settings.component.ts

diff --git a/src/app/app.component.html b/src/app/app.component.html
index 2683604..b063db6 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -45,7 +45,7 @@
           <span>{{ 'SIDENAV.SAVE_SESSION' | translate }}</span>
         </button>
       </mat-list-item>
-      <mat-list-item (click)="sidenav.close()">
+      <mat-list-item routerLink="settings" (click)="sidenav.close()">
         <mat-icon class="icon-list-item">settings</mat-icon>
         <span>{{ 'SIDENAV.CONFIGURATION' | translate }}</span>
       </mat-list-item>
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 7b886d5..6362f7e 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -6,4 +6,5 @@ export const routes: Routes = [
     { path: 'list', loadComponent: () => import('../app/views/gauging-list/gauging-list.component').then(m => m.GaugingListComponent)},
     { path: 'gauging/:id', loadComponent: () => import('../app/views/gauging/gauging.component').then(m => m.GaugingComponent)},
     { path: 'gauging/edit/:id', loadComponent: () => import('../app/views/gauging/gauging.component').then(m => m.GaugingComponent)},
+    { path: 'settings', loadComponent: () => import('../app/views/settings/settings.component').then(m => m.SettingsComponent) },
 ];
diff --git a/src/app/views/settings/settings.component.html b/src/app/views/settings/settings.component.html
new file mode 100644
index 0000000..ee9dfd2
--- /dev/null
+++ b/src/app/views/settings/settings.component.html
@@ -0,0 +1,20 @@
+<div class="settings-container">
+    <h2>Paramètres</h2>
+    <mat-card>
+      <mat-card-header>
+        <mat-card-title>Langue</mat-card-title>
+        <mat-card-subtitle>Choisissez votre langue</mat-card-subtitle>
+      </mat-card-header>
+      
+      <mat-card-content>
+        <mat-form-field appearance="fill">
+          <mat-label>Langue</mat-label>
+          <mat-select (selectionChange)="changeLanguage($event.value)">
+            <mat-option value="fr">Français</mat-option>
+            <mat-option value="en">English</mat-option>
+          </mat-select>
+        </mat-form-field>
+      </mat-card-content>
+    </mat-card>
+  </div>
+  
\ No newline at end of file
diff --git a/src/app/views/settings/settings.component.scss b/src/app/views/settings/settings.component.scss
new file mode 100644
index 0000000..689480f
--- /dev/null
+++ b/src/app/views/settings/settings.component.scss
@@ -0,0 +1,15 @@
+.settings-container {
+    margin: 20px;
+    padding: 20px;
+  }
+  
+  mat-card {
+    margin: 10px 0;
+    padding: 20px;
+    background-color: #f9f9f9;
+  }
+  
+  mat-form-field {
+    width: 100%;
+  }
+  
\ No newline at end of file
diff --git a/src/app/views/settings/settings.component.ts b/src/app/views/settings/settings.component.ts
new file mode 100644
index 0000000..1e78dca
--- /dev/null
+++ b/src/app/views/settings/settings.component.ts
@@ -0,0 +1,30 @@
+import { Component } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { MatCardModule } from '@angular/material/card';
+import { MatSelectModule } from '@angular/material/select';
+
+@Component({
+  selector: 'app-settings',
+  standalone: true,
+  imports: [MatSelectModule, MatCardModule],
+  templateUrl: './settings.component.html',
+  styleUrl: './settings.component.scss'
+})
+export class SettingsComponent {
+  constructor(private translate: TranslateService) {
+    // Définir la langue par défaut
+    this.translate.setDefaultLang('fr');
+    this.translate.use('fr'); // ou 'en' selon vos préférences
+  }
+
+  changeLanguage(lang: string) {
+    this.translate.use(lang);
+  }
+
+  saveSettings() {
+    // Logique pour enregistrer les paramètres (si nécessaire)
+    console.log('Paramètres enregistrés');
+  }
+  
+
+}
-- 
GitLab


From 66e4c27d7c096df912459c19866c1f491ece2b16 Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Mon, 14 Oct 2024 15:56:23 +0000
Subject: [PATCH 15/16] fix: refactor translation file for equipment component
 Refs #6

---
 src/app/models/equipment.model.ts             |  6 +-
 .../views/equipment/equipment.component.html  | 82 +++++++++----------
 src/assets/i18n/en.json                       | 68 +++++++--------
 src/assets/i18n/fr.json                       | 68 +++++++--------
 4 files changed, 112 insertions(+), 112 deletions(-)

diff --git a/src/app/models/equipment.model.ts b/src/app/models/equipment.model.ts
index d71f899..f7770d6 100644
--- a/src/app/models/equipment.model.ts
+++ b/src/app/models/equipment.model.ts
@@ -1,6 +1,6 @@
 export enum MaterialType {
-    ElectromagneticFlowMeter = 'EQUIPMENT.materialTypes.ElectromagneticFlowMeter',
-    PropellerFlowMeter = 'EQUIPMENT.materialTypes.PropellerFlowMeter',
-    VelocityHeadRod = 'EQUIPMENT.materialTypes.VelocityHeadRod'
+    ElectromagneticFlowMeter = 'EQUIPMENT.MATERIAL_TYPES.ELECTROMAGNETIC_FLOW_METER',
+    PropellerFlowMeter = 'EQUIPMENT.MATERIAL_TYPES.PROPELLER_FLOW_METER',
+    VelocityHeadRod = 'EQUIPMENT.MATERIAL_TYPES.VELOCITY_HEAD_ROAD'
 }
 
diff --git a/src/app/views/equipment/equipment.component.html b/src/app/views/equipment/equipment.component.html
index 2e0d6b4..355efbe 100644
--- a/src/app/views/equipment/equipment.component.html
+++ b/src/app/views/equipment/equipment.component.html
@@ -4,10 +4,10 @@
     <div class="equipment-list">
       @if((materialList$ | async)?.length! > 0){
       <div class="equipment-list-title">
-        <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1>
+        <h1>{{ 'EQUIPMENT.MATERIAL_LIST_TITLE' | translate }}</h1>
         <button mat-raised-button color="primary" [disabled]="showEditMaterialForm" class="equipment-list-title-add"
           [disabled]="needMaterial" (click)="addMaterial()">
-          <span>{{ 'EQUIPMENT.addMaterialButton' | translate }}</span>
+          <span>{{ 'EQUIPMENT.ADD_MATERIAL_BUTTON' | translate }}</span>
           <mat-icon class="icon-list-item">add</mat-icon>
         </button>
       </div>
@@ -25,7 +25,7 @@
 
         <!-- Name Column -->
         <ng-container matColumnDef="name">
-          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.nameColumn' | translate }}</th>
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.NAME' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)" id="name-row">{{
             materiel.name }}
           </td>
@@ -33,27 +33,27 @@
 
         <!-- Type Column -->
         <ng-container matColumnDef="type">
-          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.typeColumn' | translate }}</th>
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.TYPE' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{ materiel.type | translate}}
           </td>
         </ng-container>
 
         <!-- Serial Number Column -->
         <ng-container matColumnDef="serialNumber">
-          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.serialNumberColumn' | translate }}</th>
+          <th mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.SERIALNUMBER' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{
             materiel.serialNumber || '-' }}</td>
         </ng-container>
         <!-- Description Column -->
         <ng-container matColumnDef="description">
-          <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.descriptionColumn' | translate }}</th>
+          <th class="equipment-list-description" mat-header-cell *matHeaderCellDef>{{ 'EQUIPMENT.DESCRIPTION' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i=index" (click)="editMaterial(materiel, i)">{{
             materiel.description || '-' }}</td>
         </ng-container>
 
         <!-- Edit/Remove Column -->
         <ng-container matColumnDef="edit">
-          <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.actionsColumn' | translate }}</th>
+          <th class="equipment-list-action" mat-header-cell *matHeaderCellDef style=" text-align: center">{{ 'EQUIPMENT.ACTIONS' | translate }}</th>
           <td mat-cell *matCellDef="let materiel, let i =index" style="text-overflow: unset; text-align: center;">
             <button mat-icon-button color="primary" (click)="editMaterial(materiel, i)"
               [disabled]="needMaterial || showEditMaterialForm" id="edit">
@@ -77,10 +77,10 @@
       @else{
       <!-- if no created material  -->
       <div class="equipment-form-title">
-        <h1>{{ 'EQUIPMENT.materialListTitle' | translate }}</h1>
-        <p>{{ 'EQUIPMENT.noMaterialAvailable' | translate }}</p>
+        <h1>{{ 'EQUIPMENT.MATERIAL_LIST_TITLE' | translate }}</h1>
+        <p>{{ 'EQUIPMENT.NO_MATERIAL_AVAILABLE' | translate }}</p>
         @if(!needMaterial) {
-        <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.addMaterialButton' | translate }}</button>
+        <button mat-raised-button color="primary" (click)="addMaterial()" class="add-button">{{ 'EQUIPMENT.ADD_MATERIAL_BUTTON' | translate }}</button>
         }
       </div>
       }
@@ -90,14 +90,14 @@
   @if(needMaterial || showEditMaterialForm ){
     <div class="equipment-form-container">
       <form class="equipment-form" [formGroup]="form" (submit)="onSubmit()">
-        <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.newMaterialTitle' | translate) : ('EQUIPMENT.editMaterialTitle' | translate)}}</h1>
+        <h1 class="equipment-form-title">{{needMaterial ? ('EQUIPMENT.NEW_MATERIAL_TITLE' | translate) : ('EQUIPMENT.EDIT_MATERIAL_TITLE' | translate)}}</h1>
         
         <!-- Material Type Section -->
         <section class="form-section">
-          <h2>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</h2>
+          <h2>{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}</h2>
           <mat-form-field appearance="outline">
-            <mat-label>{{ 'EQUIPMENT.materialTypeLabel' | translate }}</mat-label>
-            <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.materialTypeLabel' | translate }}" (selectionChange)="onMaterialTypeChange()">
+            <mat-label>{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}</mat-label>
+            <mat-select formControlName="type" placeholder="{{ 'EQUIPMENT.MATERIAL_TYPE_LABEL' | translate }}" (selectionChange)="onMaterialTypeChange()">
               @for (type of materielTypes; track type) {
                 <mat-option [value]="type">
                   {{ type | translate }}
@@ -109,35 +109,35 @@
   
         <!-- Model Section -->
         <section class="form-section">
-          <h2>{{ 'EQUIPMENT.modelSectionTitle' | translate }}</h2>
+          <h2>{{ 'EQUIPMENT.MODEL_SECTION_TITLE' | translate }}</h2>
           <mat-form-field appearance="outline">
-            <mat-label>{{ 'EQUIPMENT.nameLabel' | translate }}</mat-label>
-            <input matInput placeholder="{{ 'EQUIPMENT.nameLabel' | translate }}" formControlName="name" autocomplete="name">
+            <mat-label>{{ 'EQUIPMENT.NAME_LABEL' | translate }}</mat-label>
+            <input matInput placeholder="{{ 'EQUIPMENT.NAME_LABEL' | translate }}" formControlName="name" autocomplete="name">
           </mat-form-field>
           @if(hasError('name', 'required')){
-            <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.requiredNameError' | translate }}</app-error-message>
+            <app-error-message [displayed]="hasError('name', 'required')">{{ 'EQUIPMENT.REQUIRED_NAME_ERROR' | translate }}</app-error-message>
           }
           <mat-form-field appearance="outline">
-            <mat-label>{{ 'EQUIPMENT.serialNumberLabel' | translate }}</mat-label>
-            <input matInput placeholder="{{ 'EQUIPMENT.serialNumberLabel' | translate }}" formControlName="serialNumber" autocomplete="off">
+            <mat-label>{{ 'EQUIPMENT.SERIALNUMBER_LABEL' | translate }}</mat-label>
+            <input matInput placeholder="{{ 'EQUIPMENT.SERIALNUMBER_LABEL' | translate }}" formControlName="serialNumber" autocomplete="off">
           </mat-form-field>
           @if(isPropeller) {
             <!-- Propeller Number -->
             <mat-form-field appearance="outline">
-              <mat-label>{{ 'EQUIPMENT.propellerNumberLabel' | translate }}</mat-label>
-              <input matInput placeholder="{{ 'EQUIPMENT.propellerNumberLabel' | translate }}" formControlName="propellerNumber" autocomplete="off">
+              <mat-label>{{ 'EQUIPMENT.PROPELLERNUMBER_LABEL' | translate }}</mat-label>
+              <input matInput placeholder="{{ 'EQUIPMENT.PROPELLERNUMBER_LABEL' | translate }}" formControlName="propellerNumber" autocomplete="off">
             </mat-form-field>
   
             <!-- Propeller Serial Number -->
             <mat-form-field appearance="outline">
-              <mat-label>{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}</mat-label>
-              <input matInput placeholder="{{ 'EQUIPMENT.propellerSerialNumberLabel' | translate }}" formControlName="propellerSerialNumber" autocomplete="off">
+              <mat-label>{{ 'EQUIPMENT.PROPELLERSERIALNUMBER_LABEL' | translate }}</mat-label>
+              <input matInput placeholder="{{ 'EQUIPMENT.PROPELLERSERIALNUMBER_LABEL' | translate }}" formControlName="propellerSerialNumber" autocomplete="off">
             </mat-form-field>
   
             <!-- Number of Velocity Formulas -->
             <mat-form-field appearance="outline">
-              <mat-label>{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}</mat-label>
-              <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.velocityFormulaCountLabel' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)">
+              <mat-label>{{ 'EQUIPMENT.VELOCITY_FORMULA_COUNT_LABEL' | translate }}</mat-label>
+              <mat-select formControlName="velocityFormulaCount" placeholder="{{ 'EQUIPMENT.VELOCITY_FORMULA_COUNT_LABEL' | translate }}" (selectionChange)="onVelocityFormulaCountChange($event.value)">
                 <mat-option *ngFor="let count of [1, 2, 3, 4, 5]" [value]="count">
                   {{count}}
                 </mat-option>
@@ -146,31 +146,31 @@
             <div formArrayName="velocityFormulas" [ngClass]="{'formulas-section': velocityFormulas.controls.length > 0}">
               @for(formula of velocityFormulas.controls; track formula; let i = $index ) {
                 <div [formGroupName]="i">
-                  <h3>{{ 'EQUIPMENT.velocityFormulaTitle' | translate }} {{ i + 1 }}</h3>
+                  <h3>{{ 'EQUIPMENT.VELOCITY_FORMULA_TITLE_LABEL' | translate }} {{ i + 1 }}</h3>
                   <div class="form-field-row">
                     <mat-form-field appearance="outline" class="form-field-inline">
-                      <mat-label>{{ 'EQUIPMENT.lowerBoundLabel' | translate }}</mat-label>
-                      <input matInput placeholder="{{ 'EQUIPMENT.lowerBoundLabel' | translate }}" formControlName="lowerBound">
+                      <mat-label>{{ 'EQUIPMENT.LOWER_BOUND_LABEL' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.LOWER_BOUND_LABEL' | translate }}" formControlName="lowerBound">
                     </mat-form-field>
                     <!-- Error Message -->
                     <mat-form-field appearance="outline" class="form-field-inline">
-                      <mat-label>{{ 'EQUIPMENT.upperBoundLabel' | translate }}</mat-label>
-                      <input matInput placeholder="{{ 'EQUIPMENT.upperBoundLabel' | translate }}" formControlName="upperBound">
+                      <mat-label>{{ 'EQUIPMENT.UPPER_BOUND_LABEL' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.UPPER_BOUND_LABEL' | translate }}" formControlName="upperBound">
                     </mat-form-field>
                   </div>
                   @if(formula.errors?.invalidBounds) {
-                    <mat-error>{{ 'EQUIPMENT.invalidBoundsError' | translate }}</mat-error>
+                    <mat-error>{{ 'EQUIPMENT.INVALID_BOUNDS_ERROR' | translate }}</mat-error>
                   }
   
                   <!-- Second row: Coefficient A and B -->
                   <div class="form-field-row">
                     <mat-form-field appearance="outline" class="form-field-inline">
-                      <mat-label>{{ 'EQUIPMENT.coefALabel' | translate }}</mat-label>
-                      <input matInput placeholder="{{ 'EQUIPMENT.coefALabel' | translate }}" formControlName="coefA">
+                      <mat-label>{{ 'EQUIPMENT.COEF_A_LABEL' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.COEF_A_LABEL' | translate }}" formControlName="coefA">
                     </mat-form-field>
                     <mat-form-field appearance="outline" class="form-field-inline">
-                      <mat-label>{{ 'EQUIPMENT.constantBLabel' | translate }}</mat-label>
-                      <input matInput placeholder="{{ 'EQUIPMENT.constantBLabel' | translate }}" formControlName="constantB">
+                      <mat-label>{{ 'EQUIPMENT.CONSTANT_B_LABEL' | translate }}</mat-label>
+                      <input matInput placeholder="{{ 'EQUIPMENT.CONSTANT_B_LABEL' | translate }}" formControlName="constantB">
                     </mat-form-field>
                   </div>
                 </div>
@@ -180,15 +180,15 @@
         </section>
   
         <section class="form-section">
-          <h2>{{ 'EQUIPMENT.additionalInfoTitle' | translate }}</h2>
+          <h2>{{ 'EQUIPMENT.ADDITIONAL_INFO_TITLE' | translate }}</h2>
           <mat-form-field class="equipment-description" appearance="outline">
-            <mat-label>{{ 'EQUIPMENT.descriptionLabel' | translate }}</mat-label>
-            <textarea matInput placeholder="{{ 'EQUIPMENT.descriptionLabel' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea>
+            <mat-label>{{ 'EQUIPMENT.DESCRIPTION_LABEL' | translate }}</mat-label>
+            <textarea matInput placeholder="{{ 'EQUIPMENT.DESCRIPTION_LABEL' | translate }}" formControlName="description" rows="4" autocomplete="off"></textarea>
           </mat-form-field>
         </section>
   
-        <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.submitButton' | translate }}</button>
-        <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.cancelButton' | translate }}</button>
+        <button style="margin-right: 4%;" mat-flat-button color="primary" class="submit-button" [disabled]="!form.valid">{{ 'EQUIPMENT.SUBMIT_BUTTON' | translate }}</button>
+        <button mat-flat-button color="warn" (click)="closeMaterialForm()" class="submit-button">{{ 'EQUIPMENT.CANCEL_BUTTON' | translate }}</button>
       </form>
     </div>
   }
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 0c16df3..ae2ddd6 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -129,41 +129,41 @@
     "GRAPHICAL_REPRESENTATION": "Graphical representation"
 },
 "EQUIPMENT": {
-  "materialListTitle": "Material List",
-  "addMaterialButton": "Add",
-  "noMaterialAvailable": "No material available.",
-  "actionsColumn": "Actions",
-  "nameColumn": "Name",
-  "typeColumn": "Type",
-  "serialNumberColumn": "Serial Number",
-  "descriptionColumn": "Description",
-  "editButton": "Edit",
-  "deleteButton": "Delete",
-  "newMaterialTitle": "New Material",
-  "editMaterialTitle": "Edit Material",
-  "materialTypeLabel": "Material Type",
-  "materialTypes": {
-    "ElectromagneticFlowMeter": "Electromagnetic Flow Meter",
-    "PropellerFlowMeter": "Propeller Flow Meter",
-    "VelocityHeadRod": "Velocity Head Rod"
+  "MATERIAL_LIST_TITLE": "Material List",
+  "ADD_MATERIAL_BUTTON": "Add",
+  "NO_MATERIAL_AVAILABLE": "No material available.",
+  "ACTIONS": "Actions",
+  "NAME": "Name",
+  "TYPE": "Type",
+  "SERIALNUMBER": "Serial Number",
+  "DESCRIPTION": "Description",
+  "EDIT_BUTTON": "Edit",
+  "DELETE_BUTTON": "Delete",
+  "NEW_MATERIAL_TITLE": "New Material",
+  "EDIT_MATERIAL_TITLE": "Edit Material",
+  "MATERIAL_TYPE_LABEL": "Material Type",
+  "MATERIAL_TYPES": {
+    "ELECTROMAGNETIC_FLOW_METER": "Electromagnetic flow meter",
+    "PROPELLER_FLOW_METER": "Propeller flow meter",
+    "VELOCITY_HEAD_ROAD": "Velocity head road"
   },
-  "modelSectionTitle": "Model",
-  "nameLabel": "Name",
-  "serialNumberLabel": "Serial Number",
-  "propellerNumberLabel": "Propeller Number",
-  "propellerSerialNumberLabel": "Propeller Serial Number",
-  "velocityFormulaCountLabel": "Number of Velocity Formulas",
-  "velocityFormulaTitle": "Velocity Formula n°",
-  "lowerBoundLabel": "Lower Bound",
-  "upperBoundLabel": "Upper Bound",
-  "coefALabel": "Coefficient A",
-  "constantBLabel": "Constant B",
-  "invalidBoundsError": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.",
-  "requiredNameError": "The name is required.",
-  "additionalInfoTitle": "Additional information",
-  "descriptionLabel": "Description",
-  "submitButton": "Submit",
-  "cancelButton": "Cancel"
+  "MODEL_SECTION_TITLE": "Model",
+  "NAME_LABEL": "Name",
+  "SERIALNUMBER_LABEL": "Serial Number",
+  "PROPELLERNUMBER_LABEL": "Propeller Number",
+  "PROPELLERSERIALNUMBER_LABEL": "Propeller Serial Number",
+  "VELOCITY_FORMULA_COUNT_LABEL": "Number of Velocity Formulas",
+  "VELOCITY_FORMULA_TITLE_LABEL": "Velocity Formula n°",
+  "LOWER_BOUND_LABEL": "Lower Bound",
+  "UPPER_BOUND_LABEL": "Upper Bound",
+  "COEF_A_LABEL": "Coefficient A",
+  "CONSTANT_B_LABEL": "Constant B",
+  "INVALID_BOUNDS_ERROR": "The specified bounds are incorrect. The lower bound must be strictly less than the upper bound.",
+  "REQUIRED_NAME_ERROR": "The name is required.",
+  "ADDITIONAL_INFO_TITLE": "Additional information",
+  "DESCRIPTION_LABEL": "Description",
+  "SUBMIT_BUTTON": "Submit",
+  "CANCEL_BUTTON": "Cancel"
 },
 "NEXT": "Next",
 "PREVIOUS": "Previous",
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index 817f5c3..467cbb4 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -129,41 +129,41 @@
     "GRAPHICAL_REPRESENTATION": "Représentation graphique"
   },
   "EQUIPMENT": {
-    "materialListTitle": "Liste de Matériel",
-    "addMaterialButton": "Ajouter",
-    "noMaterialAvailable": "Aucun matériel disponible.",
-    "actionsColumn": "Actions",
-    "nameColumn": "Nom",
-    "typeColumn": "Type",
-    "serialNumberColumn": "Numéro de Série",
-    "descriptionColumn": "Description",
-    "editButton": "Modifier",
-    "deleteButton": "Supprimer",
-    "newMaterialTitle": "Nouveau Matériel",
-    "editMaterialTitle": "Modifier Matériel",
-    "materialTypeLabel": "Type de Matériel",
-    "materialTypes": {
-      "ElectromagneticFlowMeter": "Courantomètre Électromagnétique",
-      "PropellerFlowMeter": "Moulinet",
-      "VelocityHeadRod": "Perche à Charge Dynamique Transparente"
+    "MATERIAL_LIST_TITLE": "Liste de Matériel",
+    "ADD_MATERIAL_BUTTON": "Ajouter",
+    "NO_MATERIAL_AVAILABLE": "Aucun matériel disponible.",
+    "ACTIONS": "Actions",
+    "NAME": "Nom",
+    "TYPE": "Type",
+    "SERIALNUMBER": "Numéro de Série",
+    "DESCRIPTION": "Description",
+    "EDIT_BUTTON": "Modifier",
+    "DELETE_BUTTON": "Supprimer",
+    "NEW_MATERIAL_TITLE": "Nouveau Matériel",
+    "EDIT_MATERIAL_TITLE": "Modifier Matériel",
+    "MATERIAL_TYPE_LABEL": "Type de Matériel",
+    "MATERIAL_TYPES": {
+      "ELECTROMAGNETIC_FLOW_METER": "Courantomètre Électromagnétique",
+      "PROPELLER_FLOW_METER": "Moulinet",
+      "VELOCITY_HEAD_ROAD": "Perche à Charge Dynamique Transparente"
     },
-    "modelSectionTitle": "Modèle",
-    "nameLabel": "Nom",
-    "serialNumberLabel": "Numéro de Série",
-    "propellerNumberLabel": "Numéro de Moulinet",
-    "propellerSerialNumberLabel": "Numéro de Série du Moulinet",
-    "velocityFormulaCountLabel": "Nombre de Formules de Vitesse",
-    "velocityFormulaTitle": "Formule de Vitesse n°",
-    "lowerBoundLabel": "Limite Inférieure",
-    "upperBoundLabel": "Limite Supérieure",
-    "coefALabel": "Coefficient A",
-    "constantBLabel": "Constante B",
-    "invalidBoundsError": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.",
-    "requiredNameError": "Le nom est requis.",
-    "additionalInfoTitle": "Informations complémentaires",
-    "descriptionLabel": "Description",
-    "submitButton": "Valider",
-    "cancelButton": "Annuler"
+    "MODEL_SECTION_TITLE": "Modèle",
+    "NAME_LABEL": "Nom",
+    "SERIALNUMBER_LABEL": "Numéro de Série",
+    "PROPELLERNUMBER_LABEL": "Numéro de Moulinet",
+    "PROPELLERSERIALNUMBER_LABEL": "Numéro de Série du Moulinet",
+    "VELOCITY_FORMULA_COUNT_LABEL": "Nombre de Formules de Vitesse",
+    "VELOCITY_FORMULA_TITLE_LABEL": "Formule de Vitesse n°",
+    "LOWER_BOUND_LABEL": "Limite Inférieure",
+    "UPPER_BOUND_LABEL": "Limite Supérieure",
+    "COEF_A_LABEL": "Coefficient A",
+    "CONSTANT_B_LABEL": "Constante B",
+    "INVALID_BOUNDS_ERROR": "Les limites spécifiées sont incorrectes. La limite inférieure doit être strictement inférieure à la limite supérieure.",
+    "REQUIRED_NAME_ERROR": "Le nom est requis.",
+    "ADDITIONAL_INFO_TITLE": "Informations complémentaires",
+    "DESCRIPTION_LABEL": "Description",
+    "SUBMIT_BUTTON": "Valider",
+    "CANCEL_BUTTON": "Annuler"
   },
   "NEXT": "Suivant",
   "PREVIOUS": "Précédent",
-- 
GitLab


From 7427477aa7d3a57f32919bb00f039e197088a2ed Mon Sep 17 00:00:00 2001
From: Jean-Pascal AUBRY <jean-pascal.aubry@inrae.fr>
Date: Tue, 15 Oct 2024 09:30:33 +0000
Subject: [PATCH 16/16] fix:  add LanguageService for handling language
 settings Refs #6

---
 src/app/app.component.ts                      |  9 +-
 src/app/services/language/language.service.ts | 28 ++++++
 .../views/settings/settings.component.html    | 43 +++++----
 .../views/settings/settings.component.scss    | 95 ++++++++++++++++---
 src/app/views/settings/settings.component.ts  | 33 ++++---
 5 files changed, 156 insertions(+), 52 deletions(-)
 create mode 100644 src/app/services/language/language.service.ts

diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index a51cede..6f77559 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -24,6 +24,7 @@ import { DialogConfirmNewGaugingComponent } from './components/dialog/dialog-con
 import { GaugingFormService } from './services/forms/gauging-form.service';
 import { TranslateModule, TranslateService } from '@ngx-translate/core';
 import { MatTooltipModule } from '@angular/material/tooltip';
+import { LanguageService } from './services/language/language.service';
 
 
 @Component({
@@ -41,16 +42,16 @@ export class AppComponent {
   gaugingList$: Observable<Gauging[]>;
   materialList: Material[] = [];
 
-  constructor(private translate: TranslateService,private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
+  constructor(private languageService: LanguageService, private dialog: MatDialog, private equipmentService: EquipmentService, private gaugingService: GaugingService, private gaugingFormService: GaugingFormService, private router: Router) {
     this.materialList$ = this.equipmentService.materialList$;
     this.gaugingList$ = this.gaugingService.gaugingList$;
-    this.translate.addLangs(['fr', 'en']);
-    this.translate.setDefaultLang('fr');
-    this.translate.use('en');
   }
 
   ngOnInit(): void {
     // Charger les données de session depuis le localStorage
+    // Détecter et appliquer la langue par défaut via le LanguageService
+    const browserLang = this.languageService.detectBrowserLanguage();
+    this.languageService.setDefaultLanguage(browserLang);
     this.session.loadFromLocalStorage();
     if (typeof window !== 'undefined' && typeof sessionStorage !== 'undefined') {
       const wasPageRefreshed = sessionStorage.getItem('pageRefreshed');
diff --git a/src/app/services/language/language.service.ts b/src/app/services/language/language.service.ts
new file mode 100644
index 0000000..a1802bb
--- /dev/null
+++ b/src/app/services/language/language.service.ts
@@ -0,0 +1,28 @@
+import { Injectable } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class LanguageService {
+  supportedLanguages = ['fr', 'en'];
+  constructor(private translate: TranslateService) {}
+
+  // Détecter la langue du navigateur et retourner l'anglais par défaut si elle n'est pas supportée
+  detectBrowserLanguage(): string {
+    const browserLang = navigator.language.split('-')[0];
+    // Si la langue du navigateur est supportée, on l'utilise, sinon on met 'en' (anglais) par défaut
+    return this.supportedLanguages.includes(browserLang) ? browserLang : 'en';
+  }
+
+  // Changer la langue
+  changeLanguage(lang: string) {
+    this.translate.use(lang);
+  }
+
+  // Définir la langue par défaut
+  setDefaultLanguage(lang: string) {
+    this.translate.setDefaultLang(lang);
+    this.translate.use(lang);
+  }
+}
diff --git a/src/app/views/settings/settings.component.html b/src/app/views/settings/settings.component.html
index ee9dfd2..7ecbe97 100644
--- a/src/app/views/settings/settings.component.html
+++ b/src/app/views/settings/settings.component.html
@@ -1,20 +1,23 @@
-<div class="settings-container">
-    <h2>Paramètres</h2>
-    <mat-card>
-      <mat-card-header>
-        <mat-card-title>Langue</mat-card-title>
-        <mat-card-subtitle>Choisissez votre langue</mat-card-subtitle>
-      </mat-card-header>
-      
-      <mat-card-content>
-        <mat-form-field appearance="fill">
-          <mat-label>Langue</mat-label>
-          <mat-select (selectionChange)="changeLanguage($event.value)">
-            <mat-option value="fr">Français</mat-option>
-            <mat-option value="en">English</mat-option>
-          </mat-select>
-        </mat-form-field>
-      </mat-card-content>
-    </mat-card>
-  </div>
-  
\ No newline at end of file
+<div class="container">
+  <h1>
+    <mat-label>
+      <mat-icon class="icon-list-item">settings</mat-icon> Paramètres
+    </mat-label>
+  </h1>
+  <mat-card class="form-section">
+    <mat-card-header>
+      <mat-card-title>
+        <mat-icon>public</mat-icon> Langue
+      </mat-card-title>
+    </mat-card-header>
+    <mat-card-content>
+      <mat-form-field appearance="fill">
+        <mat-label>Langue</mat-label>
+        <mat-select [(value)]="selectedLanguage" (selectionChange)="changeLanguage($event.value)">
+          <mat-option value="fr">Français</mat-option>
+          <mat-option value="en">English</mat-option>
+        </mat-select>
+      </mat-form-field>
+    </mat-card-content>
+  </mat-card>
+</div>
diff --git a/src/app/views/settings/settings.component.scss b/src/app/views/settings/settings.component.scss
index 689480f..05f5ead 100644
--- a/src/app/views/settings/settings.component.scss
+++ b/src/app/views/settings/settings.component.scss
@@ -1,15 +1,88 @@
+$primary: #00a3a6;
+$light-primary: #b3e3e4;
+$warn: #ff6347;
+$light-warn: #FBE9E7;
+$accent: #735fff;
+$light-accent: #c6c1dc;
+$sub-container-background: #f5f5f5;
+$table-header-background: #797870;
+$border-color: #ccc;
+$odd-row-color: rgba(0, 0, 0, 0.028);
+$pair-row-color: #ffffff;
+$card-shadow-color: rgba(0, 0, 0, 0.1);
+
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 95%;
+  margin: 20px;
+  border: 1px solid $border-color;
+  border-radius: 12px;
+  box-shadow: 0 4px 8px $card-shadow-color;
+  background-color: $sub-container-background;
+  padding: 20px;
+}
+
 .settings-container {
-    margin: 20px;
-    padding: 20px;
-  }
+  flex: 1;
+  margin: 10px;
+  padding: 15px;
+  border: 1px solid $border-color;
+  border-radius: 10px;
+  background-color: #ffffff;
+  box-shadow: 0 2px 5px $card-shadow-color;
+}
+
+h1 {
+  font-size: 24px;
+  text-align: center;
+  margin-bottom: 20px;
+}
+
+mat-icon {
+  vertical-align: middle;
+}
+
+.form-section {
+  margin-bottom: 30px;
+  padding: 25px;
+  border: 1px solid $border-color;
+  border-radius: 10px;
+  background-color: #ffffff;
+  box-shadow: 0 2px 4px $card-shadow-color;
+  transition: box-shadow 0.3s ease;
   
-  mat-card {
-    margin: 10px 0;
-    padding: 20px;
-    background-color: #f9f9f9;
+  &:hover {
+    box-shadow: 0 4px 10px $card-shadow-color;
   }
-  
-  mat-form-field {
-    width: 100%;
+}
+
+mat-card-header {
+  border-radius: 8px 8px 0 0;
+}
+
+mat-card-title {
+  font-size: 20px;
+  color: $primary;
+  font-weight: 500;
+}
+
+mat-form-field {
+  width: 100%;
+  margin-top: 15px;
+}
+
+mat-select {
+  border-radius: 5px;
+}
+
+mat-option {
+  &:hover {
+    background-color: $light-accent;
   }
-  
\ No newline at end of file
+}
+
+mat-card-content {
+  padding: 20px;
+  font-size: 16px;
+}
diff --git a/src/app/views/settings/settings.component.ts b/src/app/views/settings/settings.component.ts
index 1e78dca..19c6e8f 100644
--- a/src/app/views/settings/settings.component.ts
+++ b/src/app/views/settings/settings.component.ts
@@ -1,30 +1,29 @@
-import { Component } from '@angular/core';
-import { TranslateService } from '@ngx-translate/core';
+import { Component, OnInit } from '@angular/core';
 import { MatCardModule } from '@angular/material/card';
 import { MatSelectModule } from '@angular/material/select';
+import { MatIconModule } from '@angular/material/icon';
+import { LanguageService } from '../../services/language/language.service';
 
 @Component({
   selector: 'app-settings',
   standalone: true,
-  imports: [MatSelectModule, MatCardModule],
+  imports: [MatSelectModule, MatCardModule, MatIconModule],
   templateUrl: './settings.component.html',
-  styleUrl: './settings.component.scss'
+  styleUrls: ['./settings.component.scss']
 })
-export class SettingsComponent {
-  constructor(private translate: TranslateService) {
-    // Définir la langue par défaut
-    this.translate.setDefaultLang('fr');
-    this.translate.use('fr'); // ou 'en' selon vos préférences
-  }
+export class SettingsComponent implements OnInit {
+  selectedLanguage: string | undefined;
 
-  changeLanguage(lang: string) {
-    this.translate.use(lang);
-  }
+  constructor(private languageService: LanguageService) {}
 
-  saveSettings() {
-    // Logique pour enregistrer les paramètres (si nécessaire)
-    console.log('Paramètres enregistrés');
+  ngOnInit(): void {
+    // Utiliser le service pour détecter la langue du navigateur et définir la langue par défaut (anglais si aucune n'est supportée)
+    this.selectedLanguage = this.languageService.detectBrowserLanguage();
+    this.languageService.setDefaultLanguage(this.selectedLanguage);
   }
-  
 
+  changeLanguage(lang: string) {
+    this.languageService.changeLanguage(lang);
+    this.selectedLanguage = lang;
+  }
 }
-- 
GitLab