diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index fcea0adfe..f2262c1e5 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -9,6 +9,7 @@ import { IdentityService, NotificationService, CustomPageService } from "./servi import { JobService, SettingsService } from "./services"; import { ICustomizationSettings, ICustomPage } from "./interfaces"; +import { StorageService } from './shared/storage/storage-service'; @Component({ selector: "app-ombi", @@ -43,7 +44,8 @@ export class AppComponent implements OnInit { public readonly translate: TranslateService, private readonly identityService: IdentityService, private readonly customPageService: CustomPageService, - public overlayContainer: OverlayContainer) { + public overlayContainer: OverlayContainer, + private storage: StorageService) { // const base = this.platformLocation.getBaseHrefFromDOM(); // if (base.length > 1) { @@ -51,12 +53,18 @@ export class AppComponent implements OnInit { // } this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sv", "no", "pl", "pt"]); + + const selectedLang = this.storage.get("Language"); + // this language will be used as a fallback when a translation isn't found in the current language this.translate.setDefaultLang("en"); - - // See if we can match the supported langs with the current browser lang - const browserLang: string = translate.getBrowserLang(); - this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sv|no|pl|pt/) ? browserLang : "en"); + if (selectedLang) { + this.translate.use(selectedLang); + } else { + // See if we can match the supported langs with the current browser lang + const browserLang: string = translate.getBrowserLang(); + this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sv|no|pl|pt/) ? browserLang : "en"); + } } public ngOnInit() { @@ -87,7 +95,7 @@ export class AppComponent implements OnInit { this.currentUrl = event.url; if (event instanceof NavigationStart) { this.user = this.authService.claims(); - if(this.user && this.user.username) { + if (this.user && this.user.username) { this.username = this.user.username; } this.isAdmin = this.authService.hasRole("admin"); diff --git a/src/Ombi/ClientApp/src/app/app.module.ts b/src/Ombi/ClientApp/src/app/app.module.ts index cabdf1646..cb9a3d25a 100644 --- a/src/Ombi/ClientApp/src/app/app.module.ts +++ b/src/Ombi/ClientApp/src/app/app.module.ts @@ -52,6 +52,7 @@ import { SearchV2Service } from "./services/searchV2.service"; import { NavSearchComponent } from "./my-nav/nav-search.component"; import { OverlayModule } from "@angular/cdk/overlay"; import { getBaseLocation } from "./shared/functions/common-functions"; +import { StorageService } from "./shared/storage/storage-service"; const routes: Routes = [ { path: "*", component: PageNotFoundComponent }, @@ -76,6 +77,7 @@ const routes: Routes = [ { loadChildren: "./recentlyAdded/recentlyAdded.module#RecentlyAddedModule", path: "recentlyadded" }, { loadChildren: "./vote/vote.module#VoteModule", path: "vote" }, { loadChildren: "./media-details/media-details.module#MediaDetailsModule", path: "details" }, + { loadChildren: "./user-preferences/user-preferences.module#UserPreferencesModule", path: "user-preferences" }, ]; // AoT requires an exported function for factories @@ -176,6 +178,7 @@ export function JwtTokenGetter() { SearchService, SearchV2Service, MessageService, + StorageService, { provide: APP_BASE_HREF, useValue: window['_app_base'] || '/' } // { // provide: APP_BASE_HREF, diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts index 7d46774a2..ff125d8f6 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts @@ -40,6 +40,7 @@ export class MyNavComponent implements OnInit { { name: "NavigationBar.UserManagement", icon: "account_circle", link: "/usermanagement", requiresAdmin: true }, { name: "NavigationBar.Calendar", icon: "calendar_today", link: "/calendar", requiresAdmin: false }, { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true }, + { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false }, ] public logOut() { diff --git a/src/Ombi/ClientApp/src/app/shared/storage/storage-service.ts b/src/Ombi/ClientApp/src/app/shared/storage/storage-service.ts new file mode 100644 index 000000000..297effd3a --- /dev/null +++ b/src/Ombi/ClientApp/src/app/shared/storage/storage-service.ts @@ -0,0 +1,18 @@ +import { Injectable } from "@angular/core"; + +@Injectable() +export class StorageService { + + public get(key: string): string { + return localStorage.getItem(key); + } + + public save(key: string, value: string): void { + this.remove(key); + localStorage.setItem(key, value); + } + + public remove(key: string) { + localStorage.removeItem(key); + } +} diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/index.ts b/src/Ombi/ClientApp/src/app/user-preferences/components/index.ts new file mode 100644 index 000000000..3dc080554 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/index.ts @@ -0,0 +1,12 @@ +import { AuthGuard } from "../../auth/auth.guard"; +import { Routes } from "@angular/router" +import { UserPreferenceComponent } from "./user-preference/user-preference.component"; + + +export const components: any[] = [ + UserPreferenceComponent, +]; + +export const routes: Routes = [ + { path: "", component: UserPreferenceComponent, canActivate: [AuthGuard] }, +]; \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.html b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.html new file mode 100644 index 000000000..3f13f236c --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.html @@ -0,0 +1,15 @@ +
+

+ +
+
+ + + + + {{lang.display}} + + + +
+
diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.scss b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.scss new file mode 100644 index 000000000..b2bf4612b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.scss @@ -0,0 +1,5 @@ +.small-middle-container{ + margin: auto; + margin-top: 3%; + width: 80%; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.ts b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.ts new file mode 100644 index 000000000..a76df7149 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.component.ts @@ -0,0 +1,37 @@ +import { Component, OnInit } from "@angular/core"; +import { AuthService } from "../../../auth/auth.service"; +import { TranslateService } from "@ngx-translate/core"; +import { AvailableLanguages, ILanguage } from "./user-preference.constants"; +import { StorageService } from "../../../shared/storage/storage-service"; + +@Component({ + templateUrl: "./user-preference.component.html", + styleUrls: ["./user-preference.component.scss"], +}) +export class UserPreferenceComponent implements OnInit { + + public username: string; + public selectedLang: string; + public availableLanguages = AvailableLanguages; + + constructor(private authService: AuthService, + private readonly translate: TranslateService, + private storage: StorageService) { } + + public ngOnInit(): void { + const user = this.authService.claims(); + if(user.name) { + this.username = user.name; + } + const selectedLang = this.storage.get("Language"); + if(selectedLang) { + this.selectedLang = selectedLang; + } + } + + public languageSelected() { + this.storage.save("Language", this.selectedLang); + this.translate.use(this.selectedLang); + } + +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts new file mode 100644 index 000000000..64b594c58 --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/components/user-preference/user-preference.constants.ts @@ -0,0 +1,18 @@ +export const AvailableLanguages: ILanguage[] = [ + { display: 'English', value: 'en' }, + { display: 'Français', value: 'fr' }, + { display: 'Dansk', value: 'da' }, + { display: 'Deutsch', value: 'de' }, + { display: 'Italiano', value: 'it' }, + { display: 'Español', value: 'es' }, + { display: 'Nederlands', value: 'nl' }, + { display: 'Norsk', value: 'no' }, + { display: 'Português (Brasil)', value: 'pt' }, + { display: 'Polski', value: 'pl' }, + { display: 'Svenska', value: 'sv' }, +]; + +export interface ILanguage { + display: string; + value: string; +} \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/user-preferences/user-preferences.module.ts b/src/Ombi/ClientApp/src/app/user-preferences/user-preferences.module.ts new file mode 100644 index 000000000..32058c36b --- /dev/null +++ b/src/Ombi/ClientApp/src/app/user-preferences/user-preferences.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from "@angular/core"; +import { RouterModule } from "@angular/router" + +import { SharedModule } from "../shared/shared.module"; + +import * as fromComponents from './components'; + + +@NgModule({ + imports: [ + RouterModule.forChild(fromComponents.routes), + SharedModule, + ], + declarations: [ + ...fromComponents.components + ], + exports: [ + RouterModule, + ], + providers: [ + ], + +}) +export class UserPreferencesModule { } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 58ed985f3..bfdf6d5bf 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -62,7 +62,8 @@ "OpenMobileApp": "Open Mobile App", "RecentlyAdded": "Recently Added", "ChangeTheme":"Change Theme", - "Calendar":"Calendar" + "Calendar":"Calendar", + "UserPreferences": "Preferences" }, "Search": { "Title": "Search", @@ -219,5 +220,9 @@ "Writer": "Writer", "ExecProducer": "Exec Producer" } + }, + "UserPreferences": { + "Welcome":"Welcome {{username}}!", + "OmbiLanguage":"Ombi Language" } }