2018-02-14 13:54:00 -05:00
/ * *
* @license
* Copyright Google Inc . All Rights Reserved .
*
* Use of this source code is governed by an MIT - style license that can be
* found in the LICENSE file at https : //angular.io/license
* /
2018-12-13 18:51:47 -05:00
import { AttributeMarker } from '@angular/compiler/src/core' ;
2018-10-05 17:12:13 -04:00
import { setup } from '@angular/compiler/test/aot/test_util' ;
2020-05-12 03:20:02 -04:00
import * as ts from 'typescript' ;
2018-10-18 13:08:51 -04:00
2018-11-29 19:21:16 -05:00
import { DEFAULT_INTERPOLATION_CONFIG , InterpolationConfig } from '../../../compiler/src/compiler' ;
2018-10-18 13:08:51 -04:00
import { decimalDigest } from '../../../compiler/src/i18n/digest' ;
import { extractMessages } from '../../../compiler/src/i18n/extractor_merger' ;
import { HtmlParser } from '../../../compiler/src/ml_parser/html_parser' ;
2018-02-14 13:54:00 -05:00
import { compile , expectEmit } from './mock_compile' ;
2018-10-18 13:08:51 -04:00
const angularFiles = setup ( {
compileAngular : false ,
compileFakeCore : true ,
compileAnimations : false ,
} ) ;
const htmlParser = new HtmlParser ( ) ;
2019-07-31 05:52:38 -04:00
// TODO: update translation extraction RegExp to support `$localize` tags.
2019-02-25 15:42:50 -05:00
const EXTRACT_GENERATED_TRANSLATIONS_REGEXP =
/const\s*(.*?)\s*=\s*goog\.getMsg\("(.*?)",?\s*(.*?)\)/g ;
2018-10-18 13:08:51 -04:00
const diff = ( a : Set < string > , b : Set < string > ) : Set < string > = >
new Set ( [ . . . Array . from ( a ) ] . filter ( x = > ! b . has ( x ) ) ) ;
2019-06-14 06:19:09 -04:00
const extract = ( from : string , regex : any , transformFn : ( match : any [ ] , state : Set < any > ) = > any ) = > {
const result = new Set < any > ( ) ;
let item ;
while ( ( item = regex . exec ( from ) ) !== null ) {
result . add ( transformFn ( item , result ) ) ;
}
return result ;
} ;
2018-11-16 12:57:23 -05:00
2018-10-18 13:08:51 -04:00
// verify that we extracted all the necessary translations
// and their ids match the ones extracted via 'ng xi18n'
2018-11-29 19:21:16 -05:00
const verifyTranslationIds =
( source : string , output : string , exceptions = { } ,
interpolationConfig : InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG ) = > {
2019-02-08 17:10:19 -05:00
const parseResult =
htmlParser . parse ( source , 'path:://to/template' , { tokenizeExpansionForms : true } ) ;
2018-11-29 19:21:16 -05:00
const extractedIdToMsg = new Map < string , any > ( ) ;
const extractedIds = new Set < string > ( ) ;
const generatedIds = new Set < string > ( ) ;
const msgs = extractMessages ( parseResult . rootNodes , interpolationConfig , [ ] , { } ) ;
msgs . messages . forEach ( msg = > {
const id = msg . id || decimalDigest ( msg ) ;
extractedIds . add ( id ) ;
extractedIdToMsg . set ( id , msg ) ;
} ) ;
const regexp = /const\s*MSG_EXTERNAL_(.+?)\s*=\s*goog\.getMsg/g ;
const ids = extract ( output , regexp , v = > v [ 1 ] ) ;
2020-04-07 15:43:43 -04:00
ids . forEach ( id = > {
generatedIds . add ( id . split ( '$$' ) [ 0 ] ) ;
} ) ;
2018-11-29 19:21:16 -05:00
const delta = diff ( extractedIds , generatedIds ) ;
if ( delta . size ) {
// check if we have ids in exception list
const outstanding = diff ( delta , new Set ( Object . keys ( exceptions ) ) ) ;
if ( outstanding . size ) {
throw new Error ( `
2018-10-18 13:08:51 -04:00
Extracted and generated IDs don ' t match , delta :
$ { JSON . stringify ( Array . from ( delta ) ) }
` );
2018-11-29 19:21:16 -05:00
}
}
return true ;
} ;
2018-10-18 13:08:51 -04:00
// verify that placeholders in translation string match
// placeholders object defined as goog.getMsg function argument
const verifyPlaceholdersIntegrity = ( output : string ) = > {
2019-04-11 05:17:49 -04:00
const extractTranslations = ( from : string ) = > {
2019-02-25 15:42:50 -05:00
return extract ( from , EXTRACT_GENERATED_TRANSLATIONS_REGEXP , v = > [ v [ 2 ] , v [ 3 ] ] ) ;
2018-10-18 13:08:51 -04:00
} ;
const extractPlaceholdersFromBody = ( body : string ) = > {
const regex = /{\$(.*?)}/g ;
return extract ( body , regex , v = > v [ 1 ] ) ;
} ;
const extractPlaceholdersFromArgs = ( args : string ) = > {
const regex = /\s+"(.+?)":\s*".*?"/g ;
return extract ( args , regex , v = > v [ 1 ] ) ;
} ;
2019-04-11 05:17:49 -04:00
const translations = extractTranslations ( output ) ;
2018-10-18 13:08:51 -04:00
translations . forEach ( ( translation ) = > {
const bodyPhs = extractPlaceholdersFromBody ( translation [ 0 ] ) ;
const argsPhs = extractPlaceholdersFromArgs ( translation [ 1 ] ) ;
if ( bodyPhs . size !== argsPhs . size || diff ( bodyPhs , argsPhs ) . size ) {
return false ;
}
} ) ;
return true ;
} ;
2019-02-25 15:42:50 -05:00
const verifyUniqueConsts = ( output : string ) = > {
extract (
output , EXTRACT_GENERATED_TRANSLATIONS_REGEXP ,
( current : string [ ] , state : Set < any > ) : string = > {
const key = current [ 1 ] ;
if ( state . has ( key ) ) {
throw new Error ( ` Duplicate const ${ key } found in generated output! ` ) ;
}
return key ;
} ) ;
return true ;
} ;
2019-11-15 11:25:59 -05:00
/ * *
* Escape the template string for being placed inside a backtick string literal .
*
* * "\" would erroneously indicate a control character
* * "`" and "${" strings would erroneously indicate the end of a message part
* /
const escapeTemplate = ( template : string ) = >
template . replace ( /\\/g , '\\\\' ) . replace ( /`/g , '\\`' ) . replace ( /\$\{/g , '$\\{' ) ;
2018-10-18 13:08:51 -04:00
const getAppFilesWithTemplate = ( template : string , args : any = { } ) = > ( {
app : {
fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
2020-04-26 13:15:43 -04:00
'spec.template.html' : template ,
2018-10-18 13:08:51 -04:00
'spec.ts' : `
import { Component , NgModule } from '@angular/core' ;
@Component ( {
selector : 'my-component' ,
$ { args . preserveWhitespaces ? 'preserveWhitespaces: true,' : '' }
2018-11-29 19:21:16 -05:00
$ { args . interpolation ? 'interpolation: ' + JSON . stringify ( args . interpolation ) + ', ' : '' }
fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
2020-04-26 13:15:43 -04:00
$ {
args . templateUrl ? ` templateUrl: 'spec.template.html' ` :
` template: \` ${ escapeTemplate ( template ) } \` ` } )
2018-10-18 13:08:51 -04:00
export class MyComponent { }
@NgModule ( { declarations : [ MyComponent ] } )
export class MyModule { }
`
}
} ) ;
2018-11-16 12:57:23 -05:00
const maybePrint = ( output : string , verbose : boolean ) = > {
if ( ! verbose ) return ;
// tslint:disable-next-line
console . log ( `
2018-10-18 13:08:51 -04:00
=== === === = Generated output : === === === =
2018-11-16 12:57:23 -05:00
$ { output }
2018-10-18 13:08:51 -04:00
=== === === === === === === === === === === === ===
2018-11-16 12:57:23 -05:00
` );
} ;
const verify = ( input : string , output : string , extra : any = { } ) : void = > {
const files = getAppFilesWithTemplate ( input , extra . inputArgs ) ;
const opts = ( i18nUseExternalIds : boolean ) = >
( { i18nUseExternalIds , . . . ( extra . compilerOptions || { } ) } ) ;
// invoke with file-based prefix translation names
2019-01-11 20:23:51 -05:00
if ( ! extra . skipPathBasedCheck ) {
const result = compile ( files , angularFiles , opts ( false ) ) ;
maybePrint ( result . source , extra . verbose ) ;
expect ( verifyPlaceholdersIntegrity ( result . source ) ) . toBe ( true ) ;
2019-02-25 15:42:50 -05:00
expect ( verifyUniqueConsts ( result . source ) ) . toBe ( true ) ;
2019-01-11 20:23:51 -05:00
expectEmit ( result . source , output , 'Incorrect template' ) ;
}
2018-11-16 12:57:23 -05:00
// invoke with translation names based on external ids
2019-01-11 20:23:51 -05:00
if ( ! extra . skipIdBasedCheck ) {
const result = compile ( files , angularFiles , opts ( true ) ) ;
maybePrint ( result . source , extra . verbose ) ;
const interpolationConfig = extra . inputArgs && extra . inputArgs . interpolation ?
InterpolationConfig . fromArray ( extra . inputArgs . interpolation ) :
undefined ;
expect ( verifyTranslationIds ( input , result . source , extra . exceptions , interpolationConfig ) )
. toBe ( true ) ;
expect ( verifyPlaceholdersIntegrity ( result . source ) ) . toBe ( true ) ;
2019-02-25 15:42:50 -05:00
expect ( verifyUniqueConsts ( result . source ) ) . toBe ( true ) ;
2019-01-11 20:23:51 -05:00
expectEmit ( result . source , output , 'Incorrect template' ) ;
}
2018-10-18 13:08:51 -04:00
} ;
2019-09-04 11:27:29 -04:00
describe ( 'i18n support in the template compiler' , ( ) = > {
2018-10-12 17:34:38 -04:00
describe ( 'element attributes' , ( ) = > {
2019-10-02 13:17:56 -04:00
it ( 'should add the meaning and description as JsDoc comments and metadata blocks' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n = "meaningA|descA@@idA" > Content A < / div >
< div i18n - title = "meaningB|descB@@idB" title = "Title B" > Content B < / div >
2019-09-13 07:46:05 -04:00
< div i18n - title = "meaningC|" title = "Title C" > Content C < / div >
2018-10-18 13:08:51 -04:00
< div i18n - title = "meaningD|descD" title = "Title D" > Content D < / div >
< div i18n - title = "meaningE@@idE" title = "Title E" > Content E < / div >
< div i18n - title = "@@idF" title = "Title F" > Content F < / div >
2019-11-15 11:25:59 -05:00
< div i18n - title = "[BACKUP_$\{MESSAGE}_ID:idH]\`desc@@idG" title = "Title G" > Content G < / div >
< div i18n = "Some text \\' [BACKUP_MESSAGE_ID: xxx]" > Content H < / div >
2018-10-18 13:08:51 -04:00
` ;
2018-02-14 13:54:00 -05:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc descA
* @meaning meaningA
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_idA $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Content A" ) ;
$I18N_0 $ = $MSG_EXTERNAL_idA $ $APP_SPEC_TS_1 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-09-13 07:46:05 -04:00
$I18N_0 $ = $localize \ ` :meaningA|descA@@idA:Content A \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc descB
* @meaning meaningB
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_idB $ $APP_SPEC_TS_4 $ = goog . getMsg ( "Title B" ) ;
$I18N_3 $ = $MSG_EXTERNAL_idB $ $APP_SPEC_TS_4 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-09-13 07:46:05 -04:00
$I18N_3 $ = $localize \ ` :meaningB|descB@@idB:Title B \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c5 $ = [ "title" , $I18N_3 $ ] ;
var $I18N_7 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
2019-09-13 07:46:05 -04:00
* @meaning meaningC
2019-04-11 05:17:49 -04:00
* /
2019-09-13 07:46:05 -04:00
const $MSG_EXTERNAL_6435899732746131543 $ $APP_SPEC_TS_8 $ = goog . getMsg ( "Title C" ) ;
$I18N_7 $ = $MSG_EXTERNAL_6435899732746131543 $ $APP_SPEC_TS_8 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_7 $ = $localize \ ` :meaningC|:Title C \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c9 $ = [ "title" , $I18N_7 $ ] ;
var $I18N_11 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc descD
* @meaning meaningD
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_5200291527729162531 $ $APP_SPEC_TS_12 $ = goog . getMsg ( "Title D" ) ;
$I18N_11 $ = $MSG_EXTERNAL_5200291527729162531 $ $APP_SPEC_TS_12 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_11 $ = $localize \ ` :meaningD|descD:Title D \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c13 $ = [ "title" , $I18N_11 $ ] ;
var $I18N_15 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc meaningE
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_idE $ $APP_SPEC_TS_16 $ = goog . getMsg ( "Title E" ) ;
$I18N_15 $ = $MSG_EXTERNAL_idE $ $APP_SPEC_TS_16 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-09-13 07:46:05 -04:00
$I18N_15 $ = $localize \ ` :meaningE@@idE:Title E \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c17 $ = [ "title" , $I18N_15 $ ] ;
var $I18N_19 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_idF $ $APP_SPEC_TS_20 $ = goog . getMsg ( "Title F" ) ;
$I18N_19 $ = $MSG_EXTERNAL_idF $ $APP_SPEC_TS_20 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-09-13 07:46:05 -04:00
$I18N_19 $ = $localize \ ` :@@idF:Title F \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c21 $ = [ "title" , $I18N_19 $ ] ;
var $I18N_23 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
2019-11-15 11:25:59 -05:00
* @desc [ BACKUP_ $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {MESSAGE}_ID:idH] ` +
'`' + String . raw ` desc
2019-04-11 05:17:49 -04:00
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_idG $ $APP_SPEC_TS_24 $ = goog . getMsg ( "Title G" ) ;
$I18N_23 $ = $MSG_EXTERNAL_idG $ $APP_SPEC_TS_24 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-11-15 11:25:59 -05:00
$I18N_23 $ = $localize \ ` :[BACKUP_ $ \ {MESSAGE}_ID \ :idH] \\ \` desc@@idG:Title G \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c25 $ = [ "title" , $I18N_23 $ ] ;
2019-11-15 11:25:59 -05:00
var $I18N_20 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-11-15 11:25:59 -05:00
/ * *
* @desc Some text \ ' [ BACKUP_MESSAGE_ID : xxx ]
* /
const $MSG_EXTERNAL_idG $ $APP_SPEC_TS_21 $ = goog . getMsg ( "Content H" ) ;
$I18N_20 $ = $MSG_EXTERNAL_idG $ $APP_SPEC_TS_21 $ ;
}
else {
$I18N_20 $ = $localize \ ` :Some text \\ ' [BACKUP_MESSAGE_ID \ : xxx]:Content H \` ;
}
2018-10-05 17:12:13 -04:00
…
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 2 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 3 , $_c5 $ ) ;
$r3 $ . ɵ ɵ text ( 4 , "Content B" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 5 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 6 , $_c9 $ ) ;
$r3 $ . ɵ ɵ text ( 7 , "Content C" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 8 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 9 , $_c13 $ ) ;
$r3 $ . ɵ ɵ text ( 10 , "Content D" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 11 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 12 , $_c17 $ ) ;
$r3 $ . ɵ ɵ text ( 13 , "Content E" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 14 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 15 , $_c21 $ ) ;
$r3 $ . ɵ ɵ text ( 16 , "Content F" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 17 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 18 , $_c25 $ ) ;
$r3 $ . ɵ ɵ text ( 19 , "Content G" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-11-15 11:25:59 -05:00
$r3 $ . ɵ ɵ elementStart ( 20 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 21 , $I18N_20 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
2018-02-14 13:54:00 -05:00
}
2018-03-22 18:03:06 -04:00
` ;
2018-02-14 13:54:00 -05:00
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2018-10-05 17:12:13 -04:00
2020-02-26 01:59:34 -05:00
it ( 'should support i18n attributes on explicit <ng-template> elements' , ( ) = > {
const input = `
< ng - template i18n - title title = "Hello" > < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2020-02-26 01:59:34 -05:00
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_6616505470450179563 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Hello" ) ;
$I18N_0 $ = $MSG_EXTERNAL_6616505470450179563 $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` Hello \` ;
}
const $_c2 $ = [ "title" , $I18N_0 $ ] ;
…
2020-04-03 15:58:20 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2020-02-26 01:59:34 -05:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_ng_template_0_Template , 0 , 0 , "ng-template" , 0 ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c2 $ ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should support i18n attributes on explicit <ng-template> with structural directives' ,
( ) = > {
const input = `
< ng - template * ngIf = "visible" i18n - title title = "Hello" > Test < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2020-02-26 01:59:34 -05:00
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_6616505470450179563 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Hello" ) ;
$I18N_0 $ = $MSG_EXTERNAL_6616505470450179563 $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` Hello \` ;
}
const $_c2 $ = [ "title" , $I18N_0 $ ] ;
function MyComponent_0_ng_template_0_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ text ( 0 , "Test" ) ;
}
}
function MyComponent_0_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_ng_template_0_Template , 1 , 0 , "ng-template" , 1 ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c2 $ ) ;
}
}
…
2020-04-03 15:58:20 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] , [ $ { AttributeMarker . I18n } , "title" ] ] ,
2020-02-26 01:59:34 -05:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_Template , 2 , 0 , undefined , 0 ) ;
}
if ( rf & 2 ) {
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2020-03-10 00:49:02 -04:00
it ( 'should support i18n attributes with interpolations on explicit <ng-template> elements' ,
( ) = > {
const input = `
< ng - template i18n - title title = "Hello {{ name }}" > < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2020-03-10 00:49:02 -04:00
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_3771704108176831903 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Hello {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_3771704108176831903 $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` Hello $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2020-03-10 00:49:02 -04:00
}
const $_c2 $ = [ "title" , $I18N_0 $ ] ;
…
consts : [ [ $ { AttributeMarker . Bindings } , "title" ] ] ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_ng_template_0_Template , 0 , 0 , "ng-template" , 0 ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c2 $ ) ;
}
if ( rf & 2 ) {
$r3 $ . ɵ ɵ i18nExp ( ctx . name ) ;
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should support i18n attributes with interpolations on explicit <ng-template> elements with structural directives' ,
( ) = > {
const input = `
< ng - template * ngIf = "true" i18n - title title = "Hello {{ name }}" > < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2020-03-10 00:49:02 -04:00
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_3771704108176831903 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "Hello {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_3771704108176831903 $ $APP_SPEC_TS__1 $ ;
}
else {
$I18N_0 $ = $localize \ ` Hello $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2020-03-10 00:49:02 -04:00
}
const $_c2 $ = [ "title" , $I18N_0 $ ] ;
…
function MyComponent_0_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_ng_template_0_Template , 0 , 0 , "ng-template" , 1 ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c2 $ ) ;
}
if ( rf & 2 ) {
const $ctx_r2 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
$r3 $ . ɵ ɵ i18nExp ( $ctx_r2 $ . name ) ;
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
}
}
…
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] , [ $ { AttributeMarker . Bindings } , "title" ] ] ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_Template , 2 , 1 , undefined , 0 ) ;
}
if ( rf & 2 ) {
$r3 $ . ɵ ɵ property ( "ngIf" , true ) ;
}
} ,
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should not create translations for empty attributes' , ( ) = > {
const input = `
< div id = "static" i18n - title = "m|d" title > < / div >
` ;
const output = `
…
2019-09-23 14:08:51 -04:00
consts : [ [ "id" , "static" , "title" , "" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 0 , "div" , 0 ) ;
2018-10-18 13:08:51 -04:00
}
2018-02-14 13:54:00 -05:00
}
2018-10-18 13:08:51 -04:00
` ;
verify ( input , output ) ;
} ) ;
2019-07-09 21:08:33 -04:00
it ( 'should not create translations for bound attributes' , ( ) = > {
const input = `
< div
[ title ] = "title" i18n - title
[ attr . label ] = "label" i18n - attr . label >
< / div >
` ;
const output = `
…
2019-09-23 14:08:51 -04:00
consts : [ [ 3 , "title" ] ] ,
2019-07-09 21:08:33 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 0 , "div" , 0 ) ;
2019-07-09 21:08:33 -04:00
}
if ( rf & 2 ) {
$r3 $ . ɵ ɵ property ( "title" , ctx . title ) ;
$r3 $ . ɵ ɵ attribute ( "label" , ctx . label ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should translate static attributes' , ( ) = > {
const input = `
< div id = "static" i18n - title = "m|d" title = "introduction" > < / div >
` ;
2018-02-14 13:54:00 -05:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_8809028065680254561 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "introduction" ) ;
$I18N_1 $ = $MSG_EXTERNAL_8809028065680254561 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` :m|d:introduction \` ;
2019-04-11 05:17:49 -04:00
}
const $_c1 $ = [ "title" , $I18N_1 $ ] ;
2018-10-05 17:12:13 -04:00
…
2019-09-23 14:08:51 -04:00
consts : [ [ "id" , "static" , $ { AttributeMarker . I18n } , "title" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
2018-02-14 13:54:00 -05:00
}
2018-10-05 17:12:13 -04:00
` ;
2018-02-14 13:54:00 -05:00
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-05 17:12:13 -04:00
} ) ;
2018-10-05 17:12:13 -04:00
it ( 'should support interpolation' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div id = "dynamic-1"
i18n - title = "m|d" title = "intro {{ valueA | uppercase }}"
i18n - aria - label = "m1|d1" aria - label = "{{ valueB }}"
i18n - aria - roledescription aria - roledescription = "static text"
> < / div >
< div id = "dynamic-2"
i18n - title = "m2|d2" title = "{{ valueA }} and {{ valueB }} and again {{ valueA + valueB }}"
i18n - aria - roledescription aria - roledescription = "{{ valueC }}"
> < / div >
` ;
2018-10-05 17:12:13 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_5526535577705876535 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "static text" ) ;
$I18N_1 $ = $MSG_EXTERNAL_5526535577705876535 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` static text \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_8977039798304050198 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "intro {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_2 $ = $MSG_EXTERNAL_8977039798304050198 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` :m|d:intro $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d1
* @meaning m1
* /
const $MSG_EXTERNAL_7432761130955693041 $ $APP_SPEC_TS_3 $ = goog . getMsg ( "{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_3 $ = $MSG_EXTERNAL_7432761130955693041 $ $APP_SPEC_TS_3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` :m1|d1: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-11-16 12:57:23 -05:00
const $_c1 $ = [
2019-04-11 05:17:49 -04:00
"aria-roledescription" , $I18N_1 $ ,
"title" , $I18N_2 $ ,
"aria-label" , $I18N_3 $
2018-11-16 12:57:23 -05:00
] ;
2019-04-11 05:17:49 -04:00
var $I18N_6 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d2
* @meaning m2
* /
const $MSG_EXTERNAL_7566208596013750546 $ $APP_SPEC_TS_6 $ = goog . getMsg ( "{$interpolation} and {$interpolation_1} and again {$interpolation_2}" , {
"interpolation" : "\uFFFD0\uFFFD" , "interpolation_1" : "\uFFFD1\uFFFD" , "interpolation_2" : "\uFFFD2\uFFFD"
} ) ;
$I18N_6 $ = $MSG_EXTERNAL_7566208596013750546 $ $APP_SPEC_TS_6 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_6 $ = $localize \ ` :m2|d2: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: and $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: and again $ ` +
String . raw ` {" \ uFFFD2 \ uFFFD"}:INTERPOLATION_2: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_7 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_6639222533406278123 $ $APP_SPEC_TS_7 $ = goog . getMsg ( "{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_7 $ = $MSG_EXTERNAL_6639222533406278123 $ $APP_SPEC_TS_7 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_7 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-04 18:56:47 -05:00
const $_c3 $ = [
2019-04-11 05:17:49 -04:00
"title" , $I18N_6 $ ,
"aria-roledescription" , $I18N_7 $
2018-12-04 18:56:47 -05:00
] ;
2018-10-05 17:12:13 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 5 ,
2018-11-28 20:31:21 -05:00
vars : 8 ,
2020-04-07 15:43:43 -04:00
consts : [ [ "id" , "dynamic-1" , $ {
AttributeMarker
. I18n } , "aria-roledescription" , "title" , "aria-label" ] , [ "id" , "dynamic-2" , $ {
AttributeMarker . I18n } , "title" , "aria-roledescription" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 2 , $_c1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 3 , "div" , 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 4 , $_c3 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 6 , ctx . valueA ) ) ( ctx . valueB ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 3 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueA ) ( ctx . valueB ) ( ctx . valueA + ctx . valueB ) ( ctx . valueC ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 4 ) ;
2018-10-05 17:12:13 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-05 17:12:13 -04:00
} ) ;
2018-11-29 19:21:16 -05:00
it ( 'should support interpolation with custom interpolation config' , ( ) = > {
const input = `
< div i18n - title = "m|d" title = "intro {% valueA | uppercase %}" > < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 19:51:27 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_8977039798304050198 $ = goog . getMsg ( "intro {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_1 $ = $MSG_EXTERNAL_8977039798304050198 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` :m|d:intro $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c3 $ = [ "title" , $I18N_1 $ ] ;
2018-11-29 19:21:16 -05:00
…
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2018-11-29 19:21:16 -05:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 2 , $_c3 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-11-29 19:21:16 -05:00
}
if ( rf & 2 ) {
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 1 , ctx . valueA ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2018-11-29 19:21:16 -05:00
}
}
` ;
verify ( input , output , { inputArgs : { interpolation : [ '{%' , '%}' ] } } ) ;
} ) ;
2018-10-05 17:12:13 -04:00
it ( 'should correctly bind to context in nested template' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div * ngFor = "let outer of items" >
2018-12-26 20:36:26 -05:00
< div i18n - title = "m|d" title = "different scope {{ outer | uppercase }}" > < / div >
2018-10-18 13:08:51 -04:00
< / div >
` ;
2018-10-05 17:12:13 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_8538466649243975456 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "different scope {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_8538466649243975456 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` :m|d:different scope $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c2 $ = [ "title" , $I18N_1 $ ] ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_0_Template ( rf , ctx ) {
2018-10-05 17:12:13 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 1 , "div" , 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 2 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 3 , $_c2 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
const $outer_r1 $ = ctx . $implicit ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 2 , 1 , $outer_r1 $ ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 3 ) ;
2018-10-05 17:12:13 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 1 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2020-04-07 15:43:43 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngFor" , "ngForOf" ] , [ $ {
AttributeMarker . I18n } , "title" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_div_0_Template , 4 , 3 , "div" , 0 ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngForOf" , ctx . items ) ;
2018-10-05 17:12:13 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-05 17:12:13 -04:00
} ) ;
2019-08-24 17:02:30 -04:00
it ( 'should support complex expressions in interpolation' , ( ) = > {
const input = `
< div i18n - title title = "{{valueA.getRawValue()?.getTitle()}} title" > < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-08-24 17:02:30 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-24 17:02:30 -04:00
const $MSG_EXTERNAL_3462388422673575127 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "{$interpolation} title" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_3462388422673575127 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: title \` ;
2019-08-24 17:02:30 -04:00
}
const $_c3 $ = [ "title" , $I18N_1 $ ] ;
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2019-08-24 17:02:30 -04:00
vars : 1 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2019-08-24 17:02:30 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-08-24 17:02:30 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c3 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
if ( rf & 2 ) {
var $tmp_0_0 $ = null ;
const $currVal_0 $ = ( $tmp_0_0 $ = ctx . valueA . getRawValue ( ) ) == null ? null : $tmp_0_0 $ . getTitle ( ) ;
$r3 $ . ɵ ɵ i18nExp ( $currVal_0 $ ) ;
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-05 17:12:13 -04:00
it ( 'should support interpolation' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div id = "dynamic-1"
i18n - title = "m|d" title = "intro {{ valueA | uppercase }}"
i18n - aria - label = "m1|d1" aria - label = "{{ valueB }}"
i18n - aria - roledescription aria - roledescription = "static text"
> < / div >
< div id = "dynamic-2"
i18n - title = "m2|d2" title = "{{ valueA }} and {{ valueB }} and again {{ valueA + valueB }}"
i18n - aria - roledescription aria - roledescription = "{{ valueC }}"
> < / div >
` ;
2018-10-05 17:12:13 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_5526535577705876535 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "static text" ) ;
$I18N_1 $ = $MSG_EXTERNAL_5526535577705876535 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` static text \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_8977039798304050198 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "intro {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_2 $ = $MSG_EXTERNAL_8977039798304050198 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` :m|d:intro $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d1
* @meaning m1
* /
const $MSG_EXTERNAL_7432761130955693041 $ $APP_SPEC_TS_3 $ = goog . getMsg ( "{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_3 $ = $MSG_EXTERNAL_7432761130955693041 $ $APP_SPEC_TS_3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` :m1|d1: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-11-16 12:57:23 -05:00
const $_c1 $ = [
2019-04-11 05:17:49 -04:00
"aria-roledescription" , $I18N_1 $ ,
"title" , $I18N_2 $ ,
"aria-label" , $I18N_3 $
2018-11-16 12:57:23 -05:00
] ;
2019-04-11 05:17:49 -04:00
var $I18N_6 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d2
* @meaning m2
* /
const $MSG_EXTERNAL_7566208596013750546 $ $APP_SPEC_TS_6 $ = goog . getMsg ( "{$interpolation} and {$interpolation_1} and again {$interpolation_2}" , {
"interpolation" : "\uFFFD0\uFFFD" , "interpolation_1" : "\uFFFD1\uFFFD" , "interpolation_2" : "\uFFFD2\uFFFD"
} ) ;
$I18N_6 $ = $MSG_EXTERNAL_7566208596013750546 $ $APP_SPEC_TS_6 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_6 $ = $localize \ ` :m2|d2: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: and $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: and again $ ` +
String . raw ` {" \ uFFFD2 \ uFFFD"}:INTERPOLATION_2: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_7 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_6639222533406278123 $ $APP_SPEC_TS_7 $ = goog . getMsg ( "{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_7 $ = $MSG_EXTERNAL_6639222533406278123 $ $APP_SPEC_TS_7 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_7 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-04 18:56:47 -05:00
const $_c3 $ = [
2019-04-11 05:17:49 -04:00
"title" , $I18N_6 $ ,
"aria-roledescription" , $I18N_7 $
2018-12-04 18:56:47 -05:00
] ;
2018-10-05 17:12:13 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 5 ,
2018-11-28 20:31:21 -05:00
vars : 8 ,
2019-09-23 14:08:51 -04:00
consts : [ [
"id" , "dynamic-1" ,
$ { AttributeMarker . I18n } , "aria-roledescription" , "title" , "aria-label"
] , [ "id" , "dynamic-2" , $ { AttributeMarker . I18n } , "title" , "aria-roledescription" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 2 , $_c1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 3 , "div" , 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 4 , $_c3 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 6 , ctx . valueA ) ) ( ctx . valueB ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 3 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueA ) ( ctx . valueB ) ( ctx . valueA + ctx . valueB ) ( ctx . valueC ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 4 ) ;
2018-10-05 17:12:13 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-05 17:12:13 -04:00
} ) ;
it ( 'should correctly bind to context in nested template' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div * ngFor = "let outer of items" >
2018-12-26 20:36:26 -05:00
< div i18n - title = "m|d" title = "different scope {{ outer | uppercase }}" > < / div >
2018-10-18 13:08:51 -04:00
< / div >
` ;
2018-10-05 17:12:13 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 19:51:27 -04:00
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_8538466649243975456 $ $APP_SPEC_TS__3 $ = goog . getMsg ( "different scope {$interpolation}" , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_2 $ = $MSG_EXTERNAL_8538466649243975456 $ $APP_SPEC_TS__3 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` :m|d:different scope $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c4 $ = [ "title" , $I18N_2 $ ] ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_0_Template ( rf , ctx ) {
2018-10-05 17:12:13 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 1 , "div" , 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 2 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nAttributes ( 3 , $_c4 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
const $outer_r1 $ = ctx . $implicit ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 2 , 1 , $outer_r1 $ ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 3 ) ;
2018-10-05 17:12:13 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 1 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2020-04-07 15:43:43 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngFor" , "ngForOf" ] , [ $ {
AttributeMarker . I18n } , "title" ] ] ,
2018-10-05 17:12:13 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_div_0_Template , 4 , 3 , "div" , 0 ) ;
2018-10-05 17:12:13 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngForOf" , ctx . items ) ;
2018-10-05 17:12:13 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
} ) ;
it ( 'should work correctly when placed on i18n root node' , ( ) = > {
const input = `
< div i18n i18n - title = "m|d" title = "Element title" > Some content < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
/ * *
* @desc d
* @meaning m
* /
const $MSG_EXTERNAL_7727043314656808423 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "Element title" ) ;
$I18N_0 $ = $MSG_EXTERNAL_7727043314656808423 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` :m|d:Element title \` ;
2019-04-11 05:17:49 -04:00
}
const $_c1 $ = [ "title" , $I18N_0 $ ] ;
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4969674997806975147 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "Some content" ) ;
$I18N_2 $ = $MSG_EXTERNAL_4969674997806975147 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` Some content \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c1 $ ) ;
$r3 $ . ɵ ɵ i18n ( 2 , $I18N_2 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2019-01-11 20:23:51 -05:00
2019-04-11 05:17:49 -04:00
it ( 'should sanitize ids and generate proper var names' , ( ) = > {
2019-01-11 20:23:51 -05:00
const input = `
< div i18n = "@@ID.WITH.INVALID.CHARS.2" i18n - title = "@@ID.WITH.INVALID.CHARS" title = "Element title" >
Some content
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_ID_WITH_INVALID_CHARS $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Element title" ) ;
$I18N_0 $ = $MSG_EXTERNAL_ID_WITH_INVALID_CHARS $ $APP_SPEC_TS_1 $ ;
}
else {
2019-09-13 07:46:05 -04:00
$I18N_0 $ = $localize \ ` :@@ID.WITH.INVALID.CHARS:Element title \` ;
2019-04-11 05:17:49 -04:00
}
const $_c1 $ = [ "title" , $I18N_0 $ ] ;
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_ID_WITH_INVALID_CHARS_2 $ $APP_SPEC_TS_4 $ = goog . getMsg ( " Some content " ) ;
$I18N_2 $ = $MSG_EXTERNAL_ID_WITH_INVALID_CHARS_2 $ $APP_SPEC_TS_4 $ ;
}
else {
2019-09-13 07:46:05 -04:00
$I18N_2 $ = $localize \ ` :@@ID.WITH.INVALID.CHARS.2: Some content \` ;
2019-04-11 05:17:49 -04:00
}
2019-01-11 20:23:51 -05:00
…
` ;
const exceptions = {
'ID.WITH.INVALID.CHARS' : 'Verify const name generation only' ,
'ID.WITH.INVALID.CHARS.2' : 'Verify const name generation only'
} ;
verify ( input , output , { exceptions , skipPathBasedCheck : true } ) ;
} ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2018-10-12 17:34:38 -04:00
describe ( 'nested nodes' , ( ) = > {
it ( 'should not produce instructions for empty content' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n > < / div >
< div i18n > < / div >
< div i18n >
< / div >
` ;
2018-02-14 13:54:00 -05:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ element ( 0 , "div" ) ;
$r3 $ . ɵ ɵ element ( 1 , "div" ) ;
$r3 $ . ɵ ɵ element ( 2 , "div" ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
const exceptions = {
'6524085439495453930' : 'No translation is produced for empty content (whitespaces)' ,
'814405839137385666' : 'No translation is produced for empty content (line breaks)'
} ;
verify ( input , output , { exceptions } ) ;
2018-10-12 17:34:38 -04:00
} ) ;
2019-09-04 11:27:29 -04:00
it ( 'should ignore HTML comments within translated text' , ( ) = > {
const input = `
< div i18n > Some <!-- comments -- > text < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-09-04 11:27:29 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-09-13 07:46:05 -04:00
const $MSG_APP_SPEC_TS_1 $ = goog . getMsg ( "Some text" ) ;
$I18N_0 $ = $MSG_APP_SPEC_TS_1 $ ;
2019-09-04 11:27:29 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Some text \` ;
2019-09-04 11:27:29 -04:00
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should properly escape quotes in content' , ( ) = > {
const input = `
2019-11-26 09:03:19 -05:00
< div i18n > Some text 'with single quotes' , "with double quotes" , \ ` with backticks \` and without quotes.</div>
2018-10-18 13:08:51 -04:00
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-11-26 09:03:19 -05:00
const $MSG_EXTERNAL_4924931801512133405 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "Some text 'with single quotes', \"with double quotes\" , ` +
2020-04-07 15:43:43 -04:00
'`with backticks`' + String . raw ` and without quotes.");
2019-04-11 05:17:49 -04:00
$I18N_0 $ = $MSG_EXTERNAL_4924931801512133405 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-11-26 09:03:19 -05:00
$I18N_0 $ = $localize \ ` Some text 'with single quotes', "with double quotes", \\ \` with backticks \\ \` and without quotes. \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
` ;
verify ( input , output ) ;
} ) ;
2018-10-12 17:34:38 -04:00
2019-11-26 09:03:19 -05:00
it ( 'should handle interpolations wrapped in backticks' , ( ) = > {
const input = '<div i18n>`{{ count }}`</div>' ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-11-26 09:03:19 -05:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-11-26 09:03:19 -05:00
const $MSG_APP_SPEC_TS_1 $ = goog . getMsg ( " ` +
2020-04-07 15:43:43 -04:00
'`{$interpolation}`' + String . raw ` ", { "interpolation": " \ uFFFD0 \ uFFFD" });
2019-11-26 09:03:19 -05:00
$I18N_0 $ = $MSG_APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` \\ \` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \\ \` \` ;
2019-11-26 09:03:19 -05:00
} ` ;
verify ( input , output ) ;
} ) ;
2018-10-12 17:34:38 -04:00
it ( 'should handle i18n attributes with plain-text content' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n > My i18n block # 1 < / div >
< div > My non - i18n block # 1 < / div >
< div i18n > My i18n block # 2 < / div >
< div > My non - i18n block # 2 < / div >
< div i18n > My i18n block # 3 < / div >
` ;
2018-10-12 17:34:38 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "My i18n block #1" ) ;
$I18N_0 $ = $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block #1 \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_2413150872298537152 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "My i18n block #2" ) ;
$I18N_1 $ = $MSG_EXTERNAL_2413150872298537152 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` My i18n block #2 \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_5023003143537152794 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "My i18n block #3" ) ;
$I18N_2 $ = $MSG_EXTERNAL_5023003143537152794 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` My i18n block #3 \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-12 17:34:38 -04:00
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 2 , "div" ) ;
$r3 $ . ɵ ɵ text ( 3 , "My non-i18n block #1" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 4 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 5 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 6 , "div" ) ;
$r3 $ . ɵ ɵ text ( 7 , "My non-i18n block #2" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 8 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 9 , $I18N_2 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-12 17:34:38 -04:00
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should support named interpolations' , ( ) = > {
const input = `
2019-07-08 20:37:26 -04:00
< div i18n >
Named interpolation : { { valueA // i18n(ph="PH_A") }}
Named interpolation with spaces : { { valueB // i18n(ph="PH B") }}
< / div >
2018-10-18 13:08:51 -04:00
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_7597881511811528589 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " Named interpolation: {$phA} Named interpolation with spaces: {$phB} " , {
"phA" : "\uFFFD0\uFFFD" ,
"phB" : "\uFFFD1\uFFFD"
2019-04-11 05:17:49 -04:00
} ) ;
2019-07-08 20:37:26 -04:00
$I18N_0 $ = $MSG_EXTERNAL_7597881511811528589 $ $APP_SPEC_TS_0 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Named interpolation: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:PH_A: Named interpolation with spaces: $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:PH_B: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2019-07-08 20:37:26 -04:00
vars : 2 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-07-08 20:37:26 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueA ) ( ctx . valueB ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
2018-10-12 17:34:38 -04:00
}
2018-10-18 13:08:51 -04:00
` ;
verify ( input , output ) ;
} ) ;
2018-10-12 17:34:38 -04:00
2018-11-29 19:21:16 -05:00
it ( 'should support interpolation with custom interpolation config' , ( ) = > {
const input = `
< div i18n > { % valueA % } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_6749967533321674787 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_6749967533321674787 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-11-29 19:21:16 -05:00
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-11-29 19:21:16 -05:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueA ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-11-29 19:21:16 -05:00
}
}
` ;
verify ( input , output , { inputArgs : { interpolation : [ '{%' , '%}' ] } } ) ;
} ) ;
2019-02-25 18:26:10 -05:00
it ( 'should support interpolations with complex expressions' , ( ) = > {
const input = `
< div i18n >
{ { valueA | async } }
{ { valueA ? . a ? . b } }
2019-08-24 17:02:30 -04:00
{ { valueA . getRawValue ( ) ? . getTitle ( ) } }
2019-02-25 18:26:10 -05:00
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-09-13 07:46:05 -04:00
const $MSG_APP_SPEC_TS_1 $ $APP_SPEC_TS_1 $ = goog . getMsg ( " {$interpolation} {$interpolation_1} {$interpolation_2} " , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD" ,
2019-08-24 17:02:30 -04:00
"interpolation_1" : "\uFFFD1\uFFFD" ,
"interpolation_2" : "\uFFFD2\uFFFD"
2019-04-11 05:17:49 -04:00
} ) ;
2019-09-13 07:46:05 -04:00
$I18N_0 $ = $MSG_APP_SPEC_TS_1 $ $APP_SPEC_TS_1 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: $ ` +
String . raw ` {" \ uFFFD2 \ uFFFD"}:INTERPOLATION_2: \` ;
2019-04-11 05:17:49 -04:00
}
2019-02-25 18:26:10 -05:00
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ pipe ( 2 , "async" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-02-25 18:26:10 -05:00
}
if ( rf & 2 ) {
2019-08-24 17:02:30 -04:00
var $tmp_2_0 $ = null ;
const $currVal_2 $ = ( $tmp_2_0 $ = ctx . valueA . getRawValue ( ) ) == null ? null : $tmp_2_0 $ . getTitle ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-08-24 17:02:30 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 2 , 3 , ctx . valueA ) ) ( ctx . valueA == null ? null : ctx . valueA . a == null ? null : ctx . valueA . a . b ) ( $currVal_2 $ ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2019-02-25 18:26:10 -05:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should handle i18n attributes with bindings in content' , ( ) = > {
const input = `
< div i18n > My i18n block # { { one } } < / div >
< div i18n > My i18n block # { { two | uppercase } } < / div >
< div i18n > My i18n block # { { three + four + five } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_572579892698764378 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "My i18n block #{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_572579892698764378 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_609623417156596326 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "My i18n block #{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_609623417156596326 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` My i18n block # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_3998119318957372120 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "My i18n block #{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_2 $ = $MSG_EXTERNAL_3998119318957372120 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` My i18n block # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-12 17:34:38 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 7 ,
2018-11-28 20:31:21 -05:00
vars : 5 ,
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 2 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 3 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ pipe ( 4 , "uppercase" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 5 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 6 , $I18N_2 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . one ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 3 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 4 , 3 , ctx . two ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 3 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . three + ctx . four + ctx . five ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 6 ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-12 17:34:38 -04:00
} ) ;
it ( 'should handle i18n attributes with bindings and nested elements in content' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n >
My i18n block # { { one } }
< span > Plain text in nested element < / span >
< / div >
< div i18n >
My i18n block # { { two | uppercase } }
< div >
< div >
< span >
More bindings in more nested element : { { nestedInBlockTwo } }
< / span >
< / div >
< / div >
< / div >
` ;
2018-10-12 17:34:38 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7905233330103651696 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " My i18n block #{$interpolation} {$startTagSpan}Plain text in nested element{$closeTagSpan}" , {
"interpolation" : "\uFFFD0\uFFFD" ,
"startTagSpan" : "\uFFFD#2\uFFFD" ,
"closeTagSpan" : "\uFFFD/#2\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_7905233330103651696 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_TAG_SPAN:Plain text in nested element $ ` +
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_5788821996131681377 $ $APP_SPEC_TS_1 $ = goog . getMsg ( " My i18n block #{$interpolation} {$startTagDiv}{$startTagDiv}{$startTagSpan} More bindings in more nested element: {$interpolation_1} {$closeTagSpan}{$closeTagDiv}{$closeTagDiv}" , {
"interpolation" : "\uFFFD0\uFFFD" ,
"startTagDiv" : "[\uFFFD#6\uFFFD|\uFFFD#7\uFFFD]" ,
"startTagSpan" : "\uFFFD#8\uFFFD" ,
"interpolation_1" : "\uFFFD1\uFFFD" ,
"closeTagSpan" : "\uFFFD/#8\uFFFD" ,
"closeTagDiv" : "[\uFFFD/#7\uFFFD|\uFFFD/#6\uFFFD]"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_5788821996131681377 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` My i18n block # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {"[ \ uFFFD#6 \ uFFFD| \ uFFFD#7 \ uFFFD]"}:START_TAG_DIV: $ ` +
String . raw ` {"[ \ uFFFD#6 \ uFFFD| \ uFFFD#7 \ uFFFD]"}:START_TAG_DIV: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD#8 \ uFFFD"}:START_TAG_SPAN: More bindings in more nested element: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: $ ` +
String . raw ` {" \ uFFFD/#8 \ uFFFD"}:CLOSE_TAG_SPAN: $ ` +
String . raw ` {"[ \ uFFFD/#7 \ uFFFD| \ uFFFD/#6 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
String . raw ` {"[ \ uFFFD/#7 \ uFFFD| \ uFFFD/#6 \ uFFFD]"}:CLOSE_TAG_DIV: \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ ) ;
2018-10-12 17:34:38 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 9 ,
2018-11-28 20:31:21 -05:00
vars : 5 ,
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ element ( 2 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 3 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 4 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ pipe ( 5 , "uppercase" ) ;
$r3 $ . ɵ ɵ elementStart ( 6 , "div" ) ;
$r3 $ . ɵ ɵ elementStart ( 7 , "div" ) ;
$r3 $ . ɵ ɵ element ( 8 , "span" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . one ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 6 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 5 , 3 , ctx . two ) ) ( ctx . nestedInBlockTwo ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 4 ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-12 17:34:38 -04:00
} ) ;
it ( 'should handle i18n attributes with bindings in content and element attributes' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n >
My i18n block # 1 with value : { { valueA } }
< span i18n - title title = "Span title {{ valueB }} and {{ valueC }}" >
Plain text in nested element ( block # 1 )
< / span >
< / div >
< div i18n >
My i18n block # 2 with value { { valueD | uppercase } }
< span i18n - title title = "Span title {{ valueE }}" >
Plain text in nested element ( block # 2 )
< / span >
< / div >
` ;
2018-10-12 17:34:38 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 19:51:27 -04:00
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_4782264005467235841 $ $APP_SPEC_TS_3 $ = goog . getMsg ( "Span title {$interpolation} and {$interpolation_1}" , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD" ,
"interpolation_1" : "\uFFFD1\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_2 $ = $MSG_EXTERNAL_4782264005467235841 $ $APP_SPEC_TS_3 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` Span title $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: and $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c4 $ = [ "title" , $I18N_2 $ ] ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_4446430594603971069 $ $APP_SPEC_TS_5 $ = goog . getMsg ( " My i18n block #1 with value: {$interpolation} {$startTagSpan} Plain text in nested element (block #1) {$closeTagSpan}" , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD" ,
"startTagSpan" : "\uFFFD#2\uFFFD" ,
"closeTagSpan" : "\uFFFD/#2\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_0 $ = $MSG_EXTERNAL_4446430594603971069 $ $APP_SPEC_TS_5 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block #1 with value: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD#2 \ uFFFD"}:START_TAG_SPAN: Plain text in nested element (block #1) $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
var $I18N_7 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_2719594642740200058 $ $APP_SPEC_TS_8 $ = goog . getMsg ( "Span title {$interpolation}" , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_7 $ = $MSG_EXTERNAL_2719594642740200058 $ $APP_SPEC_TS_8 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_7 $ = $localize \ ` Span title $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c9 $ = [ "title" , $I18N_7 $ ] ;
var $I18N_6 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 19:51:27 -04:00
const $MSG_EXTERNAL_2778714953278357902 $ $APP_SPEC_TS_10 $ = goog . getMsg ( " My i18n block #2 with value {$interpolation} {$startTagSpan} Plain text in nested element (block #2) {$closeTagSpan}" , {
2019-04-11 05:17:49 -04:00
"interpolation" : "\uFFFD0\uFFFD" ,
"startTagSpan" : "\uFFFD#7\uFFFD" ,
"closeTagSpan" : "\uFFFD/#7\uFFFD"
} ) ;
2019-04-11 19:51:27 -04:00
$I18N_6 $ = $MSG_EXTERNAL_2778714953278357902 $ $APP_SPEC_TS_10 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_6 $ = $localize \ ` My i18n block #2 with value $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD#7 \ uFFFD"}:START_TAG_SPAN: Plain text in nested element (block #2) $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD/#7 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-12 17:34:38 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 9 ,
2018-11-28 20:31:21 -05:00
vars : 7 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . I18n } , "title" ] ] ,
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 2 , "span" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 3 , $_c4 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementStart ( 4 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 5 , $I18N_6 $ ) ;
$r3 $ . ɵ ɵ pipe ( 6 , "uppercase" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 7 , "span" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 8 , $_c9 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueB ) ( ctx . valueC ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 3 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueA ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 4 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . valueE ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 8 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 6 , 5 , ctx . valueD ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 5 ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-12 17:34:38 -04:00
} ) ;
it ( 'should handle i18n attributes in nested templates' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div >
Some content
< div * ngIf = "visible" >
< div i18n >
Some other content { { valueA } }
< div >
More nested levels with bindings { { valueB | uppercase } }
< / div >
< / div >
< / div >
< / div >
` ;
2018-10-12 17:34:38 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7679414751795588050 $ $APP_SPEC_TS__1 $ = goog . getMsg ( " Some other content {$interpolation} {$startTagDiv} More nested levels with bindings {$interpolation_1} {$closeTagDiv}" , {
"interpolation" : "\uFFFD0\uFFFD" ,
"startTagDiv" : "\uFFFD#3\uFFFD" ,
"interpolation_1" : "\uFFFD1\uFFFD" ,
"closeTagDiv" : "\uFFFD/#3\uFFFD"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_7679414751795588050 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Some other content $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG_DIV: More nested levels with bindings $ ` +
String . raw ` {" \ uFFFD1 \ uFFFD"}:INTERPOLATION_1: $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG_DIV: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-12 17:34:38 -04:00
…
2018-12-19 15:17:38 -05:00
function MyComponent_div_2_Template ( rf , ctx ) {
2018-10-12 17:34:38 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 2 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ element ( 3 , "div" ) ;
$r3 $ . ɵ ɵ pipe ( 4 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 4 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . valueA ) ( $r3 $ . ɵ ɵ pipeBind1 ( 4 , 2 , $ctx_r0 $ . valueB ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2018-10-12 17:34:38 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ text ( 1 , " Some content " ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 2 , MyComponent_div_2_Template , 5 , 4 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
2018-10-12 17:34:38 -04:00
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should ignore i18n attributes on self-closing tags' , ( ) = > {
const input = `
< img src = "logo.png" i18n / >
< img src = "logo.png" i18n * ngIf = "visible" / >
< img src = "logo.png" i18n * ngIf = "visible" i18n - title title = "App logo #{{ id }}" / >
` ;
2018-10-12 17:34:38 -04:00
2020-04-07 15:43:43 -04:00
const output = String . raw `
2018-12-19 15:17:38 -05:00
function MyComponent_img_1_Template ( rf , ctx ) {
2018-11-16 12:57:23 -05:00
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 0 , "img" , 0 ) ;
2018-11-16 12:57:23 -05:00
}
}
2019-04-11 05:17:49 -04:00
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_2367729185105559721 $ $APP_SPEC_TS__2 $ = goog . getMsg ( "App logo #{$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_2 $ = $MSG_EXTERNAL_2367729185105559721 $ $APP_SPEC_TS__2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` App logo # $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2019-04-11 19:51:27 -04:00
const $_c4 $ = [ "title" , $I18N_2 $ ] ;
2018-12-19 15:17:38 -05:00
function MyComponent_img_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "img" , 3 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nAttributes ( 1 , $_c4 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r1 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r1 $ . id ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
2018-10-12 17:34:38 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2020-04-07 15:43:43 -04:00
consts : [ [ "src" , "logo.png" ] , [ "src" , "logo.png" , $ {
AttributeMarker . Template } , "ngIf" ] , [ "src" , "logo.png" , $ {
AttributeMarker . Bindings } , "title" , $ {
AttributeMarker . Template } , "ngIf" ] , [ "src" , "logo.png" , $ {
AttributeMarker . I18n } , "title" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 0 , "img" , 0 ) ;
$r3 $ . ɵ ɵ template ( 1 , MyComponent_img_1_Template , 1 , 0 , "img" , 1 ) ;
$r3 $ . ɵ ɵ template ( 2 , MyComponent_img_2_Template , 2 , 1 , "img" , 2 ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-12 17:34:38 -04:00
2018-10-18 13:08:51 -04:00
it ( 'should handle i18n context in nested templates' , ( ) = > {
const input = `
< div i18n >
Some content
< div * ngIf = "visible" >
Some other content { { valueA } }
< div >
More nested levels with bindings { { valueB | uppercase } }
< div * ngIf = "exists" >
Content inside sub - template { { valueC } }
< div >
Bottom level element { { valueD } }
< / div >
< / div >
< / div >
< / div >
< div * ngIf = "!visible" >
Some other content { { valueE + valueF } }
< div >
More nested levels with bindings { { valueG | uppercase } }
< / div >
< / div >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2018-12-19 15:17:38 -05:00
function MyComponent_div_2_div_4_Template ( rf , ctx ) {
2018-10-12 17:34:38 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 2 ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "div" ) ;
$r3 $ . ɵ ɵ element ( 2 , "div" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r2 $ = $r3 $ . ɵ ɵ nextContext ( 2 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r2 $ . valueC ) ( $ctx_r2 $ . valueD ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-12 17:34:38 -04:00
}
}
2018-12-19 15:17:38 -05:00
function MyComponent_div_2_Template ( rf , ctx ) {
2018-10-12 17:34:38 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "div" ) ;
$r3 $ . ɵ ɵ elementStart ( 2 , "div" ) ;
$r3 $ . ɵ ɵ pipe ( 3 , "uppercase" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 4 , MyComponent_div_2_div_4_Template , 3 , 2 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 4 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , $ctx_r0 $ . exists ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . valueA ) ( $r3 $ . ɵ ɵ pipeBind1 ( 3 , 3 , $ctx_r0 $ . valueB ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-12 17:34:38 -04:00
}
}
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_1221890473527419724 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " Some content {$startTagDiv_2} Some other content {$interpolation} {$startTagDiv} More nested levels with bindings {$interpolation_1} {$startTagDiv_1} Content inside sub-template {$interpolation_2} {$startTagDiv} Bottom level element {$interpolation_3} {$closeTagDiv}{$closeTagDiv}{$closeTagDiv}{$closeTagDiv}{$startTagDiv_3} Some other content {$interpolation_4} {$startTagDiv} More nested levels with bindings {$interpolation_5} {$closeTagDiv}{$closeTagDiv}" , {
"startTagDiv_2" : "\uFFFD*2:1\uFFFD\uFFFD#1:1\uFFFD" ,
"closeTagDiv" : "[\uFFFD/#2:2\uFFFD|\uFFFD/#1:2\uFFFD\uFFFD/*4:2\uFFFD|\uFFFD/#2:1\uFFFD|\uFFFD/#1:1\uFFFD\uFFFD/*2:1\uFFFD|\uFFFD/#2:3\uFFFD|\uFFFD/#1:3\uFFFD\uFFFD/*3:3\uFFFD]" ,
"startTagDiv_3" : "\uFFFD*3:3\uFFFD\uFFFD#1:3\uFFFD" ,
"interpolation" : "\uFFFD0:1\uFFFD" ,
"startTagDiv" : "[\uFFFD#2:1\uFFFD|\uFFFD#2:2\uFFFD|\uFFFD#2:3\uFFFD]" ,
"interpolation_1" : "\uFFFD1:1\uFFFD" ,
"startTagDiv_1" : "\uFFFD*4:2\uFFFD\uFFFD#1:2\uFFFD" ,
"interpolation_2" : "\uFFFD0:2\uFFFD" ,
"interpolation_3" : "\uFFFD1:2\uFFFD" ,
"interpolation_4" : "\uFFFD0:3\uFFFD" ,
"interpolation_5" : "\uFFFD1:3\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_1221890473527419724 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Some content $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD*2:1 \ uFFFD \ uFFFD#1:1 \ uFFFD"}:START_TAG_DIV_2: Some other content $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:1 \ uFFFD"}:INTERPOLATION: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD#2:1 \ uFFFD| \ uFFFD#2:2 \ uFFFD| \ uFFFD#2:3 \ uFFFD]"}:START_TAG_DIV: More nested levels with bindings $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD1:1 \ uFFFD"}:INTERPOLATION_1: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD*4:2 \ uFFFD \ uFFFD#1:2 \ uFFFD"}:START_TAG_DIV_1: Content inside sub-template $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:2 \ uFFFD"}:INTERPOLATION_2: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD#2:1 \ uFFFD| \ uFFFD#2:2 \ uFFFD| \ uFFFD#2:3 \ uFFFD]"}:START_TAG_DIV: Bottom level element $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD1:2 \ uFFFD"}:INTERPOLATION_3: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD*3:3 \ uFFFD \ uFFFD#1:3 \ uFFFD"}:START_TAG_DIV_3: Some other content $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:3 \ uFFFD"}:INTERPOLATION_4: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD#2:1 \ uFFFD| \ uFFFD#2:2 \ uFFFD| \ uFFFD#2:3 \ uFFFD]"}:START_TAG_DIV: More nested levels with bindings $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD1:3 \ uFFFD"}:INTERPOLATION_5: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2:2 \ uFFFD| \ uFFFD/#1:2 \ uFFFD \ uFFFD/*4:2 \ uFFFD| \ uFFFD/#2:1 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD| \ uFFFD/#2:3 \ uFFFD| \ uFFFD/#1:3 \ uFFFD \ uFFFD/*3:3 \ uFFFD]"}:CLOSE_TAG_DIV: \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_3_Template ( rf , ctx ) {
2018-10-12 17:34:38 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 3 ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "div" ) ;
$r3 $ . ɵ ɵ element ( 2 , "div" ) ;
$r3 $ . ɵ ɵ pipe ( 3 , "uppercase" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r1 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 3 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r1 $ . valueE + $ctx_r1 $ . valueF ) ( $r3 $ . ɵ ɵ pipeBind1 ( 3 , 2 , $ctx_r1 $ . valueG ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-12 17:34:38 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 4 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-12 17:34:38 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 2 , MyComponent_div_2_Template , 5 , 5 , "div" , 0 ) ;
$r3 $ . ɵ ɵ template ( 3 , MyComponent_div_3_Template , 4 , 4 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-12 17:34:38 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ! ctx . visible ) ;
2018-10-12 17:34:38 -04:00
}
}
` ;
2018-02-14 13:54:00 -05:00
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
} ) ;
it ( 'should handle i18n attribute with directives' , ( ) = > {
const input = `
< div i18n * ngIf = "visible" > Some other content < span > { { valueA } } < / span > < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_119975189388320493 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "Some other content {$startTagSpan}{$interpolation}{$closeTagSpan}" , {
"startTagSpan" : "\uFFFD#2\uFFFD" ,
"interpolation" : "\uFFFD0\uFFFD" ,
"closeTagSpan" : "\uFFFD/#2\uFFFD"
} ) ;
$I18N_1 $ = $MSG_EXTERNAL_119975189388320493 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Some other content $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_TAG_SPAN: $ ` +
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2018-12-19 15:17:38 -05:00
function MyComponent_div_0_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ element ( 2 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . valueA ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 1 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_div_0_Template , 3 , 1 , "div" , 0 ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2019-03-07 17:24:54 -05:00
it ( 'should generate event listeners instructions before i18n ones' , ( ) = > {
const input = `
< div i18n ( click ) = " onClick ( ) " > Hello < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_APP_SPEC_TS_2 $ = goog . getMsg ( "Hello" ) ;
$I18N_1 $ = $MSG_APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Hello \` ;
2019-04-11 05:17:49 -04:00
}
2019-03-07 17:24:54 -05:00
…
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Bindings } , "click" ] ] ,
2019-03-07 17:24:54 -05:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 0 ) ;
2020-02-01 07:19:31 -05:00
$r3 $ . ɵ ɵ listener ( "click" , function MyComponent_Template_div_click_0_listener() { return ctx . onClick ( ) ; } ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-03-07 17:24:54 -05:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2018-10-18 13:08:51 -04:00
describe ( 'self-closing i18n instructions' , ( ) = > {
it ( 'should be generated with text-only content' , ( ) = > {
const input = `
< div i18n > My i18n block # 1 < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "My i18n block #1" ) ;
$I18N_0 $ = $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block #1 \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
2018-02-14 13:54:00 -05:00
}
2018-10-18 13:08:51 -04:00
` ;
verify ( input , output ) ;
} ) ;
it ( 'should be generated for ICU-only i18n blocks' , ( ) = > {
const input = `
< div i18n > { age , select , 10 { ten } 20 { twenty } other { other } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
2018-02-14 13:54:00 -05:00
2018-10-18 13:08:51 -04:00
verify ( input , output ) ;
} ) ;
it ( 'should be generated within <ng-container> and <ng-template> blocks' , ( ) = > {
const input = `
< ng - template i18n > My i18n block # 1 < / n g - t e m p l a t e >
< ng - container i18n > My i18n block # 2 < / n g - c o n t a i n e r >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_2413150872298537152 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "My i18n block #2" ) ;
$I18N_0 $ = $MSG_EXTERNAL_2413150872298537152 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` My i18n block #2 \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "My i18n block #1" ) ;
$I18N_1 $ = $MSG_EXTERNAL_4890179241114413722 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` My i18n block #1 \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_0_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_1 $ ) ;
2018-10-18 13:08:51 -04:00
}
}
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_ng_template_0_Template , 1 , 0 , "ng-template" ) ;
$r3 $ . ɵ ɵ elementContainerStart ( 1 ) ;
$r3 $ . ɵ ɵ i18n ( 2 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-11-28 14:34:24 -05:00
it ( 'should not be generated in case we have styling instructions' , ( ) = > {
const input = `
< span i18n class = "myClass" > Text # 1 < / span >
< span i18n style = "padding: 10px;" > Text # 2 < / span >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_5295701706185791735 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Text #1" ) ;
$I18N_1 $ = $MSG_EXTERNAL_5295701706185791735 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Text #1 \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4722270221386399294 $ $APP_SPEC_TS_3 $ = goog . getMsg ( "Text #2" ) ;
$I18N_3 $ = $MSG_EXTERNAL_4722270221386399294 $ $APP_SPEC_TS_3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` Text #2 \` ;
2019-04-11 05:17:49 -04:00
}
2018-11-28 14:34:24 -05:00
…
2019-09-23 14:08:51 -04:00
decls : 4 ,
2018-11-28 14:34:24 -05:00
vars : 0 ,
2020-04-07 15:43:43 -04:00
consts : [ [ $ { AttributeMarker . Classes } , "myClass" ] , [ $ {
AttributeMarker . Styles } , "padding" , "10px" ] ] ,
2018-11-28 14:34:24 -05:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "span" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_1 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 2 , "span" , 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 3 , $I18N_3 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-11-28 14:34:24 -05:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
} ) ;
describe ( 'ng-container and ng-template' , ( ) = > {
it ( 'should handle single translation message using <ng-container>' , ( ) = > {
const input = `
< ng - container i18n > Some content : { { valueA | uppercase } } < / n g - c o n t a i n e r >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_355394464191978948 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "Some content: {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_355394464191978948 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Some content: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 3 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementContainerStart ( 0 ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ pipe ( 2 , "uppercase" ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 2 , 1 , ctx . valueA ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle single translation message using <ng-template>' , ( ) = > {
const input = `
< ng - template i18n > Some content : { { valueA | uppercase } } < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_355394464191978948 $ $APP_SPEC_TS__0 $ = goog . getMsg ( "Some content: {$interpolation}" , {
"interpolation" : "\uFFFD0\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_355394464191978948 $ $APP_SPEC_TS__0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Some content: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_0_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
2018-10-18 13:08:51 -04:00
} if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 1 , $ctx_r0 $ . valueA ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 1 ,
2018-11-28 20:31:21 -05:00
vars : 0 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_ng_template_0_Template , 2 , 3 , "ng-template" ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-12-26 20:36:26 -05:00
it ( 'should be able to act as child elements inside i18n block' , ( ) = > {
2018-10-18 13:08:51 -04:00
const input = `
< div i18n >
< ng - template > Template content : { { valueA | uppercase } } < / n g - t e m p l a t e >
< ng - container > Container content : { { valueB | uppercase } } < / n g - c o n t a i n e r >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_702706566400598764 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{$startTagNgTemplate}Template content: {$interpolation}{$closeTagNgTemplate}{$startTagNgContainer}Container content: {$interpolation_1}{$closeTagNgContainer}" , {
"startTagNgTemplate" : "\uFFFD*2:1\uFFFD" ,
"closeTagNgTemplate" : "\uFFFD/*2:1\uFFFD" ,
"startTagNgContainer" : "\uFFFD#3\uFFFD" ,
"interpolation_1" : "\uFFFD0\uFFFD" ,
"closeTagNgContainer" : "\uFFFD/#3\uFFFD" ,
"interpolation" : "\uFFFD0:1\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_702706566400598764 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD*2:1 \ uFFFD"}:START_TAG_NG_TEMPLATE:Template content: $ ` +
String . raw ` {" \ uFFFD0:1 \ uFFFD"}:INTERPOLATION: $ ` +
String . raw ` {" \ uFFFD/*2:1 \ uFFFD"}:CLOSE_TAG_NG_TEMPLATE: $ ` +
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG_NG_CONTAINER:Container content: $ ` +
String . raw ` {" \ uFFFD0 \ uFFFD"}:INTERPOLATION_1: $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG_NG_CONTAINER: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 1 , $ctx_r0 $ . valueA ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 5 ,
2018-11-28 20:31:21 -05:00
vars : 3 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ template ( 2 , MyComponent_ng_template_2_Template , 2 , 3 , "ng-template" ) ;
2019-07-07 10:35:58 -04:00
$r3 $ . ɵ ɵ elementContainer ( 3 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ pipe ( 4 , "uppercase" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 4 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 4 , 1 , ctx . valueB ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle ICUs outside of translatable sections' , ( ) = > {
const input = `
< ng - template > { gender , select , male { male } female { female } other { other } } < / n g - t e m p l a t e >
< ng - container > { age , select , 10 { ten } 20 { twenty } other { other } } < / n g - c o n t a i n e r >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_1 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_0_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_1 $ ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_ng_template_0_Template , 1 , 1 , "ng-template" ) ;
$r3 $ . ɵ ɵ elementContainerStart ( 1 ) ;
$r3 $ . ɵ ɵ i18n ( 2 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should correctly propagate i18n context through nested templates' , ( ) = > {
const input = `
< div i18n >
< ng - template >
Template A : { { valueA | uppercase } }
< ng - template >
Template B : { { valueB } }
< ng - template >
Template C : { { valueC } }
< / n g - t e m p l a t e >
< / n g - t e m p l a t e >
< / n g - t e m p l a t e >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_2_ng_template_2_ng_template_1_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_0 $ , 3 ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r2 $ = $r3 $ . ɵ ɵ nextContext ( 3 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r2 $ . valueC ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_2_ng_template_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 2 ) ;
$r3 $ . ɵ ɵ template ( 1 , MyComponent_ng_template_2_ng_template_2_ng_template_1_Template , 1 , 1 , "ng-template" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r1 $ = $r3 $ . ɵ ɵ nextContext ( 2 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r1 $ . valueB ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_2051477021417799640 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{$startTagNgTemplate} Template A: {$interpolation} {$startTagNgTemplate} Template B: {$interpolation_1} {$startTagNgTemplate} Template C: {$interpolation_2} {$closeTagNgTemplate}{$closeTagNgTemplate}{$closeTagNgTemplate}" , {
"startTagNgTemplate" : "[\uFFFD*2:1\uFFFD|\uFFFD*2:2\uFFFD|\uFFFD*1:3\uFFFD]" ,
"closeTagNgTemplate" : "[\uFFFD/*1:3\uFFFD|\uFFFD/*2:2\uFFFD|\uFFFD/*2:1\uFFFD]" ,
"interpolation" : "\uFFFD0:1\uFFFD" ,
"interpolation_1" : "\uFFFD0:2\uFFFD" ,
"interpolation_2" : "\uFFFD0:3\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_2051477021417799640 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD*2:1 \ uFFFD| \ uFFFD*2:2 \ uFFFD| \ uFFFD*1:3 \ uFFFD]"}:START_TAG_NG_TEMPLATE: Template A: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:1 \ uFFFD"}:INTERPOLATION: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD*2:1 \ uFFFD| \ uFFFD*2:2 \ uFFFD| \ uFFFD*1:3 \ uFFFD]"}:START_TAG_NG_TEMPLATE: Template B: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:2 \ uFFFD"}:INTERPOLATION_1: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD*2:1 \ uFFFD| \ uFFFD*2:2 \ uFFFD| \ uFFFD*1:3 \ uFFFD]"}:START_TAG_NG_TEMPLATE: Template C: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD0:3 \ uFFFD"}:INTERPOLATION_2: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/*1:3 \ uFFFD| \ uFFFD/*2:2 \ uFFFD| \ uFFFD/*2:1 \ uFFFD]"}:CLOSE_TAG_NG_TEMPLATE: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/*1:3 \ uFFFD| \ uFFFD/*2:2 \ uFFFD| \ uFFFD/*2:1 \ uFFFD]"}:CLOSE_TAG_NG_TEMPLATE: $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/*1:3 \ uFFFD| \ uFFFD/*2:2 \ uFFFD| \ uFFFD/*2:1 \ uFFFD]"}:CLOSE_TAG_NG_TEMPLATE: \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ pipe ( 1 , "uppercase" ) ;
$r3 $ . ɵ ɵ template ( 2 , MyComponent_ng_template_2_ng_template_2_Template , 2 , 1 , "ng-template" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $r3 $ . ɵ ɵ pipeBind1 ( 1 , 1 , $ctx_r0 $ . valueA ) ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 0 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ template ( 2 , MyComponent_ng_template_2_Template , 3 , 3 , "ng-template" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should work with ICUs' , ( ) = > {
const input = `
< ng - container i18n > { gender , select , male { male } female { female } other { other } } < / n g - c o n t a i n e r >
< ng - template i18n > { age , select , 10 { ten } 20 { twenty } other { other } } < / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS__1 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}" ) ;
$I18N_1 $ = $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS__1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_1 $ ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementContainerStart ( 0 ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
$r3 $ . ɵ ɵ template ( 2 , MyComponent_ng_template_2_Template , 1 , 1 , "ng-template" ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle self-closing tags as content' , ( ) = > {
const input = `
< ng - container i18n >
2018-11-16 12:57:23 -05:00
< img src = "logo.png" title = "Logo" / > is my logo # 1
2018-10-18 13:08:51 -04:00
< / n g - c o n t a i n e r >
< ng - template i18n >
2018-11-16 12:57:23 -05:00
< img src = "logo.png" title = "Logo" / > is my logo # 2
2018-10-18 13:08:51 -04:00
< / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4891196282781544695 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{$tagImg} is my logo #1 " , {
"tagImg" : "\uFFFD#2\uFFFD\uFFFD/#2\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_4891196282781544695 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#2 \ uFFFD \ uFFFD/#2 \ uFFFD"}:TAG_IMG: is my logo #1 \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_461986953980355147 $ $APP_SPEC_TS__2 $ = goog . getMsg ( "{$tagImg} is my logo #2 " , {
"tagImg" : "\uFFFD#1\uFFFD\uFFFD/#1\uFFFD"
} ) ;
$I18N_2 $ = $MSG_EXTERNAL_461986953980355147 $ $APP_SPEC_TS__2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#1 \ uFFFD \ uFFFD/#1 \ uFFFD"}:TAG_IMG: is my logo #2 \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_ng_template_3_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_2 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 1 , "img" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
consts : [ [ "src" , "logo.png" , "title" , "Logo" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementContainerStart ( 0 ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ element ( 2 , "img" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
$r3 $ . ɵ ɵ template ( 3 , MyComponent_ng_template_3_Template , 2 , 0 , "ng-template" ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2019-02-25 15:42:50 -05:00
it ( 'should not emit duplicate i18n consts for nested <ng-container>s' , ( ) = > {
const input = `
< ng - template i18n >
Root content
< ng - container * ngIf = "visible" >
Nested content
< / n g - c o n t a i n e r >
< / n g - t e m p l a t e >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8537814667662432133 $ $APP_SPEC_TS__0 $ = goog . getMsg ( " Root content {$startTagNgContainer} Nested content {$closeTagNgContainer}" , {
"startTagNgContainer" : "\uFFFD*1:1\uFFFD\uFFFD#1:1\uFFFD" ,
"closeTagNgContainer" : "\uFFFD/#1:1\uFFFD\uFFFD/*1:1\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_8537814667662432133 $ $APP_SPEC_TS__0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Root content $ ` +
2019-07-30 13:02:17 -04:00
String . raw
2019-09-06 07:26:48 -04:00
` {" \ uFFFD*1:1 \ uFFFD \ uFFFD#1:1 \ uFFFD"}:START_TAG_NG_CONTAINER: Nested content $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD/#1:1 \ uFFFD \ uFFFD/*1:1 \ uFFFD"}:CLOSE_TAG_NG_CONTAINER: \` ;
2019-04-11 05:17:49 -04:00
}
2019-02-25 15:42:50 -05:00
…
` ;
verify ( input , output ) ;
} ) ;
it ( 'should not emit duplicate i18n consts for elements with the same content' , ( ) = > {
const input = `
< div i18n > Test < / div >
< div i18n > Test < / div >
` ;
2019-10-02 13:17:56 -04:00
// TODO(FW-635): currently we generate unique consts for each i18n block even though it
// might contain the same content. This should be optimized by translation statements caching,
// that can be implemented in the future within FW-635.
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_6563391987554512024 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "Test" ) ;
$I18N_0 $ = $MSG_EXTERNAL_6563391987554512024 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Test \` ;
2019-04-11 05:17:49 -04:00
}
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_6563391987554512024 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "Test" ) ;
$I18N_1 $ = $MSG_EXTERNAL_6563391987554512024 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Test \` ;
2019-04-11 05:17:49 -04:00
}
2019-02-25 15:42:50 -05:00
…
` ;
verify ( input , output ) ;
} ) ;
2019-07-07 10:35:58 -04:00
it ( 'should generate a self-closing container instruction for ng-container inside i18n' , ( ) = > {
const input = `
< div i18n >
Hello < ng - container > there < / n g - c o n t a i n e r >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-07-07 10:35:58 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-07 10:35:58 -04:00
const $MSG_APP_SPEC_TS_1 $ = goog . getMsg ( " Hello {$startTagNgContainer}there{$closeTagNgContainer}" , { "startTagNgContainer" : "\uFFFD#2\uFFFD" , "closeTagNgContainer" : "\uFFFD/#2\uFFFD" } ) ;
$I18N_0 $ = $MSG_APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Hello $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_TAG_NG_CONTAINER:there $ ` +
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_TAG_NG_CONTAINER: \` ;
2019-07-07 10:35:58 -04:00
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2019-07-07 10:35:58 -04:00
vars : 0 ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , I18N_0 ) ;
$r3 $ . ɵ ɵ elementContainer ( 2 ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should not generate a self-closing container instruction for ng-container with non-text content inside i18n' ,
( ) = > {
const input = `
< div i18n >
Hello < ng - container > there < strong > ! < / strong > < / n g - c o n t a i n e r >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-07-07 10:35:58 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-07 10:35:58 -04:00
const $MSG_APP_SPEC_TS_1 $ = goog . getMsg ( " Hello {$startTagNgContainer}there {$startTagStrong}!{$closeTagStrong}{$closeTagNgContainer}" , { "startTagNgContainer" : "\uFFFD#2\uFFFD" , "startTagStrong" : "\uFFFD#3\uFFFD" , "closeTagStrong" : "\uFFFD/#3\uFFFD" , "closeTagNgContainer" : "\uFFFD/#2\uFFFD" } ) ;
$I18N_0 $ = $MSG_APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` Hello $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_TAG_NG_CONTAINER:there $ ` +
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG_STRONG:! $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG_STRONG: $ ` +
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_TAG_NG_CONTAINER: \` ;
2019-07-07 10:35:58 -04:00
}
…
2019-09-23 14:08:51 -04:00
decls : 4 ,
2019-07-07 10:35:58 -04:00
vars : 0 ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , I18N_0 ) ;
$r3 $ . ɵ ɵ elementContainerStart ( 2 ) ;
$r3 $ . ɵ ɵ element ( 3 , "strong" ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2019-09-11 17:00:59 -04:00
// Note: applying structural directives to <ng-template> is typically user error, but it is
// technically allowed, so we need to support it.
it ( 'should handle structural directives' , ( ) = > {
const input = `
< ng - template * ngIf = "someFlag" i18n > Content A < / n g - t e m p l a t e >
< ng - container * ngIf = "someFlag" i18n > Content B < / n g - c o n t a i n e r >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-09-11 17:00:59 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-09-11 17:00:59 -04:00
const $MSG_EXTERNAL_3308216566145348998 $ $APP_SPEC_TS___2 $ = goog . getMsg ( "Content A" ) ;
$I18N_1 $ = $MSG_EXTERNAL_3308216566145348998 $ $APP_SPEC_TS___2 $ ;
} else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` Content A \` ;
2019-09-11 17:00:59 -04:00
}
function MyComponent_0_ng_template_0_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_1 $ ) ;
}
}
function MyComponent_0_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_ng_template_0_Template , 1 , 0 , "ng-template" ) ;
}
}
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-09-11 17:00:59 -04:00
const $MSG_EXTERNAL_8349021389088127654 $ $APP_SPEC_TS__4 $ = goog . getMsg ( "Content B" ) ;
$I18N_3 $ = $MSG_EXTERNAL_8349021389088127654 $ $APP_SPEC_TS__4 $ ;
} else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` Content B \` ;
2019-09-11 17:00:59 -04:00
}
function MyComponent_ng_container_1_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ elementContainerStart ( 0 ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_3 $ ) ;
$r3 $ . ɵ ɵ elementContainerEnd ( ) ;
}
}
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2019-09-11 17:00:59 -04:00
vars : 2 ,
2019-09-23 14:08:51 -04:00
consts : [ [ 4 , "ngIf" ] ] ,
2019-09-11 17:00:59 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 0 , MyComponent_0_Template , 1 , 0 , undefined , 0 ) ;
$r3 $ . ɵ ɵ template ( 1 , MyComponent_ng_container_1_Template , 2 , 0 , "ng-container" , 0 ) ;
2019-09-11 17:00:59 -04:00
}
if ( rf & 2 ) {
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . someFlag ) ;
$r3 $ . ɵ ɵ advance ( 1 ) ;
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . someFlag ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
} ) ;
describe ( 'whitespace preserving mode' , ( ) = > {
it ( 'should keep inner content of i18n block as is' , ( ) = > {
const input = `
< div i18n >
Some text
< span > Text inside span < / span >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_963542717423364282 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "\n Some text\n {$startTagSpan}Text inside span{$closeTagSpan}\n " , {
"startTagSpan" : "\uFFFD#3\uFFFD" ,
"closeTagSpan" : "\uFFFD/#3\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_963542717423364282 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-01 19:44:50 -04:00
$I18N_0 $ = $localize \ `
Some text
$ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG_SPAN:Text inside span $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG_SPAN:
2019-10-01 19:44:50 -04:00
\ ` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ text ( 0 , "\n " ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 2 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ element ( 3 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ text ( 4 , "\n " ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output , { inputArgs : { preserveWhitespaces : true } } ) ;
} ) ;
} ) ;
describe ( 'icu logic' , ( ) = > {
it ( 'should handle single icus' , ( ) = > {
const input = `
< div i18n > { gender , select , male { male } female { female } other { other } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should properly escape quotes in content' , ( ) = > {
const input = `
< div i18n > { gender , select , single { 'single quotes' } double { "double quotes" } other { other } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_4166854826696768832 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, single {'single quotes'} double {\"double quotes\"} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_4166854826696768832 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, single {'single quotes'} double {"double quotes"} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-10-18 13:08:51 -04:00
` ;
verify ( input , output ) ;
} ) ;
2019-01-13 19:56:00 -05:00
it ( 'should support ICU-only templates' , ( ) = > {
const input = `
{ age , select , 10 { ten } 20 { twenty } other { other } }
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2019-04-11 05:17:49 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-01-13 19:56:00 -05:00
…
2019-09-23 14:08:51 -04:00
decls : 1 ,
2019-01-13 19:56:00 -05:00
vars : 1 ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18n ( 0 , $I18N_0 $ ) ;
2019-01-13 19:56:00 -05:00
}
if ( rf & 2 ) {
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2019-01-13 19:56:00 -05:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should generate i18n instructions for icus generated outside of i18n blocks' , ( ) = > {
const input = `
< div > { gender , select , male { male } female { female } other { other } } < / div >
< div * ngIf = "visible" title = "icu only" >
{ age , select , 10 { ten } 20 { twenty } other { other } }
< / div >
< div * ngIf = "available" title = "icu and text" >
You have { count , select , 0 { no emails } 1 { one email } other { { { count } } emails } } .
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS__3 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}" ) ;
$I18N_3 $ = $MSG_EXTERNAL_8806993169187953163 $ $APP_SPEC_TS__3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_3 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_3 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 2 ) ;
2019-08-24 17:02:30 -04:00
$r3 $ . ɵ ɵ text ( 1 , " " ) ;
2019-08-02 07:42:04 -04:00
$r3 $ . ɵ ɵ i18n ( 2 , $I18N_3 $ ) ;
2019-08-24 17:02:30 -04:00
$r3 $ . ɵ ɵ text ( 3 , " " ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . age ) ;
2019-08-02 07:42:04 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2018-10-18 13:08:51 -04:00
}
}
2019-04-11 05:17:49 -04:00
var $I18N_5 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_1922743304863699161 $ $APP_SPEC_TS__5 $ = goog . getMsg ( "{VAR_SELECT, select, 0 {no emails} 1 {one email} other {{INTERPOLATION} emails}}" ) ;
2019-04-11 05:17:49 -04:00
$I18N_5 $ = $MSG_EXTERNAL_1922743304863699161 $ $APP_SPEC_TS__5 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_5 $ = $localize \ ` {VAR_SELECT, select, 0 {no emails} 1 {one email} other {{INTERPOLATION} emails}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_5 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_5 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"INTERPOLATION" : "\uFFFD1\uFFFD"
2018-11-16 12:57:23 -05:00
} ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_3_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" , 3 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ text ( 1 , " You have " ) ;
$r3 $ . ɵ ɵ i18n ( 2 , $I18N_5 $ ) ;
$r3 $ . ɵ ɵ text ( 3 , ". " ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r1 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r1 $ . count ) ( $ctx_r1 $ . count ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 2 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 4 ,
2018-11-28 20:31:21 -05:00
vars : 3 ,
2020-04-07 15:43:43 -04:00
consts : [ [ "title" , "icu only" , $ {
AttributeMarker . Template } , "ngIf" ] , [ "title" , "icu and text" , $ {
AttributeMarker . Template } , "ngIf" ] , [ "title" , "icu only" ] , [ "title" , "icu and text" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 2 , MyComponent_div_2_Template , 4 , 1 , "div" , 0 ) ;
$r3 $ . ɵ ɵ template ( 3 , MyComponent_div_3_Template , 4 , 2 , "div" , 1 ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . available ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-11-29 19:21:16 -05:00
it ( 'should support interpolation with custom interpolation config' , ( ) = > {
const input = `
< div i18n > { age , select , 10 { ten } 20 { twenty } other { { % other % } } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_2949673783721159566 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} other {{INTERPOLATION}}}" ) ;
2019-04-11 05:17:49 -04:00
$I18N_0 $ = $MSG_EXTERNAL_2949673783721159566 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} other {{INTERPOLATION}}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"INTERPOLATION" : "\uFFFD1\uFFFD"
2018-11-29 19:21:16 -05:00
} ) ;
…
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-11-29 19:21:16 -05:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . age ) ( ctx . other ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-11-29 19:21:16 -05:00
}
}
` ;
2019-05-09 14:47:25 -04:00
2018-11-29 19:21:16 -05:00
verify ( input , output , { inputArgs : { interpolation : [ '{%' , '%}' ] } } ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should handle icus with html' , ( ) = > {
const input = `
< div i18n >
{ gender , select , male { male - < b > male < / b > } female { female < b > female < / b > } other { < div class = "other" > < i > other < / i > < / div > } }
< b > Other content < / b >
< div class = "other" > < i > Another content < / i > < / div >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_2417296354340576868 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male - {START_BOLD_TEXT}male{CLOSE_BOLD_TEXT}} female {female {START_BOLD_TEXT}female{CLOSE_BOLD_TEXT}} other {{START_TAG_DIV}{START_ITALIC_TEXT}other{CLOSE_ITALIC_TEXT}{CLOSE_TAG_DIV}}}" ) ;
2019-04-11 05:17:49 -04:00
$I18N_1 $ = $MSG_EXTERNAL_2417296354340576868 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male - {START_BOLD_TEXT}male{CLOSE_BOLD_TEXT}} female {female {START_BOLD_TEXT}female{CLOSE_BOLD_TEXT}} other {{START_TAG_DIV}{START_ITALIC_TEXT}other{CLOSE_ITALIC_TEXT}{CLOSE_TAG_DIV}}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"START_BOLD_TEXT" : "<b>" ,
"CLOSE_BOLD_TEXT" : "</b>" ,
"START_ITALIC_TEXT" : "<i>" ,
"CLOSE_ITALIC_TEXT" : "</i>" ,
"START_TAG_DIV" : "<div class=\"other\">" ,
"CLOSE_TAG_DIV" : "</div>"
2018-11-16 12:57:23 -05:00
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_EXTERNAL_5791551881115084301 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " {$icu} {$startBoldText}Other content{$closeBoldText}{$startTagDiv}{$startItalicText}Another content{$closeItalicText}{$closeTagDiv}" , {
2019-04-11 05:17:49 -04:00
"startBoldText" : "\uFFFD#2\uFFFD" ,
"closeBoldText" : "\uFFFD/#2\uFFFD" ,
"startTagDiv" : "\uFFFD#3\uFFFD" ,
"startItalicText" : "\uFFFD#4\uFFFD" ,
"closeItalicText" : "\uFFFD/#4\uFFFD" ,
"closeTagDiv" : "\uFFFD/#3\uFFFD" ,
2019-05-21 15:59:53 -04:00
"icu" : $I18N_1 $
2019-04-11 05:17:49 -04:00
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_5791551881115084301 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` { $ I18N_1 $ }:ICU: $ ` +
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_BOLD_TEXT:Other content $ ` +
String . raw ` {" \ uFFFD/#2 \ uFFFD"}:CLOSE_BOLD_TEXT: $ ` +
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG_DIV: $ ` +
String . raw ` {" \ uFFFD#4 \ uFFFD"}:START_ITALIC_TEXT:Another content $ ` +
String . raw ` {" \ uFFFD/#4 \ uFFFD"}:CLOSE_ITALIC_TEXT: $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG_DIV: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 5 ,
2018-11-28 20:31:21 -05:00
vars : 1 ,
2019-09-23 14:08:51 -04:00
consts : [ [ 1 , "other" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ element ( 2 , "b" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ elementStart ( 3 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ element ( 4 , "i" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 4 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle icus with expressions' , ( ) = > {
const input = `
< div i18n > { gender , select , male { male of age : { { ageA + ageB + ageC } } } female { female } other { other } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_6879461626778511059 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, male {male of age: {INTERPOLATION}} female {female} other {other}}" ) ;
2019-04-11 05:17:49 -04:00
$I18N_0 $ = $MSG_EXTERNAL_6879461626778511059 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, male {male of age: {INTERPOLATION}} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"INTERPOLATION" : "\uFFFD1\uFFFD"
2018-11-16 12:57:23 -05:00
} ) ;
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ( ctx . ageA + ctx . ageB + ctx . ageC ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle multiple icus in one block' , ( ) = > {
const input = `
< div i18n >
{ gender , select , male { male } female { female } other { other } }
{ age , select , 10 { ten } 20 { twenty } 30 { thirty } other { other } }
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_1 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7068143081688428291 $ $APP_SPEC_TS_2 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}" ) ;
$I18N_2 $ = $MSG_EXTERNAL_7068143081688428291 $ $APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_2 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_2 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD1\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_EXTERNAL_2967249209167308918 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " {$icu} {$icu_1} " , {
2019-04-11 05:17:49 -04:00
"icu" : $I18N_1 $ ,
"icu_1" : $I18N_2 $
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_2967249209167308918 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` { $ I18N_1 $ }:ICU: $ ` + String . raw ` { $ I18N_2 $ }:ICU_1: \` ;
2019-04-11 05:17:49 -04:00
}
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ( ctx . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle multiple icus that share same placeholder' , ( ) = > {
const input = `
< div i18n >
{ gender , select , male { male } female { female } other { other } }
< div >
{ gender , select , male { male } female { female } other { other } }
< / div >
< div * ngIf = "visible" >
{ gender , select , male { male } female { female } other { other } }
< / div >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_1 $ = $MSG_APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_2 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_APP_SPEC_TS_2 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_2 $ = $MSG_APP_SPEC_TS_2 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_2 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_2 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_2 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD1\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_4 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_APP_SPEC_TS__4 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_4 $ = $MSG_APP_SPEC_TS__4 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_4 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_4 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_4 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0:1\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_APP_SPEC_TS_0 $ = goog . getMsg ( " {$icu} {$startTagDiv} {$icu} {$closeTagDiv}{$startTagDiv_1} {$icu} {$closeTagDiv}" , {
2019-04-11 05:17:49 -04:00
"startTagDiv" : "\uFFFD#2\uFFFD" ,
"closeTagDiv" : "[\uFFFD/#2\uFFFD|\uFFFD/#1:1\uFFFD\uFFFD/*3:1\uFFFD]" ,
"startTagDiv_1" : "\uFFFD*3:1\uFFFD\uFFFD#1:1\uFFFD" ,
"icu" : "\uFFFDI18N_EXP_ICU\uFFFD"
} ) ;
$I18N_0 $ = $MSG_APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFDI18N_EXP_ICU \ uFFFD"}:ICU: $ ` +
String . raw ` {" \ uFFFD#2 \ uFFFD"}:START_TAG_DIV: $ ` +
String . raw ` {" \ uFFFDI18N_EXP_ICU \ uFFFD"}:ICU: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*3:1 \ uFFFD]"}:CLOSE_TAG_DIV: $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {" \ uFFFD*3:1 \ uFFFD \ uFFFD#1:1 \ uFFFD"}:START_TAG_DIV_1: $ ` +
String . raw ` {" \ uFFFDI18N_EXP_ICU \ uFFFD"}:ICU: $ ` + String . raw
2019-09-06 07:26:48 -04:00
` {"[ \ uFFFD/#2 \ uFFFD| \ uFFFD/#1:1 \ uFFFD \ uFFFD/*3:1 \ uFFFD]"}:CLOSE_TAG_DIV: \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2019-04-11 05:17:49 -04:00
"ICU" : [ $I18N_1 $ , $I18N_2 $ , $I18N_4 $ ]
2018-10-18 13:08:51 -04:00
} ) ;
2018-12-19 15:17:38 -05:00
function MyComponent_div_3_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ element ( 1 , "div" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 4 ,
2018-11-28 20:31:21 -05:00
vars : 3 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ element ( 2 , "div" ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 3 , MyComponent_div_3_Template , 2 , 1 , "div" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 3 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . visible ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
2018-11-16 12:57:23 -05:00
// TODO(akushnir): this use-case is currently supported with
// file-based prefix for translation const names. Translation statements
// caching is required to support this use-case (FW-635) with id-based consts.
verify ( input , output , { skipIdBasedCheck : true } ) ;
2018-10-18 13:08:51 -04:00
} ) ;
it ( 'should handle nested icus' , ( ) = > {
const input = `
< div i18n >
{ gender , select ,
male { male of age : { age , select , 10 { ten } 20 { twenty } 30 { thirty } other { other } } }
female { female }
other { other }
}
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-08-02 07:42:04 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_343563413083115114 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT_1, select, male {male of age: {VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}} female {female} other {other}}" ) ;
2019-08-02 07:42:04 -04:00
$I18N_1 $ = $MSG_EXTERNAL_343563413083115114 $ $APP_SPEC_TS_0 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT_1, select, male {male of age: {VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-08-02 07:42:04 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-10-18 13:08:51 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"VAR_SELECT_1" : "\uFFFD1\uFFFD"
} ) ;
2019-08-02 07:42:04 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_EXTERNAL_3052001905251380936 $ $APP_SPEC_TS_3 $ = goog . getMsg ( " {$icu} " , { "icu" : $I18N_1 $ } ) ;
$I18N_0 $ = $MSG_EXTERNAL_3052001905251380936 $ $APP_SPEC_TS_3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` { $ I18N_1 $ }:ICU: \` ;
2019-08-02 07:42:04 -04:00
} …
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . age ) ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
const exceptions = {
'3052001905251380936' : 'Wrapper message generated by "ng xi18n" around ICU: " {$ICU} "'
} ;
2018-12-04 23:54:42 -05:00
verify ( input , output , { exceptions } ) ;
2018-10-18 13:08:51 -04:00
} ) ;
2019-07-11 14:59:22 -04:00
it ( 'nested with interpolations in "other" blocks' , ( ) = > {
const input = `
< div i18n > { count , plural ,
= 0 { zero }
= 2 { { { count } } { name , select ,
cat { cats }
dog { dogs }
other { animals } } ! }
other { other - { { count } } }
} < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-07-11 14:59:22 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-11 14:59:22 -04:00
const $MSG_EXTERNAL_6870293071705078389 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_PLURAL, plural, =0 {zero} =2 {{INTERPOLATION} {VAR_SELECT, select, cat {cats} dog {dogs} other {animals}} !} other {other - {INTERPOLATION}}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_6870293071705078389 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_PLURAL, plural, =0 {zero} =2 {{INTERPOLATION} {VAR_SELECT, select, cat {cats} dog {dogs} other {animals}} !} other {other - {INTERPOLATION}}} \` ;
2019-07-11 14:59:22 -04:00
}
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"VAR_PLURAL" : "\uFFFD1\uFFFD" ,
"INTERPOLATION" : "\uFFFD2\uFFFD"
} ) ;
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2019-07-11 14:59:22 -04:00
vars : 3 ,
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-07-11 14:59:22 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . name ) ( ctx . count ) ( ctx . count ) ;
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
it ( 'should handle icus in different contexts' , ( ) = > {
const input = `
< div i18n >
{ gender , select , male { male } female { female } other { other } }
< span * ngIf = "ageVisible" >
{ age , select , 10 { ten } 20 { twenty } 30 { thirty } other { other } }
< / span >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male} female {female} other {other}}" ) ;
$I18N_1 $ = $MSG_EXTERNAL_7842238767399919809 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male} female {female} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-04-11 05:17:49 -04:00
const $MSG_EXTERNAL_7068143081688428291 $ $APP_SPEC_TS__3 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}" ) ;
$I18N_3 $ = $MSG_EXTERNAL_7068143081688428291 $ $APP_SPEC_TS__3 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_3 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_3 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_3 $ , {
2018-11-16 12:57:23 -05:00
"VAR_SELECT" : "\uFFFD0:1\uFFFD"
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_EXTERNAL_1194472282609532229 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " {$icu} {$startTagSpan} {$icu_1} {$closeTagSpan}" , {
2019-04-11 05:17:49 -04:00
"startTagSpan" : "\uFFFD*2:1\uFFFD\uFFFD#1:1\uFFFD" ,
"closeTagSpan" : "\uFFFD/#1:1\uFFFD\uFFFD/*2:1\uFFFD" ,
"icu" : $I18N_1 $ ,
"icu_1" : $I18N_3 $
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_1194472282609532229 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` { $ I18N_1 $ }:ICU: $ ` +
String . raw ` {" \ uFFFD*2:1 \ uFFFD \ uFFFD#1:1 \ uFFFD"}:START_TAG_SPAN: $ ` +
String . raw ` { $ I18N_3 $ }:ICU_1: $ ` +
String . raw ` {" \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_span_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ element ( 1 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 2 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 2 , MyComponent_span_2_Template , 2 , 1 , "span" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . ageVisible ) ;
2019-06-17 11:07:44 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle icus with interpolations' , ( ) = > {
const input = `
< div i18n >
{ gender , select , male { male { { weight } } } female { female { { height } } } other { other } }
< span * ngIf = "ageVisible" >
{ age , select , 10 { ten } 20 { twenty } 30 { thirty } other { other : { { otherAge } } } }
< / span >
< / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_1 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_7825031864601787094 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, male {male {INTERPOLATION}} female {female {INTERPOLATION_1}} other {other}}" ) ;
2019-04-11 05:17:49 -04:00
$I18N_1 $ = $MSG_EXTERNAL_7825031864601787094 $ $APP_SPEC_TS_1 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_1 $ = $localize \ ` {VAR_SELECT, select, male {male {INTERPOLATION}} female {female {INTERPOLATION_1}} other {other}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_1 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_1 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"INTERPOLATION" : "\uFFFD1\uFFFD" ,
"INTERPOLATION_1" : "\uFFFD2\uFFFD"
2018-11-16 12:57:23 -05:00
} ) ;
2019-09-23 14:08:51 -04:00
var $I18N_3 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_2310343208266678305 $ $APP_SPEC_TS__3 $ = goog . getMsg ( "{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other: {INTERPOLATION}}}" ) ;
2019-09-23 14:08:51 -04:00
$I18N_3 $ = $MSG_EXTERNAL_2310343208266678305 $ $APP_SPEC_TS__3 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_4 $ = $localize \ ` {VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other: {INTERPOLATION}}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-09-23 14:08:51 -04:00
$I18N_3 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_3 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0:1\uFFFD" ,
"INTERPOLATION" : "\uFFFD1:1\uFFFD"
2018-11-16 12:57:23 -05:00
} ) ;
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-08-02 07:42:04 -04:00
const $MSG_EXTERNAL_7186042105600518133 $ $APP_SPEC_TS_0 $ = goog . getMsg ( " {$icu} {$startTagSpan} {$icu_1} {$closeTagSpan}" , {
2019-04-11 05:17:49 -04:00
"startTagSpan" : "\uFFFD*2:1\uFFFD\uFFFD#1:1\uFFFD" ,
"closeTagSpan" : "\uFFFD/#1:1\uFFFD\uFFFD/*2:1\uFFFD" ,
"icu" : $I18N_1 $ ,
2019-09-23 14:08:51 -04:00
"icu_1" : $I18N_3 $
2019-04-11 05:17:49 -04:00
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_7186042105600518133 $ $APP_SPEC_TS_0 $ ;
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` $ ` +
2020-04-07 15:43:43 -04:00
String . raw ` {I18N_1}:ICU: $ ` +
String . raw ` {" \ uFFFD*2:1 \ uFFFD \ uFFFD#1:1 \ uFFFD"}:START_TAG_SPAN: $ ` +
String . raw ` {I18N_3}:ICU_1: $ ` +
String . raw ` {" \ uFFFD/#1:1 \ uFFFD \ uFFFD/*2:1 \ uFFFD"}:CLOSE_TAG_SPAN: \` ;
2019-04-11 05:17:49 -04:00
}
2018-12-19 15:17:38 -05:00
function MyComponent_span_2_Template ( rf , ctx ) {
2018-10-18 13:08:51 -04:00
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nStart ( 0 , $I18N_0 $ , 1 ) ;
$r3 $ . ɵ ɵ element ( 1 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-05-17 21:49:21 -04:00
const $ctx_r0 $ = $r3 $ . ɵ ɵ nextContext ( ) ;
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( $ctx_r0 $ . age ) ( $ctx_r0 $ . otherAge ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 0 ) ;
2018-10-18 13:08:51 -04:00
}
}
…
2019-09-23 14:08:51 -04:00
decls : 3 ,
2018-11-28 20:31:21 -05:00
vars : 4 ,
2019-09-23 14:08:51 -04:00
consts : [ [ $ { AttributeMarker . Template } , "ngIf" ] ] ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18nStart ( 1 , $I18N_0 $ ) ;
2019-09-23 14:08:51 -04:00
$r3 $ . ɵ ɵ template ( 2 , MyComponent_span_2_Template , 2 , 2 , "span" , 0 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-09-06 17:43:16 -04:00
$r3 $ . ɵ ɵ advance ( 2 ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ property ( "ngIf" , ctx . ageVisible ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ( ctx . weight ) ( ctx . height ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle icus with named interpolations' , ( ) = > {
const input = `
< div i18n > {
gender ,
select ,
male { male { { weight // i18n(ph="PH_A") }}}
female { female { { height // i18n(ph="PH_B") }}}
2019-07-08 20:37:26 -04:00
other { other { { age // i18n(ph="PH WITH SPACES") }}}
2018-10-18 13:08:51 -04:00
} < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-04-11 05:17:49 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-07-08 20:37:26 -04:00
const $MSG_EXTERNAL_6318060397235942326 $ $APP_SPEC_TS_0 $ = goog . getMsg ( "{VAR_SELECT, select, male {male {PH_A}} female {female {PH_B}} other {other {PH_WITH_SPACES}}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_6318060397235942326 $ $APP_SPEC_TS_0 $ ;
2019-04-11 05:17:49 -04:00
}
else {
2019-10-02 13:17:56 -04:00
$I18N_0 $ = $localize \ ` {VAR_SELECT, select, male {male {PH_A}} female {female {PH_B}} other {other {PH_WITH_SPACES}}} \` ;
2019-04-11 05:17:49 -04:00
}
2019-05-17 21:49:21 -04:00
$I18N_0 $ = $r3 $ . ɵ ɵ i18nPostprocess ( $I18N_0 $ , {
2019-07-08 20:37:26 -04:00
"VAR_SELECT" : "\uFFFD0\uFFFD" ,
"PH_A" : "\uFFFD1\uFFFD" ,
"PH_B" : "\uFFFD2\uFFFD" ,
"PH_WITH_SPACES" : "\uFFFD3\uFFFD"
2018-11-16 12:57:23 -05:00
} ) ;
2018-10-18 13:08:51 -04:00
…
2019-09-23 14:08:51 -04:00
decls : 2 ,
2018-11-28 20:31:21 -05:00
vars : 4 ,
2018-10-18 13:08:51 -04:00
template : function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ elementStart ( 0 , "div" ) ;
$r3 $ . ɵ ɵ i18n ( 1 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
2018-10-18 13:08:51 -04:00
}
if ( rf & 2 ) {
2019-12-16 14:55:50 -05:00
$r3 $ . ɵ ɵ advance ( 1 ) ;
2019-06-25 11:14:07 -04:00
$r3 $ . ɵ ɵ i18nExp ( ctx . gender ) ( ctx . weight ) ( ctx . height ) ( ctx . age ) ;
2019-05-17 21:49:21 -04:00
$r3 $ . ɵ ɵ i18nApply ( 1 ) ;
2018-10-18 13:08:51 -04:00
}
}
` ;
verify ( input , output ) ;
} ) ;
2019-10-15 18:54:14 -04:00
it ( 'should attach metadata in case an ICU represents the whole message' , ( ) = > {
const input = `
< div i18n = "meaningA|descA@@idA" > { count , select , 1 { one } other { more than one } } < / div >
` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-10-15 18:54:14 -04:00
var $I18N_0 $ ;
2019-12-03 06:58:10 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
2019-10-15 18:54:14 -04:00
/ * *
* @desc descA
* @meaning meaningA
* /
const $MSG_EXTERNAL_idA $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{VAR_SELECT, select, 1 {one} other {more than one}}" ) ;
$I18N_0 $ = $MSG_EXTERNAL_idA $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` :meaningA|descA@@idA:{VAR_SELECT, select, 1 {one} other {more than one}} \` ;
}
$I18N_0 $ = i0 . ɵ ɵ i18nPostprocess ( $I18N_0 $ , { "VAR_SELECT" : "\uFFFD0\uFFFD" } ) ;
` ;
verify ( input , output ) ;
} ) ;
2018-10-18 13:08:51 -04:00
} ) ;
2019-12-03 03:36:38 -05:00
describe ( '$localize legacy message ids' , ( ) = > {
it ( 'should add legacy message ids if `enableI18nLegacyMessageIdFormat` is true' , ( ) = > {
const input = ` <div i18n>Some Message</div> ` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-12-03 03:36:38 -05:00
var $I18N_0 $ ;
2019-12-03 20:07:09 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) { … }
2019-12-03 03:36:38 -05:00
else {
$I18N_0 $ = $localize \ ` :␟ec93160d6d6a8822214060dd7938bf821c22b226␟6795333002533525253:Some Message \` ;
}
…
` ;
verify ( input , output , { compilerOptions : { enableI18nLegacyMessageIdFormat : true } } ) ;
} ) ;
it ( 'should add legacy message ids if `enableI18nLegacyMessageIdFormat` is undefined' , ( ) = > {
const input = ` <div i18n>Some Message</div> ` ;
2020-04-07 15:43:43 -04:00
const output = String . raw `
2019-12-03 03:36:38 -05:00
var $I18N_0 $ ;
2019-12-03 20:07:09 -05:00
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) { … }
2019-12-03 03:36:38 -05:00
else {
$I18N_0 $ = $localize \ ` :␟ec93160d6d6a8822214060dd7938bf821c22b226␟6795333002533525253:Some Message \` ;
}
…
` ;
verify ( input , output , { compilerOptions : { enableI18nLegacyMessageIdFormat : undefined } } ) ;
} ) ;
} ) ;
fix(compiler): normalize line endings in ICU expansions (#36741)
The html parser already normalizes line endings (converting `\r\n` to `\n`)
for most text in templates but it was missing the expressions of ICU expansions.
In ViewEngine backticked literal strings, used to define inline templates,
were already normalized by the TypeScript parser.
In Ivy we are parsing the raw text of the source file directly so the line
endings need to be manually normalized.
This change ensures that inline templates have the line endings of ICU
expression normalized correctly, which matches the ViewEngine.
In ViewEngine external templates, defined in HTML files, the behavior was
different, since TypeScript was not normalizing the line endings.
Specifically, ICU expansion "expressions" are not being normalized.
This is a problem because it means that i18n message ids can be different on
different machines that are setup with different line ending handling,
or if the developer moves a template from inline to external or vice versa.
The goal is always to normalize line endings, whether inline or external.
But this would be a breaking change since it would change i18n message ids
that have been previously computed. Therefore this commit aligns the ivy
template parsing to have the same "buggy" behavior for external templates.
There is now a compiler option `i18nNormalizeLineEndingsInICUs`, which
if set to `true` will ensure the correct non-buggy behavior. For the time
being this option defaults to `false` to ensure backward compatibility while
allowing opt-in to the desired behavior. This option's default will be
flipped in a future breaking change release.
Further, when this option is set to `false`, any ICU expression tokens,
which have not been normalized, are added to the `ParseResult` from the
`HtmlParser.parse()` method. In the future, this collection of tokens could
be used to diagnose and encourage developers to migrate their i18n message
ids. See FW-2106.
Closes #36725
PR Close #36741
2020-04-26 13:15:43 -04:00
describe ( 'line ending normalization' , ( ) = > {
[ true , false ] . forEach (
templateUrl = > describe ( templateUrl ? '[templateUrl]' : '[inline template]' , ( ) = > {
[ true , false , undefined ] . forEach (
i18nNormalizeLineEndingsInICUs = > describe (
` {i18nNormalizeLineEndingsInICUs: ${ i18nNormalizeLineEndingsInICUs } } ` , ( ) = > {
it ( 'should normalize line endings in templates' , ( ) = > {
const input =
` <div title="abc \ r \ ndef" i18n-title i18n> \ r \ nSome Message \ r \ n{ \ r \ n value, \ r \ n select, \ r \ n =0 { \ r \ n zero \ r \ n } \ r \ n}</div> ` ;
const output = String . raw `
$I18N_0 $ = $localize \ ` abc
def \ ` ;
…
$I18N_4 $ = $localize \ ` {VAR_SELECT, select, =0 {zero
} } \ `
…
$I18N_3 $ = $localize \ `
Some Message
$ ` + String.raw ` { $I18N_4 $ } : ICU : \ ` ;
` ;
verify ( input , output , {
inputArgs : { templateUrl } ,
compilerOptions : { i18nNormalizeLineEndingsInICUs }
} ) ;
} ) ;
it ( 'should compute the correct message id for messages' , ( ) = > {
const input =
` <div title="abc \ r \ ndef" i18n-title i18n> \ r \ nSome Message \ r \ n{ \ r \ n value, \ r \ n select, \ r \ n =0 { \ r \ n zero \ r \ n } \ r \ n}</div> ` ;
// The ids generated by the compiler are different if the template is external
// and we are not explicitly normalizing the line endings.
const ICU_EXPRESSION_ID =
templateUrl && i18nNormalizeLineEndingsInICUs !== true ?
` ␟70a685282be2d956e4db234fa3d985970672faa0 ` :
` ␟b5fe162f4e47ab5b3e534491d30b715e0dff0f52 ` ;
const ICU_ID = templateUrl && i18nNormalizeLineEndingsInICUs !== true ?
` ␟6a55b51b9bcf8f84b1b868c585ae09949668a72b ` :
` ␟e31c7bc4db2f2e56dc40f005958055a02fd43a2e ` ;
const output =
String . raw `
$I18N_0 $ = $localize \ ` :␟4f9ce2c66b187afd9898b25f6336d1eb2be8b5dc␟7326958852138509669:abc
def \ ` ;
…
$I18N_4 $ = $localize \ ` : ${
ICU_EXPRESSION_ID } ␟ 4863953183043480207 : { VAR_SELECT , select , = 0 { zero
} } \ `
…
$I18N_3 $ = $localize \ ` : ${ ICU_ID } ␟2773178924738647105:
Some Message
$ ` + String.raw ` { $I18N_4 $ } : ICU : \ ` ;
` ;
verify ( input , output , {
inputArgs : { templateUrl } ,
compilerOptions :
{ i18nNormalizeLineEndingsInICUs , enableI18nLegacyMessageIdFormat : true }
} ) ;
} ) ;
} ) ) ;
} ) ) ;
} ) ;
2020-05-12 03:20:02 -04:00
describe ( 'es5 support' , ( ) = > {
it ( 'should generate ES5 compliant localized messages if the target is ES5' , ( ) = > {
const input = `
< div i18n = "meaning:A|descA@@idA" > Content A < / div >
` ;
const output = String . raw `
var $I18N_0 $ ;
…
$I18N_0 $ = $localize ( … __makeTemplateObject ( [ ":meaning:A|descA@@idA:Content A" ] , [ ":meaning\\:A|descA@@idA:Content A" ] ) … ) ;
` ;
verify (
input , output , { skipIdBasedCheck : true , compilerOptions : { target : ts.ScriptTarget.ES5 } } ) ;
} ) ;
} ) ;
2018-10-18 13:08:51 -04:00
describe ( 'errors' , ( ) = > {
2019-08-03 15:24:48 -04:00
const verifyNestedSectionsError = ( errorThrown : any , expectedErrorText : string ) = > {
expect ( errorThrown . ngParseErrors . length ) . toBe ( 1 ) ;
const msg = errorThrown . ngParseErrors [ 0 ] . toString ( ) ;
expect ( msg ) . toContain (
'Cannot mark an element as translatable inside of a translatable section. Please remove the nested i18n marker.' ) ;
expect ( msg ) . toContain ( expectedErrorText ) ;
expect ( msg ) . toMatch ( /app\/spec\.ts\@\d+\:\d+/ ) ;
} ;
2018-10-18 13:08:51 -04:00
it ( 'should throw on nested i18n sections' , ( ) = > {
const files = getAppFilesWithTemplate ( `
2019-08-03 15:24:48 -04:00
< div i18n >
< div i18n > Some content < / div >
< / div >
` );
try {
compile ( files , angularFiles ) ;
} catch ( error ) {
verifyNestedSectionsError ( error , '[ERROR ->]<div i18n>Some content</div>' ) ;
}
} ) ;
it ( 'should throw on nested i18n sections with tags in between' , ( ) = > {
const files = getAppFilesWithTemplate ( `
< div i18n >
< div >
< div i18n > Some content < / div >
< / div >
< / div >
2018-10-18 13:08:51 -04:00
` );
2019-08-03 15:24:48 -04:00
try {
compile ( files , angularFiles ) ;
} catch ( error ) {
verifyNestedSectionsError ( error , '[ERROR ->]<div i18n>Some content</div>' ) ;
}
2018-02-14 13:54:00 -05:00
} ) ;
2019-08-03 15:24:48 -04:00
it ( 'should throw on nested i18n sections represented with <ng-container>s' , ( ) = > {
const files = getAppFilesWithTemplate ( `
< ng - container i18n >
< div >
< ng - container i18n > Some content < / n g - c o n t a i n e r >
< / div >
< / n g - c o n t a i n e r >
` );
try {
compile ( files , angularFiles ) ;
} catch ( error ) {
verifyNestedSectionsError (
error , '[ERROR ->]<ng-container i18n>Some content</ng-container>' ) ;
}
} ) ;
2018-02-14 13:54:00 -05:00
} ) ;
2020-05-05 20:52:49 -04:00
describe ( 'namespaces' , ( ) = > {
it ( 'should handle namespaces inside i18n blocks' , ( ) = > {
const input = `
< svg xmlns = "http://www.w3.org/2000/svg" >
< foreignObject i18n >
< xhtml : div xmlns = "http://www.w3.org/1999/xhtml" >
Count : < span > 5 < / span >
< / x h t m l : d i v >
< / foreignObject >
< / svg >
` ;
const output = String . raw `
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_7128002169381370313 $ $APP_SPEC_TS_1 $ = goog . getMsg ( "{$startTagXhtmlDiv} Count: {$startTagXhtmlSpan}5{$closeTagXhtmlSpan}{$closeTagXhtmlDiv}" , {
"startTagXhtmlDiv" : "\uFFFD#3\uFFFD" ,
"startTagXhtmlSpan" : "\uFFFD#4\uFFFD" ,
"closeTagXhtmlSpan" : "\uFFFD/#4\uFFFD" ,
"closeTagXhtmlDiv" : "\uFFFD/#3\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_7128002169381370313 $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` $ ` +
String . raw ` {" \ uFFFD#3 \ uFFFD"}:START_TAG__XHTML_DIV: Count: $ ` +
String . raw ` {" \ uFFFD#4 \ uFFFD"}:START_TAG__XHTML_SPAN:5 $ ` +
String . raw ` {" \ uFFFD/#4 \ uFFFD"}:CLOSE_TAG__XHTML_SPAN: $ ` +
String . raw ` {" \ uFFFD/#3 \ uFFFD"}:CLOSE_TAG__XHTML_DIV: \` ;
}
…
function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ namespaceSVG ( ) ;
$r3 $ . ɵ ɵ elementStart ( 0 , "svg" , 0 ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "foreignObject" ) ;
$r3 $ . ɵ ɵ i18nStart ( 2 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ namespaceHTML ( ) ;
$r3 $ . ɵ ɵ elementStart ( 3 , "div" , 1 ) ;
$r3 $ . ɵ ɵ element ( 4 , "span" ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
}
` ;
verify ( input , output ) ;
} ) ;
it ( 'should handle namespaces on i18n block containers' , ( ) = > {
const input = `
< svg xmlns = "http://www.w3.org/2000/svg" >
< foreignObject >
< xhtml : div xmlns = "http://www.w3.org/1999/xhtml" i18n >
Count : < span > 5 < / span >
< / x h t m l : d i v >
< / foreignObject >
< / svg >
` ;
const output = String . raw `
var $I18N_0 $ ;
if ( typeof ngI18nClosureMode !== "undefined" && ngI18nClosureMode ) {
const $MSG_EXTERNAL_7428861019045796010 $ $APP_SPEC_TS_1 $ = goog . getMsg ( " Count: {$startTagXhtmlSpan}5{$closeTagXhtmlSpan}" , {
"startTagXhtmlSpan" : "\uFFFD#4\uFFFD" ,
"closeTagXhtmlSpan" : "\uFFFD/#4\uFFFD"
} ) ;
$I18N_0 $ = $MSG_EXTERNAL_7428861019045796010 $ $APP_SPEC_TS_1 $ ;
}
else {
$I18N_0 $ = $localize \ ` Count: $ ` +
String . raw ` {" \ uFFFD#4 \ uFFFD"}:START_TAG__XHTML_SPAN:5 $ ` +
String . raw ` {" \ uFFFD/#4 \ uFFFD"}:CLOSE_TAG__XHTML_SPAN: \` ;
}
…
function MyComponent_Template ( rf , ctx ) {
if ( rf & 1 ) {
$r3 $ . ɵ ɵ namespaceSVG ( ) ;
$r3 $ . ɵ ɵ elementStart ( 0 , "svg" , 0 ) ;
$r3 $ . ɵ ɵ elementStart ( 1 , "foreignObject" ) ;
$r3 $ . ɵ ɵ namespaceHTML ( ) ;
$r3 $ . ɵ ɵ elementStart ( 2 , "div" , 1 ) ;
$r3 $ . ɵ ɵ i18nStart ( 3 , $I18N_0 $ ) ;
$r3 $ . ɵ ɵ element ( 4 , "span" ) ;
$r3 $ . ɵ ɵ i18nEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
$r3 $ . ɵ ɵ elementEnd ( ) ;
}
}
` ;
verify ( input , output , { verbose : true } ) ;
} ) ;
} ) ;
2018-02-14 13:54:00 -05:00
} ) ;