From 58479167ce63c965c734f8606ebec1b52c02c6c4 Mon Sep 17 00:00:00 2001
From: Carlos Santos <4a.santos@gmail.com>
Date: Wed, 21 Jun 2023 13:37:43 +0200
Subject: [PATCH] openvidu-components: Allowed override lang options with a
directive
---
.../e2e/webcomponent-app/app.js | 9 +++
.../e2e/webcomponent.test.ts | 44 ++++++++++++
.../lang-selector.component.html | 2 +-
.../lang-selector/lang-selector.component.ts | 20 ++++--
.../videoconference.component.ts | 1 +
.../directives/api/api.directive.module.ts | 3 +
.../api/videoconference.directive.ts | 67 +++++++++++++++++++
.../services/translate/translate.service.ts | 48 ++++++++++---
.../src/app/openvidu-call/call.component.html | 5 +-
.../openvidu-webcomponent.component.html | 1 +
.../openvidu-webcomponent.component.ts | 62 +++++++++++++----
11 files changed, 235 insertions(+), 27 deletions(-)
diff --git a/openvidu-components-angular/e2e/webcomponent-app/app.js b/openvidu-components-angular/e2e/webcomponent-app/app.js
index 71335ec18d..90df8eb1da 100644
--- a/openvidu-components-angular/e2e/webcomponent-app/app.js
+++ b/openvidu-components-angular/e2e/webcomponent-app/app.js
@@ -3,6 +3,7 @@ import monkeyPatchMediaDevices from './utils/media-devices.js';
var MINIMAL;
var LANG;
var CAPTIONS_LANG;
+var CUSTOM_LANG_OPTIONS;
var CUSTOM_CAPTIONS_LANG_OPTIONS;
var PREJOIN;
var VIDEO_MUTED;
@@ -52,6 +53,8 @@ $(document).ready(() => {
MINIMAL = url.searchParams.get('minimal') === null ? false : url.searchParams.get('minimal') === 'true';
LANG = url.searchParams.get('lang') || 'en';
CAPTIONS_LANG = url.searchParams.get('captionsLang') || 'en-US';
+ CUSTOM_LANG_OPTIONS =
+ url.searchParams.get('langOptions') === null ? false : url.searchParams.get('langOptions') === 'true';
CUSTOM_CAPTIONS_LANG_OPTIONS =
url.searchParams.get('captionsLangOptions') === null ? false : url.searchParams.get('captionsLangOptions') === 'true';
PARTICIPANT_NAME = url.searchParams.get('participantName') || 'TEST_USER';
@@ -216,6 +219,12 @@ async function joinSession(sessionName, participantName) {
webComponent.minimal = MINIMAL;
webComponent.lang = LANG;
webComponent.captionsLang = CAPTIONS_LANG;
+ if (CUSTOM_LANG_OPTIONS) {
+ webComponent.langOptions = [
+ { name: 'Esp', lang: 'es' },
+ { name: 'Eng', lang: 'en' }
+ ];
+ }
if (CUSTOM_CAPTIONS_LANG_OPTIONS) {
webComponent.captionsLangOptions = [
{ name: 'Esp', lang: 'es-ES' },
diff --git a/openvidu-components-angular/e2e/webcomponent.test.ts b/openvidu-components-angular/e2e/webcomponent.test.ts
index acc9b3edc2..842c059c99 100644
--- a/openvidu-components-angular/e2e/webcomponent.test.ts
+++ b/openvidu-components-angular/e2e/webcomponent.test.ts
@@ -109,6 +109,50 @@ describe('Testing API Directives', () => {
expect(await element.getText()).equal('Unirme ahora');
});
+ it('should override the LANG OPTIONS', async () => {
+ await browser.get(`${url}&prejoin=true&langOptions=true`);
+
+
+ await utils.checkPrejoinIsPresent();
+ await utils.waitForElement('.lang-button');
+ await utils.clickOn('.lang-button');
+ await browser.sleep(500);
+ expect(await utils.getNumberOfElements('.lang-menu-opt')).equals(2);
+
+ await utils.clickOn('.lang-menu-opt');
+ await browser.sleep(500);
+
+ await utils.clickOn('#join-button');
+
+ await utils.checkSessionIsPresent();
+
+ // Checking if toolbar is present
+ await utils.checkToolbarIsPresent();
+
+ // Open more options menu
+ await utils.clickOn('#more-options-btn');
+
+ await browser.sleep(500);
+
+ // Checking if button panel is present
+ await utils.waitForElement('.mat-menu-content');
+ expect(await utils.isPresent('.mat-menu-content')).to.be.true;
+
+ // Checking if captions button is present
+ await utils.waitForElement('#toolbar-settings-btn');
+ expect(await utils.isPresent('#toolbar-settings-btn')).to.be.true;
+ await utils.clickOn('#toolbar-settings-btn');
+
+ await utils.waitForElement('#settings-container');
+ await utils.waitForElement('.lang-button');
+ await utils.clickOn('.lang-button');
+
+ await browser.sleep(500);
+
+ expect(await utils.getNumberOfElements('.lang-menu-opt')).equals(2);
+
+ });
+
it('should show the PREJOIN page', async () => {
await browser.get(`${url}&prejoin=true`);
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.html b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.html
index f9be138962..ae26d5c50f 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.html
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.html
@@ -3,7 +3,7 @@
expand_more
-
\ No newline at end of file
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.ts
index 2fd453de83..1e620de639 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/settings/lang-selector/lang-selector.component.ts
@@ -1,9 +1,10 @@
-import { AfterViewInit, Component, OnInit, Output, ViewChild, EventEmitter } from '@angular/core';
+import { AfterViewInit, Component, OnInit, Output, ViewChild, EventEmitter, OnDestroy } from '@angular/core';
import { MatMenuTrigger } from '@angular/material/menu';
import { MatSelect } from '@angular/material/select';
import { StorageService } from '../../../services/storage/storage.service';
import { TranslateService } from '../../../services/translate/translate.service';
import { LangOption } from '../../../models/lang.model';
+import { Subscription } from 'rxjs';
/**
* @internal
@@ -13,11 +14,13 @@ import { LangOption } from '../../../models/lang.model';
templateUrl: './lang-selector.component.html',
styleUrls: ['./lang-selector.component.css']
})
-export class LangSelectorComponent implements OnInit, AfterViewInit {
+export class LangSelectorComponent implements OnInit, AfterViewInit, OnDestroy {
@Output() onLangSelectorClicked = new EventEmitter();
langSelected: LangOption | undefined;
languages: LangOption[] = [];
+ private langSub: Subscription;
+
/**
* @ignore
*/
@@ -31,8 +34,12 @@ export class LangSelectorComponent implements OnInit, AfterViewInit {
constructor(private translateService: TranslateService, private storageSrv: StorageService) {}
ngOnInit(): void {
+ this.subscribeToLangSelected();
this.languages = this.translateService.getLanguagesInfo();
- this.langSelected = this.translateService.getLangSelected();
+ }
+
+ ngOnDestroy(): void {
+ this.langSub?.unsubscribe();
}
ngAfterViewInit() {
@@ -47,6 +54,11 @@ export class LangSelectorComponent implements OnInit, AfterViewInit {
onLangSelected(lang: string) {
this.translateService.setLanguage(lang);
this.storageSrv.setLang(lang);
- this.langSelected = this.translateService.getLangSelected();
+ }
+
+ subscribeToLangSelected() {
+ this.langSub = this.translateService.langSelectedObs.subscribe((lang) => {
+ this.langSelected = lang;
+ });
}
}
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts
index 133d2ad451..1240eee5ad 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/components/videoconference/videoconference.component.ts
@@ -56,6 +56,7 @@ import { LangOption } from '../../models/lang.model';
* | :----------------------------: | :-------: | :---------------------------------------------: |
* | **minimal** | `boolean` | {@link MinimalDirective} |
* | **lang** | `string` | {@link LangDirective} |
+ * | **langOptions** | `LangOption []` | {@link LangOptionsDirective} |
* | **captionsLang** | `string` | {@link CaptionsLangDirective} |
* | **captionsLangOptions** | `CaptionsLangOption []` | {@link CaptionsLangOptionsDirective} |
* | **prejoin** | `boolean` | {@link PrejoinDirective} |
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts
index 8464e38571..08d78ae024 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/api.directive.module.ts
@@ -27,6 +27,7 @@ import {
AudioMutedDirective,
CaptionsLangDirective,
CaptionsLangOptionsDirective,
+ LangOptionsDirective,
LangDirective,
MinimalDirective,
ParticipantNameDirective,
@@ -38,6 +39,7 @@ import {
declarations: [
MinimalDirective,
LangDirective,
+ LangOptionsDirective,
CaptionsLangOptionsDirective,
CaptionsLangDirective,
PrejoinDirective,
@@ -73,6 +75,7 @@ import {
exports: [
MinimalDirective,
LangDirective,
+ LangOptionsDirective,
CaptionsLangOptionsDirective,
CaptionsLangDirective,
PrejoinDirective,
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts
index 96103720c1..453aafba6e 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/directives/api/videoconference.directive.ts
@@ -3,6 +3,7 @@ import { CaptionsLangOption } from '../../models/caption.model';
import { CaptionService } from '../../services/caption/caption.service';
import { OpenViduAngularConfigService } from '../../services/config/openvidu-angular.config.service';
import { TranslateService } from '../../services/translate/translate.service';
+import { LangOption } from '../../models/lang.model';
/**
@@ -116,6 +117,72 @@ export class LangDirective implements OnDestroy {
}
}
+/**
+ * The **langOptions** directive allows to set the application language options.
+ * It will override the application languages provided by default.
+ * This propety is an array of objects which must comply with the {@link LangOption} interface.
+ *
+ * It is only available for {@link VideoconferenceComponent}.
+ *
+ * Default: ```
+ * [
+ * { name: 'English', lang: 'en' },
+ * { name: 'Español', lang: 'es' },
+ * { name: 'Deutsch', lang: 'de' },
+ * { name: 'Français', lang: 'fr' },
+ * { name: '中国', lang: 'cn' },
+ * { name: 'हिन्दी', lang: 'hi' },
+ * { name: 'Italiano', lang: 'it' },
+ * { name: 'やまと', lang: 'ja' },
+ * { name: 'Dutch', lang: 'nl' },
+ * { name: 'Português', lang: 'pt' }
+ * ]```
+ *
+ * Note: If you want to add a new language, you must add a new object with the name and the language code (e.g. `{ name: 'Custom', lang: 'cus' }`)
+ * and then add the language file in the `assets/lang` folder with the name `cus.json`.
+ *
+ *
+ * @example
+ *
+ */
+@Directive({
+ selector: 'ov-videoconference[langOptions]'
+})
+export class LangOptionsDirective implements OnDestroy {
+ /**
+ * @ignore
+ */
+ @Input() set langOptions(value: LangOption []) {
+ this.update(value);
+ }
+
+ /**
+ * @ignore
+ */
+ constructor(public elementRef: ElementRef, private translateService: TranslateService) {}
+
+ /**
+ * @ignore
+ */
+ ngOnDestroy(): void {
+ this.clear();
+ }
+
+ /**
+ * @ignore
+ */
+ clear() {
+ this.update(undefined);
+ }
+
+ /**
+ * @ignore
+ */
+ update(value: LangOption [] | undefined) {
+ this.translateService.setLanguageOptions(value);
+ }
+}
+
/**
* The **captionsLang** directive allows specify the deafult language that OpenVidu will try to recognise.
*
diff --git a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts
index c2b6e49fe6..b4304e3f93 100644
--- a/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts
+++ b/openvidu-components-angular/projects/openvidu-angular/src/lib/services/translate/translate.service.ts
@@ -10,7 +10,7 @@ import * as ja from '../../lang/ja.json';
import * as nl from '../../lang/nl.json';
import * as pt from '../../lang/pt.json';
import { StorageService } from '../storage/storage.service';
-import { BehaviorSubject, Observable, Subject } from 'rxjs';
+import { BehaviorSubject, Observable } from 'rxjs';
import { LangOption } from '../../models/lang.model';
/**
@@ -36,20 +36,24 @@ export class TranslateService {
private currentLang: any;
langSelected: LangOption | undefined;
langSelectedObs: Observable;
- private _langSelected: BehaviorSubject = new BehaviorSubject(undefined);
+ private _langSelected: BehaviorSubject = new BehaviorSubject(undefined);
constructor(private storageService: StorageService) {
- const iso = this.storageService.getLang() || 'en';
- this.langSelected = this.langOptions.find((l) => l.lang === iso) || this.langOptions[0];
- this.currentLang = this.availableLanguages[this.langSelected.lang];
this.langSelectedObs = this._langSelected.asObservable();
- this._langSelected.next(this.langSelected);
+ this.updateLangSelected();
+ }
+
+ setLanguageOptions(options: LangOption[] | undefined) {
+ if (options && options.length > 0) {
+ this.langOptions = options;
+ this.updateLangSelected();
+ }
}
- setLanguage(lang: string) {
+ async setLanguage(lang: string) {
const matchingLang = this.langOptions.find((l) => l.lang === lang);
if (matchingLang) {
- this.currentLang = this.availableLanguages[lang];
+ this.currentLang = await this.getLangData(lang);
this.langSelected = matchingLang;
this._langSelected.next(this.langSelected);
}
@@ -75,4 +79,32 @@ export class TranslateService {
});
return result;
}
+
+ private async updateLangSelected() {
+ const storageLang = this.storageService.getLang();
+ const langOpt = this.langOptions.find((opt) => opt.lang === storageLang);
+ if (storageLang && langOpt) {
+ this.langSelected = langOpt;
+ } else {
+ this.langSelected = this.langOptions[0];
+ }
+ this.currentLang = await this.getLangData(this.langSelected.lang);
+ this._langSelected.next(this.langSelected);
+
+ }
+
+ private async getLangData(lang: string): Promise {
+ if (!(lang in this.availableLanguages)) {
+ // Language not found in default languages options
+ // Try to find it in the assets/lang directory
+ try {
+ const response = await fetch(`assets/lang/${lang}.json`);
+ return await response.json();
+ } catch (error) {
+ console.error(`Not found ${lang}.json in assets/lang`, error);
+ }
+ } else {
+ return this.availableLanguages[lang];
+ }
+ }
}
diff --git a/openvidu-components-angular/src/app/openvidu-call/call.component.html b/openvidu-components-angular/src/app/openvidu-call/call.component.html
index 7118e137c9..0c5057c8c3 100644
--- a/openvidu-components-angular/src/app/openvidu-call/call.component.html
+++ b/openvidu-components-angular/src/app/openvidu-call/call.component.html
@@ -1,9 +1,10 @@
+ */
+ @Input() set langOptions(value: string | LangOption[]) {
+ this._langOptions = this.castToArray(value);
+ }
+
/**
* The captionsLangOptions attribute sets the language options for the captions.
* It will override the languages provided by default.
@@ -188,19 +226,19 @@ export class OpenviduWebComponentComponent implements OnInit {
*
* Default: ```
* [
- * { name: 'English', ISO: 'en-US' },
- * { name: 'Español', ISO: 'es-ES' },
- * { name: 'Deutsch', ISO: 'de-DE' },
- * { name: 'Français', ISO: 'fr-FR' },
- * { name: '中国', ISO: 'zh-CN' },
- * { name: 'हिन्दी', ISO: 'hi-IN' },
- * { name: 'Italiano', ISO: 'it-IT' },
- * { name: 'やまと', ISO: 'jp-JP' },
- * { name: 'Português', ISO: 'pt-PT' }
+ * { name: 'English', lang: 'en-US' },
+ * { name: 'Español', lang: 'es-ES' },
+ * { name: 'Deutsch', lang: 'de-DE' },
+ * { name: 'Français', lang: 'fr-FR' },
+ * { name: '中国', lang: 'zh-CN' },
+ * { name: 'हिन्दी', lang: 'hi-IN' },
+ * { name: 'Italiano', lang: 'it-IT' },
+ * { name: 'やまと', lang: 'jp-JP' },
+ * { name: 'Português', lang: 'pt-PT' }
* ]```
*
* @example
- *
+ *
*/
@Input() set captionsLangOptions(value: string | CaptionsLangOption[]) {
this._captionsLangOptions = this.castToArray(value);
@@ -888,7 +926,7 @@ export class OpenviduWebComponentComponent implements OnInit {
return value;
} else {
throw new Error(
- 'Parameter has not a valid type. The parameters must to be string or CaptionsLangOptions [] [{name:string, ISO: string}].'
+ 'Parameter has not a valid type. The parameters must to be string or CaptionsLangOptions [] [{name:string, lang: string}].'
);
}
}