From 1b4e553a35ef19fe88882dbb58cf0e2c81892739 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 13 Nov 2024 09:50:57 +0100 Subject: [PATCH 01/28] Adding translations-button to post-head --- .../src/app/core/enums/icons.ts | 1 + .../post/post-head/post-head.component.html | 16 +++++++++++++ .../src/app/post/post.module.ts | 2 ++ .../src/assets/icons/translate.svg | 23 +++++++++++++++++++ libs/sdk/src/lib/models/posts.interface.ts | 7 ++++++ 5 files changed, 49 insertions(+) create mode 100644 apps/web-mzima-client/src/assets/icons/translate.svg diff --git a/apps/web-mzima-client/src/app/core/enums/icons.ts b/apps/web-mzima-client/src/app/core/enums/icons.ts index 28bc3415fe..4c59be5e77 100644 --- a/apps/web-mzima-client/src/app/core/enums/icons.ts +++ b/apps/web-mzima-client/src/app/core/enums/icons.ts @@ -75,4 +75,5 @@ export enum Icons { thumbUp = 'thumb-up', ellipses = 'ellipses', lock = 'lock', + translate = 'translate', } diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html index e93e68cc3d..daeada1c9a 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html @@ -33,6 +33,22 @@ > + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/sdk/src/lib/models/posts.interface.ts b/libs/sdk/src/lib/models/posts.interface.ts index 6a808ea2f6..4b01240715 100644 --- a/libs/sdk/src/lib/models/posts.interface.ts +++ b/libs/sdk/src/lib/models/posts.interface.ts @@ -61,6 +61,7 @@ export interface PostPropertiesInterface { locks?: any[]; data_source_message_id?: string; allowed_privileges: string[]; + enabled_languages: PostEnabledLanguages; } export interface PostPropertiesUser { @@ -112,6 +113,7 @@ export interface PostResult { form_id?: number; user?: PostPropertiesUser; post_content?: PostContent[]; + enabled_languages: PostEnabledLanguages; } interface PostTag { @@ -177,3 +179,8 @@ export interface PostContentField { type: string; value?: any; } + +export interface PostEnabledLanguages { + default: string; + available: string[]; +} From 08e07da1a44504d3521c7d6adfd2a0ea0e23f4c9 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 13 Nov 2024 09:54:41 +0100 Subject: [PATCH 02/28] Adding post-translations component --- .../app/post/post-head/post-head.component.ts | 19 +++++++++++++++++ .../post-translate.component.html | 0 .../post-translate.component.scss | 0 .../post-translate.component.spec.ts | 21 +++++++++++++++++++ .../post-translate.component.ts | 0 5 files changed, 40 insertions(+) create mode 100644 apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html create mode 100644 apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss create mode 100644 apps/web-mzima-client/src/app/post/post-translate/post-translate.component.spec.ts create mode 100644 apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts index 8ae42f8f93..1c2ff3da84 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts @@ -2,6 +2,7 @@ import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { CollectionsComponent } from '../../shared/components'; +import { PostTranslateComponent } from '../post-translate/post-translate.component'; import { TranslateService } from '@ngx-translate/core'; import { BreakpointService, EventBusService, EventType, SessionService } from '@services'; import { BaseComponent } from '../../base.component'; @@ -14,6 +15,8 @@ import { postHelpers, } from '@mzima-client/sdk'; import { ConfirmModalService } from '../../core/services/confirm-modal.service'; +import { LanguageService } from '../../core/services/language.service'; +import { LanguageInterface } from '@mzima-client/sdk'; @Component({ selector: 'app-post-head', @@ -31,6 +34,7 @@ export class PostHeadComponent extends BaseComponent implements OnInit { @Output() deleted = new EventEmitter(); @Output() statusChanged = new EventEmitter(); public isLocked: boolean; + public languages: LanguageInterface[]; constructor( protected override sessionService: SessionService, @@ -41,6 +45,7 @@ export class PostHeadComponent extends BaseComponent implements OnInit { private translate: TranslateService, private eventBusService: EventBusService, private snackBar: MatSnackBar, + private languageService: LanguageService, ) { super(sessionService, breakpointService); this.checkDesktop(); @@ -49,6 +54,7 @@ export class PostHeadComponent extends BaseComponent implements OnInit { ngOnInit(): void { this.checkLock(); + this.languages = this.languageService.getLanguages(); } loadData(): void {} @@ -75,6 +81,19 @@ export class PostHeadComponent extends BaseComponent implements OnInit { }); } + translatePost() { + this.dialog.open(PostTranslateComponent, { + width: '100%', + maxWidth: '768px', + panelClass: ['modal', 'select-languages-modal'], + + data: { + post: this.post, + languages: this.languages, + }, + }); + } + underReview() { this.postsService.updateStatus(this.post.id, PostStatus.Draft).subscribe((res) => { this.post = res.result; diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.spec.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.spec.ts new file mode 100644 index 0000000000..9a1a44daaf --- /dev/null +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PostTranslateComponent } from './post-translate.component'; + +describe('PostTranslateComponent', () => { + let component: PostTranslateComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostTranslateComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(PostTranslateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts new file mode 100644 index 0000000000..e69de29bb2 From 78fc84632da1f68fa7f4477c8d7782d8fdb3bf3a Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 13 Nov 2024 10:00:32 +0100 Subject: [PATCH 03/28] Fix language-length check --- .../src/app/post/post-head/post-head.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html index daeada1c9a..bb75160672 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html @@ -39,7 +39,7 @@ tabindex="-1" [iconOnly]="true" (buttonClick)="translatePost()" - *ngIf="editable || post.enabled_languages.available.length > 1" + *ngIf="editable || post.enabled_languages.available.length > 0" class="post-head__control post-head__control--share" > Date: Wed, 13 Nov 2024 10:02:16 +0100 Subject: [PATCH 04/28] Translations component for posts --- .../post-translate.component.html | 174 ++++++++++++++++++ .../post-translate.component.scss | 79 ++++++++ .../post-translate.component.ts | 108 +++++++++++ libs/sdk/src/lib/services/posts.service.ts | 4 +- 4 files changed, 364 insertions(+), 1 deletion(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index e69de29bb2..7447ab460f 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -0,0 +1,174 @@ + + + +{{ isTranslateMode ? 'Translate post to ' + activeLanguage.name : 'Translate post' }} + + +
+ +

+ Available translations (select to see post): +

+ + + + {{ language?.name }} + + + +
+

Select a language to translate to, or edit:

+
+
    +
  • + + + {{ defaultLanguage?.name }} (Default language) + +
  • +
  • + + + {{ language.name }} + +
  • +
+
+
+
+ + +
+
+
+
+ HEJ + +
+ +
+ {{ field?.translations[activeLanguage.code]?.label || field?.label }} + +
+
Text in original language:
+
+

{{ getOriginalValue(field) }}

+
+
+
+ Add your translation below: + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+ +
+ + {{ 'app.cancel' | translate }} + + + {{ 'app.save' | translate }} + +
+
+
diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss index e69de29bb2..3c8f68e94f 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss @@ -0,0 +1,79 @@ +@import 'helpers'; + +.types-list { + padding: 0; + display: flex; + margin: 0 -8px; + flex-wrap: wrap; + list-style: none; + justify-content: flex-start; +} + +.type-item { + display: flex; + cursor: pointer; + min-height: 46px; + padding: 8px 12px; + margin: 0 4px 8px; + position: relative; + border-radius: 4px; + align-items: center; + width: calc(50% - 8px); + transition: color 0.35s ease; + background: var(--color-neutral-10); + border-inline-start: 5px solid var(--color, transparent); + + @include breakpoint-max($tablet) { + border-inline-start-width: 4px; + box-shadow: inset 0 0 0 1px var(--color-neutral-20); + } + + @include breakpoint-max($mobile) { + width: calc(100% - 8px); + } +} + +.flag { + width: 30px; + height: 20px; + object-fit: contain; + margin-inline-end: 5px; + object-position: 0 50%; +} +.translate_post { + display: flex; + flex-direction: row; + gap: 16px; + &__edit { + display: flex; + width: 100%; + padding: 24px 16px; + border-radius: 4px; + flex-direction: column; + align-items: flex-start; + gap: 24px; + background: var(--Neutral-Neutral-10, #f5f5f5); + } + &__fields { + display: flex; + flex-direction: column; + width: 100%; + gap: 24px; + } + .field-label { + font-weight: 500; + line-height: 160%; /* 22.4px */ + letter-spacing: -0.07px; + } + &__original { + padding: 24px; + border: 1px solid var(--Neutral-Neutral-30, #e2e2e3); + background-color: white; + display: flex-row; + } + &__translation { + } + .mat-form-field { + background: white; + } +} diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index e69de29bb2..323ce74d0f 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -0,0 +1,108 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormGroup, FormControl } from '@angular/forms'; + +import { LanguageInterface, PostResult, PostsService } from '@mzima-client/sdk'; +import { UntilDestroy } from '@ngneat/until-destroy'; +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import * as _ from 'lodash'; +export interface PostTranslateComponentData { + post: PostResult; + languages: LanguageInterface[]; +} + +@UntilDestroy() +@Component({ + selector: 'app-post-translate', + templateUrl: './post-translate.component.html', + styleUrls: ['./post-translate.component.scss'], +}) +export class PostTranslateComponent implements OnInit { + public languages: LanguageInterface[]; + public enabledLanguages: any; + public isTranslateMode: boolean; + public activeLanguage: LanguageInterface; + public defaultLanguage: LanguageInterface | undefined; + public post: any; + public translateForm: FormGroup; + constructor( + @Inject(MAT_DIALOG_DATA) + public data: PostTranslateComponentData, + private postsService: PostsService, + ) {} + + ngOnInit(): void { + this.languages = this.data.languages; + this.isTranslateMode = false; + this.post = _.cloneDeep(this.data.post); + this.enabledLanguages = this.post.enabled_languages; + this.defaultLanguage = this.languages.find((lang) => lang.code === this.post.base_language); + } + closeModal() { + console.log('close modal'); + } + saveTranslation() { + this.post.enabled_languages = this.enabledLanguages; + this.post.post_content.forEach((task: any) => { + task.fields + .filter((field: any) => field.key in this.translateForm.controls) + .forEach((field: any) => { + const translatedValue = this.translateForm.controls[field.key].value; + if (!field.value) { + field.value = {}; + } + if (!field.value.translations) { + field.value.translations = {}; + } + field.value = { + ...field.value, + translations: [ + { + ...field.value.translations[0], + [this.activeLanguage.code]: { value: translatedValue }, + }, + ], + }; + if (field.type === 'title' || field.type === 'description') { + this.post.translations = [this.activeLanguage.code] = [ + { + ...this.post.translations[this.activeLanguage.code], + [field.type]: translatedValue, + }, + ]; + } + }); + }); + this.postsService.updateTranslations(this.post.id, this.post).subscribe((res) => { + console.log(res); + }); + } + selectLanguage(event: Event, lang: LanguageInterface) { + this.translateForm = this.createForm(); + this.isTranslateMode = true; + this.activeLanguage = lang; + this.enabledLanguages.available.push(lang.code); + } + + createForm() { + const newForm = new FormGroup({}); + this.post.post_content + .flatMap((task: any) => task.fields) + .filter((field: any) => this.isTranslateableContent(field)) + .forEach((field: any) => newForm.addControl(field.key, new FormControl(''))); + return newForm; + } + + getOriginalValue(field: any) { + if (field.type === 'title') { + return this.post.title; + } + if (field.type === 'description') { + return this.post.content; + } + return field.value.value; + } + + isTranslateableContent(field: any) { + return field.input === 'text' || field.input === 'textarea' || field.input === 'markdown'; + } +} diff --git a/libs/sdk/src/lib/services/posts.service.ts b/libs/sdk/src/lib/services/posts.service.ts index e3b8542949..3da3dfba60 100644 --- a/libs/sdk/src/lib/services/posts.service.ts +++ b/libs/sdk/src/lib/services/posts.service.ts @@ -50,7 +50,6 @@ export class PostsService extends ResourceService { private responseObject: any; private awaitedResponse = new Subject(); public awaitedResponse$ = this.awaitedResponse.asObservable(); - constructor( protected override httpClient: HttpClient, protected override currentLoader: EnvLoader, @@ -70,6 +69,9 @@ export class PostsService extends ResourceService { updateStatus(id: string | number, status: string) { return super.patch(id, { status }); } + updateTranslations(id: string, post: any) { + return super.patch(id, post); + } override post(params: any): Observable { return super.post(params); From 0cc52ef00a4ac82472d74f3462600fd115ec95d1 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 13 Nov 2024 10:03:52 +0100 Subject: [PATCH 05/28] Moving permissions-check --- .../src/app/post/post-translate/post-translate.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index 7447ab460f..d219db79da 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -75,8 +75,8 @@ - -
+ +
From 4eb4c9399418760c1958c96e113e2eb1efad1184 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 4 Dec 2024 15:07:21 +0100 Subject: [PATCH 06/28] Sending base-language when saving a post --- .../src/app/post/post-edit/post-edit.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts index e9ceac9f8f..214eede07e 100644 --- a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts +++ b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts @@ -719,9 +719,9 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange this.showMessage(error, 'error'); return; } - + const postLanguage = this.selectedLanguage.code; const postData = { - base_language: 'en', + base_language: postLanguage, completed_stages: this.completeStages, content: this.description, description: '', From a19fec441db86ccfe6e006b6d731f5b697ea6ef8 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 4 Dec 2024 15:12:16 +0100 Subject: [PATCH 07/28] Displaying existing post-translations in the translation-edit view --- .../post-translate.component.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index 323ce74d0f..847ee5b5c2 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -77,10 +77,10 @@ export class PostTranslateComponent implements OnInit { }); } selectLanguage(event: Event, lang: LanguageInterface) { - this.translateForm = this.createForm(); - this.isTranslateMode = true; this.activeLanguage = lang; + this.translateForm = this.createForm(); this.enabledLanguages.available.push(lang.code); + this.isTranslateMode = true; } createForm() { @@ -88,7 +88,13 @@ export class PostTranslateComponent implements OnInit { this.post.post_content .flatMap((task: any) => task.fields) .filter((field: any) => this.isTranslateableContent(field)) - .forEach((field: any) => newForm.addControl(field.key, new FormControl(''))); + .forEach((field: any) => { + newForm.addControl(field.key, new FormControl('')); + const translation = this.getTranslationValue(field); + if (translation) { + newForm.get(field.key)?.setValue(translation); + } + }); return newForm; } @@ -102,7 +108,20 @@ export class PostTranslateComponent implements OnInit { return field.value.value; } + getTranslationValue(field: any) { + if (field.type === 'title') { + return this.post.translations?.[this.activeLanguage.code]?.title || ''; + } + if (field.type === 'description') { + return this.post.translations?.[this.activeLanguage.code]?.content || ''; + } + return field.value?.translations?.[this.activeLanguage.code]?.value || ''; + } + isTranslateableContent(field: any) { - return field.input === 'text' || field.input === 'textarea' || field.input === 'markdown'; + if (field.type === 'title' || field.type === 'description') return true; + if (field.value && field.value.value) + return field.input === 'text' || field.input === 'textarea' || field.input === 'markdown'; + return false; } } From 3e2d960b10548ba0133aa113ff11ab45b221bc0a Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Mon, 9 Dec 2024 14:45:03 +0100 Subject: [PATCH 08/28] Saving translations properly --- .../post-translate.component.html | 2 - .../post-translate.component.ts | 82 +++++++++++++------ libs/sdk/src/lib/services/posts.service.ts | 2 +- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index d219db79da..e44bfe7522 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -80,8 +80,6 @@
- HEJ -
diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index 847ee5b5c2..49aef27b33 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -2,9 +2,11 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup, FormControl } from '@angular/forms'; import { LanguageInterface, PostResult, PostsService } from '@mzima-client/sdk'; +import { EventBusService, EventType } from '@services'; import { UntilDestroy } from '@ngneat/until-destroy'; -import { MAT_DIALOG_DATA } from '@angular/material/dialog'; -import * as _ from 'lodash'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MatSnackBar } from '@angular/material/snack-bar'; + export interface PostTranslateComponentData { post: PostResult; languages: LanguageInterface[]; @@ -28,55 +30,81 @@ export class PostTranslateComponent implements OnInit { @Inject(MAT_DIALOG_DATA) public data: PostTranslateComponentData, private postsService: PostsService, + private eventBusService: EventBusService, + private snackBar: MatSnackBar, + private matDialogRef: MatDialogRef, ) {} ngOnInit(): void { this.languages = this.data.languages; this.isTranslateMode = false; - this.post = _.cloneDeep(this.data.post); + this.post = structuredClone(this.data.post); this.enabledLanguages = this.post.enabled_languages; this.defaultLanguage = this.languages.find((lang) => lang.code === this.post.base_language); } - closeModal() { - console.log('close modal'); + public closeModal(): void { + this.matDialogRef.close(); } saveTranslation() { + this.translateForm.disable(); this.post.enabled_languages = this.enabledLanguages; this.post.post_content.forEach((task: any) => { task.fields .filter((field: any) => field.key in this.translateForm.controls) .forEach((field: any) => { const translatedValue = this.translateForm.controls[field.key].value; - if (!field.value) { - field.value = {}; - } - if (!field.value.translations) { + field.value = field.value || {}; + field.value.translations = field.value.translations || {}; + + if (Array.isArray(field.value.translations) && field.value.translations.length === 0) { field.value.translations = {}; } - field.value = { - ...field.value, - translations: [ - { - ...field.value.translations[0], - [this.activeLanguage.code]: { value: translatedValue }, - }, - ], - }; + + field.value.translations[this.activeLanguage.code] = { value: translatedValue }; + if (field.type === 'title' || field.type === 'description') { - this.post.translations = [this.activeLanguage.code] = [ - { - ...this.post.translations[this.activeLanguage.code], - [field.type]: translatedValue, - }, - ]; + this.post.translations = this.post.translations || {}; + if (Array.isArray(this.post.translations) && this.post.translations.length === 0) { + this.post.translations = {}; + } + this.post.translations[this.activeLanguage.code] = + this.post.translations[this.activeLanguage.code] || {}; + this.post.translations[this.activeLanguage.code][field.type] = translatedValue; } }); }); - this.postsService.updateTranslations(this.post.id, this.post).subscribe((res) => { - console.log(res); + + this.postsService.updateTranslations(this.post.id, this.post).subscribe({ + next: ({ result }) => { + this.postsService.unlockPost(this.post.id).subscribe(); + this.eventBusService.next({ + type: EventType.UpdatedPost, + payload: result, + }); + }, + error: ({ error }) => { + this.translateForm.enable(); + this.postsService.unlockPost(this.post.id).subscribe(); + if (error.errors?.status === 422) { + this.showMessage(`Failed to save translation. ${error.errors.message}`, 'error'); + } + }, + complete: async () => { + this.showMessage('Translation saved successfully', 'success'); + this.postsService.unlockPost(this.post.id).subscribe(); + this.closeModal(); + }, + }); + } + + private showMessage(message: string, type: string) { + this.snackBar.open(message, 'Close', { + panelClass: [type], + duration: 3000, }); } selectLanguage(event: Event, lang: LanguageInterface) { + this.postsService.lockPost(this.post.id).subscribe(); this.activeLanguage = lang; this.translateForm = this.createForm(); this.enabledLanguages.available.push(lang.code); @@ -113,7 +141,7 @@ export class PostTranslateComponent implements OnInit { return this.post.translations?.[this.activeLanguage.code]?.title || ''; } if (field.type === 'description') { - return this.post.translations?.[this.activeLanguage.code]?.content || ''; + return this.post.translations?.[this.activeLanguage.code]?.description || ''; } return field.value?.translations?.[this.activeLanguage.code]?.value || ''; } diff --git a/libs/sdk/src/lib/services/posts.service.ts b/libs/sdk/src/lib/services/posts.service.ts index 3da3dfba60..e323495000 100644 --- a/libs/sdk/src/lib/services/posts.service.ts +++ b/libs/sdk/src/lib/services/posts.service.ts @@ -70,7 +70,7 @@ export class PostsService extends ResourceService { return super.patch(id, { status }); } updateTranslations(id: string, post: any) { - return super.patch(id, post); + return super.update(id, post); } override post(params: any): Observable { From 2ac1c9d64fdcc0e7a734ae2db46ea984d61315e7 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Tue, 10 Dec 2024 16:31:43 +0100 Subject: [PATCH 09/28] Displaying translations in post-details --- .../app/core/services/event-bus.service.ts | 1 + .../post-details/post-details.component.html | 28 +++++++++++++++---- .../post-details/post-details.component.ts | 13 +++++++++ libs/sdk/src/lib/models/posts.interface.ts | 1 + 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/apps/web-mzima-client/src/app/core/services/event-bus.service.ts b/apps/web-mzima-client/src/app/core/services/event-bus.service.ts index 4edcfbb07c..2f3ec85370 100644 --- a/apps/web-mzima-client/src/app/core/services/event-bus.service.ts +++ b/apps/web-mzima-client/src/app/core/services/event-bus.service.ts @@ -22,6 +22,7 @@ export const enum EventType { RefreshSurveysCounters = 'REFRESH_SURVEYS_COUNTERS', StopExportPolling = 'STOP_EXPORT_POLLING', ExportDone = 'EXPORT_DONE', + DisplayTranslatedPost = 'DISPLAY_TRANSLATED_POST', } export interface BusEvent { diff --git a/apps/web-mzima-client/src/app/post/post-details/post-details.component.html b/apps/web-mzima-client/src/app/post/post-details/post-details.component.html index 7d93b732e1..5b180f4bd9 100644 --- a/apps/web-mzima-client/src/app/post/post-details/post-details.component.html +++ b/apps/web-mzima-client/src/app/post/post-details/post-details.component.html @@ -31,14 +31,21 @@

{{ post.form.name }}

- {{ post.title || post.content }} + {{ + post.translations[displayLanguage]?.title || + post.title || + post.translations[displayLanguage]?.description || post.content + }}

-

+

@@ -121,12 +128,21 @@

{{ field.label }}

-

-

{{ field.value.value || '-' }}

+

+ {{ + field.value.translations[displayLanguage]?.value || field.value.value || '-' + }} +

-

+

@@ -226,7 +242,9 @@

{{ field.label }}

- {{ field.value.value || '-' }} + {{ + field.value.translations[displayLanguage]?.value || field.value.value || '-' + }}
diff --git a/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts b/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts index 5de4fd001c..0f974d5962 100644 --- a/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts +++ b/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts @@ -26,6 +26,7 @@ import { } from '@mzima-client/sdk'; import { TranslateService } from '@ngx-translate/core'; import { lastValueFrom } from 'rxjs'; +import { untilDestroyed } from '@ngneat/until-destroy'; import { BaseComponent } from '../../base.component'; import { preparingVideoUrl } from '../../core/helpers/validators'; import { dateHelper } from '@helpers'; @@ -51,6 +52,7 @@ export class PostDetailsComponent extends BaseComponent implements OnChanges, On public isPostLoading: boolean = true; public isManagePosts: boolean = false; public postChanged: boolean; + public displayLanguage: string; constructor( protected override sessionService: SessionService, @@ -82,9 +84,20 @@ export class PostDetailsComponent extends BaseComponent implements OnChanges, On this.postId = Number(params['id']); this.getPost(this.postId); + this.translatePost(); } }); } + translatePost() { + this.eventBusService + .on(EventType.DisplayTranslatedPost) + .pipe(untilDestroyed(this)) + .subscribe({ + next: (language) => { + this.displayLanguage = language.code; + }, + }); + } loadData(): void {} diff --git a/libs/sdk/src/lib/models/posts.interface.ts b/libs/sdk/src/lib/models/posts.interface.ts index 4b01240715..995c096088 100644 --- a/libs/sdk/src/lib/models/posts.interface.ts +++ b/libs/sdk/src/lib/models/posts.interface.ts @@ -81,6 +81,7 @@ export enum PostStatus { } export interface PostResult { + translations: any; allowed_privileges: string[]; author_email?: string; author_realname?: string; From 6f8cb9d39bcf7402b33d89f3d1236da3f7375f9a Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 11 Dec 2024 16:26:23 +0100 Subject: [PATCH 10/28] Fixing error when saving translations --- .../app/post/post-edit/post-edit.component.ts | 3 ++- .../post-translate.component.html | 20 +++++++++---------- .../post-translate.component.ts | 17 +++++++++++++--- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts index 214eede07e..549a984b02 100644 --- a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts +++ b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts @@ -719,7 +719,8 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange this.showMessage(error, 'error'); return; } - const postLanguage = this.selectedLanguage.code; + // should be site-language + const postLanguage = this.selectedLanguage?.code || 'en'; const postData = { base_language: postLanguage, completed_stages: this.completeStages, diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index e44bfe7522..a271024418 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -17,11 +17,9 @@
-

- Available translations (select to see post): -

+

Available translations (select to see post):

@@ -29,9 +27,11 @@ name="language" disableOptionCentering [placeholder]="'app.select_language' | translate" + [(value)]="displayPostLanguage" + (selectionChange)="displayTranslatedPost($event)" > - - {{ language?.name }} + + {{ language.name }} @@ -39,7 +39,7 @@

Select a language to translate to, or edit:

    -
  • +
  • - {{ defaultLanguage?.name }} (Default language) + {{ defaultLanguage.name }} (Default language)
  • diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index 49aef27b33..7d4de8cedb 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -5,6 +5,7 @@ import { LanguageInterface, PostResult, PostsService } from '@mzima-client/sdk'; import { EventBusService, EventType } from '@services'; import { UntilDestroy } from '@ngneat/until-destroy'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { MatSelectChange } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; export interface PostTranslateComponentData { @@ -26,6 +27,7 @@ export class PostTranslateComponent implements OnInit { public defaultLanguage: LanguageInterface | undefined; public post: any; public translateForm: FormGroup; + public displayPostLanguage: LanguageInterface; constructor( @Inject(MAT_DIALOG_DATA) public data: PostTranslateComponentData, @@ -39,15 +41,23 @@ export class PostTranslateComponent implements OnInit { this.languages = this.data.languages; this.isTranslateMode = false; this.post = structuredClone(this.data.post); - this.enabledLanguages = this.post.enabled_languages; + this.enabledLanguages = this.languages.filter((lang) => + this.post.enabled_languages.available.includes(lang.code), + ); this.defaultLanguage = this.languages.find((lang) => lang.code === this.post.base_language); } public closeModal(): void { this.matDialogRef.close(); } + public displayTranslatedPost(event: MatSelectChange) { + this.eventBusService.next({ + type: EventType.DisplayTranslatedPost, + payload: event.value, + }); + this.closeModal(); + } saveTranslation() { this.translateForm.disable(); - this.post.enabled_languages = this.enabledLanguages; this.post.post_content.forEach((task: any) => { task.fields .filter((field: any) => field.key in this.translateForm.controls) @@ -73,6 +83,7 @@ export class PostTranslateComponent implements OnInit { } }); }); + this.post.enabled_languages = { default: 'en', available: this.enabledLanguages }; this.postsService.updateTranslations(this.post.id, this.post).subscribe({ next: ({ result }) => { @@ -107,7 +118,7 @@ export class PostTranslateComponent implements OnInit { this.postsService.lockPost(this.post.id).subscribe(); this.activeLanguage = lang; this.translateForm = this.createForm(); - this.enabledLanguages.available.push(lang.code); + this.enabledLanguages.push(lang.code); this.isTranslateMode = true; } From 0dd66fbd37e7f989e69cf6e59160be8c554ea221 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Thu, 12 Dec 2024 19:10:32 +0100 Subject: [PATCH 11/28] New alert for success/info --- apps/web-mzima-client/src/styles.scss | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/web-mzima-client/src/styles.scss b/apps/web-mzima-client/src/styles.scss index c7238e2ec8..c6a2c49f0c 100644 --- a/apps/web-mzima-client/src/styles.scss +++ b/apps/web-mzima-client/src/styles.scss @@ -133,6 +133,14 @@ a { .notice { margin: 0; } + + &.success-info { + background-color: #e4f9ed; + border: none; + border-radius: 4px; + padding: 16px; + font-style: normal; + } } .mat-drawer-container { From caeb1400bc984b27ea6f05a5051939ecade0ea29 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Thu, 12 Dec 2024 19:15:14 +0100 Subject: [PATCH 12/28] Info/alert-box in posts when showing a translated post --- .../post-details/post-details.component.html | 12 +++++++-- .../post-details/post-details.component.ts | 19 +++++++++++++ .../post/post-head/post-head.component.html | 2 +- .../app/post/post-head/post-head.component.ts | 1 + .../post-translated.component.html | 27 +++++++++++++++++++ .../post-translated.component.scss | 21 +++++++++++++++ .../post-translated.component.spec.ts | 24 +++++++++++++++++ .../post-translated.component.ts | 27 +++++++++++++++++++ .../src/app/post/post.module.ts | 3 +++ libs/sdk/src/lib/models/posts.interface.ts | 1 + 10 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 apps/web-mzima-client/src/app/post/post-translated/post-translated.component.html create mode 100644 apps/web-mzima-client/src/app/post/post-translated/post-translated.component.scss create mode 100644 apps/web-mzima-client/src/app/post/post-translated/post-translated.component.spec.ts create mode 100644 apps/web-mzima-client/src/app/post/post-translated/post-translated.component.ts diff --git a/apps/web-mzima-client/src/app/post/post-details/post-details.component.html b/apps/web-mzima-client/src/app/post/post-details/post-details.component.html index 5b180f4bd9..e400554c99 100644 --- a/apps/web-mzima-client/src/app/post/post-details/post-details.component.html +++ b/apps/web-mzima-client/src/app/post/post-details/post-details.component.html @@ -17,10 +17,17 @@ [deleteable]="post.allowed_privileges.includes('delete')" (statusChanged)="statusChangedHandle()" (deleted)="deletedHandle()" + (openTranslationModal)="openTranslatePost()" >
- + @@ -34,7 +41,8 @@

{{ post.translations[displayLanguage]?.title || post.title || - post.translations[displayLanguage]?.description || post.content + post.translations[displayLanguage]?.description || + post.content }}

-

{{ post.form.name }}

-

{{ post.form.description }}

+

{{ post.form.translations[displayLanguage]?.name || post.form.name }}

+

{{ post.form.translations[displayLanguage]?.description || post.form.description }}

@@ -75,7 +75,7 @@

*ngIf="field.input !== 'tags' ? field.value : field.value?.length" class="post__group" > -

{{ field.label }}

+

{{ field.translations[displayLanguage]?.label || field.label }}

diff --git a/libs/sdk/src/lib/models/posts.interface.ts b/libs/sdk/src/lib/models/posts.interface.ts index 1ef1919770..cc98ea9b8d 100644 --- a/libs/sdk/src/lib/models/posts.interface.ts +++ b/libs/sdk/src/lib/models/posts.interface.ts @@ -128,6 +128,7 @@ interface PostForm { url: string; description?: string; name?: string; + translations: any; } export interface PostContent { From fe9b90161e63774a6006ca5ea2fee3b8bf40c101 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Fri, 13 Dec 2024 10:42:30 +0100 Subject: [PATCH 15/28] Hiding translation-icon in list --- .../post/post-head/post-head.component.html | 2 +- .../app/post/post-head/post-head.component.ts | 21 +++++++------------ .../post-preview/post-preview.component.html | 1 + 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html index c1272e1a13..7c23c586f1 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.html +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.html @@ -39,7 +39,7 @@ tabindex="-1" [iconOnly]="true" (buttonClick)="openTranslationModal.emit()" - *ngIf="editable || post.enabled_languages.available.length > 0" + *ngIf="showTranslationsIcon()" class="post-head__control post-head__control--share" > { this.post = res.result; @@ -185,4 +172,10 @@ export class PostHeadComponent extends BaseComponent implements OnInit { duration, }); } + public showTranslationsIcon() { + const languagesAvailabe = + this.post && this.post.enabled_languages && this.post.enabled_languages.available; + const needToHideIcon = this.hideTranslationsIcon && this.feedView; + return !needToHideIcon && (languagesAvailabe || this.editable); + } } diff --git a/apps/web-mzima-client/src/app/post/post-preview/post-preview.component.html b/apps/web-mzima-client/src/app/post/post-preview/post-preview.component.html index 772da88e31..05fb48f59d 100644 --- a/apps/web-mzima-client/src/app/post/post-preview/post-preview.component.html +++ b/apps/web-mzima-client/src/app/post/post-preview/post-preview.component.html @@ -21,6 +21,7 @@ [deleteable]="post.allowed_privileges.includes('delete')" (deleted)="deletedHandle()" (statusChanged)="statusChangedHandle()" + [hideTranslationsIcon]="true" >
From 3cc3a57999845cc7cc2156615ad8cd38bfe3fe33 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Fri, 13 Dec 2024 14:32:35 +0100 Subject: [PATCH 16/28] Preserving translations when editing a post --- .../src/app/post/post-edit/post-edit.component.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts index 0765d684a0..f05e2740e9 100644 --- a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts +++ b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts @@ -565,11 +565,12 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange } async preparationData(): Promise { - for (const task of this.tasks) { + for (const [index, task] of this.tasks.entries()) { task.fields = await Promise.all( task.fields.map( async (field: { key: string | number; input: string; type: string; options: any }) => { let value: any = { + translations: [], value: this.form.value[field.key], }; @@ -705,8 +706,13 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange this.form.value[field.key]?.map((fieldValue: any) => fieldValue.value) || []; break; default: + const postField = this.post.post_content[index].fields.find( + (f: any) => f.key === field.key, + ); value.value = this.form.value[field.key] || null; + value.translations = postField?.value?.translations || []; } + return { ...field, value, @@ -737,13 +743,13 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange completed_stages: this.completeStages, content: this.description, description: '', - enabled_languages: {}, form_id: this.formId, locale: 'en_US', post_content: this.tasks, published_to: [], title: this.title, type: 'report', + translations: this.post?.translations || [], }; if (!this.form.valid) this.form.markAllAsTouched(); @@ -759,6 +765,7 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange } private updatePost(postId: number, postData: any) { + console.log(postData); this.postsService.update(postId, postData).subscribe({ next: ({ result }) => { this.postsService.unlockPost(postId).subscribe(); From edb49c02af35794f993bbe9168cffe1c2d5d5b12 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Fri, 13 Dec 2024 14:47:52 +0100 Subject: [PATCH 17/28] Using full language-list for post-translations --- .../src/app/core/services/language.service.ts | 4 + .../post-details/post-details.component.ts | 2 +- .../app/post/post-head/post-head.component.ts | 12 +- .../post-translate.component.html | 10 - .../post-translate.component.ts | 2 +- .../src/assets/locales/entity-languages.json | 390 ++++++++++++++++++ 6 files changed, 399 insertions(+), 21 deletions(-) create mode 100644 apps/web-mzima-client/src/assets/locales/entity-languages.json diff --git a/apps/web-mzima-client/src/app/core/services/language.service.ts b/apps/web-mzima-client/src/app/core/services/language.service.ts index cbd54c874b..6ab674cfc5 100644 --- a/apps/web-mzima-client/src/app/core/services/language.service.ts +++ b/apps/web-mzima-client/src/app/core/services/language.service.ts @@ -4,6 +4,7 @@ import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject } from 'rxjs'; import { LanguageInterface } from '@mzima-client/sdk'; import LangJSON from '../../../assets/locales/languages.json'; +import entityLanguages from '../../../assets/locales/entity-languages.json'; import { SessionService } from './session.service'; @Injectable({ @@ -41,6 +42,9 @@ export class LanguageService { private set initialLanguage(value: string) { localStorage.setItem(this.languageKey, value); } + getEntityLanguages() { + return entityLanguages; + } getLanguages(): LanguageInterface[] { if (LangJSON.languages && LangJSON.languages.length > 0) { diff --git a/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts b/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts index 2437e92b9b..a0710a29bf 100644 --- a/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts +++ b/apps/web-mzima-client/src/app/post/post-details/post-details.component.ts @@ -339,7 +339,7 @@ export class PostDetailsComponent extends BaseComponent implements OnChanges, On panelClass: ['modal', 'select-languages-modal'], data: { post: this.post, - languages: this.languageService.getLanguages(), + languages: this.languageService.getEntityLanguages(), }, }); diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts index 0951853da8..c18f46c7c4 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts @@ -8,8 +8,6 @@ import { BaseComponent } from '../../base.component'; import { ShareModalComponent } from '../../shared/components'; import { PostResult, PostsService, PostStatus, postHelpers } from '@mzima-client/sdk'; import { ConfirmModalService } from '../../core/services/confirm-modal.service'; -import { LanguageService } from '../../core/services/language.service'; -import { LanguageInterface } from '@mzima-client/sdk'; @Component({ selector: 'app-post-head', @@ -29,7 +27,6 @@ export class PostHeadComponent extends BaseComponent implements OnInit { @Output() statusChanged = new EventEmitter(); @Output() openTranslationModal = new EventEmitter(); public isLocked: boolean; - public languages: LanguageInterface[]; constructor( protected override sessionService: SessionService, @@ -40,7 +37,6 @@ export class PostHeadComponent extends BaseComponent implements OnInit { private translate: TranslateService, private eventBusService: EventBusService, private snackBar: MatSnackBar, - private languageService: LanguageService, ) { super(sessionService, breakpointService); this.checkDesktop(); @@ -49,7 +45,6 @@ export class PostHeadComponent extends BaseComponent implements OnInit { ngOnInit(): void { this.checkLock(); - this.languages = this.languageService.getLanguages(); } loadData(): void {} @@ -173,9 +168,8 @@ export class PostHeadComponent extends BaseComponent implements OnInit { }); } public showTranslationsIcon() { - const languagesAvailabe = - this.post && this.post.enabled_languages && this.post.enabled_languages.available; - const needToHideIcon = this.hideTranslationsIcon && this.feedView; - return !needToHideIcon && (languagesAvailabe || this.editable); + const languagesAvailabe = this.post?.enabled_languages?.available; + const hideIcon = this.hideTranslationsIcon && this.feedView; + return !hideIcon && (languagesAvailabe || this.editable); } } diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index a271024418..8d1f311c04 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -46,11 +46,6 @@ class="type-item__checkbox" [disabled]="true" > - {{ defaultLanguage.name }} (Default language) @@ -62,11 +57,6 @@ *ngIf="language.code !== defaultLanguage?.code" (buttonClick)="selectLanguage($event, language)" > - {{ language.name }} diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index 2e6059307a..ee6e67995a 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -42,7 +42,7 @@ export class PostTranslateComponent implements OnInit { this.isTranslateMode = false; this.post = structuredClone(this.data.post); this.enabledLanguages = this.languages.filter((lang) => - this.post.enabled_languages.available.includes(lang.code), + this.post.enabled_languages?.available?.includes(lang.code), ); this.defaultLanguage = this.languages.find((lang) => lang.code === this.post.base_language); } diff --git a/apps/web-mzima-client/src/assets/locales/entity-languages.json b/apps/web-mzima-client/src/assets/locales/entity-languages.json new file mode 100644 index 0000000000..bb0044cb69 --- /dev/null +++ b/apps/web-mzima-client/src/assets/locales/entity-languages.json @@ -0,0 +1,390 @@ +[{ "code": "ach", "name": "Acoli" }, + { "code": "ady", "name": "Adyghe" }, + { "code": "af", "name": "Afrikaans" }, + { "code": "af-ZA", "name": "Afrikaans (South Africa)" }, + { "code": "ak", "name": "Akan" }, + { "code": "sq", "name": "Albanian" }, + { "code": "sq-AL", "name": "Albanian (Albania)" }, + { "code": "aln", "name": "Albanian Gheg" }, + { "code": "am", "name": "Amharic" }, + { "code": "am-ET", "name": "Amharic (Ethiopia)" }, + { "code": "ar", "name": "Arabic" }, + { "code": "ar-EG", "name": "Arabic (Egypt)" }, + { "code": "ar-SA", "name": "Arabic (Saudi Arabia)" }, + { "code": "ar-SD", "name": "Arabic (Sudan)" }, + { "code": "ar-SY", "name": "Arabic (Syria)" }, + { "code": "ar-AA", "name": "Arabic (Unitag)" }, + { "code": "an", "name": "Aragonese" }, + { "code": "hy", "name": "Armenian" }, + { "code": "hy-AM", "name": "Armenian (Armenia)" }, + { "code": "as", "name": "Assamese" }, + { "code": "as-IN", "name": "Assamese (India)" }, + { "code": "ast", "name": "Asturian" }, + { "code": "ast-ES", "name": "Asturian (Spain)" }, + { "code": "az", "name": "Azerbaijani" }, + { "code": "az@Arab", "name": "Azerbaijani (Arabic)" }, + { "code": "az-AZ", "name": "Azerbaijani (Azerbaijan)" }, + { "code": "az-IR", "name": "Azerbaijani (Iran)" }, + { "code": "az@latin", "name": "Azerbaijani (Latin)" }, + { "code": "bal", "name": "Balochi" }, + { "code": "ba", "name": "Bashkir" }, + { "code": "eu", "name": "Basque" }, + { "code": "eu-ES", "name": "Basque (Spain)" }, + { "code": "bar", "name": "Bavarian" }, + { "code": "be", "name": "Belarusian" }, + { "code": "be-BY", "name": "Belarusian (Belarus)" }, + { "code": "be@tarask", "name": "Belarusian (Tarask)" }, + { "code": "bn", "name": "Bengali" }, + { "code": "bn-BD", "name": "Bengali (Bangladesh)" }, + { "code": "bn-IN", "name": "Bengali (India)" }, + { "code": "brx", "name": "Bodo" }, + { "code": "bs", "name": "Bosnian" }, + { "code": "bs-BA", "name": "Bosnian (Bosnia and Herzegovina)" }, + { "code": "br", "name": "Breton" }, + { "code": "bg", "name": "Bulgarian" }, + { "code": "bg-BG", "name": "Bulgarian (Bulgaria)" }, + { "code": "my", "name": "Burmese" }, + { "code": "my-MM", "name": "Burmese (Myanmar)" }, + { "code": "ca", "name": "Catalan" }, + { "code": "ca-ES", "name": "Catalan (Spain)" }, + { "code": "ca@valencia", "name": "Catalan (Valencian)" }, + { "code": "ceb", "name": "Cebuano" }, + { "code": "tzm", "name": "Central Atlas Tamazight" }, + { "code": "hne", "name": "Chhattisgarhi" }, + { "code": "cgg", "name": "Chiga" }, + { "code": "zh", "name": "Chinese" }, + { "code": "zh-CN", "name": "Chinese (China)" }, + { "code": "zh-CN.GB2312", "name": "Chinese (China) (GB2312)" }, + { "code": "gan", "name": "Chinese (Gan)" }, + { "code": "hak", "name": "Chinese (Hakka)" }, + { "code": "zh-HK", "name": "Chinese (Hong Kong)" }, + { "code": "czh", "name": "Chinese (Huizhou)" }, + { "code": "cjy", "name": "Chinese (Jinyu)" }, + { "code": "lzh", "name": "Chinese (Literary)" }, + { "code": "cmn", "name": "Chinese (Mandarin)" }, + { "code": "mnp", "name": "Chinese (Min Bei)" }, + { "code": "cdo", "name": "Chinese (Min Dong)" }, + { "code": "nan", "name": "Chinese (Min Nan)" }, + { "code": "czo", "name": "Chinese (Min Zhong)" }, + { "code": "cpx", "name": "Chinese (Pu-Xian)" }, + { "code": "zh-Hans", "name": "Chinese Simplified" }, + { "code": "zh-TW", "name": "Chinese (Taiwan)" }, + { "code": "zh-TW.Big5", "name": "Chinese (Taiwan) (Big5) " }, + { "code": "zh-Hant", "name": "Chinese Traditional" }, + { "code": "wuu", "name": "Chinese (Wu)" }, + { "code": "hsn", "name": "Chinese (Xiang)" }, + { "code": "yue", "name": "Chinese (Yue)" }, + { "code": "cv", "name": "Chuvash" }, + { "code": "ksh", "name": "Colognian" }, + { "code": "kw", "name": "Cornish" }, + { "code": "co", "name": "Corsican" }, + { "code": "crh", "name": "Crimean Turkish" }, + { "code": "hr", "name": "Croatian" }, + { "code": "hr-HR", "name": "Croatian (Croatia)" }, + { "code": "cs", "name": "Czech" }, + { "code": "cs-CZ", "name": "Czech (Czech Republic)" }, + { "code": "da", "name": "Danish" }, + { "code": "da-DK", "name": "Danish (Denmark)" }, + { "code": "dv", "name": "Divehi" }, + { "code": "doi", "name": "Dogri" }, + { "code": "nl", "name": "Dutch" }, + { "code": "nl-BE", "name": "Dutch (Belgium)" }, + { "code": "nl-NL", "name": "Dutch (Netherlands)" }, + { "code": "dz", "name": "Dzongkha" }, + { "code": "dz-BT", "name": "Dzongkha (Bhutan)" }, + { "code": "en", "name": "English" }, + { "code": "en-BD", "name": "English (Bangladesh)" }, + { "code": "en-CA", "name": "English (Canada)" }, + { "code": "en-GH", "name": "English (Ghana)" }, + { "code": "en-HK", "name": "English (Hong Kong)" }, + { "code": "en-HU", "name": "English (Hungary)" }, + { "code": "en-IN", "name": "English (India)" }, + { "code": "en-IE", "name": "English (Ireland)" }, + { "code": "en-NL", "name": "English (Netherlands)" }, + { "code": "en-NZ", "name": "English (New Zealand)" }, + { "code": "en-NG", "name": "English (Nigeria)" }, + { "code": "en-PK", "name": "English (Pakistan)" }, + { "code": "en-ZA", "name": "English (South Africa)" }, + { "code": "en-LK", "name": "English (Sri Lanka)" }, + { "code": "en-GB", "name": "English (United Kingdom)" }, + { "code": "en-US", "name": "English (United States)" }, + { "code": "en-EN", "name": "English" }, + { "code": "myv", "name": "Erzya" }, + { "code": "eo", "name": "Esperanto" }, + { "code": "et", "name": "Estonian" }, + { "code": "et-EE", "name": "Estonian (Estonia)" }, + { "code": "fo", "name": "Faroese" }, + { "code": "fo-FO", "name": "Faroese (Faroe Islands)" }, + { "code": "fil", "name": "Filipino" }, + { "code": "fi", "name": "Finnish" }, + { "code": "fi-FI", "name": "Finnish (Finland)" }, + { "code": "frp", "name": "Franco-Provençal (Arpitan)" }, + { "code": "fr", "name": "French" }, + { "code": "fr-BE", "name": "French (Belgium)" }, + { "code": "fr-CA", "name": "French (Canada)" }, + { "code": "fr-FR", "name": "French (France)" }, + { "code": "fr-CH", "name": "French (Switzerland)" }, + { "code": "fur", "name": "Friulian" }, + { "code": "ff", "name": "Fulah" }, + { "code": "ff-SN", "name": "Fulah (Senegal)" }, + { "code": "gd", "name": "Gaelic, Scottish" }, + { "code": "gl", "name": "Galician" }, + { "code": "gl-ES", "name": "Galician (Spain)" }, + { "code": "lg", "name": "Ganda" }, + { "code": "ka", "name": "Georgian" }, + { "code": "ka-GE", "name": "Georgian (Georgia)" }, + { "code": "de", "name": "German" }, + { "code": "de-AT", "name": "German (Austria)" }, + { "code": "de-DE", "name": "German (Germany)" }, + { "code": "de-CH", "name": "German (Switzerland)" }, + { "code": "el", "name": "Greek" }, + { "code": "el-GR", "name": "Greek (Greece)" }, + { "code": "kl", "name": "Greenlandic" }, + { "code": "gu", "name": "Gujarati" }, + { "code": "gu-IN", "name": "Gujarati (India)" }, + { "code": "gun", "name": "Gun" }, + { "code": "ht", "name": "Haitian (Haitian Creole)" }, + { "code": "ht-HT", "name": "Haitian (Haitian Creole) (Haiti)" }, + { "code": "ha", "name": "Hausa" }, + { "code": "haw", "name": "Hawaiian" }, + { "code": "he", "name": "Hebrew" }, + { "code": "he-IL", "name": "Hebrew (Israel)" }, + { "code": "hi", "name": "Hindi" }, + { "code": "hi-IN", "name": "Hindi (India)" }, + { "code": "hu", "name": "Hungarian" }, + { "code": "hu-HU", "name": "Hungarian (Hungary)" }, + { "code": "is", "name": "Icelandic" }, + { "code": "is-IS", "name": "Icelandic (Iceland)" }, + { "code": "io", "name": "Ido" }, + { "code": "ig", "name": "Igbo" }, + { "code": "ilo", "name": "Iloko" }, + { "code": "id", "name": "Indonesian" }, + { "code": "id-ID", "name": "Indonesian (Indonesia)" }, + { "code": "ia", "name": "Interlingua" }, + { "code": "iu", "name": "Inuktitut" }, + { "code": "ga", "name": "Irish" }, + { "code": "ga-IE", "name": "Irish (Ireland)" }, + { "code": "it", "name": "Italian" }, + { "code": "it-IT", "name": "Italian (Italy)" }, + { "code": "it-CH", "name": "Italian (Switzerland)" }, + { "code": "ja", "name": "Japanese" }, + { "code": "ja-JP", "name": "Japanese (Japan)" }, + { "code": "jv", "name": "Javanese" }, + { "code": "kab", "name": "Kabyle" }, + { "code": "kn", "name": "Kannada" }, + { "code": "kn-IN", "name": "Kannada (India)" }, + { "code": "pam", "name": "Kapampangan" }, + { "code": "ks", "name": "Kashmiri" }, + { "code": "ks-IN", "name": "Kashmiri (India)" }, + { "code": "csb", "name": "Kashubian" }, + { "code": "kk", "name": "Kazakh" }, + { "code": "kk@Arab", "name": "Kazakh (Arabic)" }, + { "code": "kk@Cyrl", "name": "Kazakh (Cyrillic)" }, + { "code": "kk-KZ", "name": "Kazakh (Kazakhstan)" }, + { "code": "kk@latin", "name": "Kazakh (Latin)" }, + { "code": "km", "name": "Khmer" }, + { "code": "km-KH", "name": "Khmer (Cambodia)" }, + { "code": "rw", "name": "Kinyarwanda" }, + { "code": "ky", "name": "Kirgyz" }, + { "code": "tlh", "name": "Klingon" }, + { "code": "kok", "name": "Konkani" }, + { "code": "ko", "name": "Korean" }, + { "code": "ko-KR", "name": "Korean (Korea)" }, + { "code": "ku", "name": "Kurdish" }, + { "code": "ku-IQ", "name": "Kurdish (Iraq)" }, + { "code": "lad", "name": "Ladino" }, + { "code": "lo", "name": "Lao" }, + { "code": "lo-LA", "name": "Lao (Laos)" }, + { "code": "ltg", "name": "Latgalian" }, + { "code": "la", "name": "Latin" }, + { "code": "lv", "name": "Latvian" }, + { "code": "lv-LV", "name": "Latvian (Latvia)" }, + { "code": "lez", "name": "Lezghian" }, + { "code": "lij", "name": "Ligurian" }, + { "code": "li", "name": "Limburgian" }, + { "code": "ln", "name": "Lingala" }, + { "code": "lt", "name": "Lithuanian" }, + { "code": "lt-LT", "name": "Lithuanian (Lithuania)" }, + { "code": "jbo", "name": "Lojban" }, + { "code": "lmo", "name": "Lombard" }, + { "code": "dsb", "name": "Lower Sorbian" }, + { "code": "nds", "name": "Low German" }, + { "code": "lb", "name": "Luxembourgish" }, + { "code": "mk", "name": "Macedonian" }, + { "code": "mk-MK", "name": "Macedonian (Macedonia)" }, + { "code": "mai", "name": "Maithili" }, + { "code": "mg", "name": "Malagasy" }, + { "code": "ms", "name": "Malay" }, + { "code": "ml", "name": "Malayalam" }, + { "code": "ml-IN", "name": "Malayalam (India)" }, + { "code": "ms-MY", "name": "Malay (Malaysia)" }, + { "code": "mt", "name": "Maltese" }, + { "code": "mt-MT", "name": "Maltese (Malta)" }, + { "code": "mni", "name": "Manipuri" }, + { "code": "mi", "name": "Maori" }, + { "code": "arn", "name": "Mapudungun" }, + { "code": "mr", "name": "Marathi" }, + { "code": "mr-IN", "name": "Marathi (India)" }, + { "code": "mh", "name": "Marshallese" }, + { "code": "mw1", "name": "Mirandese" }, + { "code": "mn", "name": "Mongolian" }, + { "code": "mn-MN", "name": "Mongolian (Mongolia)" }, + { "code": "nah", "name": "Nahuatl" }, + { "code": "nv", "name": "Navajo" }, + { "code": "nr", "name": "Ndebele, South" }, + { "code": "nap", "name": "Neapolitan" }, + { "code": "ne", "name": "Nepali" }, + { "code": "ne-NP", "name": "Nepali (Nepal)" }, + { "code": "nia", "name": "Nias" }, + { "code": "nqo", "name": "N'ko" }, + { "code": "se", "name": "Northern Sami" }, + { "code": "nso", "name": "Northern Sotho" }, + { "code": "no", "name": "Norwegian" }, + { "code": "nb", "name": "Norwegian Bokmål" }, + { "code": "nb-NO", "name": "Norwegian Bokmål (Norway)" }, + { "code": "no-NO", "name": "Norwegian (Norway)" }, + { "code": "nn", "name": "Norwegian Nynorsk" }, + { "code": "nn-NO", "name": "Norwegian Nynorsk (Norway)" }, + { "code": "ny", "name": "Nyanja" }, + { "code": "oc", "name": "Occitan (post 1500)" }, + { "code": "or", "name": "Oriya" }, + { "code": "or-IN", "name": "Oriya (India)" }, + { "code": "om", "name": "Oromo" }, + { "code": "os", "name": "Ossetic" }, + { "code": "pfl", "name": "Palatinate German" }, + { "code": "pa", "name": "Panjabi (Punjabi)" }, + { "code": "pa-IN", "name": "Panjabi (Punjabi) (India)" }, + { "code": "pap", "name": "Papiamento" }, + { "code": "fa", "name": "Persian" }, + { "code": "fa-AF", "name": "Persian (Afghanistan)" }, + { "code": "fa-IR", "name": "Persian (Iran)" }, + { "code": "pms", "name": "Piemontese" }, + { "code": "pl", "name": "Polish" }, + { "code": "pl-PL", "name": "Polish (Poland)" }, + { "code": "pt", "name": "Portuguese" }, + { "code": "pt-BR", "name": "Portuguese (Brazil)" }, + { "code": "pt-PT", "name": "Portuguese (Portugal)" }, + { "code": "ps", "name": "Pushto" }, + { "code": "ro", "name": "Romanian" }, + { "code": "ro-RO", "name": "Romanian (Romania)" }, + { "code": "rm", "name": "Romansh" }, + { "code": "ru", "name": "Russian" }, + { "code": "ru-ee", "name": "Russian (Estonia)" }, + { "code": "ru-lv", "name": "Russian (Latvia)" }, + { "code": "ru-lt", "name": "Russian (Lithuania)" }, + { "code": "ru@petr1708", "name": "Russian Petrine orthography" }, + { "code": "ru-RU", "name": "Russian (Russia)" }, + { "code": "sah", "name": "Sakha (Yakut)" }, + { "code": "sm", "name": "Samoan" }, + { "code": "sa", "name": "Sanskrit" }, + { "code": "sat", "name": "Santali" }, + { "code": "sc", "name": "Sardinian" }, + { "code": "sco", "name": "Scots" }, + { "code": "sr", "name": "Serbian" }, + { "code": "sr@Ijekavian", "name": "Serbian (Ijekavian)" }, + { "code": "sr@ijekavianlatin", "name": "Serbian (Ijekavian Latin)" }, + { "code": "sr@latin", "name": "Serbian (Latin)" }, + { "code": "sr-RS@latin", "name": "Serbian (Latin) (Serbia)" }, + { "code": "sr-RS", "name": "Serbian (Serbia)" }, + { "code": "sn", "name": "Shona" }, + { "code": "scn", "name": "Sicilian" }, + { "code": "szl", "name": "Silesian" }, + { "code": "sd", "name": "Sindhi" }, + { "code": "si", "name": "Sinhala" }, + { "code": "si-LK", "name": "Sinhala (Sri Lanka)" }, + { "code": "sk", "name": "Slovak" }, + { "code": "sk-SK", "name": "Slovak (Slovakia)" }, + { "code": "sl", "name": "Slovenian" }, + { "code": "sl-SI", "name": "Slovenian (Slovenia)" }, + { "code": "so", "name": "Somali" }, + { "code": "son", "name": "Songhay" }, + { "code": "st", "name": "Sotho, Southern" }, + { "code": "st-ZA", "name": "Sotho, Southern (South Africa)" }, + { "code": "sma", "name": "Southern Sami" }, + { "code": "es", "name": "Spanish" }, + { "code": "es-AR", "name": "Spanish (Argentina)" }, + { "code": "es-BO", "name": "Spanish (Bolivia)" }, + { "code": "es-CL", "name": "Spanish (Chile)" }, + { "code": "es-CO", "name": "Spanish (Colombia)" }, + { "code": "es-CR", "name": "Spanish (Costa Rica)" }, + { "code": "es-DO", "name": "Spanish (Dominican Republic)" }, + { "code": "es-EC", "name": "Spanish (Ecuador)" }, + { "code": "es-SV", "name": "Spanish (El Salvador)" }, + { "code": "es-GT", "name": "Spanish (Guatemala)" }, + { "code": "es-419", "name": "Spanish (Latin America)" }, + { "code": "es-MX", "name": "Spanish (Mexico)" }, + { "code": "es-NI", "name": "Spanish (Nicaragua)" }, + { "code": "es-PA", "name": "Spanish (Panama)" }, + { "code": "es-PY", "name": "Spanish (Paraguay)" }, + { "code": "es-PE", "name": "Spanish (Peru)" }, + { "code": "es-PR", "name": "Spanish (Puerto Rico)" }, + { "code": "es-ES", "name": "Spanish (Spain)" }, + { "code": "es-US", "name": "Spanish (United States)" }, + { "code": "es-UY", "name": "Spanish (Uruguay)" }, + { "code": "es-VE", "name": "Spanish (Venezuela)" }, + { "code": "su", "name": "Sundanese" }, + { "code": "sw", "name": "Swahili" }, + { "code": "sw-KE", "name": "Swahili (Kenya)" }, + { "code": "ss", "name": "Swati" }, + { "code": "sv", "name": "Swedish" }, + { "code": "sv-FI", "name": "Swedish (Finland)" }, + { "code": "sv-SE", "name": "Swedish (Sweden)" }, + { "code": "tl", "name": "Tagalog" }, + { "code": "tl-PH", "name": "Tagalog (Philippines)" }, + { "code": "tg", "name": "Tajik" }, + { "code": "tg-TJ", "name": "Tajik (Tajikistan)" }, + { "code": "tzl", "name": "Talossan" }, + { "code": "ta", "name": "Tamil" }, + { "code": "ta-IN", "name": "Tamil (India)" }, + { "code": "ta-LK", "name": "Tamil (Sri-Lanka)" }, + { "code": "tt", "name": "Tatar" }, + { "code": "te", "name": "Telugu" }, + { "code": "te-IN", "name": "Telugu (India)" }, + { "code": "tet", "name": "Tetum (Tetun)" }, + { "code": "th", "name": "Thai" }, + { "code": "th-TH", "name": "Thai (Thailand)" }, + { "code": "bo", "name": "Tibetan" }, + { "code": "bo-CN", "name": "Tibetan (China)" }, + { "code": "ti", "name": "Tigrinya" }, + { "code": "to", "name": "Tongan" }, + { "code": "ts", "name": "Tsonga" }, + { "code": "tn", "name": "Tswana" }, + { "code": "tr", "name": "Turkish" }, + { "code": "tr-TR", "name": "Turkish (Turkey)" }, + { "code": "tk", "name": "Turkmen" }, + { "code": "tk-TM", "name": "Turkmen (Turkmenistan)" }, + { "code": "udm", "name": "Udmurt" }, + { "code": "ug", "name": "Uighur" }, + { "code": "ug@Arab", "name": "Uighur (Arabic)" }, + { "code": "ug@Cyrl", "name": "Uighur (Cyrillic)" }, + { "code": "ug@Latin", "name": "Uighur (Latin)" }, + { "code": "uk", "name": "Ukrainian" }, + { "code": "uk-UA", "name": "Ukrainian (Ukraine)" }, + { "code": "vmf", "name": "Upper Franconian" }, + { "code": "hsb", "name": "Upper Sorbian" }, + { "code": "ur", "name": "Urdu" }, + { "code": "ur-PK", "name": "Urdu (Pakistan)" }, + { "code": "uz", "name": "Uzbek" }, + { "code": "uz@Arab", "name": "Uzbek (Arabic)" }, + { "code": "uz@Cyrl", "name": "Uzbek (Cyrillic)" }, + { "code": "uz@Latn", "name": "Uzbek (Latin)" }, + { "code": "uz-UZ", "name": "Uzbek (Uzbekistan)" }, + { "code": "ve", "name": "Venda" }, + { "code": "vec", "name": "Venetian" }, + { "code": "vi", "name": "Vietnamese" }, + { "code": "vi-VN", "name": "Vietnamese (Viet Nam)" }, + { "code": "vls", "name": "Vlaams" }, + { "code": "wa", "name": "Walloon" }, + { "code": "war", "name": "Wáray-Wáray" }, + { "code": "cy", "name": "Welsh" }, + { "code": "cy-GB", "name": "Welsh (United Kingdom)" }, + { "code": "fy", "name": "Western Frisian" }, + { "code": "fy-NL", "name": "Western Frisian (Netherlands)" }, + { "code": "wo", "name": "Wolof" }, + { "code": "wo-SN", "name": "Wolof (Senegal)" }, + { "code": "xh", "name": "Xhosa" }, + { "code": "yi", "name": "Yiddish" }, + { "code": "yo", "name": "Yoruba" }, + { "code": "zu", "name": "Zulu" }, + { "code": "zu-ZA", "name": "Zulu (South Africa)" }] + \ No newline at end of file From 789abfa8ba213fee4317223cabc435552f5266df Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Mon, 16 Dec 2024 19:46:36 +0100 Subject: [PATCH 18/28] Adding validation+small style-fixes --- .../post-translate.component.html | 242 +++++++++--------- .../post-translate.component.scss | 25 +- .../post-translate.component.ts | 8 +- 3 files changed, 148 insertions(+), 127 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index 8d1f311c04..76cac78d04 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -11,136 +11,142 @@ > + {{ isTranslateMode ? 'Translate post to ' + activeLanguage.name : 'Translate post' }}
-

Available translations (select to see post):

- - - - {{ language.name }} - - - +
+

Available translations (select to see post):

+ + + + {{ language.name }} + + + +
-

Select a language to translate to, or edit:

-
-
    -
  • - - {{ defaultLanguage.name }} (Default language) - -
  • -
  • - - {{ language.name }} - -
  • -
-
+

Select a language to translate to, or edit:

+
    +
  • + + {{ defaultLanguage.name }} (Default language) + +
  • +
  • + + {{ language.name }} + +
  • +
-
- -
- -
- {{ field?.translations[activeLanguage.code]?.label || field?.label }} - -
-
Text in original language:
-
-

{{ getOriginalValue(field) }}

-
-
-
- Add your translation below: - - - - - - - - - - - - - - - - - - - - - - - - + +
+ +
+ {{ field?.translations[activeLanguage.code]?.label || field?.label }} + +
+
Text in original language:
+
+

{{ getOriginalValue(field) }}

- -
- -
+
+ Add your translation below: + + * + + + + + + * + + + + + + + + + + + + + + + + + + + +

+ {{ 'post.modify.errors.required' | translate : { label: field.label } }} +

+
+
+
+ +
+
@@ -154,7 +160,11 @@ > {{ 'app.cancel' | translate }} - + {{ 'app.save' | translate }}
diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss index 3c8f68e94f..95edb86ef4 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss @@ -1,5 +1,17 @@ @import 'helpers'; +.select_language { + margin-bottom: 26px; + padding-bottom: 26px; + border-bottom: 1px solid var(--color-neutral-20); +} + +.field-label { + margin: 4px 0 8px 0; + font-size: 14px; + font-weight: 700; +} + .types-list { padding: 0; display: flex; @@ -33,13 +45,6 @@ } } -.flag { - width: 30px; - height: 20px; - object-fit: contain; - margin-inline-end: 5px; - object-position: 0 50%; -} .translate_post { display: flex; flex-direction: row; @@ -54,25 +59,27 @@ gap: 24px; background: var(--Neutral-Neutral-10, #f5f5f5); } + &__fields { display: flex; flex-direction: column; width: 100%; gap: 24px; } + .field-label { font-weight: 500; line-height: 160%; /* 22.4px */ letter-spacing: -0.07px; } + &__original { padding: 24px; border: 1px solid var(--Neutral-Neutral-30, #e2e2e3); background-color: white; display: flex-row; } - &__translation { - } + .mat-form-field { background: white; } diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index ee6e67995a..dee9274b42 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -1,5 +1,5 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup, FormControl } from '@angular/forms'; +import { FormGroup, FormControl, Validators } from '@angular/forms'; import { LanguageInterface, PostResult, PostsService } from '@mzima-client/sdk'; import { EventBusService, EventType } from '@services'; @@ -121,7 +121,11 @@ export class PostTranslateComponent implements OnInit { .flatMap((task: any) => task.fields) .filter((field: any) => this.isTranslateableContent(field)) .forEach((field: any) => { - newForm.addControl(field.key, new FormControl('')); + if (field.type === 'title' || field.type === 'description') { + newForm.addControl(field.key, new FormControl('', Validators.required)); + } else { + newForm.addControl(field.key, new FormControl('')); + } const translation = this.getTranslationValue(field); if (translation) { newForm.get(field.key)?.setValue(translation); From 42c54a4fc4d6de3423614e936c416c62ccd3893a Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Mon, 16 Dec 2024 20:03:40 +0100 Subject: [PATCH 19/28] CSS-cleanup for post-translations --- .../post-translate.component.html | 162 ++++++++---------- .../post-translate.component.scss | 30 +--- 2 files changed, 81 insertions(+), 111 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index 76cac78d04..527f00441f 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -18,7 +18,7 @@
-
+

Available translations (select to see post):

-
-

Select a language to translate to, or edit:

+
+

Select a language to translate to, or edit:

  • Select a language to translate to, or edit: -
    -
    -
    -
    - -
    - {{ field?.translations[activeLanguage.code]?.label || field?.label }} - -
    -
    Text in original language:
    -
    -

    {{ getOriginalValue(field) }}

    -
    -
    -
    - Add your translation below: - - * - - - - - - * - - - - - - - - - - - - - - - - - - - -

    - {{ 'post.modify.errors.required' | translate : { label: field.label } }} -

    -
    +
    + +
    + +
    + {{ field?.translations[activeLanguage.code]?.label || field?.label }} + +
    +
    Text in original language:
    +
    +

    {{ getOriginalValue(field) }}

    - -
    - -
    + Add your translation below: + + * + + + + + + * + + + + + + + + + + + + + + + + + + + +

    + {{ 'post.modify.errors.required' | translate : { label: field.label } }} +

    +
    +
    + +
    +
    diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss index 95edb86ef4..e75ea52ec7 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss @@ -1,39 +1,31 @@ @import 'helpers'; -.select_language { +.select-language { margin-bottom: 26px; padding-bottom: 26px; border-bottom: 1px solid var(--color-neutral-20); } -.field-label { +.list-label { margin: 4px 0 8px 0; font-size: 14px; font-weight: 700; } .types-list { - padding: 0; display: flex; margin: 0 -8px; flex-wrap: wrap; - list-style: none; - justify-content: flex-start; } .type-item { display: flex; - cursor: pointer; - min-height: 46px; padding: 8px 12px; margin: 0 4px 8px; - position: relative; border-radius: 4px; - align-items: center; width: calc(50% - 8px); transition: color 0.35s ease; background: var(--color-neutral-10); - border-inline-start: 5px solid var(--color, transparent); @include breakpoint-max($tablet) { border-inline-start-width: 4px; @@ -45,28 +37,17 @@ } } -.translate_post { - display: flex; - flex-direction: row; - gap: 16px; - &__edit { +.translate-post { + &__fields { display: flex; + flex-direction: column; width: 100%; padding: 24px 16px; border-radius: 4px; - flex-direction: column; - align-items: flex-start; gap: 24px; background: var(--Neutral-Neutral-10, #f5f5f5); } - &__fields { - display: flex; - flex-direction: column; - width: 100%; - gap: 24px; - } - .field-label { font-weight: 500; line-height: 160%; /* 22.4px */ @@ -77,7 +58,6 @@ padding: 24px; border: 1px solid var(--Neutral-Neutral-30, #e2e2e3); background-color: white; - display: flex-row; } .mat-form-field { From 6fc87860b5e6b367dd7ee97ea63ae07b35d15b58 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Mon, 16 Dec 2024 20:19:19 +0100 Subject: [PATCH 20/28] Moving strings to en.json --- .../post-translate.component.html | 20 ++++++++++++------- .../src/assets/locales/en.json | 7 ++++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html index 527f00441f..329c7fbd5e 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.html @@ -12,14 +12,18 @@ -{{ isTranslateMode ? 'Translate post to ' + activeLanguage.name : 'Translate post' }} +{{ 'translations.translate_post' | translate }} + + +{{ 'translations.translate_post_to' | translate : { language: activeLanguage.name } }}
    -

    Available translations (select to see post):

    +

    {{ 'translations.available_languages' | translate }}

    -

    Select a language to translate to, or edit:

    +

    {{ 'translations.select_translate_edit' | translate }}

    • Select a language to translate to, or edit: class="type-item__checkbox" [disabled]="true" > - {{ defaultLanguage.name }} (Default language) + {{ defaultLanguage.name }} ({{ 'translations.default_language' | translate }})
    • @@ -72,12 +76,14 @@

      Select a language to translate to, or edit:

      >{{ field?.translations[activeLanguage.code]?.label || field?.label }}
      -
      Text in original language:
      +
      + {{ 'translations.text_in_original' | translate }} +

      {{ getOriginalValue(field) }}

      - Add your translation below: + {{ 'translations.add_translation' | translate }} * diff --git a/apps/web-mzima-client/src/assets/locales/en.json b/apps/web-mzima-client/src/assets/locales/en.json index 78873aa0b4..a3424e83e7 100644 --- a/apps/web-mzima-client/src/assets/locales/en.json +++ b/apps/web-mzima-client/src/assets/locales/en.json @@ -2162,15 +2162,19 @@ "i_agree": "I agree to Ushahidi's Privacy Policy and\nTerms and Conditions." }, "translations": { + "available_languages": "Available translations (select to see post):", + "translate_post": "Translate post", + "translate_post_to": "Translate post to {{language}}", "languages": "Languages", "language": "Language", "default": "default", + "default_language": "Default language", + "text_in_original": "Text in original language:", "translation_default": "(default)", "translate_field": "Translate field", "survey_select_default": "Select default language for this survey", "category_select_default": "Select default language for this category", "error_translation_exists": "You cannot select this language since there is already a translation for it.", - "edit_default_text": "Text in default language", "edit_placeholder": "Write your translation here", "add_translation": "Add your translation below:", "survey_name_required": "Translation for survey-name is required", @@ -2184,6 +2188,7 @@ "add_a_language": "Add a language", "error_no_default": "You need to specify a default language before adding a new translation.", "select_language": "Select a language to add translation for", + "select_translate_edit": "Select a language to translate to, or edit:", "default_lang_info": "This is the language that will be used if no translations are available for the language the user has set for the deployment." }, "languages": { From 928c32944643c37bf3628e784f84d5113f903f2b Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Mon, 16 Dec 2024 20:23:11 +0100 Subject: [PATCH 21/28] Removing console.log --- .../src/app/post/post-edit/post-edit.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts index f05e2740e9..5809b2ed05 100644 --- a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts +++ b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts @@ -765,7 +765,6 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange } private updatePost(postId: number, postData: any) { - console.log(postData); this.postsService.update(postId, postData).subscribe({ next: ({ result }) => { this.postsService.unlockPost(postId).subscribe(); From f1d50b9fb1e09ab118bec5889bb1384d902cd661 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 10:50:15 +0100 Subject: [PATCH 22/28] Using site-language if no base_language is set --- .../src/app/post/post-edit/post-edit.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts index 5809b2ed05..ee5643dc06 100644 --- a/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts +++ b/apps/web-mzima-client/src/app/post/post-edit/post-edit.component.ts @@ -736,8 +736,8 @@ export class PostEditComponent extends BaseComponent implements OnInit, OnChange this.showMessage(error, 'error'); return; } - // should be site-language - const postLanguage = this.selectedLanguage?.code || 'en'; + + const postLanguage = this.selectedLanguage?.code || this.languageService.initialLanguage; const postData = { base_language: postLanguage, completed_stages: this.completeStages, From 5f2f268a1990e89f8e87437bc1f98087222de84e Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 10:50:57 +0100 Subject: [PATCH 23/28] Hiding translations-icon everywhere except in details --- .../src/app/post/post-head/post-head.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts index c18f46c7c4..98c9dbea2e 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts @@ -169,7 +169,6 @@ export class PostHeadComponent extends BaseComponent implements OnInit { } public showTranslationsIcon() { const languagesAvailabe = this.post?.enabled_languages?.available; - const hideIcon = this.hideTranslationsIcon && this.feedView; - return !hideIcon && (languagesAvailabe || this.editable); + return !this.hideTranslationsIcon && (languagesAvailabe || this.editable); } } From 7333f3fa91f913ec9c568f4fa3ae235ef772bacb Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 10:52:52 +0100 Subject: [PATCH 24/28] Adding strings to en.json --- .../post-translated.component.html | 15 ++++++++++----- apps/web-mzima-client/src/assets/locales/en.json | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.html b/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.html index a0e777c71c..303d1ae40f 100644 --- a/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.html +++ b/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.html @@ -4,11 +4,13 @@
    -

    Translated from {{ getLanguageName(baseLanguage) }}

    +

    + {{ + 'translations.translated_to' | translate : { language: getLanguageName(displayLanguage) } + }} +

    - This post was translated from {{ getLanguageName(baseLanguage) }} to your selected language - {{ getLanguageName(displayLanguage) }}. - Change language + {{ 'translations.viewing_translated' | translate }}

    Translated from {{ getLanguageName(baseLanguage) }} iconPosition="first" > - See original + {{ 'translations.view_original' | translate }} + {{ + 'translations.change_lang' | translate + }}
    diff --git a/apps/web-mzima-client/src/assets/locales/en.json b/apps/web-mzima-client/src/assets/locales/en.json index a3424e83e7..071cc81787 100644 --- a/apps/web-mzima-client/src/assets/locales/en.json +++ b/apps/web-mzima-client/src/assets/locales/en.json @@ -2189,7 +2189,11 @@ "error_no_default": "You need to specify a default language before adding a new translation.", "select_language": "Select a language to add translation for", "select_translate_edit": "Select a language to translate to, or edit:", - "default_lang_info": "This is the language that will be used if no translations are available for the language the user has set for the deployment." + "default_lang_info": "This is the language that will be used if no translations are available for the language the user has set for the deployment.", + "translated_to": "Translated to {{language}}", + "viewing_translated":"You are viewing a translated version of this post.", + "view_original":"View original post", + "change_lang": "Change language" }, "languages": { "ach": "Acoli", From 495122bfae61d30d6cf3d242dec5c8ea29fa5ee7 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 10:54:49 +0100 Subject: [PATCH 25/28] Displaying translation-info in post-modal --- .../src/app/post/post-translate/post-translate.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts index dee9274b42..9870dfbdda 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.ts @@ -1,6 +1,5 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; - import { LanguageInterface, PostResult, PostsService } from '@mzima-client/sdk'; import { EventBusService, EventType } from '@services'; import { UntilDestroy } from '@ngneat/until-destroy'; @@ -54,7 +53,7 @@ export class PostTranslateComponent implements OnInit { type: EventType.DisplayTranslatedPost, payload: event.value, }); - this.closeModal(); + this.closeModal({ displayLanguage: event.value, post: this.post }); } saveTranslation() { this.translateForm.disable(); From 98f50da047fd0d59d469ce2b2cb8b351df8e64a0 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 10:55:13 +0100 Subject: [PATCH 26/28] Using full language-list for translations --- .../src/app/post/post-translated/post-translated.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.ts b/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.ts index 0b65edde87..37818ed46f 100644 --- a/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.ts +++ b/apps/web-mzima-client/src/app/post/post-translated/post-translated.component.ts @@ -14,7 +14,9 @@ export class PostTranslatedComponent { constructor(private languageService: LanguageService) {} public getLanguageName(code: string) { - return this.languageService.getLanguages().find((lang) => lang.code === code)?.name || code; + return ( + this.languageService.getEntityLanguages().find((lang) => lang.code === code)?.name || code + ); } originalPost() { From 0eb4f9fe325be813e918f35a82a9fd4a7925455a Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 13:47:15 +0100 Subject: [PATCH 27/28] Only displaying icon if translations are available (for non-edit-users) --- .../src/app/post/post-head/post-head.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts index 98c9dbea2e..c630626898 100644 --- a/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts +++ b/apps/web-mzima-client/src/app/post/post-head/post-head.component.ts @@ -168,7 +168,7 @@ export class PostHeadComponent extends BaseComponent implements OnInit { }); } public showTranslationsIcon() { - const languagesAvailabe = this.post?.enabled_languages?.available; + const languagesAvailabe = this.post?.enabled_languages?.available?.length > 0; return !this.hideTranslationsIcon && (languagesAvailabe || this.editable); } } From e9a5bf6975656abc002bb9e39a3242fe6bf107b9 Mon Sep 17 00:00:00 2001 From: Anna Iosif Date: Wed, 18 Dec 2024 16:35:37 +0100 Subject: [PATCH 28/28] Remove line under dropdown but keep spacing --- .../src/app/post/post-translate/post-translate.component.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss index e75ea52ec7..315b343d62 100644 --- a/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss +++ b/apps/web-mzima-client/src/app/post/post-translate/post-translate.component.scss @@ -1,11 +1,7 @@ @import 'helpers'; - .select-language { margin-bottom: 26px; - padding-bottom: 26px; - border-bottom: 1px solid var(--color-neutral-20); } - .list-label { margin: 4px 0 8px 0; font-size: 14px;