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
@@ -316,33 +321,45 @@ export async function inlineCode(request: InlineCodeRequest): Promise<InlineCode
316321
317322 return {
318323 output : result . code ?? request . code ,
319- messages : result . diagnostics . messages ,
324+ messages : result . diagnostics ,
320325 } ;
321326}
322327
323- /**
324- * A Type representing the localize tools module.
325- */
326- type LocalizeUtilityModule = typeof import ( '@angular/localize/tools' ) ;
328+ type DiagnosticMessage = { type : 'error' | 'warning' ; message : string } ;
327329
328330/**
329- * Cached instance of the ` @angular/localize/tools` module .
330- * This is used to remove the need to repeatedly import the module per file translation .
331+ * Translates a $localize message using @angular/localize low-level runtime functions .
332+ * Handles missing translations and errors without requiring @angular/localize/tools .
331333 */
332- let localizeToolsModule : LocalizeUtilityModule | undefined ;
334+ function translateMessage (
335+ diagnostics : DiagnosticMessage [ ] ,
336+ translations : Record < string , ɵParsedTranslation > ,
337+ messageParts : TemplateStringsArray ,
338+ substitutions : readonly number [ ] ,
339+ missingTranslation : 'error' | 'warning' | 'ignore' ,
340+ ) : [ TemplateStringsArray , readonly number [ ] ] {
341+ try {
342+ return ɵtranslate ( translations , messageParts , substitutions ) as [
343+ TemplateStringsArray ,
344+ readonly number [ ] ,
345+ ] ;
346+ } catch ( error ) {
347+ if ( ɵisMissingTranslationError ( error ) ) {
348+ if ( missingTranslation !== 'ignore' ) {
349+ diagnostics . push ( { type : missingTranslation , message : error . message } ) ;
350+ }
333351
334- /**
335- * Attempts to load the `@angular/localize/tools` module containing the functionality to
336- * perform the file translations.
337- * This module must be dynamically loaded as it is an ESM module and this file is CommonJS.
338- */
339- async function loadLocalizeTools ( ) : Promise < LocalizeUtilityModule > {
340- // Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
341- // Once TypeScript provides support for keeping the dynamic import this workaround can be
342- // changed to a direct dynamic import.
343- localizeToolsModule ??= await import ( '@angular/localize/tools' ) ;
352+ return [
353+ ɵmakeTemplateObject ( error . parsedMessage . messageParts , error . parsedMessage . messageParts ) ,
354+ substitutions ,
355+ ] ;
356+ } else {
357+ const message = error instanceof Error ? error . message : String ( error ) ;
358+ diagnostics . push ( { type : 'error' , message } ) ;
344359
345- return localizeToolsModule ;
360+ return [ messageParts , substitutions ] ;
361+ }
362+ }
346363}
347364
348365/**
@@ -464,21 +481,20 @@ async function inlineLocalize(
464481 missingTranslation : 'error' | 'warning' | 'ignore' = 'warning' ,
465482) {
466483 const magicString = new MagicString ( code ) ;
467- const { Diagnostics, translate } = await loadLocalizeTools ( ) ;
468- const diagnostics = new Diagnostics ( ) ;
484+ const diagnostics : DiagnosticMessage [ ] = [ ] ;
469485
470486 if ( metadata . diagnostics ) {
471487 for ( const message of metadata . diagnostics ) {
472- diagnostics . error ( message ) ;
488+ diagnostics . push ( { type : 'error' , message } ) ;
473489 }
474490 }
475491
476492 if ( metadata . localeInsertSites . length > 0 ) {
477493 const localeData = await loadLocaleData ( locale ) ;
478494 if ( localeData . error ) {
479- diagnostics . error ( localeData . error ) ;
495+ diagnostics . push ( { type : 'error' , message : localeData . error } ) ;
480496 } else if ( localeData . warning ) {
481- diagnostics . warn ( localeData . warning ) ;
497+ diagnostics . push ( { type : 'warning' , message : localeData . warning } ) ;
482498 }
483499 let injected = false ;
484500 for ( const site of metadata . localeInsertSites ) {
@@ -492,7 +508,7 @@ async function inlineLocalize(
492508 }
493509
494510 for ( const callSite of metadata . callSites ) {
495- const [ translatedParts , translatedSubstitutions ] = translate (
511+ const [ translatedParts , translatedSubstitutions ] = translateMessage (
496512 diagnostics ,
497513 translation || { } ,
498514 callSite . messageParts ,
0 commit comments