diff --git a/.vscode/launch.json b/.vscode/launch.json index 2ca13c319af..196840c108c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -38,7 +38,9 @@ "--inspect-brk", "${workspaceFolder}/apps/heft/lib/start.js", "--debug", - "test-watch" + "test", + "--test-path-pattern", + "${fileBasenameNoExtension}" ], "skipFiles": ["/**"], "outFiles": [], diff --git a/common/changes/@rushstack/webpack5-localization-plugin/main_2025-06-27-23-15.json b/common/changes/@rushstack/webpack5-localization-plugin/main_2025-06-27-23-15.json new file mode 100644 index 00000000000..9c7b24a8b2a --- /dev/null +++ b/common/changes/@rushstack/webpack5-localization-plugin/main_2025-06-27-23-15.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/webpack5-localization-plugin", + "comment": "Add a feature for injecting custom localized values into a compilation via the `getCustomDataPlaceholderForValueFunction` function on an instance of the `LocalizationPlugin`.", + "type": "minor" + } + ], + "packageName": "@rushstack/webpack5-localization-plugin" +} \ No newline at end of file diff --git a/common/reviews/api/webpack5-localization-plugin.api.md b/common/reviews/api/webpack5-localization-plugin.api.md index 5870ff56ae1..b985e49c966 100644 --- a/common/reviews/api/webpack5-localization-plugin.api.md +++ b/common/reviews/api/webpack5-localization-plugin.api.md @@ -14,6 +14,11 @@ import type { IPseudolocaleOptions } from '@rushstack/localization-utilities'; import type { LoaderContext } from 'webpack'; import type { WebpackPluginInstance } from 'webpack'; +// @internal (undocumented) +export interface _ICustomDataPlaceholder extends IValuePlaceholderBase { + valueForLocaleFn: ValueForLocaleFn; +} + // @public (undocumented) export interface IDefaultLocaleOptions { fillMissingTranslationStrings?: boolean; @@ -121,13 +126,13 @@ export interface IPseudolocalesOptions { export type IResolvedMissingTranslations = ReadonlyMap; // @public (undocumented) -export interface _IStringPlaceholder { +interface IStringPlaceholder extends IValuePlaceholderBase { locFilePath: string; stringName: string; - suffix: string; translations: ReadonlyMap>; - value: string; } +export { IStringPlaceholder } +export { IStringPlaceholder as _IStringPlaceholder } // @public (undocumented) export interface ITrueHashPluginOptions { @@ -135,6 +140,12 @@ export interface ITrueHashPluginOptions { stageOverride?: number; } +// @public (undocumented) +export interface IValuePlaceholderBase { + suffix: string; + value: string; +} + // @public export class LocalizationPlugin implements WebpackPluginInstance { constructor(options: ILocalizationPluginOptions); @@ -142,9 +153,13 @@ export class LocalizationPlugin implements WebpackPluginInstance { addDefaultLocFileAsync(context: LoaderContext<{}>, localizedFileKey: string, localizedResourceData: ILocalizationFile): Promise>; apply(compiler: Compiler): void; // @internal (undocumented) - getDataForSerialNumber(serialNumber: string): _IStringPlaceholder | undefined; + _getCustomDataForSerialNumber(suffix: string): _ICustomDataPlaceholder | undefined; + // @beta (undocumented) + getCustomDataPlaceholderForValueFunction(valueForLocaleFn: ValueForLocaleFn, placeholderUniqueId: string): string; // (undocumented) - getPlaceholder(localizedFileKey: string, stringName: string): _IStringPlaceholder | undefined; + getPlaceholder(localizedFileKey: string, stringName: string): IStringPlaceholder | undefined; + // @internal (undocumented) + _getStringDataForSerialNumber(suffix: string): IStringPlaceholder | undefined; // @internal (undocumented) readonly _options: ILocalizationPluginOptions; } @@ -156,6 +171,9 @@ export class TrueHashPlugin implements WebpackPluginInstance { apply(compiler: Compiler): void; } +// @public (undocumented) +export type ValueForLocaleFn = (locale: string, chunk: Chunk) => string; + // (No @packageDocumentation comment for this package) ``` diff --git a/webpack/webpack5-localization-plugin/README.md b/webpack/webpack5-localization-plugin/README.md index ffe6bc458ad..792b6e70a73 100644 --- a/webpack/webpack5-localization-plugin/README.md +++ b/webpack/webpack5-localization-plugin/README.md @@ -209,6 +209,17 @@ use the true hash of the content, rather than an intermediate hash that is share Note that this option is not compatible with the `runtimeLocaleExpression` option and will cause an error if both are set. +## Custom Localized Data + +If you need to provide custom localized data, you can use the `getCustomDataPlaceholderForValueFunction` method +of the plugin. This method takes a function that receives a locale name and the chunk +that the placeholder is used in and returns a string that will be used as a placeholder for the localized data. +The provided function will be called for each locale that is used in the build and the returned value will replace +the returned placeholder in the output. + +Note that this may produce unexpected results if there are no other localized values in the chunk that the +placeholder is used in. + ## Links - [CHANGELOG.md](https://github.com/microsoft/rushstack/blob/main/webpack/localization-plugin/CHANGELOG.md) - Find diff --git a/webpack/webpack5-localization-plugin/src/AssetProcessor.ts b/webpack/webpack5-localization-plugin/src/AssetProcessor.ts index f74de81575d..b9169c4c9a9 100644 --- a/webpack/webpack5-localization-plugin/src/AssetProcessor.ts +++ b/webpack/webpack5-localization-plugin/src/AssetProcessor.ts @@ -4,11 +4,19 @@ import type { Asset, AssetInfo, Chunk, Compilation, sources } from 'webpack'; import * as Constants from './utilities/Constants'; -import type { LocalizationPlugin, IStringPlaceholder } from './LocalizationPlugin'; +import type { + LocalizationPlugin, + IStringPlaceholder, + ValueForLocaleFn, + ICustomDataPlaceholder +} from './LocalizationPlugin'; import type { ILocalizedWebpackChunk, IAssetPathOptions } from './webpackInterfaces'; +const LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: 1 = 1; +const DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: 2 = 2; + interface ILocalizedReconstructionElement { - kind: 'localized'; + kind: typeof LOCALIZED_RECONSTRUCTION_ELEMENT_KIND; start: number; end: number; escapedBackslash: string; @@ -16,14 +24,19 @@ interface ILocalizedReconstructionElement { } interface IDynamicReconstructionElement { - kind: 'dynamic'; + kind: typeof DYNAMIC_RECONSTRUCTION_ELEMENT_KIND; start: number; end: number; - valueFn: (locale: string) => string; + valueFn: ValueForLocaleFn; } type IReconstructionElement = ILocalizedReconstructionElement | IDynamicReconstructionElement; -type FormatLocaleForFilenameFn = (locale: string) => string; +/** + * @remarks + * Include the `chunk` parameter so that the functions arity is the same as the + * `ValueForLocaleFn` type. + */ +type FormatLocaleForFilenameFn = (locale: string, chunk: unknown) => string; interface IParseResult { issues: string[]; @@ -64,23 +77,13 @@ export interface IProcessLocalizedAssetOptions extends IProcessAssetOptionsBase formatLocaleForFilenameFn: FormatLocaleForFilenameFn; } -export interface IProcessAssetResult { - filename: string; - asset: sources.Source; -} - -export const PLACEHOLDER_REGEX: RegExp = new RegExp( - `${Constants.STRING_PLACEHOLDER_PREFIX}_([A-C])_(\\\\*)_([0-9a-f$]+)_`, - 'g' -); - -export interface IProcessedAsset { +interface IProcessedAsset { filename: string; source: sources.CachedSource; info: AssetInfo; } -export interface IProcessLocalizedAssetResult { +interface IProcessLocalizedAssetResult { localizedFiles: Record; processedAssets: IProcessedAsset[]; } @@ -124,12 +127,22 @@ export async function processLocalizedAssetCachedAsync( } export function processLocalizedAsset(options: IProcessLocalizedAssetOptions): IProcessLocalizedAssetResult { - const { compilation, asset, chunk, filenameTemplate, locales, formatLocaleForFilenameFn } = options; - + const { + compilation, + asset, + chunk, + filenameTemplate, + locales, + formatLocaleForFilenameFn, + plugin, + fillMissingTranslationStrings, + defaultLocale, + passthroughLocaleName + } = options; const { sources, WebpackError } = compilation.compiler.webpack; - const { source: originalSource } = asset; + const fallbackLocale: string | undefined = fillMissingTranslationStrings ? defaultLocale : undefined; const rawSource: sources.CachedSource = originalSource instanceof sources.CachedSource ? originalSource @@ -137,7 +150,7 @@ export function processLocalizedAsset(options: IProcessLocalizedAssetOptions): I const assetSource: string = rawSource.source().toString(); const parsedAsset: IParseResult = _parseStringToReconstructionSequence( - options.plugin, + plugin, assetSource, formatLocaleForFilenameFn ); @@ -158,8 +171,9 @@ export function processLocalizedAsset(options: IProcessLocalizedAssetOptions): I new sources.ReplaceSource(rawSource, locale), parsedAsset.reconstructionSeries, locale, - options.fillMissingTranslationStrings ? options.defaultLocale : undefined, - options.passthroughLocaleName + fallbackLocale, + passthroughLocaleName, + chunk ); for (const issue of localeIssues) { @@ -236,7 +250,7 @@ export async function processNonLocalizedAssetCachedAsync( } export function processNonLocalizedAsset(options: IProcessNonLocalizedAssetOptions): IProcessedAsset { - const { asset, fileName, compilation, formatLocaleForFilenameFn, hasUrlGenerator } = options; + const { asset, fileName, compilation, formatLocaleForFilenameFn, hasUrlGenerator, chunk } = options; const { sources, WebpackError } = compilation.compiler.webpack; @@ -260,7 +274,8 @@ export function processNonLocalizedAsset(options: IProcessNonLocalizedAssetOptio const { issues: localeIssues, result } = _reconstructNonLocalized( new sources.ReplaceSource(cachedSource, locale), parsedAsset.reconstructionSeries, - locale + locale, + chunk ); for (const issue of localeIssues) { @@ -307,14 +322,16 @@ function _reconstructLocalized( reconstructionSeries: IReconstructionElement[], locale: string, fallbackLocale: string | undefined, - passthroughLocale: string | undefined + passthroughLocale: string | undefined, + chunk: Chunk ): ILocalizedReconstructionResult { const issues: string[] = []; for (const element of reconstructionSeries) { - switch (element.kind) { - case 'localized': { - const { data } = element; + const { kind, start, end } = element; + switch (kind) { + case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: { + const { data, escapedBackslash } = element; const { stringName, translations } = data; let newValue: string | undefined = locale === passthroughLocale ? stringName : translations.get(locale)?.get(stringName); @@ -330,8 +347,6 @@ function _reconstructLocalized( newValue = '-- MISSING STRING --'; } - const escapedBackslash: string = element.escapedBackslash || '\\'; - if (newValue.includes('\\')) { // The vast majority of localized strings do not contain `\\`, so this check avoids an allocation. // Replace backslashes with the properly escaped backslash @@ -352,13 +367,13 @@ function _reconstructLocalized( ); } - result.replace(element.start, element.end - 1, newValue); + result.replace(start, end - 1, newValue); break; } - case 'dynamic': { - const newValue: string = element.valueFn(locale); - result.replace(element.start, element.end - 1, newValue); + case DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: { + const newValue: string = element.valueFn(locale, chunk); + result.replace(start, end - 1, newValue); break; } } @@ -373,13 +388,14 @@ function _reconstructLocalized( function _reconstructNonLocalized( result: sources.ReplaceSource, reconstructionSeries: IReconstructionElement[], - noStringsLocaleName: string + noStringsLocaleName: string, + chunk: Chunk ): INonLocalizedReconstructionResult { const issues: string[] = []; for (const element of reconstructionSeries) { switch (element.kind) { - case 'localized': { + case LOCALIZED_RECONSTRUCTION_ELEMENT_KIND: { issues.push( `The string "${element.data.stringName}" in "${element.data.locFilePath}" appeared in an asset ` + 'that is not expected to contain localized resources.' @@ -390,8 +406,8 @@ function _reconstructNonLocalized( break; } - case 'dynamic': { - const newValue: string = element.valueFn(noStringsLocaleName); + case DYNAMIC_RECONSTRUCTION_ELEMENT_KIND: { + const newValue: string = element.valueFn(noStringsLocaleName, chunk); result.replace(element.start, element.end - 1, newValue); break; } @@ -425,18 +441,18 @@ function _parseStringToReconstructionSequence( switch (elementLabel) { case Constants.STRING_PLACEHOLDER_LABEL: { const backslashEnd: number = source.indexOf('_', end); - const escapedBackslash: string = source.slice(end, backslashEnd); + const escapedBackslash: string = source.slice(end, backslashEnd) || '\\'; end = backslashEnd + 1; - const serialEnd: number = source.indexOf('_', end); - const serial: string = source.slice(end, serialEnd); - end = serialEnd + 1; + const suffixEnd: number = source.indexOf('_', end); + const suffix: string = source.slice(end, suffixEnd); + end = suffixEnd + 1; - const stringData: IStringPlaceholder | undefined = plugin.getDataForSerialNumber(serial); + const stringData: IStringPlaceholder | undefined = plugin._getStringDataForSerialNumber(suffix); if (!stringData) { - issues.push(`Missing placeholder ${serial}`); + issues.push(`Missing placeholder ${suffix}`); } else { const localizedElement: ILocalizedReconstructionElement = { - kind: 'localized', + kind: LOCALIZED_RECONSTRUCTION_ELEMENT_KIND, start, end, escapedBackslash, @@ -446,9 +462,10 @@ function _parseStringToReconstructionSequence( } break; } + case Constants.LOCALE_NAME_PLACEHOLDER_LABEL: { const dynamicElement: IDynamicReconstructionElement = { - kind: 'dynamic', + kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND, start, end, valueFn: formatLocaleForFilenameFn @@ -456,11 +473,12 @@ function _parseStringToReconstructionSequence( reconstructionSeries.push(dynamicElement); break; } + case Constants.JSONP_PLACEHOLDER_LABEL: { - jsonStringifyFormatLocaleForFilenameFn ||= (locale: string) => - JSON.stringify(formatLocaleForFilenameFn(locale)); + jsonStringifyFormatLocaleForFilenameFn ||= (locale: string, chunk: unknown) => + JSON.stringify(formatLocaleForFilenameFn(locale, chunk)); const dynamicElement: IDynamicReconstructionElement = { - kind: 'dynamic', + kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND, start, end, valueFn: jsonStringifyFormatLocaleForFilenameFn @@ -468,6 +486,26 @@ function _parseStringToReconstructionSequence( reconstructionSeries.push(dynamicElement); break; } + + case Constants.CUSTOM_PLACEHOLDER_LABEL: { + const serialEnd: number = source.indexOf('_', end); + const serial: string = source.slice(end, serialEnd); + end = serialEnd + 1; + const customData: ICustomDataPlaceholder | undefined = plugin._getCustomDataForSerialNumber(serial); + if (!customData) { + issues.push(`Missing custom placeholder ${serial}`); + } else { + const dynamicElement: IDynamicReconstructionElement = { + kind: DYNAMIC_RECONSTRUCTION_ELEMENT_KIND, + start, + end, + valueFn: customData.valueForLocaleFn + }; + reconstructionSeries.push(dynamicElement); + } + break; + } + default: { throw new Error(`Unexpected label ${elementLabel} in pattern ${source.slice(start, end)}`); } diff --git a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts index 8af635859fa..1848be90f98 100644 --- a/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts +++ b/webpack/webpack5-localization-plugin/src/LocalizationPlugin.ts @@ -36,33 +36,58 @@ import { chunkIsJs } from './utilities/chunkUtilities'; /** * @public */ -export interface IStringPlaceholder { +export type ValueForLocaleFn = (locale: string, chunk: Chunk) => string; + +/** + * @public + */ +export interface IValuePlaceholderBase { /** * The literal string that will be injected for later replacement. */ value: string; + /** * The identifier for this particular placeholder, for lookup. */ suffix: string; +} + +/** + * @public + */ +export interface IStringPlaceholder extends IValuePlaceholderBase { /** * The values of this string in each output locale. */ translations: ReadonlyMap>; + /** * The key used to identify the source file containing the string. */ locFilePath: string; + /** * The identifier of the string within its original source file. */ stringName: string; } +/** + * @internal + */ +export interface ICustomDataPlaceholder extends IValuePlaceholderBase { + /** + * The function that will be invoked to get the value for this placeholder. + * The function will be invoked with the locale name as the first argument. + */ + valueForLocaleFn: ValueForLocaleFn; +} + export interface IFileTranslationInfo { placeholders: Map; translations: Map>; - renderedPlacholders: Record; + renderedPlaceholders: Record; } const PLUGIN_NAME: 'localization' = 'localization'; @@ -97,12 +122,19 @@ export class LocalizationPlugin implements WebpackPluginInstance { string, Map> > = new Map(); - private readonly _stringPlaceholderMap: Map = new Map(); + private readonly _stringPlaceholderBySuffix: Map = new Map(); + private readonly _customDataPlaceholderBySuffix: Map = new Map(); + private readonly _customDataPlaceholderByUniqueId: Map = new Map(); private _passthroughLocaleName!: string; private _defaultLocale!: string; private _noStringsLocaleName!: string; private _fillMissingTranslationStrings!: boolean; - private _formatLocaleForFilename!: (loc: string) => string; + /** + * @remarks + * Include the `chunk` parameter so that the functions arity is the same as the + * `ValueForLocaleFn` type. + */ + private _formatLocaleForFilename!: (loc: string, chunk: unknown) => string; private readonly _pseudolocalizers: Map string> = new Map(); /** @@ -246,7 +278,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } if (chunkIdsWithStrings.size === 0) { - return this._formatLocaleForFilename(this._noStringsLocaleName); + return this._formatLocaleForFilename(this._noStringsLocaleName, undefined); } else if (chunkIdsWithoutStrings.size === 0) { return `" + ${localeExpression} + "`; } else { @@ -269,7 +301,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } const noLocaleExpression: string = JSON.stringify( - this._formatLocaleForFilename(this._noStringsLocaleName) + this._formatLocaleForFilename(this._noStringsLocaleName, undefined) ); return `" + (${JSON.stringify(chunkMapping)}[chunkId]?${ @@ -290,7 +322,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { } return assetPath.replace( Constants.LOCALE_FILENAME_TOKEN_REGEX, - this._formatLocaleForFilename(locale) + this._formatLocaleForFilename(locale, undefined) ); } } else { @@ -525,7 +557,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { markEntity(context._module!, true); - return fileInfo.renderedPlacholders; + return fileInfo.renderedPlaceholders; } /** @@ -539,11 +571,47 @@ export class LocalizationPlugin implements WebpackPluginInstance { return file.placeholders.get(stringName); } + /** + * @beta + */ + public getCustomDataPlaceholderForValueFunction( + valueForLocaleFn: ValueForLocaleFn, + placeholderUniqueId: string + ): string { + let placeholder: ICustomDataPlaceholder | undefined = + this._customDataPlaceholderByUniqueId.get(placeholderUniqueId); + if (!placeholder) { + // Get a hash of the unique ID to make sure its value doesn't interfere with our placeholder tokens + const suffix: string = Buffer.from(placeholderUniqueId, 'utf-8').toString('hex'); + placeholder = { + value: `${Constants.STRING_PLACEHOLDER_PREFIX}_${Constants.CUSTOM_PLACEHOLDER_LABEL}_${suffix}_`, + suffix, + valueForLocaleFn + }; + this._customDataPlaceholderBySuffix.set(suffix, placeholder); + this._customDataPlaceholderByUniqueId.set(placeholderUniqueId, placeholder); + } else if (placeholder.valueForLocaleFn !== valueForLocaleFn) { + throw new Error( + `${this.getCustomDataPlaceholderForValueFunction.name} has already been called with "${placeholderUniqueId}" ` + + `and a different valueForLocaleFn.` + ); + } + + return placeholder.value; + } + /** * @internal */ - public getDataForSerialNumber(serialNumber: string): IStringPlaceholder | undefined { - return this._stringPlaceholderMap.get(serialNumber); + public _getStringDataForSerialNumber(suffix: string): IStringPlaceholder | undefined { + return this._stringPlaceholderBySuffix.get(suffix); + } + + /** + * @internal + */ + public _getCustomDataForSerialNumber(suffix: string): ICustomDataPlaceholder | undefined { + return this._customDataPlaceholderBySuffix.get(suffix); } private _addLocFileAndGetPlaceholders( @@ -556,7 +624,7 @@ export class LocalizationPlugin implements WebpackPluginInstance { fileInfo = { placeholders: new Map(), translations: new Map(), - renderedPlacholders: {} + renderedPlaceholders: {} }; this._locFiles.set(localizedFileKey, fileInfo); } @@ -572,32 +640,24 @@ export class LocalizationPlugin implements WebpackPluginInstance { placeholder = { value: `${Constants.STRING_PLACEHOLDER_PREFIX}_${Constants.STRING_PLACEHOLDER_LABEL}_\\_${suffix}_`, suffix, - translations, + translations: translations, locFilePath: localizedFileKey, stringName }; placeholders.set(stringName, placeholder); - this._stringPlaceholderMap.set(suffix, placeholder); + this._stringPlaceholderBySuffix.set(suffix, placeholder); } resultObject[stringName] = placeholder.value; } translations.set(localeName, localizedFileData); - fileInfo.renderedPlacholders = resultObject; + fileInfo.renderedPlaceholders = resultObject; return fileInfo; } - private _addTranslations( - localeName: string, - fileInfo: IFileTranslationInfo, - localizedFileData: ReadonlyMap - ): void { - fileInfo.translations.set(localeName, localizedFileData); - } - private _initializeAndValidateOptions( compiler: Compiler, isWebpackDevServer: boolean diff --git a/webpack/webpack5-localization-plugin/src/index.ts b/webpack/webpack5-localization-plugin/src/index.ts index ed20360a302..6d0227a0a6d 100644 --- a/webpack/webpack5-localization-plugin/src/index.ts +++ b/webpack/webpack5-localization-plugin/src/index.ts @@ -3,7 +3,15 @@ /// -export { LocalizationPlugin, type IStringPlaceholder as _IStringPlaceholder } from './LocalizationPlugin'; +export { + LocalizationPlugin, + // TODO: Remove this export in the next major version + type IStringPlaceholder as _IStringPlaceholder, + type IStringPlaceholder, + type ICustomDataPlaceholder as _ICustomDataPlaceholder, + type IValuePlaceholderBase, + type ValueForLocaleFn +} from './LocalizationPlugin'; export { TrueHashPlugin, type ITrueHashPluginOptions } from './TrueHashPlugin'; export type { diff --git a/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts b/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts index 2d1841c4ae8..08c5df649bf 100644 --- a/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts +++ b/webpack/webpack5-localization-plugin/src/test/LocalizedRuntimeTestBase.ts @@ -11,6 +11,86 @@ import { MemFSPlugin } from './MemFSPlugin'; import type { ILocalizationPluginOptions } from '../interfaces'; import { LocalizationPlugin } from '../LocalizationPlugin'; import { type ITrueHashPluginOptions, TrueHashPlugin } from '../TrueHashPlugin'; +import { markEntity } from '../utilities/EntityMarker'; + +class InjectCustomPlaceholderPlugin implements webpack.WebpackPluginInstance { + private readonly _localizationPlugin: LocalizationPlugin; + private readonly _localizedChunkNameByLocaleName: Map>; + + public constructor( + localizationPlugin: LocalizationPlugin, + localizedChunkNameByLocaleName: Map> + ) { + this._localizationPlugin = localizationPlugin; + this._localizedChunkNameByLocaleName = localizedChunkNameByLocaleName; + } + + public apply(compiler: Compiler): void { + const PLUGIN_NAME: 'inject-custom-placeholder' = 'inject-custom-placeholder'; + const printLocalizedChunkName: 'printLocalizedChunkName' = 'printLocalizedChunkName'; + + const { runtime, RuntimeModule, Template, RuntimeGlobals } = compiler.webpack; + const localizationPlugin: LocalizationPlugin = this._localizationPlugin; + const localizedChunkNameByLocaleName: Map> = this + ._localizedChunkNameByLocaleName; + + function getLocalizedChunkNamesString(locale: string): string { + return `/* ${locale} */ ${JSON.stringify(localizedChunkNameByLocaleName.get(locale))}`; + } + + class GetIntegrityHashRuntimeModule extends RuntimeModule { + public constructor() { + super('custom data module', -10); + this.fullHash = true; + } + + public override generate(): string { + const placeholder: string = localizationPlugin.getCustomDataPlaceholderForValueFunction( + getLocalizedChunkNamesString, + printLocalizedChunkName + ); + + return Template.asString([ + `var localizedChunkNames = ${placeholder};`, + `function ${printLocalizedChunkName}(chunkId) {`, + Template.indent([`console.log(localizedChunkNames[chunkId]);`]), + `}` + ]); + } + + public override shouldIsolate(): boolean { + return false; + } + } + + compiler.hooks.thisCompilation.tap({ name: PLUGIN_NAME, stage: 10 }, (compilation, data) => { + runtime.LoadScriptRuntimeModule.getCompilationHooks(compilation).createScript.tap( + PLUGIN_NAME, + (originalSource): string => { + return Template.asString([originalSource, '', `${printLocalizedChunkName}(chunkId);`]); + } + ); + + function integrityHandler(chunk: webpack.Chunk, set: Set): void { + markEntity(chunk, true); + set.add(printLocalizedChunkName); + } + + compilation.hooks.runtimeRequirementInTree + .for(printLocalizedChunkName) + .tap(PLUGIN_NAME, (chunk: webpack.Chunk, set: Set) => { + compilation.addRuntimeModule(chunk, new GetIntegrityHashRuntimeModule()); + return true; + }); + compilation.hooks.runtimeRequirementInTree + .for(RuntimeGlobals.loadScript) + .tap(PLUGIN_NAME, integrityHandler); + compilation.hooks.runtimeRequirementInTree + .for(RuntimeGlobals.preloadChunkHandlers) + .tap(PLUGIN_NAME, integrityHandler); + }); + } +} export function runTests(trueHashPluginOptions: ITrueHashPluginOptions = {}): void { async function testLocalizedRuntimeInner(minimize: boolean): Promise { @@ -51,6 +131,11 @@ export function runTests(trueHashPluginOptions: ITrueHashPluginOptions = {}): vo const localizationPlugin: LocalizationPlugin = new LocalizationPlugin(options); + const localizedChunkNameByLocaleName: Map> = new Map([ + ['LOCALE1', { async1: 'async1-LOCALE1-123456', async2: 'async2-LOCALE1-123456' }], + ['LOCALE2', { async1: 'async1-LOCALE2-abcdef', async2: 'async2-LOCALE2-abcdef' }] + ]); + const compiler: Compiler = webpack({ entry: { mainSingleChunk: '/a/entrySingleChunk.js', @@ -80,7 +165,12 @@ export function runTests(trueHashPluginOptions: ITrueHashPluginOptions = {}): vo }, context: '/', mode: 'production', - plugins: [localizationPlugin, trueHashPlugin, new MemFSPlugin(memoryFileSystem)] + plugins: [ + localizationPlugin, + new InjectCustomPlaceholderPlugin(localizationPlugin, localizedChunkNameByLocaleName), + trueHashPlugin, + new MemFSPlugin(memoryFileSystem) + ] }); const stats: Stats | undefined = await promisify(compiler.run.bind(compiler))(); diff --git a/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntime.test.ts.snap b/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntime.test.ts.snap index dd38b8e8af6..54e4d692756 100644 --- a/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntime.test.ts.snap +++ b/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntime.test.ts.snap @@ -6,10 +6,10 @@ Object { "/release/chunks/async1-LOCALE2-1e57833357912f77511d.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[230],{\\"./a/async1.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test,a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"baz\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"some random translation\\"}}}]);", "/release/chunks/async2-LOCALE1-0c2f434469639436732a.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[421],{\\"./a/async2.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test+a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"blah\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"something else\\"}}}]);", "/release/chunks/async2-LOCALE2-664388d6b7aa642fc965.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[421],{\\"./a/async2.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test+a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"baz\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"some random translation\\"}}}]);", - "/release/mainSingleChunk-LOCALE1-609ca833ca6d471a329e.js": "(()=>{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/async1-\\"+\\"LOCALE1\\"+\\"-44d1a3fadec3f8385e08.js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var l=document.getElementsByTagName(\\"script\\"),s=0;s{i.onerror=i.onload=null,clearTimeout(d);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},d=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={331:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,l]=t,s=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);l&&l(o)}for(r&&r(t);s{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/async1-\\"+\\"LOCALE2\\"+\\"-1e57833357912f77511d.js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var l=document.getElementsByTagName(\\"script\\"),s=0;s{i.onerror=i.onload=null,clearTimeout(d);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},d=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={331:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,l]=t,s=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);l&&l(o)}for(r&&r(t);s{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE1\\"+\\"-\\"+{230:\\"44d1a3fadec3f8385e08\\",421:\\"0c2f434469639436732a\\"}[e]+\\".js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var s=document.getElementsByTagName(\\"script\\"),l=0;l{i.onerror=i.onload=null,clearTimeout(p);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},p=setTimeout(d.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={580:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,s]=t,l=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);s&&s(o)}for(r&&r(t);l{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE2\\"+\\"-\\"+{230:\\"1e57833357912f77511d\\",421:\\"664388d6b7aa642fc965\\"}[e]+\\".js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var s=document.getElementsByTagName(\\"script\\"),l=0;l{i.onerror=i.onload=null,clearTimeout(p);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},p=setTimeout(d.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={580:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,s]=t,l=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);s&&s(o)}for(r&&r(t);l{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/async1-\\"+\\"LOCALE1\\"+\\"-44d1a3fadec3f8385e08.js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,l;if(void 0!==a)for(var s=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),l&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={331:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,l]=o,s=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);l&&l(t)}for(r&&r(o);s{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/async1-\\"+\\"LOCALE2\\"+\\"-1e57833357912f77511d.js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,l;if(void 0!==a)for(var s=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),l&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={331:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,l]=o,s=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);l&&l(t)}for(r&&r(o);s{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE1\\"+\\"-\\"+{230:\\"44d1a3fadec3f8385e08\\",421:\\"0c2f434469639436732a\\"}[e]+\\".js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,s;if(void 0!==a)for(var l=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),s&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={580:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,s]=o,l=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);s&&s(t)}for(r&&r(o);l{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE2\\"+\\"-\\"+{230:\\"1e57833357912f77511d\\",421:\\"664388d6b7aa642fc965\\"}[e]+\\".js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,s;if(void 0!==a)for(var l=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),s&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={580:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,s]=o,l=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);s&&s(t)}for(r&&r(o);l { // webpackBootstrap + "/release/mainSingleChunk-LOCALE1-a09e66b038c209b52c2b.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -194,6 +194,12 @@ const strings = {\\"another\\":\\"some random translation\\"}; /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -272,6 +278,9 @@ const strings = {\\"another\\":\\"some random translation\\"}; /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -420,7 +429,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\")); /******/ })() ;", - "/release/mainSingleChunk-LOCALE2-67b32b007b29ddb53f0b.js": "/******/ (() => { // webpackBootstrap + "/release/mainSingleChunk-LOCALE2-5382793b5c1b412e361b.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -451,6 +460,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -529,6 +544,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -677,7 +695,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\")); /******/ })() ;", - "/release/mainTwoChunks-LOCALE1-cfdd1876abd4e14c70f8.js": "/******/ (() => { // webpackBootstrap + "/release/mainTwoChunks-LOCALE1-5efaa974620f14b4f849.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -708,6 +726,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -786,6 +810,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -934,7 +961,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\"));__webpack_require__.e(/* import() | async2 */ 421).then(__webpack_require__.bind(__webpack_require__, \\"./a/async2.js\\")); /******/ })() ;", - "/release/mainTwoChunks-LOCALE2-63de465a5cef8fc90a51.js": "/******/ (() => { // webpackBootstrap + "/release/mainTwoChunks-LOCALE2-621e175eb55ea9b3280f.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -965,6 +992,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -1043,6 +1076,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { diff --git a/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntimeDifferentHashLengths.test.ts.snap b/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntimeDifferentHashLengths.test.ts.snap index cdc0c726246..d635b9d6af8 100644 --- a/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntimeDifferentHashLengths.test.ts.snap +++ b/webpack/webpack5-localization-plugin/src/test/__snapshots__/LocalizedRuntimeDifferentHashLengths.test.ts.snap @@ -6,10 +6,10 @@ Object { "/release/chunks/async1-LOCALE2-fa6798298a8e8fb0d1bfe76c5e91205c5fed97626fa266ba799a906a58a693e8.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[230],{\\"./a/async1.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test,a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"baz\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"some random translation\\"}}}]);", "/release/chunks/async2-LOCALE1-2878fc254efcf861ebdb1de8ffe2da978f78d90bdb657ca96126fe284386851a.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[421],{\\"./a/async2.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test+a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"blah\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"something else\\"}}}]);", "/release/chunks/async2-LOCALE2-c2b6b66a1486798af745222597d7f7f64daf16f5566e28a3e34dda6da6f41f87.js": "\\"use strict\\";(self.webpackChunk=self.webpackChunk||[]).push([[421],{\\"./a/async2.js\\":(s,e,_)=>{_.r(e);var n=_(\\"./a/strings1.resjson\\"),a=_(\\"./a/strings2.resjson\\");console.log(n.A.test+a.A.another)},\\"./a/strings1.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={test:\\"baz\\"}},\\"./a/strings2.resjson\\":(s,e,_)=>{_.d(e,{A:()=>n});const n={another:\\"some random translation\\"}}}]);", - "/release/mainSingleChunk-LOCALE1-179143d6cdf37c2d8ddf8bdec1e84471cf20bcf862e85158609ce777b1a5e0bc.js": "(()=>{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/async1-\\"+\\"LOCALE1\\"+\\"-9bd32294abc47c2bd95cbd4f4a64ac12f94cfd89dbb3cc1056c8ca83c94b3f83.js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var l=document.getElementsByTagName(\\"script\\"),s=0;s{i.onerror=i.onload=null,clearTimeout(d);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},d=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={331:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,l]=t,s=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);l&&l(o)}for(r&&r(t);s{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/async1-\\"+\\"LOCALE2\\"+\\"-fa6798298a8e8fb0d1bfe76c5e91205c5fed97626fa266ba799a906a58a693e8.js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var l=document.getElementsByTagName(\\"script\\"),s=0;s{i.onerror=i.onload=null,clearTimeout(d);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},d=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={331:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,l]=t,s=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);l&&l(o)}for(r&&r(t);s{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE1\\"+\\"-\\"+{230:\\"9bd32294abc47c2bd95cbd4f4a64ac12f94cfd89dbb3cc1056c8ca83c94b3f83\\",421:\\"2878fc254efcf861ebdb1de8ffe2da978f78d90bdb657ca96126fe284386851a\\"}[e]+\\".js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var s=document.getElementsByTagName(\\"script\\"),l=0;l{i.onerror=i.onload=null,clearTimeout(p);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},p=setTimeout(d.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={580:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,s]=t,l=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);s&&s(o)}for(r&&r(t);l{var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var a=t[e]={exports:{}};return r[e](a,a.exports,o),a.exports}o.m=r,o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.f={},o.e=e=>Promise.all(Object.keys(o.f).reduce(((r,t)=>(o.f[t](e,r),r)),[])),o.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE2\\"+\\"-\\"+{230:\\"fa6798298a8e8fb0d1bfe76c5e91205c5fed97626fa266ba799a906a58a693e8\\",421:\\"c2b6b66a1486798af745222597d7f7f64daf16f5566e28a3e34dda6da6f41f87\\"}[e]+\\".js\\",o.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},o.l=(r,t,n,a)=>{if(e[r])e[r].push(t);else{var i,c;if(void 0!==n)for(var s=document.getElementsByTagName(\\"script\\"),l=0;l{i.onerror=i.onload=null,clearTimeout(p);var n=e[r];if(delete e[r],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(o))),t)return t(o)},p=setTimeout(d.bind(null,void 0,{type:\\"timeout\\",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),c&&document.head.appendChild(i)}},o.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;o.g.importScripts&&(e=o.g.location+\\"\\");var r=o.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName(\\"script\\");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),o.p=e})(),(()=>{var e={580:0};o.f.j=(r,t)=>{var n=o.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=a);var i=o.p+o.u(r),c=new Error;o.l(i,(t=>{if(o.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&(\\"load\\"===t.type?\\"missing\\":t.type),i=t&&t.target&&t.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,t)=>{var n,a,[i,c,s]=t,l=0;if(i.some((r=>0!==e[r]))){for(n in c)o.o(c,n)&&(o.m[n]=c[n]);s&&s(o)}for(r&&r(t);l{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/async1-\\"+\\"LOCALE1\\"+\\"-9bd32294abc47c2bd95cbd4f4a64ac12f94cfd89dbb3cc1056c8ca83c94b3f83.js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,l;if(void 0!==a)for(var s=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),l&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={331:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,l]=o,s=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);l&&l(t)}for(r&&r(o);s{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/async1-\\"+\\"LOCALE2\\"+\\"-fa6798298a8e8fb0d1bfe76c5e91205c5fed97626fa266ba799a906a58a693e8.js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,l;if(void 0!==a)for(var s=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),l&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={331:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,l]=o,s=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);l&&l(t)}for(r&&r(o);s{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE1\\"+\\"-\\"+{230:\\"9bd32294abc47c2bd95cbd4f4a64ac12f94cfd89dbb3cc1056c8ca83c94b3f83\\",421:\\"2878fc254efcf861ebdb1de8ffe2da978f78d90bdb657ca96126fe284386851a\\"}[e]+\\".js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,s;if(void 0!==a)for(var l=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),s&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={580:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,s]=o,l=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);s&&s(t)}for(r&&r(o);l{var e={},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var a=r[o]={exports:{}};return e[o](a,a.exports,t),a.exports}t.m=e;var o,n=/* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"};t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((r,o)=>(t.f[o](e,r),r)),[])),t.u=e=>\\"chunks/\\"+{230:\\"async1\\",421:\\"async2\\"}[e]+\\"-\\"+\\"LOCALE2\\"+\\"-\\"+{230:\\"fa6798298a8e8fb0d1bfe76c5e91205c5fed97626fa266ba799a906a58a693e8\\",421:\\"c2b6b66a1486798af745222597d7f7f64daf16f5566e28a3e34dda6da6f41f87\\"}[e]+\\".js\\",t.g=function(){if(\\"object\\"==typeof globalThis)return globalThis;try{return this||new Function(\\"return this\\")()}catch(e){if(\\"object\\"==typeof window)return window}}(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o={},t.l=(e,r,a,i)=>{if(o[e])o[e].push(r);else{var c,s;if(void 0!==a)for(var l=document.getElementsByTagName(\\"script\\"),u=0;u{c.onerror=c.onload=null,clearTimeout(f);var n=o[e];if(delete o[e],c.parentNode&&c.parentNode.removeChild(c),n&&n.forEach((e=>e(t))),r)return r(t)},f=setTimeout(p.bind(null,void 0,{type:\\"timeout\\",target:c}),12e4);c.onerror=p.bind(null,c.onerror),c.onload=p.bind(null,c.onload),s&&document.head.appendChild(c)}},t.r=e=>{\\"undefined\\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\\"Module\\"}),Object.defineProperty(e,\\"__esModule\\",{value:!0})},(()=>{var e;t.g.importScripts&&(e=t.g.location+\\"\\");var r=t.g.document;if(!e&&r&&(r.currentScript&&\\"SCRIPT\\"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var o=r.getElementsByTagName(\\"script\\");if(o.length)for(var n=o.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=o[n--].src}if(!e)throw new Error(\\"Automatic publicPath is not supported in this browser\\");e=e.replace(/^blob:/,\\"\\").replace(/#.*$/,\\"\\").replace(/\\\\?.*$/,\\"\\").replace(/\\\\/[^\\\\/]+$/,\\"/\\"),t.p=e})(),(()=>{var e={580:0};t.f.j=(r,o)=>{var n=t.o(e,r)?e[r]:void 0;if(0!==n)if(n)o.push(n[2]);else{var a=new Promise(((t,o)=>n=e[r]=[t,o]));o.push(n[2]=a);var i=t.p+t.u(r),c=new Error;t.l(i,(o=>{if(t.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=o&&(\\"load\\"===o.type?\\"missing\\":o.type),i=o&&o.target&&o.target.src;c.message=\\"Loading chunk \\"+r+\\" failed.\\\\n(\\"+a+\\": \\"+i+\\")\\",c.name=\\"ChunkLoadError\\",c.type=a,c.request=i,n[1](c)}}),\\"chunk-\\"+r,r)}};var r=(r,o)=>{var n,a,[i,c,s]=o,l=0;if(i.some((r=>0!==e[r]))){for(n in c)t.o(c,n)&&(t.m[n]=c[n]);s&&s(t)}for(r&&r(o);l { // webpackBootstrap + "/release/mainSingleChunk-LOCALE1-d6fa89a28e2fa52fe9de08e06af1bbadddce89ce7bcef6c01d2709993630806b.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -194,6 +194,12 @@ const strings = {\\"another\\":\\"some random translation\\"}; /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -272,6 +278,9 @@ const strings = {\\"another\\":\\"some random translation\\"}; /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -420,7 +429,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\")); /******/ })() ;", - "/release/mainSingleChunk-LOCALE2-b2e39e32c029a427c28af2e128dabbbbfbcd9f486499430fc62d0e900bc979ff.js": "/******/ (() => { // webpackBootstrap + "/release/mainSingleChunk-LOCALE2-6ce640a695a120867bdbd13eb91fa9cccb619aa0468f5f6997dc775abbdb8133.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -451,6 +460,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -529,6 +544,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -677,7 +695,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\")); /******/ })() ;", - "/release/mainTwoChunks-LOCALE1-f7cd4b957f36ff5c60b9e4dfff02b4200b71e754ae1d9fe44edb8cc62950b59e.js": "/******/ (() => { // webpackBootstrap + "/release/mainTwoChunks-LOCALE1-88b9507279db4beebecf847e23c169f45022bf8fed391e23a91aeb3201799771.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -708,6 +726,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE1 */ {\\"async1\\":\\"async1-LOCALE1-123456\\",\\"async2\\":\\"async2-LOCALE1-123456\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -786,6 +810,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { @@ -934,7 +961,7 @@ var __webpack_exports__ = {}; __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind(__webpack_require__, \\"./a/async1.js\\"));__webpack_require__.e(/* import() | async2 */ 421).then(__webpack_require__.bind(__webpack_require__, \\"./a/async2.js\\")); /******/ })() ;", - "/release/mainTwoChunks-LOCALE2-aaf5ae131e791886ef6259d6318b94aa867c88c7913622857594843d03f2c039.js": "/******/ (() => { // webpackBootstrap + "/release/mainTwoChunks-LOCALE2-d7460ccdbe34a16a0224016e2120e797b3b1489308d88f1f5d9f2c6b1c4eb415.js": "/******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({}); /************************************************************************/ /******/ // The module cache @@ -965,6 +992,12 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ __webpack_require__.m = __webpack_modules__; /******/ /************************************************************************/ +/******/ /* webpack/runtime/custom data module */ +/******/ var localizedChunkNames = /* LOCALE2 */ {\\"async1\\":\\"async1-LOCALE2-abcdef\\",\\"async2\\":\\"async2-LOCALE2-abcdef\\"}; +/******/ function printLocalizedChunkName(chunkId) { +/******/ console.log(localizedChunkNames[chunkId]); +/******/ } +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -1043,6 +1076,9 @@ __webpack_require__.e(/* import() | async1 */ 230).then(__webpack_require__.bind /******/ /******/ /******/ script.src = url; +/******/ +/******/ +/******/ printLocalizedChunkName(chunkId); /******/ } /******/ inProgress[url] = [done]; /******/ var onScriptComplete = (prev, event) => { diff --git a/webpack/webpack5-localization-plugin/src/utilities/Constants.ts b/webpack/webpack5-localization-plugin/src/utilities/Constants.ts index a8870b4453b..0e01025361f 100644 --- a/webpack/webpack5-localization-plugin/src/utilities/Constants.ts +++ b/webpack/webpack5-localization-plugin/src/utilities/Constants.ts @@ -13,6 +13,7 @@ export const RESOURCE_FILE_NAME_REGEXP: RegExp = /\.(resx|resx\.json|loc\.json|r export const STRING_PLACEHOLDER_LABEL: 'A' = 'A'; export const LOCALE_NAME_PLACEHOLDER_LABEL: 'B' = 'B'; export const JSONP_PLACEHOLDER_LABEL: 'C' = 'C'; +export const CUSTOM_PLACEHOLDER_LABEL: 'D' = 'D'; // _LOCALIZED_STRING_f12dy0i7_n4bo_dqwj_39gf_sasqehjmihz9_B_ export const LOCALE_NAME_PLACEHOLDER: `${typeof STRING_PLACEHOLDER_PREFIX}_${typeof LOCALE_NAME_PLACEHOLDER_LABEL}_` = `${STRING_PLACEHOLDER_PREFIX}_${LOCALE_NAME_PLACEHOLDER_LABEL}_`;