improved language picker (#6890)

* improved language picker

* fix import path

* update tests
This commit is contained in:
Denys Vuika
2021-04-06 10:35:41 +01:00
committed by GitHub
parent cf7ffba81a
commit 145c05321d
11 changed files with 131 additions and 120 deletions

View File

@@ -33,77 +33,6 @@
"name": "Alfresco ADF Application", "name": "Alfresco ADF Application",
"copyright": "© 2016 - 2018 Alfresco Software, Inc. All Rights Reserved." "copyright": "© 2016 - 2018 Alfresco Software, Inc. All Rights Reserved."
}, },
"languages": [
{
"key": "en",
"label": "English"
},
{
"key": "fr",
"label": "Français"
},
{
"key": "de",
"label": "Deutsch"
},
{
"key": "it",
"label": "Italiano"
},
{
"key": "es",
"label": "Español"
},
{
"key": "ja",
"label": "日本語"
},
{
"key": "nl",
"label": "Nederlands"
},
{
"key": "pt-BR",
"label": "Português (Brasil)"
},
{
"key": "nb",
"label": "Bokmål"
},
{
"key": "ru",
"label": "Русский"
},
{
"key": "zh-CN",
"label": "中文简体"
},
{
"key": "ar",
"label": "عربى",
"direction": "rtl"
},
{
"key": "cs",
"label": "Čeština"
},
{
"key": "pl",
"label": "Polski"
},
{
"key": "fi",
"label": "Suomi"
},
{
"key": "da",
"label": "Dansk"
},
{
"key": "sv",
"label": "Svenska"
}
],
"search": { "search": {
"filterWithContains": true, "filterWithContains": true,
"app:fields": [ "app:fields": [

View File

@@ -1,5 +1,6 @@
{ {
"ADF": { "ADF": {
"LANGUAGE": "Language",
"ROLES": { "ROLES": {
"ALL": "All", "ALL": "All",
"CONTRIBUTOR": "Contributor", "CONTRIBUTOR": "Contributor",

View File

@@ -1,2 +0,0 @@
<button mat-menu-item *ngFor="let language of languages" (click)="changeLanguage(language)">{{language.label}}
</button>

View File

@@ -18,10 +18,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppConfigService } from '../app-config/app-config.service'; import { AppConfigService } from '../app-config/app-config.service';
import { LanguageMenuComponent } from './language-menu.component'; import { LanguageMenuComponent } from './language-menu.component';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module'; import { CoreTestingModule } from '../testing/core.testing.module';
import { UserPreferencesService } from '../services/user-preferences.service'; import { UserPreferencesService } from '../services/user-preferences.service';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { LanguageService } from '../services/language.service';
describe('LanguageMenuComponent', () => { describe('LanguageMenuComponent', () => {
@@ -29,6 +29,7 @@ describe('LanguageMenuComponent', () => {
let component: LanguageMenuComponent; let component: LanguageMenuComponent;
let appConfig: AppConfigService; let appConfig: AppConfigService;
let userPreferencesService: UserPreferencesService; let userPreferencesService: UserPreferencesService;
let languageService: LanguageService;
const languages = <any> [ const languages = <any> [
{ {
@@ -46,33 +47,35 @@ describe('LanguageMenuComponent', () => {
} }
]; ];
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
fixture = TestBed.createComponent(LanguageMenuComponent); fixture = TestBed.createComponent(LanguageMenuComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
appConfig = TestBed.inject(AppConfigService); appConfig = TestBed.inject(AppConfigService);
userPreferencesService = TestBed.inject(UserPreferencesService); userPreferencesService = TestBed.inject(UserPreferencesService);
languageService = TestBed.inject(LanguageService);
}); });
afterEach(() => { afterEach(() => {
fixture.destroy(); fixture.destroy();
}); });
it('should fetch the languages from the app config if present', () => { it('should fetch the languages from the app config if present', async (done) => {
languageService.setLanguages(languages);
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
expect(component.languages).toEqual([{ key: 'en', label: 'English' }]); component.languages$.subscribe(langs => {
expect(langs).toEqual(languages);
appConfig.config.languages = languages; done();
});
component.ngOnInit();
expect(component.languages).toEqual(languages);
}); });
it('should change user preference locale', () => { it('should change user preference locale', () => {

View File

@@ -15,35 +15,28 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; import { LanguageItem, LanguageService } from '../services/language.service';
import { UserPreferencesService } from '../services/user-preferences.service'; import { Observable } from 'rxjs';
import { LanguageItem } from './language.interface';
@Component({ @Component({
selector: 'adf-language-menu', selector: 'adf-language-menu',
templateUrl: 'language-menu.component.html' template: `
<button
mat-menu-item
*ngFor="let language of languages$ | async"
(click)="changeLanguage(language)">{{language.label}}</button>
`
}) })
export class LanguageMenuComponent implements OnInit { export class LanguageMenuComponent {
languages: Array<LanguageItem> = [ languages$: Observable<LanguageItem[]>;
{ key: 'en', label: 'English'}
];
constructor( constructor(private languageService: LanguageService) {
private appConfig: AppConfigService, this.languages$ = languageService.languages$;
private userPreference: UserPreferencesService) {
}
ngOnInit() {
const languagesConfigApp = this.appConfig.get<Array<LanguageItem>>(AppConfigValues.APP_CONFIG_LANGUAGES_KEY);
if (languagesConfigApp) {
this.languages = languagesConfigApp;
}
} }
changeLanguage(language: LanguageItem) { changeLanguage(language: LanguageItem) {
this.userPreference.locale = language.key; this.languageService.changeLanguage(language);
this.userPreference.set('textOrientation', language.direction || 'ltr');
} }
} }

View File

@@ -20,17 +20,22 @@ import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module'; import { MaterialModule } from '../material.module';
import { LanguageMenuComponent } from './language-menu.component'; import { LanguageMenuComponent } from './language-menu.component';
import { LanguagePickerComponent } from './language-picker.component';
import { TranslateModule } from '@ngx-translate/core';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
MaterialModule MaterialModule,
TranslateModule
], ],
declarations: [ declarations: [
LanguageMenuComponent LanguageMenuComponent,
LanguagePickerComponent
], ],
exports: [ exports: [
LanguageMenuComponent LanguageMenuComponent,
LanguagePickerComponent
] ]
}) })
export class LanguageMenuModule {} export class LanguageMenuModule {}

View File

@@ -15,10 +15,18 @@
* limitations under the License. * limitations under the License.
*/ */
import { Direction } from '@angular/cdk/bidi'; import { Component } from '@angular/core';
export interface LanguageItem { @Component({
key: string; selector: 'adf-picker-button',
label: string; template: `
direction?: Direction; <button mat-menu-item [matMenuTriggerFor]="langMenu">
} <mat-icon>language</mat-icon>
{{ 'ADF.LANGUAGE' | translate }}
</button>
<mat-menu #langMenu="matMenu">
<adf-language-menu></adf-language-menu>
</mat-menu>
`
})
export class LanguagePickerComponent {}

View File

@@ -16,5 +16,5 @@
*/ */
export * from './language-menu.component'; export * from './language-menu.component';
export * from './language.interface';
export * from './language-menu.module'; export * from './language-menu.module';
export * from './language-picker.component';

View File

@@ -0,0 +1,73 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Injectable } from '@angular/core';
import { Direction } from '@angular/cdk/bidi';
import { BehaviorSubject } from 'rxjs';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { UserPreferencesService } from './user-preferences.service';
export interface LanguageItem {
key: string;
label: string;
direction?: Direction;
}
@Injectable({providedIn: 'root'})
export class LanguageService {
private languages = new BehaviorSubject<LanguageItem[]>([
{'key': 'de', 'label': 'Deutsch'},
{'key': 'en', 'label': 'English'},
{'key': 'es', 'label': 'Español'},
{'key': 'fr', 'label': 'Français'},
{'key': 'it', 'label': 'Italiano'},
{'key': 'ja', 'label': '日本語'},
{'key': 'nb', 'label': 'Bokmål'},
{'key': 'nl', 'label': 'Nederlands'},
{'key': 'pt-BR', 'label': 'Português (Brasil)'},
{'key': 'ru', 'label': 'Русский'},
{'key': 'zh-CN', 'label': '中文简体'},
{'key': 'cs', 'label': 'Čeština'},
{'key': 'da', 'label': 'Dansk'},
{'key': 'fi', 'label': 'Suomi'},
{'key': 'pl', 'label': 'Polski'},
{'key': 'sv', 'label': 'Svenska'},
{'key': 'ar', 'label': 'العربية', direction: 'rtl'}
]);
languages$ = this.languages.asObservable();
constructor(
appConfigService: AppConfigService,
private userPreferencesService: UserPreferencesService) {
const customLanguages = appConfigService.get<Array<LanguageItem>>(AppConfigValues.APP_CONFIG_LANGUAGES_KEY);
this.setLanguages(customLanguages);
}
changeLanguage(language: LanguageItem) {
this.userPreferencesService.locale = language.key;
this.userPreferencesService.set('textOrientation', language.direction || 'ltr');
}
setLanguages(items: LanguageItem[]) {
if (items && items.length > 0) {
this.languages.next(items);
}
}
}

View File

@@ -64,3 +64,4 @@ export * from './identity-role.service';
export * from './version-compatibility.service'; export * from './version-compatibility.service';
export * from './auth-bearer.interceptor'; export * from './auth-bearer.interceptor';
export * from './oauth2.service'; export * from './oauth2.service';
export * from './language.service';

View File

@@ -19,7 +19,7 @@ import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Observable, BehaviorSubject } from 'rxjs'; import { Observable, BehaviorSubject } from 'rxjs';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service'; import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { LanguageItem } from '../language-menu/language.interface'; import { LanguageItem } from './language.service';
import { StorageService } from './storage.service'; import { StorageService } from './storage.service';
import { distinctUntilChanged, map, filter } from 'rxjs/operators'; import { distinctUntilChanged, map, filter } from 'rxjs/operators';
import { AlfrescoApiService } from './alfresco-api.service'; import { AlfrescoApiService } from './alfresco-api.service';