diff --git a/src/app/app.component.html b/src/app/app.component.html
index 6a5adae..f8a4bb2 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -236,6 +236,13 @@
{{"app.switch_account.title" | tr
+
+
+ {{"app.language" | transloco}}
+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 64420b2..e5d831e 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -49,6 +49,9 @@ export class AppComponent implements OnInit {
public maintainerLink: string | null = null;
public availableAccounts: Observable = this.database.availableAccountsObservable;
+ public availableLanguages: string[] = [];
+ public selectedLanguage: string | null = null;
+
constructor(
private readonly titleService: TitleService,
private readonly authenticationManager: AuthenticationManagerService,
@@ -67,13 +70,20 @@ export class AppComponent implements OnInit {
public async ngOnInit(): Promise {
this.titleService.titleChanged.subscribe(title => this.title = title);
- const availableLanguages = this.transloco.getAvailableLangs().map(value => typeof value === 'string' ? value : value.id);
- for (const language of navigator.languages.map(language => language.split("-")[0])) {
- if (availableLanguages.includes(language)) {
- this.transloco.setActiveLang(language);
- break;
+ this.availableLanguages = this.transloco.getAvailableLangs().map(value => typeof value === 'string' ? value : value.id);
+ if (this.database.storedLanguage) {
+ this.transloco.setActiveLang(this.database.storedLanguage);
+ this.selectedLanguage = this.database.storedLanguage;
+ } else {
+ for (const language of navigator.languages.map(language => language.split("-")[0])) {
+ if (this.availableLanguages.includes(language)) {
+ this.transloco.setActiveLang(language);
+ this.selectedLanguage = language;
+ break;
+ }
}
}
+ this.selectedLanguage ??= this.transloco.config.defaultLang;
const darkModeDetected = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (darkModeDetected) {
@@ -209,4 +219,9 @@ export class AppComponent implements OnInit {
this.logout();
}
}
+
+ public changeLanguage(language: string) {
+ this.transloco.setActiveLang(language);
+ this.database.storedLanguage = language;
+ }
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 6779116..cd4edec 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -7,7 +7,7 @@ import {HttpClientModule} from "@angular/common/http";
import {NotificationComponent} from './components/notification/notification.component';
import {HomePageComponent} from './pages/home-page/home-page.component';
import {SharedModule} from "./shared/shared.module";
-import {ReactiveFormsModule} from "@angular/forms";
+import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {TranslocoRootModule} from './transloco-root.module';
import {defaultTranslocoMarkupTranspilers, provideTranslationMarkupTranspiler} from "ngx-transloco-markup";
import {translocoMarkupRouterLinkRenderer} from "ngx-transloco-markup-router-link";
diff --git a/src/app/services/database.service.ts b/src/app/services/database.service.ts
index f26a9dd..c4678ee 100644
--- a/src/app/services/database.service.ts
+++ b/src/app/services/database.service.ts
@@ -17,6 +17,7 @@ export class DatabaseService {
private readonly lemmyPasswordKey = 'lemmy_password';
private readonly censureListFiltersKey = 'censure_list_filters';
private readonly availableAccountsKey = 'available_accounts';
+ private readonly storedLanguageKey = 'language';
private readonly _availableAccountsObservable = new BehaviorSubject(this.availableAccounts);
@@ -187,4 +188,25 @@ export class DatabaseService {
}
localStorage.setItem(this.censureListFiltersKey, JSON.stringify(filters));
}
+
+ public get storedLanguage(): string | null {
+ if (typeof localStorage === 'undefined') {
+ return null;
+ }
+
+ return localStorage.getItem(this.storedLanguageKey);
+ }
+
+ public set storedLanguage(language: string | null) {
+ if (typeof localStorage === 'undefined') {
+ return;
+ }
+
+ if (language === null) {
+ localStorage.removeItem(this.storedLanguageKey);
+ return;
+ }
+
+ localStorage.setItem(this.storedLanguageKey, language);
+ }
}
diff --git a/src/app/shared/pipes/language-name.pipe.ts b/src/app/shared/pipes/language-name.pipe.ts
new file mode 100644
index 0000000..b7ad752
--- /dev/null
+++ b/src/app/shared/pipes/language-name.pipe.ts
@@ -0,0 +1,15 @@
+import {Pipe, PipeTransform} from '@angular/core';
+
+@Pipe({
+ name: 'languageName'
+})
+export class LanguageNamePipe implements PipeTransform {
+
+ transform(language: string, locale: string | null = null): string {
+ locale ??= language;
+
+ const intl = new Intl.DisplayNames(locale, {type: 'language'});
+ return intl.of(language) ?? language;
+ }
+
+}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 8b845b0..4a6d0bd 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -17,6 +17,7 @@ import {InstanceMoveToListComponent} from './components/instance-move-to-list/in
import {ReactiveFormsModule} from "@angular/forms";
import {FlagsComponent} from './components/flags/flags.component';
import {InstanceLogoComponent} from './components/instance-logo/instance-logo.component';
+import {LanguageNamePipe} from './pipes/language-name.pipe';
@NgModule({
@@ -34,6 +35,7 @@ import {InstanceLogoComponent} from './components/instance-logo/instance-logo.co
InstanceMoveToListComponent,
FlagsComponent,
InstanceLogoComponent,
+ LanguageNamePipe,
],
exports: [
ToObservablePipe,
@@ -52,6 +54,7 @@ import {InstanceLogoComponent} from './components/instance-logo/instance-logo.co
InstanceMoveToListComponent,
FlagsComponent,
InstanceLogoComponent,
+ LanguageNamePipe,
],
imports: [
CommonModule,
diff --git a/src/app/transloco-root.module.ts b/src/app/transloco-root.module.ts
index f050978..f29d765 100644
--- a/src/app/transloco-root.module.ts
+++ b/src/app/transloco-root.module.ts
@@ -1,9 +1,6 @@
-import {
- provideTransloco,
- TranslocoModule
-} from '@ngneat/transloco';
-import { NgModule } from '@angular/core';
-import { TranslocoHttpLoader } from './shared/helper/transloco-loader';
+import {provideTransloco, TranslocoModule} from '@ngneat/transloco';
+import {NgModule} from '@angular/core';
+import {TranslocoHttpLoader} from './shared/helper/transloco-loader';
import {environment} from "../environments/environment";
@@ -14,7 +11,7 @@ import {environment} from "../environments/environment";
config: {
availableLangs: ['cs', 'de', 'en', 'pt'],
defaultLang: 'en',
- reRenderOnLangChange: false,
+ reRenderOnLangChange: true,
prodMode: environment.production,
fallbackLang: 'en',
missingHandler: {
diff --git a/src/assets/i18n/cs.json b/src/assets/i18n/cs.json
index 30afa3a..4679762 100644
--- a/src/assets/i18n/cs.json
+++ b/src/assets/i18n/cs.json
@@ -1,3 +1,4 @@
{
- "app.home": "Domů"
+ "app.home": "Domů",
+ "app.language": "Jazyk"
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index f4538fd..f7dd53e 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -172,5 +172,6 @@
"app.censures.no_censures_message": "You haven't put a censure on any instance yet.",
"app.censures.unguaranteed": "No one guaranteed for this instance, you cannot censure others.",
"app.censures.my.title": "My censures",
- "error.censures.moving_failed": "Failed moving the instance {{instance}}. Please reload the page to see whether it was removed from your censures or not."
+ "error.censures.moving_failed": "Failed moving the instance {{instance}}. Please reload the page to see whether it was removed from your censures or not.",
+ "app.language": "Language"
}