-
-
Notifications
You must be signed in to change notification settings - Fork 424
Expand file tree
/
Copy pathgenerate-i18n-schema.ts
More file actions
76 lines (64 loc) · 2.36 KB
/
generate-i18n-schema.ts
File metadata and controls
76 lines (64 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* oxlint-disable no-console */
import { readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { colors } from './utils/colors.ts'
const I18N_DIRECTORY = join(import.meta.dirname, '../i18n')
const LOCALES_DIRECTORY = join(I18N_DIRECTORY, 'locales')
const REFERENCE_FILE_NAME = 'en.json'
const SCHEMA_FILE_NAME = 'schema.json'
type Json = Record<string, unknown>
type LocaleJson = Json & { $schema: string }
interface JsonSchema {
$schema?: string
title?: string
description?: string
type: string
properties?: Record<string, JsonSchema>
additionalProperties?: boolean
}
const generateSubSchema = (obj: Json): JsonSchema => {
const properties: Record<string, JsonSchema> = {}
for (const [key, value] of Object.entries(obj)) {
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
properties[key] = generateSubSchema(value as Json)
} else {
properties[key] = { type: 'string' }
}
}
return {
type: 'object',
properties,
additionalProperties: false,
}
}
const generateSchema = (obj: LocaleJson): JsonSchema => {
const { $schema: _, ...rest } = obj // Exclude $schema from schema generation
const baseSchema = generateSubSchema(rest)
return {
$schema: 'http://json-schema.org/draft-07/schema#',
title: 'npmx i18n locale file',
description:
'Schema for npmx i18n translation files. Generated from en.json — do not edit manually.',
...baseSchema,
// Allow $schema property at root level
properties: {
...baseSchema.properties,
$schema: { type: 'string' },
},
}
}
/*
* Generates a JSON Schema from the reference locale file (en.json) and writes it to
* i18n/schema.json. All locale files include a $schema property that points to this file.
*
* This allows IDEs to provide validation, autocompletion, and other hints in translation files.
*/
const main = async (): Promise<void> => {
const referenceFilePath = join(LOCALES_DIRECTORY, REFERENCE_FILE_NAME)
const referenceContent = JSON.parse(await readFile(referenceFilePath, 'utf-8')) as LocaleJson
const schema = generateSchema(referenceContent)
const schemaFilePath = join(I18N_DIRECTORY, SCHEMA_FILE_NAME)
await writeFile(schemaFilePath, JSON.stringify(schema, null, 2) + '\n', 'utf-8')
console.log(colors.green(`✅ Generated schema at ${schemaFilePath}`))
}
await main()