fix: translate simple pipe doesn't update on language changes

This commit is contained in:
2023-01-31 13:39:29 +01:00
committed by Rainer Killinger
parent 33a74d96ae
commit f5ca1508fb
4 changed files with 173 additions and 113 deletions

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2023 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core';
import {Subscription} from 'rxjs';
import {TranslateService} from '@ngx-translate/core';
import {ThingTranslateService} from './thing-translate.service';
import {isThing, SCThings, SCThingType} from '@openstapps/core';
@Injectable()
@Pipe({
name: 'propertyNameTranslate',
pure: false, // required to update the value when the promise is resolved
})
export class PropertyNameTranslatePipe implements PipeTransform, OnDestroy {
value: unknown;
lastKey?: string;
lastType: string;
onLangChange: Subscription;
constructor(
private readonly translate: TranslateService,
private readonly thingTranslate: ThingTranslateService,
) {}
updateValue(key: string, type: string): void {
this.value = this.thingTranslate.getPropertyName(type as SCThingType, key);
}
transform(query: unknown, thingOrType: SCThings | string | unknown): unknown {
if (typeof query !== 'string' || query.length <= 0) {
return query;
}
if (!isThing(thingOrType) && typeof thingOrType !== 'string') {
throw new SyntaxError(
`Wrong parameter in ThingTranslatePipe. Expected a valid SCThing or String, received: ${thingOrType}`,
);
}
// store the params, in case they change
this.lastKey = query;
this.lastType = typeof thingOrType === 'string' ? thingOrType : thingOrType.type;
this.updateValue(query, this.lastType);
// if there is a subscription to onLangChange, clean it
this._dispose();
if (this.onLangChange?.closed ?? true) {
this.onLangChange = this.translate.onLangChange.subscribe(() => {
if (typeof this.lastKey === 'string') {
this.lastKey = undefined; // we want to make sure it doesn't return the same value until it's been updated
this.updateValue(query, this.lastType);
}
});
}
return this.value;
}
/**
* Clean any existing subscription to change events
*/
private _dispose(): void {
if (this.onLangChange?.closed) {
this.onLangChange?.unsubscribe();
}
}
ngOnDestroy(): void {
this._dispose();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 StApps
* Copyright (C) 2023 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -17,25 +17,23 @@ import {ModuleWithProviders, NgModule, Provider} from '@angular/core';
import {
ArrayJoinPipe,
DateLocalizedFormatPipe,
NumberLocalizedPipe,
MetersLocalizedPipe,
SentenceCasePipe,
StringSplitPipe,
OpeningHoursPipe,
DurationLocalizedPipe,
ToUnixPipe,
EntriesPipe,
IsNaNPipe,
IsNumericPipe,
MetersLocalizedPipe,
NumberLocalizedPipe,
OpeningHoursPipe,
SentenceCasePipe,
StringSplitPipe,
ToUnixPipe,
} from './common-string-pipes';
import {ThingTranslateDefaultParser, ThingTranslateParser} from './thing-translate.parser';
import {
ThingPropertyNameTranslatePipe,
ThingTranslatePipe,
TranslateSimplePipe,
} from './thing-translate.pipe';
import {ThingTranslatePipe} from './thing-translate.pipe';
import {ThingTranslateService} from './thing-translate.service';
import {IonIconModule} from '../util/ion-icon/ion-icon.module';
import {TranslateSimplePipe} from './translate-simple.pipe';
import {PropertyNameTranslatePipe} from './property-name-translate.pipe';
export interface ThingTranslateModuleConfig {
parser?: Provider;
@@ -49,7 +47,7 @@ export interface ThingTranslateModuleConfig {
NumberLocalizedPipe,
MetersLocalizedPipe,
StringSplitPipe,
ThingPropertyNameTranslatePipe,
PropertyNameTranslatePipe,
ThingTranslatePipe,
TranslateSimplePipe,
DateLocalizedFormatPipe,
@@ -67,7 +65,7 @@ export interface ThingTranslateModuleConfig {
NumberLocalizedPipe,
MetersLocalizedPipe,
StringSplitPipe,
ThingPropertyNameTranslatePipe,
PropertyNameTranslatePipe,
ThingTranslatePipe,
TranslateSimplePipe,
DateLocalizedFormatPipe,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 StApps
* Copyright (C) 2023 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -12,13 +12,11 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {isThing, SCThings, SCThingType, SCThingWithoutReferences} from '@openstapps/core';
import {isThing, SCThings, SCThingWithoutReferences} from '@openstapps/core';
import {Subscription} from 'rxjs';
import {ThingTranslateService} from './thing-translate.service';
import {get} from '../_helpers/collections/get';
@Injectable()
@Pipe({
@@ -92,98 +90,3 @@ export class ThingTranslatePipe implements PipeTransform, OnDestroy {
this._dispose();
}
}
@Injectable()
@Pipe({
name: 'translateSimple',
pure: true,
})
export class TranslateSimplePipe implements PipeTransform {
constructor(private readonly translate: TranslateService) {}
// eslint-disable-next-line @typescript-eslint/ban-types
transform(query: string, value: object | unknown): unknown {
try {
return (
get(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(value as any).translations[this.translate.currentLang] ?? value,
query,
) ?? value
);
} catch (error) {
console.warn(`${query}: ${error}`);
return value;
}
}
}
@Injectable()
@Pipe({
name: 'propertyNameTranslate',
pure: false, // required to update the value when the promise is resolved
})
export class ThingPropertyNameTranslatePipe implements PipeTransform, OnDestroy {
value: unknown;
lastKey?: string;
lastType: string;
onLangChange: Subscription;
constructor(
private readonly translate: TranslateService,
private readonly thingTranslate: ThingTranslateService,
) {}
updateValue(key: string, type: string): void {
this.value = this.thingTranslate.getPropertyName(type as SCThingType, key);
}
transform(query: unknown, thingOrType: SCThings | string | unknown): unknown {
if (typeof query !== 'string' || query.length <= 0) {
return query;
}
if (!isThing(thingOrType) && typeof thingOrType !== 'string') {
throw new SyntaxError(
`Wrong parameter in ThingTranslatePipe. Expected a valid SCThing or String, received: ${thingOrType}`,
);
}
// store the params, in case they change
this.lastKey = query;
this.lastType = typeof thingOrType === 'string' ? thingOrType : thingOrType.type;
this.updateValue(query, this.lastType);
// if there is a subscription to onLangChange, clean it
this._dispose();
if (this.onLangChange?.closed ?? true) {
this.onLangChange = this.translate.onLangChange.subscribe(() => {
if (typeof this.lastKey === 'string') {
this.lastKey = undefined; // we want to make sure it doesn't return the same value until it's been updated
this.updateValue(query, this.lastType);
}
});
}
return this.value;
}
/**
* Clean any existing subscription to change events
*/
private _dispose(): void {
if (this.onLangChange?.closed) {
this.onLangChange?.unsubscribe();
}
}
ngOnDestroy(): void {
this._dispose();
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {get} from '../_helpers/collections/get';
import {Subscription} from 'rxjs';
@Injectable()
@Pipe({
name: 'translateSimple',
pure: false,
})
export class TranslateSimplePipe implements PipeTransform, OnDestroy {
value: unknown;
query: unknown;
thing: unknown;
onLangChange: Subscription;
constructor(private readonly translate: TranslateService) {}
// eslint-disable-next-line @typescript-eslint/ban-types
private updateValue() {
try {
this.value =
get(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(this.thing as any).translations[this.translate.currentLang] ?? this.thing,
this.query as string,
) ?? this.thing;
} catch (error) {
console.warn(`${this.query}: ${error}`);
this.value = this.thing;
}
}
transform<T extends object, P extends string[] | string | keyof T>(
query: P,
thing: T,
): P extends keyof T ? T[P] : P | unknown {
// store the params, in case they change
this.query = query;
this.thing = thing;
this.updateValue();
this.onLangChange ??= this.translate.onLangChange.subscribe(() => {
this.updateValue();
});
return this.value as never;
}
ngOnDestroy(): void {
this.onLangChange?.unsubscribe();
}
}