import { JsonTranslationSerializer } from '../extract/translation_files/json_translation_serializer' ; import { TranslationSerializer } from '../extract/translation_files/translation_serializer' ; import { Xliff1TranslationSerializer } from '../extract/translation_files/xliff1_translation_serializer' ; import { Xliff2TranslationSerializer } from '../extract/translation_files/xliff2_translation_serializer' ; import { XmbTranslationSerializer } from '../extract/translation_files/xmb_translation_serializer' ; import { ɵMessageId , ɵParsedMessage } from '@angular/localize' ; import { ParsedTranslation } from '../convert/translations' ; import { XtbTranslationSerializer } from '../extract/translation_files/xtb_translation_serializer' ; export type TranslationFormat = 'json' | 'xmb' | 'xliff1' | 'xliff2' | 'xlf' | 'xlf2' | 'xtb' ; export function getTranslationSerializer ( format ) { switch ( format ) { case 'json' : return new JsonTranslationSerializer ( ) ; case 'xliff1' : case 'xlf' : return new Xliff1TranslationSerializer ( ) ; case 'xliff2' : case 'xlf2' : return new Xliff2TranslationSerializer ( ) ; case 'xmb' : return new XmbTranslationSerializer ( ) ; case 'xtb' : return new XtbTranslationSerializer ( ) ; } } export function getExtension ( format ) { switch ( format ) { case 'json' : case 'xmb' : case 'xtb' : return format ; default : return 'xlf' ; } } /**
 * The character used to mark the start and end of a "block" in a `$localize` tagged string.
 * A block can indicate metadata about the message or specify a name of a placeholder for a
 * substitution expressions.
 *
 * For example:
 *
 * ```ts
 * $localize`Hello, ${title}:title:!`;
 * $localize`:meaning|description@@id:source message text`;
 * ```
 */ export const BLOCK_MARKER = ':' ; param cooked param raw returns throws export function findEndOfBlock ( cooked , raw ) { /************************************************************************************************
     * This function is repeated in `src/localize/src/localize.ts` and the two should be kept in sync.
     * (See that file for more explanation of why.)
     ************************************************************************************************/ for ( let cookedIndex = 1 , rawIndex = 1 ; cookedIndex < cooked . length ; cookedIndex ++ , rawIndex ++ ) { if ( raw [ rawIndex ] === '\\' ) { rawIndex ++ ; } else if ( cooked [ cookedIndex ] === BLOCK_MARKER ) { return cookedIndex ; } } throw new Error ( `Unterminated $localize metadata block in "${ raw }". I18n metadata should follow the syntax "<meaning>|<description>@@<id>" in templates and ":<meaning>|<description>@@<id>:" in code translations` ) ; } param cooked param raw returns throws export function splitBlock ( cooked , raw ) { if ( raw . charAt ( 0 ) !== BLOCK_MARKER ) { return { text : cooked } ; } else { const endOfBlock = findEndOfBlock ( cooked , raw ) ; return { block : cooked . substring ( 1 , endOfBlock ) , text : cooked . substring ( endOfBlock + 1 ) , } ; } } function computePlaceholderName ( index ) { return index === 1 ? 'PH' : `PH_${ index - 1 }` ; } export function translationToMessage ( id , translation ) { const messageParts = translation . messageParts ; const legacyIds = [ ] ; const cleanedMessageParts = [ messageParts [ 0 ] ] ; const substitutions = { } ; const placeholderNames = [ ] ; let text = messageParts [ 0 ] ; for ( let i = 1 ; i < messageParts . length ; i ++ ) { const { text : messagePart , block : placeholderName = translation . placeholderNames [ i - 1 ] || computePlaceholderName ( i ) , } = splitBlock ( messageParts [ i ] , messageParts . raw [ i ] ) ; text += `{$${ placeholderName }}${ messagePart }` ; if ( translation . placeholderNames . length ) { substitutions [ placeholderName ] = translation . placeholderNames [ i - 1 ] ; } placeholderNames . push ( placeholderName ) ; cleanedMessageParts . push ( messagePart ) ; } return { id , legacyIds , substitutions , text , meaning : translation . meaning || '' , description : translation . description || '' , messageParts : cleanedMessageParts , placeholderNames , } ; } export interface ParsedMessageLegacy { /**
     * The key used to look up the appropriate translation target.
     */ messageId : ɵMessageId ; /**
     * Legacy message ids, if provided.
     *
     * In legacy message formats the message id can only be computed directly from the original
     * template source.
     *
     * Since this information is not available in `$localize` calls, the legacy message ids may be
     * attached by the compiler to the `$localize` metablock so it can be used if needed at the point
     * of translation if the translations are encoded using the legacy message id.
     */ legacyIds : ɵMessageId [ ] ; /**
     * A mapping of placeholder names to substitution values.
     */ substitutions : Record < string , any > ; /**
     * A human readable rendering of the message
     */ messageString : string ; /**
     * The meaning of the `message`, used to distinguish identical `messageString`s.
     */ meaning : string ; /**
     * The description of the `message`, used to aid translation.
     */ description : string ; /**
     * The static parts of the message.
     */ messageParts : string [ ] ; /**
     * The names of the placeholders that will be replaced with substitutions.
     */ placeholderNames : string [ ] ; }