Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Edit Project Info): Multiple languages setting #1546

Merged
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@angular/platform-browser": "^16.2.9",
"@angular/platform-browser-dynamic": "^16.2.9",
"@angular/router": "^16.2.9",
"@ng-select/ng-select": "^11.2.0",
"@ng-web-apis/common": "^2.0.1",
"@ng-web-apis/intersection-observer": "^3.0.0",
"@stomp/rx-stomp": "^1.1.4",
Expand Down
10 changes: 8 additions & 2 deletions src/app/domain/localeToLanguage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
export const localeToLanguage = {
export const localeToLanguage: { [locale: string]: string } = {
en_US: $localize`English`,
es: $localize`Spanish`,
de: $localize`German`,
ja: $localize`Japanese`,
it: $localize`Italian`
it: $localize`Italian`,
ko: $localize`Korean`,
nl: $localize`Dutch (Netherlands)`,
vi: $localize`Vietnamese`,
zh_CN: $localize`Chinese (Simplified)`,
zh_TW: $localize`Chinese (Traditional)`
};
33 changes: 20 additions & 13 deletions src/app/domain/projectLocale.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
import { Language } from './language';
import { localeToLanguage } from './localeToLanguage';

const defaultLocales = {
default: 'en_US',
supported: []
};
const defaultProjectLocale = { default: 'en_US', supported: [] };
export class ProjectLocale {
private default: string;
private supported: string[];
private locale: { default: string; supported: string[] };

constructor(locales: any = defaultLocales) {
this.default = locales.default;
this.supported = locales.supported;
constructor(locale: any = defaultProjectLocale) {
this.locale = locale;
}

getDefaultLanguage(): Language {
return { language: localeToLanguage[this.locale.default], locale: this.locale.default };
}

setDefaultLocale(locale: string): void {
this.locale.default = locale;
}

getSupportedLanguages(): Language[] {
return this.supported.map((locale) => ({
return this.locale.supported.map((locale) => ({
language: localeToLanguage[locale],
locale: locale
}));
}

setSupportedLanguages(languages: Language[]): void {
this.locale.supported = languages.map((language) => language.locale);
}

private hasLocale(locale: string): boolean {
return this.supported.includes(locale);
return this.locale.supported.includes(locale);
}

hasTranslations(): boolean {
return this.supported.length > 1;
return this.locale.supported.length > 1;
}

hasTranslationsToApply(locale: string): boolean {
return !this.isDefaultLocale(locale) && this.hasLocale(locale);
}

isDefaultLocale(locale: string): boolean {
return this.default === locale;
return this.locale.default === locale;
}
}
4 changes: 2 additions & 2 deletions src/app/services/translateProjectService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('TranslateProjectService', () => {
spyOn(projectService, 'getLocale').and.returnValue(new ProjectLocale());
});
it('should keep original project in tact', () => {
service.translate().subscribe(() => {
service.translate().then(() => {
expect(projectService.getProjectTitle()).toEqual('Demo Project');
});
});
Expand All @@ -44,7 +44,7 @@ describe('TranslateProjectService', () => {
spyOn(configService, 'getConfigParam').and.returnValue('/123/project.json');
});
it('should retrieve translation mapping file and translate project', () => {
service.translate('es').subscribe(() => {
service.translate('es').then(() => {
expect(projectService.getProjectTitle()).toEqual('Proyecto de demostración');
});
http
Expand Down
4 changes: 4 additions & 0 deletions src/app/teacher/authoring-tool.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';
import { AddYourOwnNode } from '../../assets/wise5/authoringTool/addNode/add-your-own-node/add-your-own-node.component';
import { ChooseNewNodeLocation } from '../../assets/wise5/authoringTool/addNode/choose-new-node-location/choose-new-node-location.component';
import { ChooseNewNodeTemplate } from '../../assets/wise5/authoringTool/addNode/choose-new-node-template/choose-new-node-template.component';
Expand Down Expand Up @@ -56,6 +57,7 @@ import { ComponentTypeButtonComponent } from '../../assets/wise5/authoringTool/c
import { ComponentInfoDialogComponent } from '../../assets/wise5/authoringTool/components/component-info-dialog/component-info-dialog.component';
import { ComponentTypeSelectorComponent } from '../../assets/wise5/authoringTool/components/component-type-selector/component-type-selector.component';
import { EditNodeTitleComponent } from '../../assets/wise5/authoringTool/node/edit-node-title/edit-node-title.component';
import { EditProjectLanguageSettingComponent } from '../../assets/wise5/authoringTool/project-info/edit-project-language-setting/edit-project-language-setting.component';

@NgModule({
declarations: [
Expand Down Expand Up @@ -85,6 +87,7 @@ import { EditNodeTitleComponent } from '../../assets/wise5/authoringTool/node/ed
ConcurrentAuthorsMessageComponent,
ConfigureAutomatedAssessmentComponent,
EditNodeTitleComponent,
EditProjectLanguageSettingComponent,
InsertNodeAfterButtonComponent,
InsertNodeInsideButtonComponent,
MilestonesAuthoringComponent,
Expand All @@ -111,6 +114,7 @@ import { EditNodeTitleComponent } from '../../assets/wise5/authoringTool/node/ed
MatBadgeModule,
MatChipsModule,
ImportComponentModule,
NgSelectModule,
NodeAdvancedAuthoringModule,
PreviewComponentModule,
ProjectAssetAuthoringModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@
(ngModelChange)="metadataChanged.next()"
/>
</mat-form-field>
<ng-container *ngIf="metadataField.type === 'radio'">
<edit-project-language-setting
*ngIf="metadataField.name === 'Language'"
></edit-project-language-setting>
<ng-container *ngIf="metadataField.type === 'radio' && metadataField.name !== 'Language'">
<label class="bold">{{ metadataField.name }}:</label>
<mat-radio-group class="radio-group margin-bottom-20" fxLayout="column">
<ng-container *ngFor="let choice of metadataField.choices">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<h3 i18n>Language</h3>
<span i18n>Default language:</span>
<ng-select
[items]="availableLanguages"
bindLabel="language"
[(ngModel)]="defaultLanguage"
[clearable]="false"
(change)="updateDefaultLanguage()"
>
</ng-select>
<span i18n>Additional languages:</span>
<ng-select
[items]="availableLanguages"
bindLabel="language"
[(ngModel)]="supportedLanguages"
[multiple]="true"
(change)="updateSupportedLanguages()"
>
</ng-select>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NgSelectModule } from '@ng-select/ng-select';
import { EditProjectLanguageSettingComponent } from './edit-project-language-setting.component';
import { TeacherProjectService } from '../../../services/teacherProjectService';
import { ProjectLocale } from '../../../../../app/domain/projectLocale';
import { FormsModule } from '@angular/forms';

class MockTeacherProjectService {
getLocale() {}
saveProject() {}
}
describe('EditProjectLanguageSettingComponent', () => {
let component: EditProjectLanguageSettingComponent;
let fixture: ComponentFixture<EditProjectLanguageSettingComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [EditProjectLanguageSettingComponent],
imports: [FormsModule, NgSelectModule],
providers: [{ provide: TeacherProjectService, useClass: MockTeacherProjectService }]
});
fixture = TestBed.createComponent(EditProjectLanguageSettingComponent);
component = fixture.componentInstance;
spyOn(TestBed.inject(TeacherProjectService), 'getLocale').and.returnValue(new ProjectLocale());
fixture.detectChanges();
});

it('creates', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Component } from '@angular/core';
import { Language } from '../../../../../app/domain/language';
import { TeacherProjectService } from '../../../services/teacherProjectService';
import { ProjectLocale } from '../../../../../app/domain/projectLocale';
import { localeToLanguage } from '../../../../../app/domain/localeToLanguage';

@Component({
selector: 'edit-project-language-setting',
templateUrl: './edit-project-language-setting.component.html'
})
export class EditProjectLanguageSettingComponent {
protected availableLanguages: Language[] = Object.entries(
localeToLanguage
).map(([locale, language]) => ({ locale: locale, language: language }));
protected defaultLanguage: Language;
private projectLocale: ProjectLocale;
protected supportedLanguages: Language[];

constructor(private projectService: TeacherProjectService) {}

ngOnInit(): void {
this.projectLocale = this.projectService.getLocale();
this.defaultLanguage = this.projectLocale.getDefaultLanguage();
this.supportedLanguages = this.projectLocale.getSupportedLanguages();
}

protected updateDefaultLanguage(): void {
this.projectLocale.setDefaultLocale(this.defaultLanguage.locale);
this.projectService.saveProject();
}

protected updateSupportedLanguages(): void {
this.projectLocale.setSupportedLanguages(this.supportedLanguages);
this.projectService.saveProject();
}
}
72 changes: 66 additions & 6 deletions src/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -2279,18 +2279,60 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<context context-type="linenumber">3</context>
</context-group>
</trans-unit>
<trans-unit id="1858110241312746425" datatype="html">
<source>German</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit id="6924606686202701860" datatype="html">
<source>Japanese</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">4</context>
<context context-type="linenumber">5</context>
</context-group>
</trans-unit>
<trans-unit id="2935232983274991580" datatype="html">
<source>Italian</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">6</context>
</context-group>
</trans-unit>
<trans-unit id="6145439649200570157" datatype="html">
<source>Korean</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">7</context>
</context-group>
</trans-unit>
<trans-unit id="1134844588409242643" datatype="html">
<source>Dutch (Netherlands)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="3611216939636790848" datatype="html">
<source>Vietnamese</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">9</context>
</context-group>
</trans-unit>
<trans-unit id="511208907501917679" datatype="html">
<source>Chinese (Simplified)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">10</context>
</context-group>
</trans-unit>
<trans-unit id="4303868626158306518" datatype="html">
<source>Chinese (Traditional)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/domain/localeToLanguage.ts</context>
<context context-type="linenumber">11</context>
</context-group>
</trans-unit>
<trans-unit id="8954371642157143595" datatype="html">
Expand Down Expand Up @@ -2790,7 +2832,7 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.ts</context>
<context context-type="linenumber">91</context>
<context context-type="linenumber">90</context>
</context-group>
</trans-unit>
<trans-unit id="6244139ed5734258736685c4d638b4fac1b04bbb" datatype="html">
Expand Down Expand Up @@ -2869,7 +2911,7 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.ts</context>
<context context-type="linenumber">81</context>
<context context-type="linenumber">80</context>
</context-group>
</trans-unit>
<trans-unit id="c83b838d845690bcb897f775f53b5316535306dc" datatype="html">
Expand Down Expand Up @@ -3342,14 +3384,14 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<source>You have submitted an invalid verification code too many times. For security reasons, we will lock the ability to change your password for 10 minutes. After 10 minutes, you can try again.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.ts</context>
<context context-type="linenumber">85</context>
<context context-type="linenumber">84</context>
</context-group>
</trans-unit>
<trans-unit id="243316711119938992" datatype="html">
<source>The server has encountered an error and was unable to send you an email. Please try again. If the error continues to occur, please contact us.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/forgot/teacher/forgot-teacher-password/forgot-teacher-password.component.ts</context>
<context context-type="linenumber">88</context>
<context context-type="linenumber">87</context>
</context-group>
</trans-unit>
<trans-unit id="5c112eccf2cd10cf48736fb8fd2c18c1788b6bb9" datatype="html">
Expand Down Expand Up @@ -7392,6 +7434,10 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<context context-type="sourcefile">src/app/teacher/account/edit-profile/edit-profile.component.html</context>
<context context-type="linenumber">109</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/project-info/edit-project-language-setting/edit-project-language-setting.component.html</context>
<context context-type="linenumber">1</context>
</context-group>
</trans-unit>
<trans-unit id="cabad35c321f1c28ef7c11f848cd458bb934e304" datatype="html">
<source>Language required</source>
Expand Down Expand Up @@ -12268,6 +12314,20 @@ Click &quot;Cancel&quot; to keep the invalid JSON open so you can fix it.</sourc
<context context-type="linenumber">22,24</context>
</context-group>
</trans-unit>
<trans-unit id="d5633c7ffb5d36eebe0dbe84efa93a1e95713391" datatype="html">
<source>Default language:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/project-info/edit-project-language-setting/edit-project-language-setting.component.html</context>
<context context-type="linenumber">2</context>
</context-group>
</trans-unit>
<trans-unit id="a4822ae93998e191f2bed67a380af96f2b5e63bb" datatype="html">
<source>Additional languages:</source>
<context-group purpose="location">
<context context-type="sourcefile">src/assets/wise5/authoringTool/project-info/edit-project-language-setting/edit-project-language-setting.component.html</context>
<context context-type="linenumber">11</context>
</context-group>
</trans-unit>
<trans-unit id="abf24af7ad0fd7ffecdad3210051c47589373d68" datatype="html">
<source>Back to Teacher Home</source>
<context-group purpose="location">
Expand Down
Loading