-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
194 lines (160 loc) · 6.94 KB
/
index.js
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
===========================================================================
Internationalization Key Validation Script
===========================================================================
Script Purpose:
----------------
This Node.js script checks the usage of internationalization keys in your Ember project's JavaScript and Handlebars files. It ensures that all keys referenced in your project files are present in the specified YAML translation file. This helps prevent missing translations during runtime.
Usage:
------
To use this script, run it with Node.js from the command line, providing the path to your Ember project directory and the path to the YAML translation file. Optionally, you can include the '--silent' flag to suppress error throwing and allow the script to run to completion even if there are missing translations.
Example Command:
----------------
node index.js --silent
Script Behavior:
----------------
1. The script recursively processes all JavaScript (.js) and Handlebars (.hbs) files in the specified Ember project directory.
2. It extracts translation keys using regular expressions tailored for Handlebars and JavaScript files.
3. For each key found, it checks if the key exists in the specified YAML translation file.
4. If any missing keys are detected, the script logs them and optionally throws an error.
Script Options:
---------------
- Ember Project Path: The root directory of your Ember project. Modify the 'projectPath' variable to set the path.
- Translation File Path: The path to the YAML translation file. Modify the 'translationFilePath' variable to set the path.
- Silent Mode: Include the '--silent' flag to suppress error throwing and allow the script to run to completion even if there are missing translations.
Authors:
---------
- Fleetbase Pte Ltd <[email protected]>
- Ronald A. Richardson <[email protected]>
Contact:
---------
If you encounter issues or have questions, feel free to contact the authors or raise an issue on the project repository.
License:
--------
This script is open-source and distributed under the MIT license. Refer to the LICENSE file for details.
===========================================================================
*/
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const argv = yargs(hideBin(process.argv))
.option('silent', {
alias: 's',
type: 'boolean',
description: 'Run in silent mode',
})
.option('path', {
alias: 'p',
type: 'string',
description: 'Path to the Ember project',
default: './app',
})
.option('translation-path', {
type: 'string',
description: 'Path to the translation YAML file',
default: './translations/en-us.yaml',
}).argv;
function findTranslationKeys(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
// Regular expression for finding translation keys
let regex;
if (filePath.endsWith('.hbs')) {
// Regular expression for finding translation keys in Handlebars files
regex = /\{\{\s*t\s+["'`]([^"']+?)["'`]\s*}}|\(t\s+["'`]([^"']+?)["'`]\)/g;
} else if (filePath.endsWith('.js')) {
// Regular expression for finding translation keys in JavaScript files
regex = /this\.intl\.t\s*\(\s*["'`]([^"']+?)["'`]\s*(?:,\s*\{.*?\}\s*)?\)/g;
} else {
console.log(`Unsupported file type: ${filePath}`);
return [];
}
const keys = [];
let match;
while ((match = regex.exec(content)) !== null) {
// Matched key will be in one of the capturing groups 1 or 2
const key = match[1] || match[2];
if (key.trim() !== '') {
keys.push(key);
}
}
// Log the number of translation keys found in the file
console.log(`Found ${keys.length} translation key(s) in file: ${filePath}`);
return keys;
}
function checkKeysInTranslationFile(keys, translationFilePath) {
console.log(`Checking if translation keys exist in file: ${translationFilePath}`);
const translationContent = fs.readFileSync(translationFilePath, 'utf8');
const translationData = yaml.load(translationContent);
const missingKeys = keys.filter((key) => {
const nestedKeys = key.split('.');
let currentLevel = translationData;
for (const nestedKey of nestedKeys) {
if (currentLevel && currentLevel.hasOwnProperty(nestedKey)) {
currentLevel = currentLevel[nestedKey];
} else {
return true; // Missing key found
}
}
return false; // All nested keys found
});
return missingKeys;
}
function processDirectory(directoryPath, translationFilePath, silentMode = false) {
const files = fs.readdirSync(directoryPath);
for (const file of files) {
const filePath = path.join(directoryPath, file);
if (fs.statSync(filePath).isDirectory()) {
// Recursively process subdirectories
processDirectory(filePath, translationFilePath, silentMode);
} else if (file.endsWith('.js') || file.endsWith('.hbs')) {
console.log(`Checking file: ${filePath}`);
// Process JavaScript and Handlebars files
const keys = findTranslationKeys(filePath);
if (keys.length === 0) {
console.log('');
continue;
}
const missingKeys = checkKeysInTranslationFile(keys, translationFilePath);
if (missingKeys.length > 0) {
console.error(`File: ${filePath}`);
missingKeys.forEach((missingKey) => {
console.error(`🚫 Missing Translation: ${missingKey}`);
if (!silentMode) {
throw new Error(`Missing Tranlation: ${missingKey}`);
}
});
} else {
console.log(`All translation keys found in file: ${filePath}`);
}
console.log('');
}
}
}
function checkTranslationsInProject(projectPath, translationFilePath, silentMode = false) {
console.log(`⏳ Starting translation key check in project: ${projectPath}`);
try {
processDirectory(projectPath, translationFilePath, silentMode);
} catch (error) {
throw error;
}
console.log('✅ Translation key check completed.');
}
function lint(options = {}) {
const silentMode = options.silent === true;
const projectPath = path.join(process.cwd(), options.path);
const translationFilePath = path.join(process.cwd(), options.translationPath);
try {
checkTranslationsInProject(projectPath, translationFilePath, silentMode);
} catch (error) {
console.error('💣 Translation key check failed!');
process.exit(1);
}
}
lint({
silent: argv.silent,
path: argv.path,
translationPath: argv['translation-path'],
});
module.exports = lint;