aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/generateLocales.ts164
1 files changed, 144 insertions, 20 deletions
diff --git a/scripts/generateLocales.ts b/scripts/generateLocales.ts
index 0d3d2fd2..4419e523 100644
--- a/scripts/generateLocales.ts
+++ b/scripts/generateLocales.ts
@@ -4,6 +4,9 @@ import type { Options } from 'prettier';
import { format } from 'prettier';
import options from '../.prettierrc.cjs';
import type { LocaleDefinition } from '../src';
+import { DEFINITIONS } from '../src/definitions';
+
+// Constants
const pathRoot = resolve(__dirname, '..');
const pathLocale = resolve(pathRoot, 'src', 'locale');
@@ -16,36 +19,58 @@ const pathDocsApiLocalization = resolve(
'localization.md'
);
-const scriptCommand = 'pnpm run generate:locales';
const prettierTsOptions: Options = { ...options, parser: 'typescript' };
const prettierMdOptions: Options = { ...options, parser: 'markdown' };
-const locales = readdirSync(pathLocales);
-locales.splice(locales.indexOf('index.ts'), 1);
-
-let localeIndexImports = "import type { LocaleDefinition } from '..';\n";
-let localeIndexType = 'export type KnownLocale =\n';
-let localeIndexLocales = 'const locales: KnownLocales = {\n';
-
-let localizationLocales = '| Locale | Name |\n| :--- | :--- |\n';
+const scriptCommand = 'pnpm run generate:locales';
const autoGeneratedCommentHeader = `/*
* This file is automatically generated.
* Run '${scriptCommand}' to update.
*/`;
-for (const locale of locales) {
- // eslint-disable-next-line @typescript-eslint/no-var-requires
- const localeDef: LocaleDefinition = require('../src/locales/' +
- locale).default;
- const localeTitle = localeDef.title;
+// Helper functions
- localeIndexImports += `import ${locale} from './${locale}';\n`;
- localeIndexType += ` | '${locale}'\n`;
- localeIndexLocales += ` ${locale},\n`;
- localizationLocales += `| ${locale} | ${localeTitle} |\n`;
+function removeIndexTs(files: string[]): string[] {
+ const index = files.indexOf('index.ts');
+ if (index !== -1) {
+ files.splice(index, 1);
+ }
+ return files;
+}
- // src/locale/<locale>.ts
+function removeTsSuffix(files: string[]): string[] {
+ return files.map((file) => file.replace('.ts', ''));
+}
+
+function escapeImport(module: string): string {
+ if (module === 'name') {
+ return 'name_';
+ } else if (module === 'type') {
+ return 'type_';
+ } else {
+ return module;
+ }
+}
+
+function escapeField(module: string): string {
+ if (module === 'name') {
+ return 'name: name_';
+ } else if (module === 'type') {
+ return 'type: type_';
+ } else {
+ return module;
+ }
+}
+
+function containsAll(checked?: string[], expected?: string[]): boolean {
+ if (typeof expected === 'undefined' || typeof checked === 'undefined') {
+ return true;
+ }
+ return expected.every((c) => checked.includes(c));
+}
+
+function generateLocaleFile(locale: string) {
let content = `
${autoGeneratedCommentHeader}
@@ -69,6 +94,106 @@ for (const locale of locales) {
writeFileSync(resolve(pathLocale, locale + '.ts'), content);
}
+function generateLocalesIndexFile(
+ path: string,
+ name: string,
+ type: string,
+ depth: number,
+ extra: string = '',
+ expected?: string[]
+) {
+ let modules = readdirSync(path);
+ modules = removeIndexTs(modules);
+ modules = removeTsSuffix(modules);
+ const importType = type;
+ if (!containsAll(modules, expected)) {
+ type = `Partial<${type}>`;
+ }
+ let fieldType = '';
+ let asType = '';
+ if (!containsAll(expected, modules)) {
+ asType = ` as ${type}`;
+ } else {
+ fieldType = `: ${type}`;
+ }
+ let content = `${autoGeneratedCommentHeader}
+ import type { ${importType} } from '..${'/..'.repeat(depth)}';
+ ${modules
+ .map((module) => `import ${escapeImport(module)} from './${module}';`)
+ .join('\n')}
+
+ const ${name}${fieldType} = {
+ ${extra}
+ ${modules.map((module) => `${escapeField(module)},`).join('\n')}
+ }${asType};
+
+ export default ${name};
+ `;
+ content = format(content, prettierTsOptions);
+ writeFileSync(resolve(path, 'index.ts'), content);
+}
+
+// Start of actual logic
+
+const locales = readdirSync(pathLocales);
+removeIndexTs(locales);
+
+let localeIndexImports = "import type { LocaleDefinition } from '..';\n";
+let localeIndexType = 'export type KnownLocale =\n';
+let localeIndexLocales = 'const locales: KnownLocales = {\n';
+
+let localizationLocales = '| Locale | Name |\n| :--- | :--- |\n';
+
+for (const locale of locales) {
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ const localeDef: LocaleDefinition = require('../src/locales/' +
+ locale).default;
+ const localeTitle = localeDef.title;
+ const localeSeparator = localeDef.separator;
+
+ localeIndexImports += `import ${locale} from './${locale}';\n`;
+ localeIndexType += ` | '${locale}'\n`;
+ localeIndexLocales += ` ${locale},\n`;
+ localizationLocales += `| ${locale} | ${localeTitle} |\n`;
+
+ // src/locale/<locale>.ts
+ generateLocaleFile(locale);
+
+ // src/locales/<locale>/index.ts
+ const pathModules = resolve(pathLocales, locale);
+ generateLocalesIndexFile(
+ pathModules,
+ locale,
+ 'LocaleDefinition',
+ 1,
+ `title: '${localeTitle}',` +
+ (localeSeparator ? `\nseparator: '${localeSeparator}',` : ''),
+ undefined
+ );
+
+ let modules = readdirSync(pathModules);
+ modules = removeIndexTs(modules);
+ modules = removeTsSuffix(modules);
+ for (const module of modules) {
+ // src/locales/<locale>/<module>/index.ts
+ const pathModule = resolve(pathModules, module);
+ const moduleFiles: string[] = DEFINITIONS[module];
+ if (typeof moduleFiles === 'undefined') {
+ continue;
+ }
+ generateLocalesIndexFile(
+ pathModule,
+ module,
+ `${module.replace(/(^|_)([a-z])/g, (s) =>
+ s.replace('_', '').toUpperCase()
+ )}Definitions`,
+ 2,
+ '',
+ moduleFiles
+ );
+ }
+}
+
// src/locales/index.ts
let indexContent = `
@@ -86,7 +211,6 @@ let indexContent = `
`;
indexContent = format(indexContent, prettierTsOptions);
-
writeFileSync(pathLocalesIndex, indexContent);
// docs/api/localization.md