Skip to content

Commit f8c1a92

Browse files
feat(i18n): Finalize translations (#57)
* createProjectDialog * project dashboard * edit project * project list * template variables 1 * template variable editor * edit version component * project version list * project service * user edit dialog * user list * me component * dialogs * . * language switcher * localized dates * update dependencies * review fixes Co-authored-by: Tom <[email protected]>
1 parent 214c9f6 commit f8c1a92

39 files changed

+2355
-1949
lines changed

frontend/package-lock.json

Lines changed: 1599 additions & 1691 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,50 +13,50 @@
1313
},
1414
"private": true,
1515
"dependencies": {
16-
"@angular/animations": "12.0.3",
17-
"@angular/cdk": "12.0.3",
18-
"@angular/common": "12.0.3",
19-
"@angular/compiler": "12.0.3",
20-
"@angular/core": "12.0.3",
16+
"@angular/animations": "12.2.3",
17+
"@angular/cdk": "12.2.3",
18+
"@angular/common": "12.2.3",
19+
"@angular/compiler": "12.2.3",
20+
"@angular/core": "12.2.3",
2121
"@angular/flex-layout": "12.0.0-beta.34",
22-
"@angular/forms": "12.0.3",
23-
"@angular/localize": "12.0.3",
24-
"@angular/material": "12.0.3",
25-
"@angular/platform-browser": "12.0.3",
26-
"@angular/platform-browser-dynamic": "12.0.3",
27-
"@angular/router": "12.0.3",
22+
"@angular/forms": "12.2.3",
23+
"@angular/localize": "12.2.3",
24+
"@angular/material": "12.2.3",
25+
"@angular/platform-browser": "12.2.3",
26+
"@angular/platform-browser-dynamic": "12.2.3",
27+
"@angular/router": "12.2.3",
2828
"@mdi/svg": "5.9.55",
2929
"@ngx-translate/core": "13.0.0",
3030
"@ngx-translate/http-loader": "6.0.0",
3131
"@ngxs/logger-plugin": "3.7.2",
3232
"@ngxs/storage-plugin": "3.7.2",
3333
"@ngxs/store": "3.7.2",
34-
"core-js": "3.13.1",
35-
"date-fns": "2.22.1",
36-
"hash-it": "5.0.0",
34+
"core-js": "3.16.3",
35+
"date-fns": "2.23.0",
36+
"hash-it": "5.0.2",
3737
"lodash": "4.17.21",
3838
"messageformat": "2.3.0",
3939
"ngx-mat-select-search": "3.3.0",
4040
"ngx-monaco-editor": "9.0.0",
41-
"ngx-translate-messageformat-compiler": "4.9.0",
41+
"ngx-translate-messageformat-compiler": "4.10.0",
4242
"rxjs": "6.6.7",
43-
"tslib": "2.2.0",
43+
"tslib": "2.3.1",
4444
"typescript-logging": "1.0.0",
4545
"web-animations-js": "2.3.2",
4646
"zone.js": "0.11.4"
4747
},
4848
"devDependencies": {
49-
"@angular-devkit/build-angular": "12.0.3",
50-
"@angular/cli": "12.0.3",
51-
"@angular/compiler-cli": "12.0.3",
52-
"@angular/language-service": "12.0.3",
49+
"@angular-devkit/build-angular": "12.2.3",
50+
"@angular/cli": "12.2.3",
51+
"@angular/compiler-cli": "12.2.3",
52+
"@angular/language-service": "12.2.3",
5353
"@ngxs/devtools-plugin": "3.7.2",
5454
"@types/jasmine": "3.7.6",
5555
"@types/jasminewd2": "2.0.9",
5656
"@types/lodash": "4.14.170",
5757
"@types/node": "15.12.0",
58-
"codelyzer": "^6.0.0",
59-
"gzipper": "4.3.0",
58+
"codelyzer": "^6.0.2",
59+
"gzipper": "5.0.0",
6060
"jasmine-core": "~3.6.0",
6161
"jasmine-spec-reporter": "~5.0.0",
6262
"karma": "~6.3.3",

frontend/src/app/app.module.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ import {
9696
} from "./configuration/configuration";
9797
import {MainComponent} from "./views/main/main.component";
9898
import {ExpandableMenuComponent} from "./components/expandable-menu/expandable-menu.component";
99-
import {NgxsModule} from "@ngxs/store";
99+
import {NgxsModule, Store} from "@ngxs/store";
100100
import {environment} from "../environments/environment.prod";
101101
import {NgxsStoragePluginModule} from "@ngxs/storage-plugin";
102102
import {NgxsReduxDevtoolsPluginModule} from "@ngxs/devtools-plugin";
@@ -115,6 +115,8 @@ import {HelmRegistryListComponent} from "./registries/helm/list/helm-registry-li
115115
import {HelmRegistryEditDialogComponent} from "./registries/helm/edit-dialog/helm-registry-edit-dialog.component";
116116
import {DistinctObjectArrayPipe} from "./util/distinct-object-array.pipe";
117117
import {FilterDeepPipe} from "./util/filter-deep.pipe";
118+
import {I18nSwitcherComponent} from "./components/i18n-switcher/i18n-switcher.component";
119+
import {I18nState} from "./store/i18n/i18n.state";
118120

119121
@NgModule({
120122
declarations: [
@@ -172,7 +174,8 @@ import {FilterDeepPipe} from "./util/filter-deep.pipe";
172174
HelmRegistryListComponent,
173175
HelmRegistryEditDialogComponent,
174176
DistinctObjectArrayPipe,
175-
FilterDeepPipe
177+
FilterDeepPipe,
178+
I18nSwitcherComponent
176179
],
177180
imports: [
178181
BrowserModule,
@@ -213,7 +216,7 @@ import {FilterDeepPipe} from "./util/filter-deep.pipe";
213216
MatRadioModule,
214217
NgxMatSelectSearchModule,
215218
NgxsModule.forRoot(appStates, {developmentMode: !environment.production}),
216-
NgxsStoragePluginModule.forRoot({key: [ThemingState]}),
219+
NgxsStoragePluginModule.forRoot({key: [ThemingState, I18nState]}),
217220
NgxsReduxDevtoolsPluginModule.forRoot(),
218221
NgxsLoggerPluginModule.forRoot(),
219222
TranslateModule.forRoot({
@@ -262,9 +265,15 @@ import {FilterDeepPipe} from "./util/filter-deep.pipe";
262265
bootstrap: [AppComponent]
263266
})
264267
export class AppModule {
265-
constructor(translateService: TranslateService, matIconRegistry: MatIconRegistry, domSanitizer: DomSanitizer, rest: RestService, auth: AuthService, ws: WebSocketService) {
268+
constructor(translateService: TranslateService,
269+
matIconRegistry: MatIconRegistry,
270+
domSanitizer: DomSanitizer,
271+
rest: RestService,
272+
auth: AuthService,
273+
ws: WebSocketService,
274+
store: Store) {
266275
configureSvgIcons(matIconRegistry, domSanitizer);
267-
configureTranslations(translateService);
276+
configureTranslations(translateService, store);
268277

269278
auth.isAuthenticated().subscribe(authenticated => {
270279
if (authenticated) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<button mat-icon-button [matMenuTriggerFor]="modeMenu">
2+
<mat-icon svgIcon="language"></mat-icon>
3+
</button>
4+
<mat-menu #modeMenu class="i18n-switcher-menu">
5+
<button mat-menu-item *ngFor="let locale of locales" (click)="setLocale(locale.locale)" [class.active]="(currentLocale$ | async) === locale.locale">
6+
<mat-icon [svgIcon]="((currentLocale$ | async) === locale.locale) ? 'mdi:radiobox-marked' : 'mdi:radiobox-blank'"></mat-icon>
7+
<span>{{locale.label}}</span>
8+
</button>
9+
</mat-menu>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "src/styles/mixins";
2+
3+
.active {
4+
font-weight: 600;
5+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
@use '~@angular/material' as mat;
2+
@import "src/styles/mixins";
3+
4+
@mixin i18n-switcher-component-theme($theme) {
5+
$primary: map-get($theme, primary);
6+
.i18n-switcher-menu {
7+
.active {
8+
font-weight: 600;
9+
color: mat.get-color-from-palette($primary, 600);
10+
}
11+
}
12+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import {Component} from "@angular/core";
2+
import {Select, Store} from "@ngxs/store";
3+
import {Observable} from "rxjs";
4+
import {I18nState, OnekoLocale, SetLocale} from "../../store/i18n/i18n.state";
5+
6+
@Component({
7+
selector: 'on-i18n-switcher',
8+
templateUrl: './i18n-switcher.component.html',
9+
styleUrls: ['./i18n-switcher.component.scss']
10+
})
11+
export class I18nSwitcherComponent {
12+
13+
locales: Array<{ label: string, locale: OnekoLocale }>;
14+
15+
@Select(I18nState.locale) currentLocale$: Observable<OnekoLocale>;
16+
17+
constructor(private store: Store) {
18+
this.locales = [
19+
{
20+
label: 'English',
21+
locale: 'en'
22+
}, {
23+
label: 'Deutsch',
24+
locale: 'de'
25+
}
26+
];
27+
}
28+
29+
setLocale(locale: OnekoLocale) {
30+
this.store.dispatch(new SetLocale(locale));
31+
}
32+
}

frontend/src/app/configuration/configuration.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
} from '@angular/animations/browser';
88
import {TranslateService} from "@ngx-translate/core";
99
import {MatPaginatorIntl} from "@angular/material/paginator";
10+
import {Store} from "@ngxs/store";
11+
import {I18nState} from "../store/i18n/i18n.state";
1012

1113
export const configureSvgIcons = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer) => {
1214
iconRegistry.addSvgIconResolver((name, namespace) => {
@@ -27,10 +29,11 @@ export const provideAnimationDriverBasedOnUserPreferences = (): AnimationDriver
2729
return prefersReducedMotion ? noop : driver;
2830
};
2931

30-
export const configureTranslations = (translate: TranslateService) => {
32+
export const configureTranslations = (translate: TranslateService, store: Store) => {
3133
translate.setDefaultLang('en');
32-
//translate.use(translate.getBrowserLang()); // todo: use once translation is finished
33-
translate.use('en'); // todo: remove once translation is finished
34+
store.select(I18nState.locale).subscribe(locale => {
35+
translate.use(locale);
36+
});
3437
};
3538

3639
export const configureMatPaginatorI18n = (translate: TranslateService): MatPaginatorIntl => {

frontend/src/app/navigation/navigation.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<mat-icon svgIcon="menu"></mat-icon>
44
</button>
55
<div fxFlex *ngIf="!isDesktop"></div>
6+
<on-i18n-switcher></on-i18n-switcher>
67
<on-theme-switcher></on-theme-switcher>
78
<mat-divider [vertical]="true"></mat-divider>
89
<button mat-button routerLinkActive="active" [matMenuTriggerFor]="userMenu">

frontend/src/app/project/create-project-dialog/create-project-dialog.component.html

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="project-edit-dialog create-dialog">
2-
<h1 mat-dialog-title *ngIf="!showImport">Create a new project</h1>
3-
<h1 mat-dialog-title *ngIf="showImport">Import a project</h1>
2+
<h1 mat-dialog-title *ngIf="!showImport">{{ 'components.project.createProjectDialog.createNewProject' | translate }}</h1>
3+
<h1 mat-dialog-title *ngIf="showImport">{{ 'components.project.createProjectDialog.importProject' | translate }}</h1>
44
<div mat-dialog-content>
55
<mat-horizontal-stepper [linear]="true" #stepper>
66
<ng-template matStepperIcon="import" let-index="index" *ngIf="showImport">
@@ -16,73 +16,70 @@ <h1 mat-dialog-title *ngIf="showImport">Import a project</h1>
1616
{{index + 1}}
1717
</ng-template>
1818
<mat-step [stepControl]="projectImportFormGroup" *ngIf="showImport">
19-
<ng-template matStepLabel>Import a project configuration file</ng-template>
20-
<p>Import a project from a <i>.json</i> configuration file. You can configure the import in the next steps.</p>
19+
<ng-template matStepLabel>{{ 'components.project.createProjectDialog.importProjectConfigurationFile' | translate }}</ng-template>
20+
<div [innerHTML]="'components.project.createProjectDialog.importProjectDescription' | translate"></div>
2121
<file-upload *ngIf="!projectExport"
2222
[multiple]="false"
2323
(filesCallback)="onProjectExportUpload($event)"
2424
displayType="dnd"
2525
accept=".json"
26-
label="Upload project configuration"></file-upload>
26+
[label]="'components.project.createProjectDialog.fileUploadLabel' | translate"></file-upload>
2727
<div *ngIf="projectExport">
2828
<p fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
2929
<mat-icon svgIcon="check"></mat-icon>
30-
<span>Upload successful!</span>
30+
<span>{{ 'components.project.createProjectDialog.uploadSuccessful' | translate }}</span>
3131
</p>
32-
<p>The imported project has <b>{{projectExport.defaultConfigurationTemplates.length}}</b> configuration templates.</p>
32+
<div [innerHTML]="'components.project.createProjectDialog.importCompleteDescription' | translate: {count: projectExport.defaultConfigurationTemplates.length}"></div>
3333
</div>
3434
<div>
35-
<button mat-button matStepperNext>Next</button>
35+
<button mat-button matStepperNext>{{ 'components.project.createProjectDialog.next' | translate }}</button>
3636
</div>
3737
</mat-step>
3838
<mat-step [stepControl]="projectNameFormGroup">
3939
<form [formGroup]="projectNameFormGroup">
40-
<ng-template matStepLabel>Enter the new projects name</ng-template>
41-
<p>Enter a meaningful name for your new project.</p>
42-
<p>The name can be chosen arbitrarily but should be distinguishable from the names of yet existing projects.</p>
40+
<ng-template matStepLabel>{{ 'components.project.createProjectDialog.enterProjectNameLabel' | translate }}</ng-template>
41+
<div [innerHTML]="'components.project.createProjectDialog.enterProjectNameDescription' | translate"></div>
4342
<mat-form-field>
44-
<input matInput placeholder="Project name" required formControlName="nameCtrl" >
43+
<input matInput [placeholder]="'components.project.createProjectDialog.projectName' | translate" required formControlName="nameCtrl" >
4544
</mat-form-field>
4645
<figure *ngIf="getCollidingProjectName()" class="warning">
47-
<figcaption>Warning</figcaption>
48-
<p>There is yet a project with the name {{getCollidingProjectName()}}.</p>
46+
<figcaption>{{ 'general.warning' | translate }}</figcaption>
47+
<p>{{ 'components.project.createProjectDialog.collidingProjectNameMessage' | translate: {name: getCollidingProjectName()} }}</p>
4948
</figure>
5049
<div>
51-
<button mat-button matStepperPrevious *ngIf="showImport">Back</button>
52-
<button mat-button matStepperNext>Next</button>
50+
<button mat-button matStepperPrevious *ngIf="showImport">{{'components.project.createProjectDialog.back' | translate}}</button>
51+
<button mat-button matStepperNext>{{ 'components.project.createProjectDialog.next' | translate }}</button>
5352
</div>
5453
</form>
5554
</mat-step>
5655
<mat-step [stepControl]="dockerRegistryFormGroup">
5756
<form [formGroup]="dockerRegistryFormGroup">
58-
<ng-template matStepLabel>Select a docker registry</ng-template>
59-
<p>All images for this project will be picked from the docker registry you select here.</p>
57+
<ng-template matStepLabel>{{ 'components.project.createProjectDialog.selectDockerRegistry' | translate }}</ng-template>
58+
<p>{{ 'components.project.createProjectDialog.selectDockerRegistryDescription' | translate }}</p>
6059
<mat-form-field>
61-
<mat-label>Docker registry</mat-label>
60+
<mat-label>{{ 'components.project.createProjectDialog.dockerRegistry' | translate }}</mat-label>
6261
<mat-select required formControlName="registryUuidCtrl">
6362
<mat-option *ngFor="let dockerRegistry of dockerRegistries" [value]="dockerRegistry.uuid">
6463
{{ dockerRegistry.name }}
6564
</mat-option>
6665
</mat-select>
6766
</mat-form-field>
6867
<div>
69-
<button mat-button matStepperPrevious>Back</button>
70-
<button mat-button matStepperNext>Next</button>
68+
<button mat-button matStepperPrevious>{{'components.project.createProjectDialog.back' | translate}}</button>
69+
<button mat-button matStepperNext>{{ 'components.project.createProjectDialog.next' | translate }}</button>
7170
</div>
7271
</form>
7372
</mat-step>
7473
<mat-step [stepControl]="imageNameFormGroup">
7574
<form [formGroup]="imageNameFormGroup">
76-
<ng-template matStepLabel>Enter the new projects image name</ng-template>
77-
<p>Type in the name of the docker image. This must match the image name as present on the docker registry.</p>
78-
<p>We totally would like to offer you a list of image names to select from, but the docker API for retrieving these is a bit picky in terms of permissions.</p>
79-
<p><span>Until we fix this, you have to type this on your own.</span><mat-icon svgIcon="mdi:emoticon-sad"></mat-icon></p>
75+
<ng-template matStepLabel>{{ 'components.project.createProjectDialog.enterProjectImageName' | translate }}</ng-template>
76+
<p>{{ 'components.project.createProjectDialog.enterProjectImageNameDescription' | translate }}</p>
8077
<mat-form-field>
8178
<input matInput placeholder="Image name" required formControlName="imageNameCtrl" >
8279
</mat-form-field>
8380
<div>
84-
<button mat-button matStepperPrevious>Back</button>
85-
<button mat-button [disabled]="!imageNameFormGroup.valid" (click)="finish()">Done</button>
81+
<button mat-button matStepperPrevious>{{'components.project.createProjectDialog.back' | translate}}</button>
82+
<button mat-button [disabled]="!imageNameFormGroup.valid" (click)="finish()">{{ 'general.done' | translate }}</button>
8683
</div>
8784
</form>
8885
</mat-step>

0 commit comments

Comments
 (0)