diff --git a/packages/angular/cli/lib/config/schema.json b/packages/angular/cli/lib/config/schema.json index 55172332bb79..dc77721409b2 100644 --- a/packages/angular/cli/lib/config/schema.json +++ b/packages/angular/cli/lib/config/schema.json @@ -1403,7 +1403,9 @@ "xlif", "xliff", "xlf2", - "xliff2" + "xliff2", + "json", + "arb" ] }, "i18nFormat": { @@ -1417,7 +1419,9 @@ "xlif", "xliff", "xlf2", - "xliff2" + "xliff2", + "json", + "arb" ] }, "i18nLocale": { diff --git a/packages/angular_devkit/build_angular/src/extract-i18n/index.ts b/packages/angular_devkit/build_angular/src/extract-i18n/index.ts index 8acaefecef34..dd91d803a662 100644 --- a/packages/angular_devkit/build_angular/src/extract-i18n/index.ts +++ b/packages/angular_devkit/build_angular/src/extract-i18n/index.ts @@ -37,6 +37,10 @@ function getI18nOutfile(format: string | undefined) { case 'xlf2': case 'xliff2': return 'messages.xlf'; + case 'json': + return 'messages.json'; + case 'arb': + return 'messages.arb'; default: throw new Error(`Unsupported format "${format}"`); } @@ -65,6 +69,24 @@ async function getSerializer(format: Format, sourceLocale: string, basePath: str // tslint:disable-next-line: no-any return new Xliff2TranslationSerializer(sourceLocale, basePath as any, useLegacyIds, {}); + case Format.Json: + const { SimpleJsonTranslationSerializer } = + await import('@angular/localize/src/tools/src/extract/translation_files/json_translation_serializer'); + + // tslint:disable-next-line: no-any + return new SimpleJsonTranslationSerializer(sourceLocale); + case Format.Arb: + const { ArbTranslationSerializer } = + await import('@angular/localize/src/tools/src/extract/translation_files/arb_translation_serializer'); + + const fileSystem = { + relative(from: string, to: string): string { + return path.relative(from, to); + }, + }; + + // tslint:disable-next-line: no-any + return new ArbTranslationSerializer(sourceLocale, basePath as any, fileSystem as any); } } @@ -86,6 +108,12 @@ function normalizeFormatOption(options: ExtractI18nBuilderOptions) { case Format.Xliff2: format = Format.Xlf2; break; + case Format.Json: + format = Format.Json; + break; + case Format.Arb: + format = Format.Arb; + break; case undefined: format = Format.Xlf; break; diff --git a/packages/angular_devkit/build_angular/src/extract-i18n/schema.json b/packages/angular_devkit/build_angular/src/extract-i18n/schema.json index 3d08debc2cb0..79739483be7c 100644 --- a/packages/angular_devkit/build_angular/src/extract-i18n/schema.json +++ b/packages/angular_devkit/build_angular/src/extract-i18n/schema.json @@ -19,7 +19,9 @@ "xlif", "xliff", "xlf2", - "xliff2" + "xliff2", + "json", + "arb" ] }, "i18nFormat": { @@ -33,7 +35,9 @@ "xlif", "xliff", "xlf2", - "xliff2" + "xliff2", + "json", + "arb" ] }, "i18nLocale": { diff --git a/packages/angular_devkit/build_angular/src/utils/load-translations.ts b/packages/angular_devkit/build_angular/src/utils/load-translations.ts index b76b4bd3541f..ac78333e0c27 100644 --- a/packages/angular_devkit/build_angular/src/utils/load-translations.ts +++ b/packages/angular_devkit/build_angular/src/utils/load-translations.ts @@ -66,6 +66,10 @@ async function importParsers() { const diagnostics = new localizeDiag.Diagnostics(); const parsers = { + arb: new (await import( + // tslint:disable-next-line:trailing-comma + '@angular/localize/src/tools/src/translate/translation_files/translation_parsers/arb_translation_parser' + )).ArbTranslationParser(), json: new (await import( // tslint:disable-next-line:trailing-comma '@angular/localize/src/tools/src/translate/translation_files/translation_parsers/simple_json_translation_parser' diff --git a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-arb.ts b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-arb.ts new file mode 100644 index 000000000000..d53aa837e815 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-arb.ts @@ -0,0 +1,10 @@ +import { executeTest } from './ivy-localize-dl-xliff2'; +import { setupI18nConfig } from './legacy'; + +export default async function() { + // Setup i18n tests and config. + await setupI18nConfig(true, 'arb'); + + // Execute the tests + await executeTest(); +} diff --git a/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-json.ts b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-json.ts new file mode 100644 index 000000000000..46f45c4d6275 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/i18n/ivy-localize-dl-json.ts @@ -0,0 +1,10 @@ +import { executeTest } from './ivy-localize-dl-xliff2'; +import { setupI18nConfig } from './legacy'; + +export default async function() { + // Setup i18n tests and config. + await setupI18nConfig(true, 'json'); + + // Execute the tests + await executeTest(); +} diff --git a/tests/legacy-cli/e2e/tests/i18n/legacy.ts b/tests/legacy-cli/e2e/tests/i18n/legacy.ts index 00697c5f2d2d..ef1e132cee7d 100644 --- a/tests/legacy-cli/e2e/tests/i18n/legacy.ts +++ b/tests/legacy-cli/e2e/tests/i18n/legacy.ts @@ -89,6 +89,18 @@ export const formats = { [/.*?<\/source>/g, ''], ], }, + 'json': { + ext: 'json', + sourceCheck: '"locale": "en-US"', + replacements: [ + ], + }, + 'arb': { + ext: 'arb', + sourceCheck: '"@@locale": "en-US"', + replacements: [ + ], + } }; export async function setupI18nConfig(useLocalize = true, format: keyof typeof formats = 'xlf') { @@ -226,7 +238,10 @@ export async function setupI18nConfig(useLocalize = true, format: keyof typeof f const translationFile = `src/locale/messages.${formats[format].ext}`; await expectFileToExist(translationFile); await expectFileToMatch(translationFile, formats[format].sourceCheck); - await expectFileToMatch(translationFile, `An introduction header for this sample`); + + if (format !== 'json') { + await expectFileToMatch(translationFile, `An introduction header for this sample`); + } // Make translations for each language. for (const { lang, translationReplacements } of langTranslations) {