Skip to content

Commit

Permalink
More type cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeAndWeb committed Sep 23, 2024
1 parent 7d31fbc commit 196fac8
Show file tree
Hide file tree
Showing 12 changed files with 297 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
TranslateLoader,
TranslateModule,
TranslateService, Translation, TranslationKey,
TranslationObject, TranslationResult
TranslationObject
} from "../public-api";

let translations: TranslationObject = {"TEST": "This is a test"};
Expand Down Expand Up @@ -64,7 +64,7 @@ describe('MissingTranslationHandler', () => {
translate.use('en');
spyOn(missingTranslationHandler, 'handle').and.callThrough();

translate.get('nonExistingKey').subscribe((res: TranslationResult) => {
translate.get('nonExistingKey').subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({key: 'nonExistingKey'}));
//test that the instance of the last called argument is string
expect(res).toEqual('handled');
Expand All @@ -77,7 +77,7 @@ describe('MissingTranslationHandler', () => {
spyOn(missingTranslationHandler, 'handle').and.callThrough();
const interpolateParams = {some: 'params'};

translate.get('nonExistingKey', interpolateParams).subscribe((res: TranslationResult) => {
translate.get('nonExistingKey', interpolateParams).subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({interpolateParams: interpolateParams}));
//test that the instance of the last called argument is string
expect(res).toEqual('handled');
Expand All @@ -91,7 +91,7 @@ describe('MissingTranslationHandler', () => {
const interpolateParams = {some: 'params'};

translate.get('nonExistingKey', interpolateParams)
.subscribe((res: TranslationResult) => {
.subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({translateService: translate}));
//test that the instance of the last called argument is string
expect(res).toEqual('handled');
Expand All @@ -111,7 +111,7 @@ describe('MissingTranslationHandler', () => {
translate.use('en');
spyOn(missingTranslationHandler, 'handle').and.callThrough();

translate.get('nonExistingKey').subscribe((res: TranslationResult) => {
translate.get('nonExistingKey').subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({key: 'nonExistingKey'}));
expect(res).toEqual('nonExistingKey');
});
Expand Down Expand Up @@ -141,7 +141,7 @@ describe('MissingTranslationHandler', () => {
translate.use('en');
spyOn(missingTranslationHandler, 'handle').and.callThrough();

translate.get('nonExistingKey').subscribe((res: TranslationResult) => {
translate.get('nonExistingKey').subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({key: 'nonExistingKey'}));
expect(res).toEqual('handled: nonExistingKey');
});
Expand All @@ -158,7 +158,7 @@ describe('MissingTranslationHandler', () => {
translate.use('en');
spyOn(missingTranslationHandler, 'handle').and.callThrough();

translate.get(Object.keys(tr)).subscribe((res: TranslationResult) => {
translate.get(Object.keys(tr)).subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledTimes(3);
expect(res).toEqual(tr);
});
Expand Down Expand Up @@ -196,7 +196,7 @@ describe('MissingTranslationHandler', () => {
translate.use('fake');

spyOn(missingTranslationHandler, 'handle').and.callThrough();
translate.get('TEST').subscribe((res: TranslationResult) => {
translate.get('TEST').subscribe((res: Translation) => {
expect(missingTranslationHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining({key: 'TEST'}));
//test that the instance of the last called argument is string
expect(res).toEqual('handled');
Expand All @@ -209,7 +209,7 @@ describe('MissingTranslationHandler', () => {
translate.use('fake');

spyOn(missingTranslationHandler, 'handle').and.callThrough();
translate.get('TEST').subscribe((res: TranslationResult) => {
translate.get('TEST').subscribe((res: Translation) => {
expect(res).toEqual('This is a test');
});
});
Expand Down
6 changes: 3 additions & 3 deletions projects/ngx-translate/src/lib/translate.compiler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
TranslateLoader,
TranslateModule,
TranslateService,
TranslationObject, TranslationResult
TranslationObject, Translation
} from "../public-api";

const translations: TranslationObject = {LOAD: 'This is a test'};
Expand Down Expand Up @@ -44,7 +44,7 @@ describe('TranslateCompiler', () => {
});

it('should use the compiler on loading translations', () => {
translate.get('LOAD').subscribe((res: TranslationResult) => {
translate.get('LOAD').subscribe((res: Translation) => {
expect(res).toBe('This is a test');
});
});
Expand Down Expand Up @@ -97,7 +97,7 @@ describe('TranslateCompiler', () => {
});

it('should use the compiler on loading translations', () => {
translate.get('LOAD').subscribe((res: TranslationResult) => {
translate.get('LOAD').subscribe((res: Translation) => {
expect(res).toBe('This is a test|compiled');
});
});
Expand Down
39 changes: 29 additions & 10 deletions projects/ngx-translate/src/lib/translate.directive.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import {AfterViewChecked, ChangeDetectorRef, Directive, ElementRef, Input, OnDestroy} from '@angular/core';
import {Subscription, isObservable} from 'rxjs';
import {DefaultLangChangeEvent, LangChangeEvent, TranslateService, TranslationChangeEvent} from './translate.service';
import {
DefaultLangChangeEvent,
InterpolatableTranslation,
LangChangeEvent,
TranslateService,
TranslationChangeEvent,
Translation
} from "./translate.service";
import {equals, isDefined} from './util';
import {InterpolationParameters} from "./translate.parser";

interface ExtendedNode extends Text {
originalContent: string;
currentValue: string;
lookupKey: string;
lastKey: string|null;
data: string;
}


@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
selector: '[translate],[ngx-translate]'
})
export class TranslateDirective implements AfterViewChecked, OnDestroy {
key!: string;
lastParams: any;
currentParams: any;
lastParams: InterpolationParameters;
currentParams: InterpolationParameters;
onLangChangeSub!: Subscription;
onDefaultLangChangeSub!: Subscription;
onTranslationChangeSub!: Subscription;
Expand All @@ -21,7 +39,7 @@ export class TranslateDirective implements AfterViewChecked, OnDestroy {
}
}

@Input() set translateParams(params: any) {
@Input() set translateParams(params: InterpolationParameters) {
if (!equals(this.currentParams, params)) {
this.currentParams = params;
this.checkNodes(true);
Expand Down Expand Up @@ -58,7 +76,8 @@ export class TranslateDirective implements AfterViewChecked, OnDestroy {
this.checkNodes();
}

checkNodes(forceUpdate = false, translations?: any) {

checkNodes(forceUpdate = false, translations?: InterpolatableTranslation) {
let nodes: NodeList = this.element.nativeElement.childNodes;
// if the element is empty
if (!nodes.length) {
Expand Down Expand Up @@ -98,15 +117,15 @@ export class TranslateDirective implements AfterViewChecked, OnDestroy {
}
}

updateValue(key: string, node: any, translations: any) {
updateValue(key: string, node: ExtendedNode, translations: InterpolatableTranslation) {
if (key) {
if (node.lastKey === key && this.lastParams === this.currentParams) {
return;
}

this.lastParams = this.currentParams;

const onTranslation = (res: unknown) => {
const onTranslation = (res: Translation) => {
if (res !== key) {
node.lastKey = key;
}
Expand All @@ -132,11 +151,11 @@ export class TranslateDirective implements AfterViewChecked, OnDestroy {
}
}

getContent(node: any): string {
return isDefined(node.textContent) ? node.textContent : node.data;
getContent(node: ExtendedNode): string {
return (isDefined(node.textContent) ? node.textContent : node.data) as string;
}

setContent(node: any, content: string): void {
setContent(node: ExtendedNode, content: string): void {
if (isDefined(node.textContent)) {
node.textContent = content;
} else {
Expand Down
8 changes: 4 additions & 4 deletions projects/ngx-translate/src/lib/translate.loader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
TranslateLoader,
TranslateModule,
TranslateService,
TranslationObject, TranslationResult
TranslationObject, Translation
} from "../public-api";

const translations: TranslationObject = {"TEST": "This is a test"};
Expand Down Expand Up @@ -37,7 +37,7 @@ describe('TranslateLoader', () => {
translate.use('en');

// this will request the translation from the backend because we use a static files loader for TranslateService
translate.get('TEST').subscribe((res: TranslationResult) => {
translate.get('TEST').subscribe((res: Translation) => {
expect(res).toEqual('This is a test');
});
});
Expand Down Expand Up @@ -66,7 +66,7 @@ describe('TranslateLoader', () => {
translate.use('en');

// this will request the translation from the CustomLoader
translate.get('TEST').subscribe((res: TranslationResult) => {
translate.get('TEST').subscribe((res: Translation) => {
expect(res).toEqual('This is also a test');
});
});
Expand All @@ -89,7 +89,7 @@ describe('TranslateLoader', () => {
translate.use('en');

// this will request the translation from the backend because we use a static files loader for TranslateService
translate.getTranslation('en').subscribe((res: TranslationResult) => {
translate.getTranslation('en').subscribe((res: Translation) => {
expect(res).toEqual({});
});
});
Expand Down
75 changes: 40 additions & 35 deletions projects/ngx-translate/src/lib/translate.parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,55 @@ describe('Parser', () => {

it('is defined', () => {
expect(TranslateParser).toBeDefined();

expect(parser instanceof TranslateParser).toBeTruthy();
});

it('should interpolate strings', () => {
expect(parser.interpolate("This is a {{ key }}", {key: "value"})).toEqual("This is a value");
});
describe('interpolate()', () => {

it('should interpolate strings with falsy values', () => {
expect(parser.interpolate("This is a {{ key }}", {key: ""})).toEqual("This is a ");
expect(parser.interpolate("This is a {{ key }}", {key: 0})).toEqual("This is a 0");
});
it('should interpolate strings', () => {
expect(parser.interpolate("This is a {{ key }}", {key: "value"})).toEqual("This is a value");
});

it('should interpolate strings with object properties', () => {
expect(parser.interpolate("This is a {{ key1.key2 }}", {key1: {key2: "value2"}})).toEqual("This is a value2");
expect(parser.interpolate("This is a {{ key1.key2.key3 }}", {key1: {key2: {key3: "value3"}}})).toEqual("This is a value3");
});
it('should interpolate strings with falsy values', () => {
expect(parser.interpolate("This is a {{ key }}", {key: ""})).toEqual("This is a ");
expect(parser.interpolate("This is a {{ key }}", {key: 0})).toEqual("This is a 0");
});

it('should interpolate strings with arrays', () => {
expect(parser.interpolate("This is a {{ key.0 }}", {key: ["A", "B", "C"]})).toEqual("This is a A");
expect(parser.interpolate("This is a {{ key.11 }}", {key: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]})).toEqual("This is a L");
expect(parser.interpolate("This is a {{ key.1.x }}", {key: ["A", {x: "B"}]})).toEqual("This is a B");
});
it('should interpolate strings with object properties', () => {
expect(parser.interpolate("This is a {{ key1.key2 }}", {key1: {key2: "value2"}})).toEqual("This is a value2");
expect(parser.interpolate("This is a {{ key1.key2.key3 }}", {key1: {key2: {key3: "value3"}}})).toEqual("This is a value3");
});

it('should support interpolation functions', () => {
expect(parser.interpolate((v: string) => v.toUpperCase() + ' YOU!', 'bless')).toBe('BLESS YOU!');
});
it('should interpolate strings with arrays', () => {
expect(parser.interpolate("This is a {{ key.0 }}", {key: ["A", "B", "C"]})).toEqual("This is a A");
expect(parser.interpolate("This is a {{ key.11 }}", {key: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]})).toEqual("This is a L");
expect(parser.interpolate("This is a {{ key.1.x }}", {key: ["A", {x: "B"}]})).toEqual("This is a B");
});

it('should get the addressed value', () => {
expect(parser.getValue({key1: {key2: "value2"}}, 'key1.key2')).toEqual("value2");
expect(parser.getValue({key1: {key2: "value"}}, 'keyWrong.key2')).not.toBeDefined();
expect(parser.getValue({key1: {key2: {key3: "value3"}}}, 'key1.key2.key3')).toEqual("value3");
expect(parser.getValue({key1: {key2: {key3: "value3"}}}, 'key1.keyWrong.key3')).not.toBeDefined();
expect(parser.getValue({key1: {key2: {key3: "value3"}}}, 'key1.key2.keyWrong')).not.toBeDefined();
it('should support interpolation functions', () => {
expect(parser.interpolate((v: string) => v.toUpperCase() + ' YOU!', 'bless')).toBe('BLESS YOU!');
});

it('should handle edge cases: array', () => {
expect(parser.interpolate("This is an array {{ key1.key2 }}", {key1: {key2: ['A', 'B', 'C']}})).toEqual("This is an array A,B,C");
});

it('should handle edge cases: bool', () => {
expect(parser.interpolate("This is a bool: {{ key1.key2 }}", {key1: {key2: true}})).toEqual("This is a bool: true");
});

it('should handle edge cases: object', () => {
expect(parser.interpolate("This is a {{ key1.key2 }}", {key1: {key2: {key3: "value3"}}})).toEqual("This is a [object Object]");
});

it('should handle edge cases: object', () => {
const object = {
toString: () => "OBJECT A"
}
expect(parser.interpolate("This is {{ key1.key2 }}", {key1: {key2: object}})).toEqual("This is OBJECT A");
});

})

expect(parser.getValue({'key1.key2': {key3: "value3"}}, 'key1.key2.key3')).toEqual("value3");
expect(parser.getValue({key1: {'key2.key3': "value3"}}, 'key1.key2.key3')).toEqual("value3");
expect(parser.getValue({'key1.key2.key3': "value3"}, 'key1.key2.key3')).toEqual("value3");
expect(parser.getValue({'key1.key2': {key3: "value3"}}, 'key1.key2.keyWrong')).not.toBeDefined();
expect(parser.getValue({
'key1': "value1",
'key1.key2': "value2"
}, 'key1.key2')).toEqual("value2");

});
});
Loading

0 comments on commit 196fac8

Please sign in to comment.