1- import { TmplAstNode , parseTemplate , BindingPipe , LiteralPrimitive , Conditional , TmplAstTextAttribute } from '@angular/compiler' ;
1+ import {
2+ AST ,
3+ TmplAstNode ,
4+ parseTemplate ,
5+ BindingPipe ,
6+ LiteralPrimitive ,
7+ Conditional ,
8+ TmplAstTextAttribute ,
9+ Binary ,
10+ LiteralMap ,
11+ LiteralArray ,
12+ Interpolation
13+ } from '@angular/compiler' ;
214
315import { ParserInterface } from './parser.interface' ;
416import { TranslationCollection } from '../utils/translation.collection' ;
@@ -36,9 +48,8 @@ export class PipeParser implements ParserInterface {
3648 ) ;
3749 }
3850
39- if ( node ?. value ?. ast ?. expressions ) {
40- const translateables = node . value . ast . expressions . filter ( ( exp : any ) => this . expressionIsOrHasBindingPipe ( exp ) ) ;
41- ret . push ( ...translateables ) ;
51+ if ( node ?. value ?. ast ) {
52+ ret . push ( ...this . getTranslatablesFromAst ( node . value . ast ) ) ;
4253 }
4354
4455 if ( node ?. attributes ) {
@@ -51,17 +62,8 @@ export class PipeParser implements ParserInterface {
5162 if ( node ?. inputs ) {
5263 node . inputs . forEach ( ( input : any ) => {
5364 // <element [attrib]="'identifier' | translate">
54- if ( input ?. value ?. ast && this . expressionIsOrHasBindingPipe ( input . value . ast ) ) {
55- ret . push ( input . value . ast ) ;
56- }
57-
58- // <element attrib="{{'identifier' | translate}}>"
59- if ( input ?. value ?. ast ?. expressions ) {
60- input . value . ast . expressions . forEach ( ( exp : BindingPipe ) => {
61- if ( this . expressionIsOrHasBindingPipe ( exp ) ) {
62- ret . push ( exp ) ;
63- }
64- } ) ;
65+ if ( input ?. value ?. ast ) {
66+ ret . push ( ...this . getTranslatablesFromAst ( input . value . ast ) ) ;
6567 }
6668 } ) ;
6769 }
@@ -84,7 +86,63 @@ export class PipeParser implements ParserInterface {
8486 return ret ;
8587 }
8688
87- protected expressionIsOrHasBindingPipe ( exp : any ) : boolean {
89+ protected getTranslatablesFromAst ( ast : AST ) : BindingPipe [ ] {
90+ // the entire expression is the translate pipe, e.g.:
91+ // - 'foo' | translate
92+ // - (condition ? 'foo' : 'bar') | translate
93+ if ( this . expressionIsOrHasBindingPipe ( ast ) ) {
94+ return [ ast ] ;
95+ }
96+
97+ // angular double curly bracket interpolation, e.g.:
98+ // - {{ expressions }}
99+ if ( ast instanceof Interpolation ) {
100+ return this . getTranslatablesFromAsts ( ast . expressions ) ;
101+ }
102+
103+ // ternary operator, e.g.:
104+ // - condition ? null : ('foo' | translate)
105+ // - condition ? ('foo' | translate) : null
106+ if ( ast instanceof Conditional ) {
107+ return this . getTranslatablesFromAsts ( [ ast . trueExp , ast . falseExp ] ) ;
108+ }
109+
110+ // string concatenation, e.g.:
111+ // - 'foo' + 'bar' + ('baz' | translate)
112+ if ( ast instanceof Binary ) {
113+ return this . getTranslatablesFromAsts ( [ ast . left , ast . right ] ) ;
114+ }
115+
116+ // a pipe on the outer expression, but not the translate pipe - ignore the pipe, visit the expression, e.g.:
117+ // - { foo: 'Hello' | translate } | json
118+ if ( ast instanceof BindingPipe ) {
119+ return this . getTranslatablesFromAst ( ast . exp ) ;
120+ }
121+
122+ // object - ignore the keys, visit all values, e.g.:
123+ // - { key1: 'value1' | translate, key2: 'value2' | translate }
124+ if ( ast instanceof LiteralMap ) {
125+ return this . getTranslatablesFromAsts ( ast . values ) ;
126+ }
127+
128+ // array - visit all its values, e.g.:
129+ // - [ 'value1' | translate, 'value2' | translate ]
130+ if ( ast instanceof LiteralArray ) {
131+ return this . getTranslatablesFromAsts ( ast . expressions ) ;
132+ }
133+
134+ return [ ] ;
135+ }
136+
137+ protected getTranslatablesFromAsts ( asts : AST [ ] ) : BindingPipe [ ] {
138+ return this . flatten ( asts . map ( ast => this . getTranslatablesFromAst ( ast ) ) ) ;
139+ }
140+
141+ protected flatten < T extends AST > ( array : T [ ] [ ] ) : T [ ] {
142+ return [ ] . concat ( ...array ) ;
143+ }
144+
145+ protected expressionIsOrHasBindingPipe ( exp : any ) : exp is BindingPipe {
88146 if ( exp . name && exp . name === TRANSLATE_PIPE_NAME ) {
89147 return true ;
90148 }
0 commit comments