77 */
88
99import remapping , { type DecodedSourceMap , type SourceMapInput } from '@ampproject/remapping' ;
10- import type { ɵParsedTranslation } from '@angular/localize' ;
10+ import {
11+ type ɵParsedTranslation ,
12+ ɵisMissingTranslationError ,
13+ ɵmakeTemplateObject ,
14+ ɵtranslate ,
15+ } from '@angular/localize' ;
1116import { MagicString } from 'magic-string' ;
1217import { deserialize } from 'node:v8' ;
1318import { parseSync } from 'oxc-parser' ;
@@ -285,7 +290,7 @@ export async function inlineFileBatch(
285290 locale,
286291 code : result . code ,
287292 map : result . map ,
288- messages : result . diagnostics . messages ,
293+ messages : result . diagnostics ,
289294 } ;
290295 } ) ,
291296 ) ;
@@ -317,33 +322,45 @@ export async function inlineCode(request: InlineCodeRequest): Promise<InlineCode
317322
318323 return {
319324 output : result . code ?? request . code ,
320- messages : result . diagnostics . messages ,
325+ messages : result . diagnostics ,
321326 } ;
322327}
323328
324- /**
325- * A Type representing the localize tools module.
326- */
327- type LocalizeUtilityModule = typeof import ( '@angular/localize/tools' ) ;
329+ type DiagnosticMessage = { type : 'error' | 'warning' ; message : string } ;
328330
329331/**
330- * Cached instance of the ` @angular/localize/tools` module .
331- * This is used to remove the need to repeatedly import the module per file translation .
332+ * Translates a $localize message using @angular/localize low-level runtime functions .
333+ * Handles missing translations and errors without requiring @angular/localize/tools .
332334 */
333- let localizeToolsModule : LocalizeUtilityModule | undefined ;
335+ function translateMessage (
336+ diagnostics : DiagnosticMessage [ ] ,
337+ translations : Record < string , ɵParsedTranslation > ,
338+ messageParts : TemplateStringsArray ,
339+ substitutions : readonly number [ ] ,
340+ missingTranslation : 'error' | 'warning' | 'ignore' ,
341+ ) : [ TemplateStringsArray , readonly number [ ] ] {
342+ try {
343+ return ɵtranslate ( translations , messageParts , substitutions ) as [
344+ TemplateStringsArray ,
345+ readonly number [ ] ,
346+ ] ;
347+ } catch ( error ) {
348+ if ( ɵisMissingTranslationError ( error ) ) {
349+ if ( missingTranslation !== 'ignore' ) {
350+ diagnostics . push ( { type : missingTranslation , message : error . message } ) ;
351+ }
334352
335- /**
336- * Attempts to load the `@angular/localize/tools` module containing the functionality to
337- * perform the file translations.
338- * This module must be dynamically loaded as it is an ESM module and this file is CommonJS.
339- */
340- async function loadLocalizeTools ( ) : Promise < LocalizeUtilityModule > {
341- // Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
342- // Once TypeScript provides support for keeping the dynamic import this workaround can be
343- // changed to a direct dynamic import.
344- localizeToolsModule ??= await import ( '@angular/localize/tools' ) ;
353+ return [
354+ ɵmakeTemplateObject ( error . parsedMessage . messageParts , error . parsedMessage . messageParts ) ,
355+ substitutions ,
356+ ] ;
357+ } else {
358+ const message = error instanceof Error ? error . message : String ( error ) ;
359+ diagnostics . push ( { type : 'error' , message } ) ;
345360
346- return localizeToolsModule ;
361+ return [ messageParts , substitutions ] ;
362+ }
363+ }
347364}
348365
349366/**
@@ -465,21 +482,20 @@ async function inlineLocalize(
465482 missingTranslation : 'error' | 'warning' | 'ignore' = 'warning' ,
466483) {
467484 const magicString = new MagicString ( code ) ;
468- const { Diagnostics, translate } = await loadLocalizeTools ( ) ;
469- const diagnostics = new Diagnostics ( ) ;
485+ const diagnostics : DiagnosticMessage [ ] = [ ] ;
470486
471487 if ( metadata . diagnostics ) {
472488 for ( const message of metadata . diagnostics ) {
473- diagnostics . error ( message ) ;
489+ diagnostics . push ( { type : 'error' , message } ) ;
474490 }
475491 }
476492
477493 if ( metadata . localeInsertSites . length > 0 ) {
478494 const localeData = await loadLocaleData ( locale ) ;
479495 if ( localeData . error ) {
480- diagnostics . error ( localeData . error ) ;
496+ diagnostics . push ( { type : 'error' , message : localeData . error } ) ;
481497 } else if ( localeData . warning ) {
482- diagnostics . warn ( localeData . warning ) ;
498+ diagnostics . push ( { type : 'warning' , message : localeData . warning } ) ;
483499 }
484500 let injected = false ;
485501 for ( const site of metadata . localeInsertSites ) {
@@ -493,7 +509,7 @@ async function inlineLocalize(
493509 }
494510
495511 for ( const callSite of metadata . callSites ) {
496- const [ translatedParts , translatedSubstitutions ] = translate (
512+ const [ translatedParts , translatedSubstitutions ] = translateMessage (
497513 diagnostics ,
498514 translation || { } ,
499515 callSite . messageParts ,
0 commit comments