Skip to content

Commit 73db493

Browse files
committed
fix(#621): fix after rebase
1 parent 1c6af4d commit 73db493

File tree

6 files changed

+344
-328
lines changed

6 files changed

+344
-328
lines changed

libs/transloco-validator/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env node
22
import commandLineArgs from 'command-line-args';
3+
34
import validator from './lib/transloco-validator';
45

56

libs/transloco-validator/src/lib/transloco-validator.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import validator from './transloco-validator';
21
import fs from 'fs';
32

3+
import validator from './transloco-validator';
4+
45
jest.mock('fs');
56

67
describe('transloco-validator', () => {
@@ -23,7 +24,7 @@ describe('transloco-validator', () => {
2324
jest.mocked(fs.readFileSync).mockImplementation(() => '{"test":{"erreur"}}');
2425

2526
const callValidator = () => validator('', ['mytest.json']);
26-
expect(callValidator).toThrowError(new SyntaxError("Unexpected token } in JSON at position 17 (mytest.json)"));
27+
expect(callValidator).toThrowError(SyntaxError);
2728
})
2829

2930
it('should return success', () => {
Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,56 @@
1-
import fs from 'fs';
2-
3-
import findDuplicatedPropertyKeys from 'find-duplicated-property-keys';
4-
5-
export default function (interpolationForbiddenChars: string, translationFilePaths: string[]) {
6-
translationFilePaths.forEach((path) => {
7-
const translation = fs.readFileSync(path, 'utf-8');
8-
9-
// Verify that we can parse the JSON
10-
let parsedTranslation;
11-
try {
12-
parsedTranslation = JSON.parse(translation);
13-
} catch(error) {
14-
throw new SyntaxError(
15-
`${error.message} (${path})`
16-
);
17-
}
18-
19-
// Verify that we don't have any duplicate keys
20-
const duplicatedKeys = findDuplicatedPropertyKeys(translation);
21-
if (duplicatedKeys.length) {
22-
throw new Error(
23-
`Found duplicate keys: ${duplicatedKeys.map(dupl => dupl.toString())} (${path})`
24-
);
25-
}
26-
27-
const forbiddenKeys = findPropertyKeysContaining(parsedTranslation, interpolationForbiddenChars);
28-
if (forbiddenKeys.length) {
29-
throw new Error(
30-
`Found forbidden characters [${interpolationForbiddenChars}] in keys: ${forbiddenKeys} (${path})`
31-
);
32-
}
33-
});
34-
}
35-
36-
function findPropertyKeysContaining(object: unknown, chars: string, parent = '<instance>') {
37-
const found = [];
38-
if (Array.isArray(object)) {
39-
for(let i = 0; i < object.length; i++) {
40-
const value = object[i];
41-
found.push(...findPropertyKeysContaining(value, chars, `${parent}[${i}]`));
42-
}
43-
} else if (typeof object === 'object') {
44-
for(const key in object) {
45-
const value = object[key];
46-
for (const char of chars) {
47-
if (key.includes(char)) {
48-
found.push(parent + '.' + key);
49-
break;
50-
}
51-
}
52-
found.push(...findPropertyKeysContaining(value, chars, `${parent}.${key}`));
53-
}
54-
}
55-
return found;
1+
import fs from 'fs';
2+
3+
import findDuplicatedPropertyKeys from 'find-duplicated-property-keys';
4+
5+
export default function (interpolationForbiddenChars: string, translationFilePaths: string[]) {
6+
translationFilePaths.forEach((path) => {
7+
const translation = fs.readFileSync(path, 'utf-8');
8+
9+
// Verify that we can parse the JSON
10+
let parsedTranslation;
11+
try {
12+
parsedTranslation = JSON.parse(translation);
13+
} catch(error) {
14+
throw new SyntaxError(
15+
`${error.message} (${path})`
16+
);
17+
}
18+
19+
// Verify that we don't have any duplicate keys
20+
const duplicatedKeys = findDuplicatedPropertyKeys(translation);
21+
if (duplicatedKeys.length) {
22+
throw new Error(
23+
`Found duplicate keys: ${duplicatedKeys.map(dupl => dupl.toString())} (${path})`
24+
);
25+
}
26+
27+
const forbiddenKeys = findPropertyKeysContaining(parsedTranslation, interpolationForbiddenChars);
28+
if (forbiddenKeys.length) {
29+
throw new Error(
30+
`Found forbidden characters [${interpolationForbiddenChars}] in keys: ${forbiddenKeys} (${path})`
31+
);
32+
}
33+
});
34+
}
35+
36+
function findPropertyKeysContaining(object: unknown, chars: string, parent = '<instance>') {
37+
const found = [];
38+
if (Array.isArray(object)) {
39+
for(let i = 0; i < object.length; i++) {
40+
const value = object[i];
41+
found.push(...findPropertyKeysContaining(value, chars, `${parent}[${i}]`));
42+
}
43+
} else if (typeof object === 'object') {
44+
for(const key in object) {
45+
const value = object[key];
46+
for (const char of chars) {
47+
if (key.includes(char)) {
48+
found.push(parent + '.' + key);
49+
break;
50+
}
51+
}
52+
found.push(...findPropertyKeysContaining(value, chars, `${parent}.${key}`));
53+
}
54+
}
55+
return found;
5656
}

libs/transloco/src/lib/tests/transpiler.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,26 @@ describe('TranslocoTranspiler', () => {
123123

124124
function testDefaultBehaviour(
125125
parser: TranslocoTranspiler,
126-
[start, end]: [string, string] = defaultConfig.interpolation
126+
[start, end, forbiddenChars]: [string, string, string?] = defaultConfig.interpolation
127127
) {
128128
function wrapParam(param: string) {
129129
return `${start} ${param} ${end}`;
130130
}
131131

132+
it('should skip if forbidden chars are used', () => {
133+
if (forbiddenChars?.length) {
134+
for (const char of forbiddenChars) {
135+
const parsed = parser.transpile(
136+
`Hello ${wrapParam('value ' + char)}`,
137+
{ value: 'World' },
138+
{},
139+
'key'
140+
);
141+
expect(parsed).toEqual(`Hello ${wrapParam('value ' + char)}`);
142+
}
143+
}
144+
});
145+
132146
it('should translate simple string from params', () => {
133147
const parsed = parser.transpile(
134148
`Hello ${wrapParam('value')}`,
Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,72 @@
1-
import { InjectionToken } from '@angular/core';
2-
3-
import { AvailableLangs } from './types';
4-
5-
export interface TranslocoConfig {
6-
defaultLang: string;
7-
reRenderOnLangChange: boolean;
8-
prodMode: boolean;
9-
fallbackLang?: string | string[];
10-
failedRetries: number;
11-
availableLangs: AvailableLangs;
12-
flatten: {
13-
aot: boolean;
14-
};
15-
missingHandler: {
16-
logMissingKey: boolean;
17-
useFallbackTranslation: boolean;
18-
allowEmpty: boolean;
19-
};
20-
interpolation: [start: string, end: string, forbiddenChars?: string];
21-
}
22-
23-
export const TRANSLOCO_CONFIG = new InjectionToken<TranslocoConfig>(
24-
'TRANSLOCO_CONFIG',
25-
{
26-
providedIn: 'root',
27-
factory: () => defaultConfig,
28-
}
29-
);
30-
31-
export const defaultConfig: TranslocoConfig = {
32-
defaultLang: 'en',
33-
reRenderOnLangChange: false,
34-
prodMode: false,
35-
failedRetries: 2,
36-
fallbackLang: [],
37-
availableLangs: [],
38-
missingHandler: {
39-
logMissingKey: true,
40-
useFallbackTranslation: false,
41-
allowEmpty: false,
42-
},
43-
flatten: {
44-
aot: false,
45-
},
46-
interpolation: ['{{', '}}', '{}'],
47-
};
48-
49-
type DeepPartial<T> = T extends Array<any>
50-
? T
51-
: T extends object
52-
? { [P in keyof T]?: DeepPartial<T[P]> }
53-
: T;
54-
55-
export type PartialTranslocoConfig = DeepPartial<TranslocoConfig>;
56-
57-
export function translocoConfig(
58-
config: PartialTranslocoConfig = {}
59-
): TranslocoConfig {
60-
return {
61-
...defaultConfig,
62-
...config,
63-
missingHandler: {
64-
...defaultConfig.missingHandler,
65-
...config.missingHandler,
66-
},
67-
flatten: {
68-
...defaultConfig.flatten,
69-
...config.flatten,
70-
},
71-
};
72-
}
1+
import { InjectionToken } from '@angular/core';
2+
3+
import { AvailableLangs } from './types';
4+
5+
export interface TranslocoConfig {
6+
defaultLang: string;
7+
reRenderOnLangChange: boolean;
8+
prodMode: boolean;
9+
fallbackLang?: string | string[];
10+
failedRetries: number;
11+
availableLangs: AvailableLangs;
12+
flatten: {
13+
aot: boolean;
14+
};
15+
missingHandler: {
16+
logMissingKey: boolean;
17+
useFallbackTranslation: boolean;
18+
allowEmpty: boolean;
19+
};
20+
interpolation: [start: string, end: string, forbiddenChars?: string];
21+
}
22+
23+
export const TRANSLOCO_CONFIG = new InjectionToken<TranslocoConfig>(
24+
'TRANSLOCO_CONFIG',
25+
{
26+
providedIn: 'root',
27+
factory: () => defaultConfig,
28+
}
29+
);
30+
31+
export const defaultConfig: TranslocoConfig = {
32+
defaultLang: 'en',
33+
reRenderOnLangChange: false,
34+
prodMode: false,
35+
failedRetries: 2,
36+
fallbackLang: [],
37+
availableLangs: [],
38+
missingHandler: {
39+
logMissingKey: true,
40+
useFallbackTranslation: false,
41+
allowEmpty: false,
42+
},
43+
flatten: {
44+
aot: false,
45+
},
46+
interpolation: ['{{', '}}', '{}'],
47+
};
48+
49+
type DeepPartial<T> = T extends Array<any>
50+
? T
51+
: T extends object
52+
? { [P in keyof T]?: DeepPartial<T[P]> }
53+
: T;
54+
55+
export type PartialTranslocoConfig = DeepPartial<TranslocoConfig>;
56+
57+
export function translocoConfig(
58+
config: PartialTranslocoConfig = {}
59+
): TranslocoConfig {
60+
return {
61+
...defaultConfig,
62+
...config,
63+
missingHandler: {
64+
...defaultConfig.missingHandler,
65+
...config.missingHandler,
66+
},
67+
flatten: {
68+
...defaultConfig.flatten,
69+
...config.flatten,
70+
},
71+
};
72+
}

0 commit comments

Comments
 (0)