Skip to content

Commit

Permalink
Feat: Add language selector (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
RikudouSage committed Oct 16, 2023
1 parent 56373d0 commit 06fe584
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 15 deletions.
7 changes: 7 additions & 0 deletions src/app/app.component.html
Expand Up @@ -236,6 +236,13 @@ <h4 class="modal-title" id="modal-basic-title">{{"app.switch_account.title" | tr
</p>
</a>
</li>
<li><hr></li>
<li class="nav-item">
{{"app.language" | transloco}}
<select class="form-control" *ngIf="availableLanguages.length && selectedLanguage" (change)="changeLanguage($any($event.target).value)">
<option *ngFor="let option of availableLanguages" [value]="option" [selected]="option === selectedLanguage">{{option | languageName}}</option>
</select>
</li>
</ul>
</nav>
<!-- /.sidebar-menu -->
Expand Down
25 changes: 20 additions & 5 deletions src/app/app.component.ts
Expand Up @@ -49,6 +49,9 @@ export class AppComponent implements OnInit {
public maintainerLink: string | null = null;
public availableAccounts: Observable<Instance[]> = this.database.availableAccountsObservable;

public availableLanguages: string[] = [];
public selectedLanguage: string | null = null;

constructor(
private readonly titleService: TitleService,
private readonly authenticationManager: AuthenticationManagerService,
Expand All @@ -67,13 +70,20 @@ export class AppComponent implements OnInit {
public async ngOnInit(): Promise<void> {
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) {
Expand Down Expand Up @@ -209,4 +219,9 @@ export class AppComponent implements OnInit {
this.logout();
}
}

public changeLanguage(language: string) {
this.transloco.setActiveLang(language);
this.database.storedLanguage = language;
}
}
2 changes: 1 addition & 1 deletion src/app/app.module.ts
Expand Up @@ -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";
Expand Down
22 changes: 22 additions & 0 deletions src/app/services/database.service.ts
Expand Up @@ -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<Instance[]>(this.availableAccounts);

Expand Down Expand Up @@ -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);
}
}
15 changes: 15 additions & 0 deletions 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;
}

}
3 changes: 3 additions & 0 deletions src/app/shared/shared.module.ts
Expand Up @@ -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({
Expand All @@ -34,6 +35,7 @@ import {InstanceLogoComponent} from './components/instance-logo/instance-logo.co
InstanceMoveToListComponent,
FlagsComponent,
InstanceLogoComponent,
LanguageNamePipe,
],
exports: [
ToObservablePipe,
Expand All @@ -52,6 +54,7 @@ import {InstanceLogoComponent} from './components/instance-logo/instance-logo.co
InstanceMoveToListComponent,
FlagsComponent,
InstanceLogoComponent,
LanguageNamePipe,
],
imports: [
CommonModule,
Expand Down
11 changes: 4 additions & 7 deletions 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";


Expand All @@ -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: {
Expand Down
3 changes: 2 additions & 1 deletion src/assets/i18n/cs.json
@@ -1,3 +1,4 @@
{
"app.home": "Domů"
"app.home": "Domů",
"app.language": "Jazyk"
}
3 changes: 2 additions & 1 deletion src/assets/i18n/en.json
Expand Up @@ -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"
}

0 comments on commit 06fe584

Please sign in to comment.