1 | #!/usr/bin/env node
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | require('@babel/register')({
|
13 | babelrc: false,
|
14 | only: [__dirname, `${process.cwd()}/core`],
|
15 | plugins: [
|
16 | require('./server/translate-plugin.js'),
|
17 | require('@babel/plugin-proposal-class-properties').default,
|
18 | require('@babel/plugin-proposal-object-rest-spread').default,
|
19 | ],
|
20 | presets: [
|
21 | require('@babel/preset-react').default,
|
22 | require('@babel/preset-env').default,
|
23 | ],
|
24 | });
|
25 |
|
26 | const traverse = require('@babel/traverse').default;
|
27 | const babylon = require('babylon');
|
28 | const fs = require('fs-extra');
|
29 | const glob = require('glob');
|
30 | const mkdirp = require('mkdirp');
|
31 | const nodePath = require('path');
|
32 | const _ = require('lodash');
|
33 |
|
34 | const readMetadata = require('./server/readMetadata.js');
|
35 |
|
36 | const CWD = process.cwd();
|
37 | const siteConfig = require(`${CWD}/siteConfig.js`);
|
38 | const sidebars = require(`${CWD}/sidebars.json`);
|
39 |
|
40 | let customTranslations = {
|
41 | 'localized-strings': {
|
42 | docs: {},
|
43 | links: {},
|
44 | categories: {},
|
45 | },
|
46 | 'pages-strings': {},
|
47 | };
|
48 | if (fs.existsSync(`${CWD}/data/custom-translation-strings.json`)) {
|
49 | customTranslations = _.merge(
|
50 | {},
|
51 | JSON.parse(
|
52 | fs.readFileSync(`${CWD}/data/custom-translation-strings.json`, 'utf8'),
|
53 | ),
|
54 | customTranslations,
|
55 | );
|
56 | }
|
57 |
|
58 | function writeFileAndCreateFolder(file, content) {
|
59 | mkdirp.sync(file.replace(new RegExp('/[^/]*$'), ''));
|
60 | fs.writeFileSync(file, content);
|
61 | }
|
62 |
|
63 | function execute() {
|
64 | const translations = {
|
65 | 'localized-strings': {
|
66 | next: 'Next',
|
67 | previous: 'Previous',
|
68 | tagline: siteConfig.tagline,
|
69 | docs: {},
|
70 | links: {},
|
71 | categories: {},
|
72 | },
|
73 | 'pages-strings': {},
|
74 | };
|
75 |
|
76 |
|
77 | const docsDir = nodePath.join(CWD, '../', readMetadata.getDocsPath());
|
78 | const versionedDocsDir = nodePath.join(CWD, 'versioned_docs');
|
79 |
|
80 | const translateDoc = (file, refDir) => {
|
81 | const extension = nodePath.extname(file);
|
82 | if (extension === '.md' || extension === '.markdown') {
|
83 | let res;
|
84 | try {
|
85 | res = readMetadata.processMetadata(file, refDir);
|
86 | } catch (e) {
|
87 | console.error(e);
|
88 | process.exit(1);
|
89 | }
|
90 | if (!res) {
|
91 | return;
|
92 | }
|
93 | const metadata = res.metadata;
|
94 | const id = metadata.localized_id;
|
95 |
|
96 | translations['localized-strings'].docs[id] = {};
|
97 | translations['localized-strings'].docs[id].title = metadata.title;
|
98 |
|
99 | if (metadata.sidebar_label) {
|
100 | translations['localized-strings'].docs[id].sidebar_label =
|
101 | metadata.sidebar_label;
|
102 | }
|
103 | }
|
104 | };
|
105 | glob.sync(`${docsDir}/**`).forEach(file => translateDoc(file, docsDir));
|
106 | glob
|
107 | .sync(`${versionedDocsDir}/**`)
|
108 | .forEach(file => translateDoc(file, versionedDocsDir));
|
109 |
|
110 |
|
111 | siteConfig.headerLinks.forEach(link => {
|
112 | if (link.label) {
|
113 | translations['localized-strings'].links[link.label] = link.label;
|
114 | }
|
115 | });
|
116 |
|
117 |
|
118 | Object.keys(sidebars).forEach(sb => {
|
119 | const categories = sidebars[sb];
|
120 | Object.keys(categories).forEach(category => {
|
121 | translations['localized-strings'].categories[category] = category;
|
122 | });
|
123 | });
|
124 |
|
125 | glob.sync(`${CWD}/versioned_sidebars/*`).forEach(file => {
|
126 | if (!file.endsWith('-sidebars.json')) {
|
127 | if (file.endsWith('-sidebar.json')) {
|
128 | console.warn(
|
129 | `Skipping ${file}. Make sure your sidebar filenames follow this format: 'version-VERSION-sidebars.json'.`,
|
130 | );
|
131 | }
|
132 | return;
|
133 | }
|
134 | let sidebarContent;
|
135 | try {
|
136 | sidebarContent = JSON.parse(fs.readFileSync(file, 'utf8'));
|
137 | } catch (e) {
|
138 | console.error(`Could not parse ${file} into json. ${e}`);
|
139 | process.exit(1);
|
140 | }
|
141 |
|
142 | Object.keys(sidebarContent).forEach(sb => {
|
143 | const categories = sidebarContent[sb];
|
144 | Object.keys(categories).forEach(category => {
|
145 | translations['localized-strings'].categories[category] = category;
|
146 | });
|
147 | });
|
148 | });
|
149 |
|
150 |
|
151 | glob.sync(`${CWD}/pages/en/**`).forEach(file => {
|
152 | const extension = nodePath.extname(file);
|
153 | if (extension === '.js') {
|
154 | const ast = babylon.parse(fs.readFileSync(file, 'utf8'), {
|
155 | plugins: ['jsx'],
|
156 | });
|
157 | traverse(ast, {
|
158 | enter(path) {
|
159 | if (
|
160 | path.node.type === 'JSXElement' &&
|
161 | path.node.openingElement.name.name === 'translate'
|
162 | ) {
|
163 | const text = path.node.children[0].value
|
164 | .trim()
|
165 | .replace(/\s+/g, ' ');
|
166 | let description = 'no description given';
|
167 | const attributes = path.node.openingElement.attributes;
|
168 | for (let i = 0; i < attributes.length; i++) {
|
169 | if (attributes[i].name.name === 'desc') {
|
170 | description = attributes[i].value.value;
|
171 | }
|
172 | }
|
173 | translations['pages-strings'][`${text}|${description}`] = text;
|
174 | }
|
175 | },
|
176 | });
|
177 | }
|
178 | });
|
179 |
|
180 |
|
181 | translations['pages-strings'][
|
182 | 'Help Translate|recruit community translators for your project'
|
183 | ] = 'Help Translate';
|
184 | translations['pages-strings'][
|
185 | 'Edit this Doc|recruitment message asking to edit the doc source'
|
186 | ] = 'Edit';
|
187 | translations['pages-strings'][
|
188 | 'Translate this Doc|recruitment message asking to translate the docs'
|
189 | ] = 'Translate';
|
190 | translations['pages-strings'] = Object.assign(
|
191 | translations['pages-strings'],
|
192 | customTranslations['pages-strings'],
|
193 | );
|
194 | translations['localized-strings'] = _.merge(
|
195 | {},
|
196 | translations['localized-strings'],
|
197 | customTranslations['localized-strings'],
|
198 | );
|
199 | writeFileAndCreateFolder(
|
200 | `${CWD}/i18n/en.json`,
|
201 | `${JSON.stringify(
|
202 | Object.assign(
|
203 | {
|
204 | _comment: 'This file is auto-generated by write-translations.js',
|
205 | },
|
206 | translations,
|
207 | ),
|
208 | null,
|
209 | 2,
|
210 | )}\n`,
|
211 | );
|
212 | }
|
213 |
|
214 | execute();
|
215 |
|
216 | module.exports = execute;
|