Skip to content
This repository was archived by the owner on Sep 6, 2022. It is now read-only.

Commit 83cfd52

Browse files
authored
fix #34 (#36)
fix #34
2 parents 86e865b + 080f599 commit 83cfd52

File tree

4 files changed

+172
-174
lines changed

4 files changed

+172
-174
lines changed

babel.config.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,11 @@ module.exports = {
77
},
88
],
99
'@babel/preset-react',
10-
// '@babel/typescript',
1110
],
1211
plugins: [
1312
'styled-components',
1413
'@babel/plugin-proposal-class-properties',
1514
'@babel/plugin-syntax-dynamic-import',
16-
// [
17-
// '@babel/plugin-transform-typescript',
18-
// {
19-
// allowNamespaces: true,
20-
// },
21-
// ],
2215
],
2316
env: {
2417
production: {

internals/scripts/extract-intl.js

Lines changed: 164 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,164 @@
1-
// /* eslint-disable no-restricted-syntax */
2-
// /**
3-
// * This script will extract the internationalization messages from all components
4-
// * and package them in the translation json files in the translations file.
5-
// */
6-
7-
// COMMENTED OUT - TODO
8-
9-
// require('shelljs/global');
10-
11-
// const fs = require('fs');
12-
// const nodeGlob = require('glob');
13-
// const { transform } = require('@babel/core');
14-
// const get = require('lodash/get');
15-
16-
// const animateProgress = require('./helpers/progress');
17-
// const addCheckmark = require('./helpers/checkmark');
18-
19-
// const { appLocales, DEFAULT_LOCALE } = require('../../app/i18n.ts');
20-
21-
// const babel = require('../../babel.config.js');
22-
// const { presets } = babel;
23-
// let plugins = babel.plugins || [];
24-
25-
// plugins.push('react-intl');
26-
27-
// // NOTE: styled-components plugin is filtered out as it creates errors when used with transform
28-
// plugins = plugins.filter(p => p !== 'styled-components');
29-
30-
// // Glob to match all js files except test files
31-
// const FILES_TO_PARSE = 'app/**/!(*.test).ts*';
32-
33-
// const newLine = () => process.stdout.write('\n');
34-
35-
// // Progress Logger
36-
// let progress;
37-
// const task = message => {
38-
// progress = animateProgress(message);
39-
// process.stdout.write(message);
40-
41-
// return error => {
42-
// if (error) {
43-
// process.stderr.write(error);
44-
// }
45-
// clearTimeout(progress);
46-
// return addCheckmark(() => newLine());
47-
// };
48-
// };
49-
50-
// // Wrap async functions below into a promise
51-
// const glob = pattern =>
52-
// new Promise((resolve, reject) => {
53-
// nodeGlob(
54-
// pattern,
55-
// (error, value) => (error ? reject(error) : resolve(value)),
56-
// );
57-
// });
58-
59-
// const readFile = fileName =>
60-
// new Promise((resolve, reject) => {
61-
// fs.readFile(
62-
// fileName,
63-
// 'utf8',
64-
// (error, value) => (error ? reject(error) : resolve(value)),
65-
// );
66-
// });
67-
68-
// // Store existing translations into memory
69-
// const oldLocaleMappings = [];
70-
// const localeMappings = [];
71-
72-
// // Loop to run once per locale
73-
// for (const locale of appLocales) {
74-
// oldLocaleMappings[locale] = {};
75-
// localeMappings[locale] = {};
76-
// // File to store translation messages into
77-
// const translationFileName = `app/translations/${locale}.json`;
78-
// try {
79-
// // Parse the old translation message JSON files
80-
// const messages = JSON.parse(fs.readFileSync(translationFileName));
81-
// const messageKeys = Object.keys(messages);
82-
// for (const messageKey of messageKeys) {
83-
// oldLocaleMappings[locale][messageKey] = messages[messageKey];
84-
// }
85-
// } catch (error) {
86-
// if (error.code !== 'ENOENT') {
87-
// process.stderr.write(
88-
// `There was an error loading this translation file: ${translationFileName}
89-
// \n${error}`,
90-
// );
91-
// }
92-
// }
93-
// }
94-
95-
// const extractFromFile = async filename => {
96-
// try {
97-
// const code = await readFile(filename);
98-
99-
// const output = await transform(code, { filename, presets, plugins });
100-
// const messages = get(output, 'metadata.react-intl.messages', []);
101-
102-
// for (const message of messages) {
103-
// for (const locale of appLocales) {
104-
// const oldLocaleMapping = oldLocaleMappings[locale][message.id];
105-
// // Merge old translations into the babel extracted instances where react-intl is used
106-
// const newMsg = locale === DEFAULT_LOCALE ? message.defaultMessage : '';
107-
// localeMappings[locale][message.id] = oldLocaleMapping || newMsg;
108-
// }
109-
// }
110-
// } catch (error) {
111-
// process.stderr.write(`\nError transforming file: ${filename}\n${error}\n`);
112-
// }
113-
// };
114-
115-
// const memoryTask = glob(FILES_TO_PARSE);
116-
// const memoryTaskDone = task('Storing language files in memory');
117-
118-
// memoryTask.then(files => {
119-
// memoryTaskDone();
120-
121-
// const extractTask = Promise.all(
122-
// files.map(fileName => extractFromFile(fileName)),
123-
// );
124-
// const extractTaskDone = task('Run extraction on all files');
125-
// // Run extraction on all files that match the glob on line 16
126-
// extractTask.then(() => {
127-
// extractTaskDone();
128-
129-
// // Make the directory if it doesn't exist, especially for first run
130-
// mkdir('-p', 'app/translations'); // eslint-disable-line
131-
132-
// let localeTaskDone;
133-
// let translationFileName;
134-
135-
// for (const locale of appLocales) {
136-
// translationFileName = `app/translations/${locale}.json`;
137-
// localeTaskDone = task(
138-
// `Writing translation messages for ${locale} to: ${translationFileName}`,
139-
// );
140-
141-
// // Sort the translation JSON file so that git diffing is easier
142-
// // Otherwise the translation messages will jump around every time we extract
143-
// const messages = {};
144-
// Object.keys(localeMappings[locale])
145-
// .sort()
146-
// .forEach(key => {
147-
// messages[key] = localeMappings[locale][key];
148-
// });
149-
150-
// // Write to file the JSON representation of the translation messages
151-
// const prettified = `${JSON.stringify(messages, null, 2)}\n`;
152-
153-
// try {
154-
// fs.writeFileSync(translationFileName, prettified);
155-
// localeTaskDone();
156-
// } catch (error) {
157-
// localeTaskDone(
158-
// `There was an error saving this translation file: ${translationFileName}
159-
// \n${error}`,
160-
// );
161-
// }
162-
// }
163-
164-
// process.exit();
165-
// });
166-
// });
1+
/* eslint-disable no-restricted-syntax */
2+
/**
3+
* This script will extract the internationalization messages from all components
4+
* and package them in the translation json files in the translations file.
5+
*/
6+
7+
require('shelljs/global');
8+
9+
const fs = require('fs');
10+
const nodeGlob = require('glob');
11+
const { transform } = require('@babel/core');
12+
const get = require('lodash/get');
13+
14+
const animateProgress = require('./helpers/progress');
15+
const addCheckmark = require('./helpers/checkmark');
16+
17+
const { appLocales, DEFAULT_LOCALE } = require('./../../app/i18n.ts');
18+
19+
const babel = require('../../babel.config.js');
20+
const { presets } = babel;
21+
let plugins = babel.plugins || [];
22+
23+
plugins.push('react-intl');
24+
25+
// NOTE: styled-components plugin is filtered out as it creates errors when used with transform
26+
plugins = plugins.filter(p => p !== 'styled-components');
27+
28+
// Glob to match all js files except test files
29+
const FILES_TO_PARSE = 'app/**/!(*.test).ts*';
30+
31+
const newLine = () => process.stdout.write('\n');
32+
33+
// Progress Logger
34+
let progress;
35+
const task = message => {
36+
progress = animateProgress(message);
37+
process.stdout.write(message);
38+
39+
return error => {
40+
if (error) {
41+
process.stderr.write(error);
42+
}
43+
clearTimeout(progress);
44+
return addCheckmark(() => newLine());
45+
};
46+
};
47+
48+
// Wrap async functions below into a promise
49+
const glob = pattern =>
50+
new Promise((resolve, reject) => {
51+
nodeGlob(
52+
pattern,
53+
(error, value) => (error ? reject(error) : resolve(value)),
54+
);
55+
});
56+
57+
const readFile = fileName =>
58+
new Promise((resolve, reject) => {
59+
fs.readFile(
60+
fileName,
61+
'utf8',
62+
(error, value) => (error ? reject(error) : resolve(value)),
63+
);
64+
});
65+
66+
// Store existing translations into memory
67+
const oldLocaleMappings = [];
68+
const localeMappings = [];
69+
70+
// Loop to run once per locale
71+
for (const locale of appLocales) {
72+
oldLocaleMappings[locale] = {};
73+
localeMappings[locale] = {};
74+
// File to store translation messages into
75+
const translationFileName = `app/translations/${locale}.json`;
76+
try {
77+
// Parse the old translation message JSON files
78+
const messages = JSON.parse(fs.readFileSync(translationFileName));
79+
const messageKeys = Object.keys(messages);
80+
for (const messageKey of messageKeys) {
81+
oldLocaleMappings[locale][messageKey] = messages[messageKey];
82+
}
83+
} catch (error) {
84+
if (error.code !== 'ENOENT') {
85+
process.stderr.write(
86+
`There was an error loading this translation file: ${translationFileName}
87+
\n${error}`,
88+
);
89+
}
90+
}
91+
}
92+
93+
const extractFromFile = async filename => {
94+
try {
95+
const code = await readFile(filename);
96+
97+
const output = await transform(code, { filename, presets, plugins });
98+
const messages = get(output, 'metadata.react-intl.messages', []);
99+
100+
for (const message of messages) {
101+
for (const locale of appLocales) {
102+
const oldLocaleMapping = oldLocaleMappings[locale][message.id];
103+
// Merge old translations into the babel extracted instances where react-intl is used
104+
const newMsg = locale === DEFAULT_LOCALE ? message.defaultMessage : '';
105+
localeMappings[locale][message.id] = oldLocaleMapping || newMsg;
106+
}
107+
}
108+
} catch (error) {
109+
process.stderr.write(`\nError transforming file: ${filename}\n${error}\n`);
110+
}
111+
};
112+
113+
const memoryTask = glob(FILES_TO_PARSE);
114+
const memoryTaskDone = task('Storing language files in memory');
115+
116+
memoryTask.then(files => {
117+
memoryTaskDone();
118+
119+
const extractTask = Promise.all(
120+
files.map(fileName => extractFromFile(fileName)),
121+
);
122+
const extractTaskDone = task('Run extraction on all files');
123+
// Run extraction on all files that match the glob on line 16
124+
extractTask.then(() => {
125+
extractTaskDone();
126+
127+
// Make the directory if it doesn't exist, especially for first run
128+
mkdir('-p', 'app/translations'); // eslint-disable-line
129+
130+
let localeTaskDone;
131+
let translationFileName;
132+
133+
for (const locale of appLocales) {
134+
translationFileName = `app/translations/${locale}.json`;
135+
localeTaskDone = task(
136+
`Writing translation messages for ${locale} to: ${translationFileName}`,
137+
);
138+
139+
// Sort the translation JSON file so that git diffing is easier
140+
// Otherwise the translation messages will jump around every time we extract
141+
const messages = {};
142+
Object.keys(localeMappings[locale])
143+
.sort()
144+
.forEach(key => {
145+
messages[key] = localeMappings[locale][key];
146+
});
147+
148+
// Write to file the JSON representation of the translation messages
149+
const prettified = `${JSON.stringify(messages, null, 2)}\n`;
150+
151+
try {
152+
fs.writeFileSync(translationFileName, prettified);
153+
localeTaskDone();
154+
} catch (error) {
155+
localeTaskDone(
156+
`There was an error saving this translation file: ${translationFileName}
157+
\n${error}`,
158+
);
159+
}
160+
}
161+
162+
process.exit();
163+
});
164+
});

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"analyze:clean": "rimraf stats.json",
1717
"preanalyze": "npm run analyze:clean",
1818
"analyze": "node ./internals/scripts/analyze.js",
19-
"extract-intl": "node ./internals/scripts/extract-intl.js",
19+
"extract-intl": "node -r esm ./internals/scripts/extract-intl.js",
2020
"npmcheckversion": "node ./internals/scripts/npmcheckversion.js",
2121
"preinstall": "npm run npmcheckversion",
2222
"prebuild": "npm run build:clean",
@@ -163,6 +163,7 @@
163163
"eslint-plugin-react": "7.14.2",
164164
"eslint-plugin-react-hooks": "1.6.1",
165165
"eslint-plugin-redux-saga": "1.0.0",
166+
"esm": "^3.2.25",
166167
"file-loader": "4.0.0",
167168
"fork-ts-checker-webpack-plugin": "1.5.0",
168169
"html-loader": "0.5.5",

0 commit comments

Comments
 (0)