diff --git a/package-lock.json b/package-lock.json index f4e21a2..e51e586 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,8 @@ "@angular/platform-browser-dynamic": "", "@angular/router": "", "@ng-bootstrap/ng-bootstrap": "", + "@ngx-translate/core": "14.0.0", + "@ngx-translate/http-loader": "7.0.0", "angular-oauth2-oidc": "", "bootstrap": "", "bootstrap-icons": "", @@ -2758,6 +2760,31 @@ "webpack": "^5.30.0" } }, + "node_modules/@ngx-translate/core": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", + "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": ">=13.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@ngx-translate/http-loader": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", + "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@ngx-translate/core": ">=14.0.0", + "rxjs": "^6.5.3 || ^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", @@ -16214,6 +16241,22 @@ "dev": true, "requires": {} }, + "@ngx-translate/core": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", + "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@ngx-translate/http-loader": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", + "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", + "requires": { + "tslib": "^2.3.0" + } + }, "@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 84cfcc2..c39f027 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@angular/platform-browser-dynamic": "", "@angular/router": "", "@ng-bootstrap/ng-bootstrap": "", + "@ngx-translate/core": "14.0.0", + "@ngx-translate/http-loader": "7.0.0", "angular-oauth2-oidc": "", "bootstrap": "", "bootstrap-icons": "", @@ -64,4 +66,4 @@ "ts-node": "", "typescript": "" } -} \ No newline at end of file +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 6eb232f..aa61dab 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,6 +1,6 @@ import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; -import { HttpClientModule } from '@angular/common/http'; +import { HttpClientModule, HttpClient } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { OAuthModule } from 'angular-oauth2-oidc'; @@ -26,6 +26,12 @@ import { ConfigComponent } from './components/config/config.compon import { UsersComponent } from './components/user/user.component'; import { ClientComponent } from './components/client/client.component'; import { InputfieldComponent } from './components/inputfield/inputfield.component'; +import {TranslateModule, TranslateLoader} from '@ngx-translate/core'; +import {TranslateHttpLoader} from '@ngx-translate/http-loader'; + +export function HttpLoaderFactory(http: HttpClient) { + return new TranslateHttpLoader(http); +} @NgModule({ declarations: [ @@ -52,6 +58,14 @@ import { InputfieldComponent } from './components/inputfield/inputfiel FormsModule, ReactiveFormsModule, OAuthModule.forRoot(), + TranslateModule.forRoot({ + defaultLanguage: 'en', + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient] + } + }), ], providers: [ SettingsService, diff --git a/src/app/components/app/app.component.css b/src/app/components/app/app.component.css index bb23128..5bb2676 100644 --- a/src/app/components/app/app.component.css +++ b/src/app/components/app/app.component.css @@ -14,6 +14,8 @@ div.img-container{ display: flex; justify-content: center; align-items: center; + margin-left: 5px; + margin-right: 5px; } .active { diff --git a/src/app/components/app/app.component.html b/src/app/components/app/app.component.html index 6a88441..5761527 100644 --- a/src/app/components/app/app.component.html +++ b/src/app/components/app/app.component.html @@ -23,7 +23,8 @@ class="nav-link {{ currentRoute == 'user' ? 'active' : '' }}" href="./user" (click)="isMenuCollapsed = true" - >UserApp.Menus.User @@ -90,6 +95,7 @@ ngbDropdownItem class="border-0 d-flex flex-row justify-content-start align-items-center py-2 btn btn-outline-primary bg-transparent px-0" (click)="changelLanguage('en')" + translate > english-icon
- English + Langs.en @@ -128,7 +135,7 @@ class="btn-logout btn btn-outline-primary border-0 d-flex flex-row justify-content-center align-items-center" ngbDropdownToggle > -
+
{{ getId() }}
@@ -142,7 +149,7 @@ [routerLink]="['/selfservice']" *ngIf="isLoggedIn()" > -
+
{{ getId() }} @@ -150,8 +157,9 @@ class="btn btn-primary btn-lg py-3 d-flex align-items-center justify-content-center" ngbDropdownItem (click)="isLoggedIn() ? logout() : login()" + translate > - {{ isLoggedIn() ? "Log Out" : "Login" }} + {{ isLoggedIn() ? "App.Menus.Logout" : "Login" }} diff --git a/src/app/components/app/app.component.ts b/src/app/components/app/app.component.ts index a5088a3..9edcb30 100644 --- a/src/app/components/app/app.component.ts +++ b/src/app/components/app/app.component.ts @@ -6,6 +6,7 @@ import { SettingsService } from "../../services/settings.service"; import { UserService } from "../../services/user.service"; import { User } from "../../interfaces/user"; import jwt_decode from "jwt-decode"; +import { TranslateService } from '@ngx-translate/core'; @Component({ selector: "app-root", @@ -28,7 +29,8 @@ export class AppComponent { private router: Router, private location: Location, private settings: SettingsService, - private userService: UserService + private userService: UserService, + private translate: TranslateService, ) { // Configure OAuth this.oauthService.configure({ @@ -70,6 +72,10 @@ export class AppComponent { this.breadcrumbs = event.url.split('/').filter(route => route); } }); + + this.translate.onLangChange.subscribe((event) => { + this.currentLanguage = event.lang as typeof this.currentLanguage; + }) } setActive(route: string) { @@ -162,13 +168,13 @@ export class AppComponent { } currentLanguageLabel() { - switch (this.currentLanguage) { + switch (this.translate.currentLang) { case "en": - return "English"; + return this.translate.get('Langs.en'); case "tw": - return "Taiwan"; + return this.translate.get('Langs.tw'); default: - return "English"; + return this.translate.get('Langs.en'); } } @@ -184,7 +190,7 @@ export class AppComponent { } changelLanguage(value: "en" | "tw") { - this.currentLanguage = value; + this.translate.use(value); } } diff --git a/src/app/components/user/user.component.html b/src/app/components/user/user.component.html index c118930..7c191e5 100644 --- a/src/app/components/user/user.component.html +++ b/src/app/components/user/user.component.html @@ -2,28 +2,28 @@
-
+
-
-
- Please enter a new Username - +
+ User.PleaseEnterUserName +
-
-
@@ -32,7 +32,7 @@ + class="alert alert-secondary alert-dismissible fade show" role="alert" translate>User.NoUsersToShow
@@ -52,16 +52,15 @@ {{ getAttribute(user, 'preferred_username') || user.username}}
-
-
- This user has no attributes. Maybe try adding some? +
+ User.NoAttributes1 User.NoAttributes2
- Attributes: + Common.Attributes
@@ -71,7 +70,7 @@
- ... and {{user.attributes.length -3}} more attributes
+ {{'User.MoreAttributes' | translate: { value: user.attributes.length - 3} }}
@@ -80,27 +79,27 @@
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json new file mode 100644 index 0000000..dea08e5 --- /dev/null +++ b/src/assets/i18n/en.json @@ -0,0 +1,36 @@ +{ + "Common": { + "Back": "Back", + "Edit": "Edit", + "Delete": "Delete", + "Cancel": "Cancel", + "Attributes": "Attributes: ", + "ShowAll": "Show all", + "ShowLess": "Show less" + }, + "Langs": { + "en": "English", + "tw": "Taiwan" + }, + "App": { + "Menus": { + "User": "User", + "Client": "Client", + "Config": "Config", + "Webfinger": "Webfinger", + "Endpoints": "Endpoints", + "Logout": "Log out" + } + }, + "User": { + "SearchUserPlaceholder": "Search User", + "Add": "Add User", + "EnterUserName": "Enter username", + "PleaseEnterUserName": "Please enter a new Username", + "NoUsersToShow": "No users to show", + "NoAttributes1": "This user has no attributes. Maybe try ", + "NoAttributes2": "adding some?", + "WantDelete": "Do you really want to delete this user?", + "MoreAttributes": "... and {{value}} more attributes" + } +} \ No newline at end of file diff --git a/src/assets/i18n/tw.json b/src/assets/i18n/tw.json new file mode 100644 index 0000000..7d946b4 --- /dev/null +++ b/src/assets/i18n/tw.json @@ -0,0 +1,12 @@ +{ + "App": { + "Menus": { + "User": "User", + "Client": "Client", + "Config": "Config", + "Webfinger": "Webfinger", + "Endpoints": "Endpoints", + "Logout": "Log out" + } + } +} \ No newline at end of file