Skip to content

Commit d10e148

Browse files
committed
Generate JSON locale files in build
1 parent 930a5b8 commit d10e148

1 file changed

Lines changed: 60 additions & 3 deletions

File tree

vite.config.js

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { exec } from 'child_process';
22
import { existsSync } from 'fs';
3-
import { appendFile, cp, mkdir, readFile, writeFile } from 'fs/promises';
3+
import { appendFile, cp, mkdir, readdir, readFile, writeFile } from 'fs/promises';
44
import path from 'path';
5+
import { fileURLToPath } from 'url';
56

67
import { svelte } from '@sveltejs/vite-plugin-svelte';
78
import { isObject } from '@sveltia/utils/object';
@@ -26,6 +27,14 @@ const MAIN_TYPE_PATH = 'package/main.d.ts';
2627
* Path to the generated public type declaration file.
2728
*/
2829
const PUBLIC_TYPE_PATH = 'package/types/public.d.ts';
30+
/**
31+
* Path to the app’s locale files.
32+
*/
33+
const APP_LOCALES_DIR = 'src/lib/locales';
34+
/**
35+
* Path to the generated locale files.
36+
*/
37+
const OUTPUT_LOCALES_DIR = 'package/locales';
2938

3039
/**
3140
* Recursively squash multiline strings in a parsed YAML object into single lines.
@@ -109,7 +118,7 @@ const copyPackageFiles = () => ({
109118
devDependencies: Object.fromEntries(
110119
DEV_DEPENDENCIES.map((key) => [key, dependencies[key] ?? devDependencies[key]]),
111120
),
112-
files: ['dist', 'schema', 'services', 'types', 'main.d.ts'],
121+
files: ['dist', 'locales', 'schema', 'services', 'types', 'main.d.ts'],
113122
main: './dist/sveltia-cms.mjs',
114123
module: './dist/sveltia-cms.mjs',
115124
exports: {
@@ -216,7 +225,54 @@ const generateSchema = async () => {
216225
};
217226

218227
/**
219-
* Generate extra files such as TypeScript type declaration and JSON schema.
228+
* Read a YAML file and parse it, stripping comments and squashing multiline strings, just like the
229+
* {@link yamlToJS} plugin does for imported YAML files.
230+
* @param {string} filePath Path to the YAML file.
231+
* @returns {Promise<Record<string, any>>} Parsed object.
232+
*/
233+
const parseYAMLFile = async (filePath) =>
234+
/** @type {Record<string, any>} */ (squashStrings(parseYAML(await readFile(filePath, 'utf-8'))));
235+
236+
/**
237+
* Generate JSON locale files from the YAML sources. The Sveltia CMS strings are merged with the
238+
* Sveltia UI strings, the latter being prefixed with `_sui`, in the same way as `initAppLocale`
239+
* does at runtime. These files are published so that developers can look up the string keys, for
240+
* example to override some strings with the `i18n` option.
241+
* @see https://unpkg.com/@sveltia/cms/locales/en-US.json - Our published locale file
242+
*/
243+
const generateLocales = async () => {
244+
// Resolve the path to the locale files bundled with the `@sveltia/ui` package
245+
const uiLocalesDir = path.resolve(
246+
path.dirname(fileURLToPath(import.meta.resolve('@sveltia/ui'))),
247+
'locales',
248+
);
249+
250+
const locales = (await readdir(APP_LOCALES_DIR))
251+
.filter((name) => name.endsWith('.yaml'))
252+
.map((name) => path.basename(name, '.yaml'));
253+
254+
await mkdir(OUTPUT_LOCALES_DIR, { recursive: true });
255+
256+
await Promise.all(
257+
locales.map(async (locale) => {
258+
const uiLocalePath = path.resolve(uiLocalesDir, `${locale}.yaml`);
259+
260+
const [appStrings, componentStrings] = await Promise.all([
261+
parseYAMLFile(path.resolve(APP_LOCALES_DIR, `${locale}.yaml`)),
262+
// Sveltia UI may not have the locale yet
263+
existsSync(uiLocalePath) ? parseYAMLFile(uiLocalePath) : {},
264+
]);
265+
266+
await writeFile(
267+
path.resolve(OUTPUT_LOCALES_DIR, `${locale}.json`),
268+
JSON.stringify({ ...appStrings, _sui: componentStrings }).concat('\n'),
269+
);
270+
}),
271+
);
272+
};
273+
274+
/**
275+
* Generate extra files such as TypeScript type declaration, JSON schema and JSON locales.
220276
* @returns {import('vite').Plugin} Vite plugin.
221277
*/
222278
const generateExtraFiles = () => ({
@@ -229,6 +285,7 @@ const generateExtraFiles = () => ({
229285
handler: async () => {
230286
await generateTypes();
231287
await generateSchema();
288+
await generateLocales();
232289
},
233290
},
234291
});

0 commit comments

Comments
 (0)