@objectql/cli 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/IMPLEMENTATION_SUMMARY.md +437 -0
- package/README.md +385 -7
- package/USAGE_EXAMPLES.md +804 -0
- package/__tests__/commands.test.ts +153 -0
- package/dist/commands/i18n.d.ts +27 -0
- package/dist/commands/i18n.js +280 -0
- package/dist/commands/i18n.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +202 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/migrate.d.ts +26 -0
- package/dist/commands/migrate.js +301 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/new.d.ts +7 -0
- package/dist/commands/new.js +279 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/studio.js +70 -9
- package/dist/commands/studio.js.map +1 -1
- package/dist/index.js +130 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/commands/i18n.ts +303 -0
- package/src/commands/init.ts +191 -0
- package/src/commands/migrate.ts +314 -0
- package/src/commands/new.ts +268 -0
- package/src/commands/studio.ts +75 -10
- package/src/index.ts +131 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { newMetadata } from '../src/commands/new';
|
|
4
|
+
import { i18nExtract, i18nInit, i18nValidate } from '../src/commands/i18n';
|
|
5
|
+
|
|
6
|
+
describe('CLI Commands', () => {
|
|
7
|
+
const testDir = path.join(__dirname, '__test_output__');
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
// Create test directory
|
|
11
|
+
if (!fs.existsSync(testDir)) {
|
|
12
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
// Clean up test directory
|
|
18
|
+
if (fs.existsSync(testDir)) {
|
|
19
|
+
fs.rmSync(testDir, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('new command', () => {
|
|
24
|
+
it('should create an object file', async () => {
|
|
25
|
+
await newMetadata({
|
|
26
|
+
type: 'object',
|
|
27
|
+
name: 'test_users',
|
|
28
|
+
dir: testDir
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const filePath = path.join(testDir, 'test_users.object.yml');
|
|
32
|
+
expect(fs.existsSync(filePath)).toBe(true);
|
|
33
|
+
|
|
34
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
35
|
+
expect(content).toContain('label: Test Users');
|
|
36
|
+
expect(content).toContain('type: text');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should create action with both yml and ts files', async () => {
|
|
40
|
+
await newMetadata({
|
|
41
|
+
type: 'action',
|
|
42
|
+
name: 'test_action',
|
|
43
|
+
dir: testDir
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const ymlPath = path.join(testDir, 'test_action.action.yml');
|
|
47
|
+
const tsPath = path.join(testDir, 'test_action.action.ts');
|
|
48
|
+
|
|
49
|
+
expect(fs.existsSync(ymlPath)).toBe(true);
|
|
50
|
+
expect(fs.existsSync(tsPath)).toBe(true);
|
|
51
|
+
|
|
52
|
+
const tsContent = fs.readFileSync(tsPath, 'utf-8');
|
|
53
|
+
expect(tsContent).toContain('action_test_action');
|
|
54
|
+
expect(tsContent).toContain('ActionContext');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should create hook with both yml and ts files', async () => {
|
|
58
|
+
await newMetadata({
|
|
59
|
+
type: 'hook',
|
|
60
|
+
name: 'test_hook',
|
|
61
|
+
dir: testDir
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const ymlPath = path.join(testDir, 'test_hook.hook.yml');
|
|
65
|
+
const tsPath = path.join(testDir, 'test_hook.hook.ts');
|
|
66
|
+
|
|
67
|
+
expect(fs.existsSync(ymlPath)).toBe(true);
|
|
68
|
+
expect(fs.existsSync(tsPath)).toBe(true);
|
|
69
|
+
|
|
70
|
+
const tsContent = fs.readFileSync(tsPath, 'utf-8');
|
|
71
|
+
expect(tsContent).toContain('beforeInsert');
|
|
72
|
+
expect(tsContent).toContain('afterInsert');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should validate object name format', async () => {
|
|
76
|
+
await expect(
|
|
77
|
+
newMetadata({
|
|
78
|
+
type: 'object',
|
|
79
|
+
name: 'InvalidName', // Should be lowercase
|
|
80
|
+
dir: testDir
|
|
81
|
+
})
|
|
82
|
+
).rejects.toThrow();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('i18n commands', () => {
|
|
87
|
+
beforeEach(async () => {
|
|
88
|
+
// Create a test object file
|
|
89
|
+
await newMetadata({
|
|
90
|
+
type: 'object',
|
|
91
|
+
name: 'test_users',
|
|
92
|
+
dir: testDir
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should extract translatable strings', async () => {
|
|
97
|
+
await i18nExtract({
|
|
98
|
+
source: testDir,
|
|
99
|
+
output: path.join(testDir, 'i18n'),
|
|
100
|
+
lang: 'en'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const i18nFile = path.join(testDir, 'i18n/en/test_users.json');
|
|
104
|
+
expect(fs.existsSync(i18nFile)).toBe(true);
|
|
105
|
+
|
|
106
|
+
const content = JSON.parse(fs.readFileSync(i18nFile, 'utf-8'));
|
|
107
|
+
expect(content.label).toBe('Test Users');
|
|
108
|
+
expect(content.fields.name.label).toBe('Name');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should initialize new language', async () => {
|
|
112
|
+
await i18nInit({
|
|
113
|
+
lang: 'zh-CN',
|
|
114
|
+
baseDir: path.join(testDir, 'i18n')
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const langDir = path.join(testDir, 'i18n/zh-CN');
|
|
118
|
+
expect(fs.existsSync(langDir)).toBe(true);
|
|
119
|
+
|
|
120
|
+
const commonFile = path.join(langDir, 'common.json');
|
|
121
|
+
expect(fs.existsSync(commonFile)).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should validate translations', async () => {
|
|
125
|
+
// Extract for base language
|
|
126
|
+
await i18nExtract({
|
|
127
|
+
source: testDir,
|
|
128
|
+
output: path.join(testDir, 'i18n'),
|
|
129
|
+
lang: 'en'
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Extract for target language
|
|
133
|
+
await i18nInit({
|
|
134
|
+
lang: 'zh-CN',
|
|
135
|
+
baseDir: path.join(testDir, 'i18n')
|
|
136
|
+
});
|
|
137
|
+
await i18nExtract({
|
|
138
|
+
source: testDir,
|
|
139
|
+
output: path.join(testDir, 'i18n'),
|
|
140
|
+
lang: 'zh-CN'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Should not throw - validation passes
|
|
144
|
+
await expect(
|
|
145
|
+
i18nValidate({
|
|
146
|
+
lang: 'zh-CN',
|
|
147
|
+
baseDir: path.join(testDir, 'i18n'),
|
|
148
|
+
baseLang: 'en'
|
|
149
|
+
})
|
|
150
|
+
).resolves.not.toThrow();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface I18nExtractOptions {
|
|
2
|
+
source?: string;
|
|
3
|
+
output?: string;
|
|
4
|
+
lang?: string;
|
|
5
|
+
}
|
|
6
|
+
interface I18nInitOptions {
|
|
7
|
+
lang: string;
|
|
8
|
+
baseDir?: string;
|
|
9
|
+
}
|
|
10
|
+
interface I18nValidateOptions {
|
|
11
|
+
lang: string;
|
|
12
|
+
baseDir?: string;
|
|
13
|
+
baseLang?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract translatable strings from metadata files and create i18n files
|
|
17
|
+
*/
|
|
18
|
+
export declare function i18nExtract(options: I18nExtractOptions): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Initialize i18n structure for a new language
|
|
21
|
+
*/
|
|
22
|
+
export declare function i18nInit(options: I18nInitOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate translation completeness
|
|
25
|
+
*/
|
|
26
|
+
export declare function i18nValidate(options: I18nValidateOptions): Promise<void>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.i18nExtract = i18nExtract;
|
|
40
|
+
exports.i18nInit = i18nInit;
|
|
41
|
+
exports.i18nValidate = i18nValidate;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const yaml = __importStar(require("js-yaml"));
|
|
46
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
47
|
+
/**
|
|
48
|
+
* Extract translatable strings from metadata files and create i18n files
|
|
49
|
+
*/
|
|
50
|
+
async function i18nExtract(options) {
|
|
51
|
+
var _a;
|
|
52
|
+
const sourceDir = path.resolve(process.cwd(), options.source || '.');
|
|
53
|
+
const outputDir = path.resolve(process.cwd(), options.output || './src/i18n');
|
|
54
|
+
const lang = options.lang || 'en';
|
|
55
|
+
console.log(chalk_1.default.blue('🌐 Extracting translatable strings...'));
|
|
56
|
+
console.log(chalk_1.default.gray(`Source: ${sourceDir}`));
|
|
57
|
+
console.log(chalk_1.default.gray(`Output: ${outputDir}/${lang}\n`));
|
|
58
|
+
try {
|
|
59
|
+
// Find all metadata files
|
|
60
|
+
const files = await (0, fast_glob_1.default)('**/*.{object,view,form,page,action,permission,validation,workflow,report,menu}.yml', {
|
|
61
|
+
cwd: sourceDir,
|
|
62
|
+
ignore: ['node_modules/**', 'dist/**', 'i18n/**']
|
|
63
|
+
});
|
|
64
|
+
console.log(chalk_1.default.gray(`Found ${files.length} metadata files`));
|
|
65
|
+
const translations = {};
|
|
66
|
+
for (const file of files) {
|
|
67
|
+
const filePath = path.join(sourceDir, file);
|
|
68
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
69
|
+
const data = yaml.load(content);
|
|
70
|
+
if (!data)
|
|
71
|
+
continue;
|
|
72
|
+
// Extract object name from filename
|
|
73
|
+
const objectName = path.basename(file).split('.')[0];
|
|
74
|
+
// Extract translatable fields
|
|
75
|
+
const objectTranslations = {};
|
|
76
|
+
if (data.label) {
|
|
77
|
+
objectTranslations.label = data.label;
|
|
78
|
+
}
|
|
79
|
+
if (data.description) {
|
|
80
|
+
objectTranslations.description = data.description;
|
|
81
|
+
}
|
|
82
|
+
// Extract field labels
|
|
83
|
+
if (data.fields) {
|
|
84
|
+
objectTranslations.fields = {};
|
|
85
|
+
for (const [fieldName, fieldConfig] of Object.entries(data.fields)) {
|
|
86
|
+
const fieldTrans = {};
|
|
87
|
+
if (fieldConfig.label) {
|
|
88
|
+
fieldTrans.label = fieldConfig.label;
|
|
89
|
+
}
|
|
90
|
+
if (fieldConfig.description) {
|
|
91
|
+
fieldTrans.description = fieldConfig.description;
|
|
92
|
+
}
|
|
93
|
+
if (fieldConfig.help_text) {
|
|
94
|
+
fieldTrans.help_text = fieldConfig.help_text;
|
|
95
|
+
}
|
|
96
|
+
// Extract select options
|
|
97
|
+
if (fieldConfig.options && Array.isArray(fieldConfig.options)) {
|
|
98
|
+
fieldTrans.options = {};
|
|
99
|
+
for (const option of fieldConfig.options) {
|
|
100
|
+
if (option.value && option.label) {
|
|
101
|
+
fieldTrans.options[option.value] = option.label;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (Object.keys(fieldTrans).length > 0) {
|
|
106
|
+
objectTranslations.fields[fieldName] = fieldTrans;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Extract action labels
|
|
111
|
+
if (data.actions) {
|
|
112
|
+
objectTranslations.actions = {};
|
|
113
|
+
for (const [actionName, actionConfig] of Object.entries(data.actions)) {
|
|
114
|
+
const actionTrans = {};
|
|
115
|
+
if (actionConfig.label) {
|
|
116
|
+
actionTrans.label = actionConfig.label;
|
|
117
|
+
}
|
|
118
|
+
if (actionConfig.confirm_text) {
|
|
119
|
+
actionTrans.confirm_text = actionConfig.confirm_text;
|
|
120
|
+
}
|
|
121
|
+
if (Object.keys(actionTrans).length > 0) {
|
|
122
|
+
objectTranslations.actions[actionName] = actionTrans;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Extract validation messages
|
|
127
|
+
if ((_a = data.validation) === null || _a === void 0 ? void 0 : _a.rules) {
|
|
128
|
+
objectTranslations.validation = {};
|
|
129
|
+
for (const rule of data.validation.rules) {
|
|
130
|
+
if (rule.name && rule.message) {
|
|
131
|
+
objectTranslations.validation[rule.name] = rule.message;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (Object.keys(objectTranslations).length > 0) {
|
|
136
|
+
translations[objectName] = objectTranslations;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Write translation files
|
|
140
|
+
const langDir = path.join(outputDir, lang);
|
|
141
|
+
if (!fs.existsSync(langDir)) {
|
|
142
|
+
fs.mkdirSync(langDir, { recursive: true });
|
|
143
|
+
}
|
|
144
|
+
// Write one file per object
|
|
145
|
+
for (const [objectName, objectTranslations] of Object.entries(translations)) {
|
|
146
|
+
const outputFile = path.join(langDir, `${objectName}.json`);
|
|
147
|
+
fs.writeFileSync(outputFile, JSON.stringify(objectTranslations, null, 4), 'utf-8');
|
|
148
|
+
console.log(chalk_1.default.green(`✓ ${objectName}.json`));
|
|
149
|
+
}
|
|
150
|
+
console.log(chalk_1.default.green(`\n✅ Extracted translations to ${langDir}`));
|
|
151
|
+
console.log(chalk_1.default.gray(`Total: ${Object.keys(translations).length} files`));
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error(chalk_1.default.red(`❌ Failed to extract translations: ${error.message}`));
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Initialize i18n structure for a new language
|
|
160
|
+
*/
|
|
161
|
+
async function i18nInit(options) {
|
|
162
|
+
const baseDir = path.resolve(process.cwd(), options.baseDir || './src/i18n');
|
|
163
|
+
const { lang } = options;
|
|
164
|
+
console.log(chalk_1.default.blue(`🌐 Initializing i18n for language: ${lang}`));
|
|
165
|
+
// Validate language code
|
|
166
|
+
if (!/^[a-z]{2}(-[A-Z]{2})?$/.test(lang)) {
|
|
167
|
+
console.error(chalk_1.default.red('❌ Invalid language code. Use format: en, zh-CN, etc.'));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
const langDir = path.join(baseDir, lang);
|
|
171
|
+
if (fs.existsSync(langDir)) {
|
|
172
|
+
console.error(chalk_1.default.red(`❌ Language directory already exists: ${langDir}`));
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
fs.mkdirSync(langDir, { recursive: true });
|
|
177
|
+
// Create a sample translation file
|
|
178
|
+
const sampleTranslation = {
|
|
179
|
+
_meta: {
|
|
180
|
+
language: lang,
|
|
181
|
+
created: new Date().toISOString()
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const sampleFile = path.join(langDir, 'common.json');
|
|
185
|
+
fs.writeFileSync(sampleFile, JSON.stringify(sampleTranslation, null, 4), 'utf-8');
|
|
186
|
+
console.log(chalk_1.default.green(`✅ Initialized i18n for ${lang}`));
|
|
187
|
+
console.log(chalk_1.default.gray(`Directory: ${langDir}`));
|
|
188
|
+
console.log(chalk_1.default.gray(`\nNext steps:`));
|
|
189
|
+
console.log(chalk_1.default.gray(` 1. Run: objectql i18n extract --lang ${lang}`));
|
|
190
|
+
console.log(chalk_1.default.gray(` 2. Translate the JSON files in ${langDir}`));
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
console.error(chalk_1.default.red(`❌ Failed to initialize i18n: ${error.message}`));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validate translation completeness
|
|
199
|
+
*/
|
|
200
|
+
async function i18nValidate(options) {
|
|
201
|
+
const baseDir = path.resolve(process.cwd(), options.baseDir || './src/i18n');
|
|
202
|
+
const { lang, baseLang = 'en' } = options;
|
|
203
|
+
console.log(chalk_1.default.blue(`🌐 Validating translations for ${lang} against ${baseLang}...\n`));
|
|
204
|
+
const baseLangDir = path.join(baseDir, baseLang);
|
|
205
|
+
const targetLangDir = path.join(baseDir, lang);
|
|
206
|
+
if (!fs.existsSync(baseLangDir)) {
|
|
207
|
+
console.error(chalk_1.default.red(`❌ Base language directory not found: ${baseLangDir}`));
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
if (!fs.existsSync(targetLangDir)) {
|
|
211
|
+
console.error(chalk_1.default.red(`❌ Target language directory not found: ${targetLangDir}`));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const baseFiles = fs.readdirSync(baseLangDir).filter(f => f.endsWith('.json'));
|
|
216
|
+
const targetFiles = fs.readdirSync(targetLangDir).filter(f => f.endsWith('.json'));
|
|
217
|
+
let totalMissing = 0;
|
|
218
|
+
let totalFiles = 0;
|
|
219
|
+
for (const file of baseFiles) {
|
|
220
|
+
totalFiles++;
|
|
221
|
+
const basePath = path.join(baseLangDir, file);
|
|
222
|
+
const targetPath = path.join(targetLangDir, file);
|
|
223
|
+
if (!fs.existsSync(targetPath)) {
|
|
224
|
+
console.log(chalk_1.default.red(`✗ ${file} - Missing file`));
|
|
225
|
+
totalMissing++;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const baseData = JSON.parse(fs.readFileSync(basePath, 'utf-8'));
|
|
229
|
+
const targetData = JSON.parse(fs.readFileSync(targetPath, 'utf-8'));
|
|
230
|
+
const missing = findMissingKeys(baseData, targetData);
|
|
231
|
+
if (missing.length > 0) {
|
|
232
|
+
console.log(chalk_1.default.yellow(`⚠ ${file} - ${missing.length} missing keys:`));
|
|
233
|
+
for (const key of missing) {
|
|
234
|
+
console.log(chalk_1.default.gray(` - ${key}`));
|
|
235
|
+
}
|
|
236
|
+
totalMissing += missing.length;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
console.log(chalk_1.default.green(`✓ ${file} - Complete`));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Check for extra files in target
|
|
243
|
+
const extraFiles = targetFiles.filter(f => !baseFiles.includes(f));
|
|
244
|
+
if (extraFiles.length > 0) {
|
|
245
|
+
console.log(chalk_1.default.yellow(`\n⚠ Extra files in ${lang}:`));
|
|
246
|
+
for (const file of extraFiles) {
|
|
247
|
+
console.log(chalk_1.default.gray(` - ${file}`));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
console.log(chalk_1.default.blue(`\n📊 Summary:`));
|
|
251
|
+
console.log(chalk_1.default.gray(`Total files: ${totalFiles}`));
|
|
252
|
+
console.log(totalMissing > 0
|
|
253
|
+
? chalk_1.default.yellow(`Missing translations: ${totalMissing}`)
|
|
254
|
+
: chalk_1.default.green('All translations complete ✓'));
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
console.error(chalk_1.default.red(`❌ Failed to validate translations: ${error.message}`));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function findMissingKeys(base, target, prefix = '') {
|
|
262
|
+
const missing = [];
|
|
263
|
+
for (const key in base) {
|
|
264
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
265
|
+
if (!(key in target)) {
|
|
266
|
+
missing.push(fullKey);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (typeof base[key] === 'object' && base[key] !== null && !Array.isArray(base[key])) {
|
|
270
|
+
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
271
|
+
missing.push(...findMissingKeys(base[key], target[key], fullKey));
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
missing.push(fullKey);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return missing;
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/commands/i18n.ts"],"names":[],"mappings":"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"}
|