import { joinPathFragments, logger } from '@nx/devkit';
import { basename } from 'path';
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
interface GenerateAndServeConfiguration {
[locale: string]: {
serveTarget: string;
};
}
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
interface BuildTargetConfiguration {
[locale: string]: {
localize: string[];
};
}
interface InternationalizationConfiguration {
sourceLocale: SourceLocaleConfiguration;
locales: LocaleConfiguration;
}
interface SourceLocaleConfiguration {
code: string;
baseHref: string;
}
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
interface LocaleConfiguration {
[locale: string]: {
translation: string;
baseHref: string;
};
}
export function extractInternationalizationGenerateAndServeConfigurations(
locales: string[],
projectName: string
): GenerateAndServeConfiguration {
return locales.reduce((acc, locale: string) => {
return {
...acc,
[locale]: {
serveTarget: `${projectName}:serve-generated-app:${locale}`
}
};
}, {});
}
export function extractInternationalizationBuildConfigurations(
locales: string[],
localesDestinationFolder: string
): BuildTargetConfiguration {
return locales.reduce((acc, locale: string) => {
return {
...acc,
[locale]: {
localize: [locale],
fileReplacements: [
{
replace: joinPathFragments(localesDestinationFolder, 'locale.ts'),
with: joinPathFragments(localesDestinationFolder, `locale.${locale}.ts`)
}
]
}
};
}, {});
}
export function extractInternationalizationServeConfigurations(
locales: string[],
projectName: string
): BuildTargetConfiguration {
return locales.reduce((acc, locale: string) => {
return {
...acc,
[locale]: {
buildTarget: `${projectName}:build-generated-app:${locale}`
}
};
}, {});
}
export function extractInternationalizationRootConfiguration(
sourceLocale: SourceLocaleConfiguration | undefined,
localeFilePaths: string[],
stripLocaleBaseHref = false
): InternationalizationConfiguration {
const localeConfig: LocaleConfiguration = localeFilePaths.reduce((acc, localeFilePath) => {
const locale = extractLocaleFromFilePath(localeFilePath);
if (!locale) {
return acc;
}
return {
...acc,
[locale]: {
translation: localeFilePath,
baseHref: stripLocaleBaseHref ? '' : `/${locale}/`
}
};
}, {});
let updatedSourceLocale: SourceLocaleConfiguration;
const defaultSourceLocaleCode = 'en-US';
const defaultSourceLocaleConflictsWithTranslations = localeFilePaths.some((localesValue) =>
localesValue.includes(defaultSourceLocaleCode)
);
const configuredSourceLocaleConflictsWithTranslations = sourceLocale?.code
? localeFilePaths.some((localesValue) => localesValue.includes(sourceLocale.code))
: false;
if (sourceLocale?.code && !configuredSourceLocaleConflictsWithTranslations) {
updatedSourceLocale = {
code: sourceLocale.code,
baseHref: stripLocaleBaseHref ? '' : sourceLocale.baseHref
};
} else if (
configuredSourceLocaleConflictsWithTranslations ||
defaultSourceLocaleConflictsWithTranslations
) {
if (configuredSourceLocaleConflictsWithTranslations) {
logger.warn(
`⚠️ The existent "sourceLocale.code" ${
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
sourceLocale!.code
} conflicts with one of the translation files and was therefore removed by TALY. Please set the "sourceLocale.code" manually.`
);
} else {
logger.warn(
`⚠️ The default "sourceLocale.code" ${defaultSourceLocaleCode} could not be set by TALY, since it conflicts with one of the translation files. Please set the "sourceLocale.code" manually.`
);
}
// set sourceLocale to empty string if sourceLocale conflicts with translation files
updatedSourceLocale = {
code: '',
baseHref: ''
};
} else {
// set sourceLocales to default en-US if there is no preset value
updatedSourceLocale = {
code: defaultSourceLocaleCode,
baseHref: stripLocaleBaseHref ? '' : `/${defaultSourceLocaleCode}/`
};
}
return {
sourceLocale: updatedSourceLocale,
locales: localeConfig
};
}
export function extractLocalesFromFileNames(localeFilePaths: string[]): string[] {
return localeFilePaths
.map(extractLocaleFromFilePath)
.filter((locale): locale is string => Boolean(locale));
}
function extractLocaleFromFilePath(filePath: string): string | undefined {
const fileName = basename(filePath);
//ignore dotfiles
if (fileName.startsWith('.')) {
return undefined;
}
const fileNameParts = fileName.match(/^[a-z-]+\.([a-z-]+)\.[a-z-]+$/i);
if (fileNameParts === null) {
throw new Error(
`The given file name ${fileName} is not an accepted file name for translations. Please use the format: "messages.[locale].[extension]".`
);
}
return fileNameParts[1];
}