Skip to content

Commit 3b40829

Browse files
authored
Merge pull request #837 from yukienomiya/getenJSON
Add script that generates the English Reference file
2 parents 3f2a2f0 + 81606fd commit 3b40829

File tree

4 files changed

+7630
-10
lines changed

4 files changed

+7630
-10
lines changed

contributor_docs/i18n_contribution.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ p5.js-website/
135135
],
136136
```
137137
4. Duplicate `en.yml` - stored under `src/data/` - and name it `language_abbreviation.yml`. For example, when the Spanish version was created it was named `es.yml`. Check [How the website works](#how-the-website-works) and [File Structure](#file-structure) for further information.
138-
5. Duplicate `es.json` - stored under `src/data/reference/` - and name it `[language_abbreviation].json`.
138+
5. Duplicate `en.json` - stored under `src/data/reference/` - and name it `[language_abbreviation].json`.
139139
6. Duplicate `en` folder - stored under `src/data/examples` - and name it `language_abbreviation`.
140140
7. Add a new menu entry in [`src/templates/partials/i18n.hbs`](https://github.com/processing/p5.js-website/blob/main/src/templates/partials/i18n.hbs#L8) like so `<li><a href='#' lang='[language_abbreviation]' data-lang='[language_abbreviation]'>[language_name]</a></li>`.
141141
@@ -198,15 +198,24 @@ In some cases, the text translated from the original .hbs file (written in HTML)
198198

199199
### Translation of Reference
200200

201-
* The reference works a bit differently. The pages are built in English based on the inline documentation in the p5.js source code. The English text is then swapped out with the appropriate translation using JS on the front-end.
202-
* The inline API documentation is automatically extracted from the p5.js repository using [YUIdoc](https://yui.github.io/yuidoc/) and saved in a [JSON file](https://github.com/processing/p5.js-website/blob/main/src/templates/pages/reference/data.json).
203-
* The translation files are created from the data.json file, but have a different structure (i.e. [es.json](https://github.com/processing/p5.js-website/blob/main/src/data/reference/es.json)).
204-
* The top level keys in the JSON object correspond to the page headings, menu, footer, etc. You can see all the swaps in [this file](https://github.com/processing/p5.js-website/blob/main/src/templates/pages/reference/index.hbs#L60).
205-
* The "p5" key in the JSON object contains individual keys for each reference entry, indexed by variable/function/object name.
206-
* Any entries in the JSON object which are not filled in will be left in English when the page is loaded.
207-
* The translated versions of the JSON file need to be manually created and updated.
208-
* This is a somewhat hacky solution and not ideal. However, it comes from balancing the desire to have documentation directly in the source code, with the unwieldiness of having multiple languages of documentation inline. It will be our working solution until a better one is found.
209-
* The source content for the reference is handled inline in the [p5.js source code](https://github.com/processing/p5.js). See [Inline documentation](https://github.com/processing/p5.js/blob/main/contributor_docs/inline_documentation.md) in the p5.js repo for information on how to contribute.
201+
The Reference works a bit differently. The pages are built in English based on the inline documentation in the p5.js source code. The English text is then swapped out with the appropriate translation using JS on the front-end.
202+
203+
The inline API documentation is automatically extracted from the p5.js repository using [YUIdoc](https://yui.github.io/yuidoc/) and saved in a JSON file, the [data.json](https://github.com/processing/p5.js-website/blob/main/src/templates/pages/reference/data.json).
204+
This file is then used to create the English version of the Reference files, *the en.json, which serves as the model for all the other translations*.
205+
206+
The en.json is made up of three sections:
207+
- static strings: static text from the Reference section of the website (page headings, menu, footer, etc.). These strings are hardcoded in the webpages and can't be extracted from the documentation; therefore, they are stored in a [separate JSON file](https://github.com/processing/p5.js-website/blob/main/src/templates/pages/reference/staticStrings.json).
208+
- module names: the names of all the p5.js modules. They are needed for the group and subgroup titles in the [Reference's main page](https://p5js.org/reference/). They're extracted from the modules object in the data.json file.
209+
- p5.js documentation, also extracted from the data.json file. This section contains a key for each p5.js Class (i.e., "p5.Color"), which holds information about the Class itself and its Methods and Fields.
210+
In this section, you might find HTML Anchor elements. You only need to translate the text between the two tags. For example, in `<a href=\"#/p5.Color\">p5.Color</a>`, you need to translate the second 'p5.Color' and leave the rest as is.
211+
212+
All the translation swaps of the Reference pages happen is [this function](https://github.com/processing/p5.js-website/blob/main/src/templates/pages/reference/index.hbs#L61).
213+
Any entries in the JSON object which are not filled in will be left in English when the page is loaded.
214+
215+
The translated versions of the JSON file need to be manually created and updated.
216+
This is a somewhat hacky solution and not ideal. However, it comes from balancing the desire to have documentation directly in the source code, with the unwieldiness of having multiple languages of documentation inline. It will be our working solution until a better one is found.
217+
218+
The source content for the Reference is handled inline in the [p5.js source code](https://github.com/processing/p5.js). See [Inline documentation](https://github.com/processing/p5.js/blob/main/contributor_docs/inline_documentation.md) in the p5.js repo for information on how to contribute.
210219

211220
### Translation of Examples
212221

getenJSON.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
This script generates the en.json file with the data from the data.json.
3+
It's run by the Grunt task runner.
4+
*/
5+
function getenJSON() {
6+
var fs = require('fs');
7+
var data = fs.readFileSync('src/templates/pages/reference/data.json');
8+
var dataJSON = JSON.parse(data);
9+
var staticStrings = fs.readFileSync(
10+
'src/templates/pages/reference/staticStrings.json'
11+
);
12+
var staticStringsJSON = JSON.parse(staticStrings);
13+
var enJSON = {};
14+
15+
// static strings
16+
for (var sstr in staticStringsJSON) {
17+
enJSON[sstr] = staticStringsJSON[sstr];
18+
}
19+
20+
// modules
21+
for (var p5Module in dataJSON.modules) {
22+
if (p5Module !== 'p5.sound') {
23+
enJSON[p5Module] = p5Module;
24+
}
25+
}
26+
27+
// classes: builds the p5 classes objects
28+
for (var p5Class in dataJSON.classes) {
29+
var entry = dataJSON['classes'][p5Class];
30+
var classObj = buildClassObj(entry);
31+
enJSON[entry.name] = classObj;
32+
}
33+
34+
// classitems: adds methods and properties to their respective class object
35+
for (var p5ItemIdx in dataJSON.classitems) {
36+
var entry2 = dataJSON.classitems[p5ItemIdx];
37+
// only consider the items that have a name
38+
if (entry2.name) {
39+
var itemObj = buildItemObj(entry2);
40+
enJSON[entry2.class][entry2.name] = itemObj;
41+
}
42+
}
43+
44+
fs.writeFileSync(
45+
'src/data/reference/en.json',
46+
JSON.stringify(enJSON, null, 2),
47+
err => {
48+
if (err) {
49+
console.error(err);
50+
return;
51+
}
52+
}
53+
);
54+
}
55+
56+
function buildClassObj(p5Class) {
57+
var classObj = {};
58+
59+
if (p5Class.description) {
60+
classObj['description'] = getParagraphs(p5Class.description);
61+
}
62+
63+
if (p5Class.return) {
64+
classObj['returns'] = buildReturnObj(p5Class.return);
65+
}
66+
67+
if (p5Class.params) {
68+
classObj['params'] = buildParamsObj(p5Class.params);
69+
}
70+
return classObj;
71+
}
72+
73+
function buildItemObj(p5Item) {
74+
var itemObj = {};
75+
76+
if (p5Item.description) {
77+
itemObj['description'] = getParagraphs(p5Item.description);
78+
}
79+
if (p5Item.return) {
80+
itemObj['returns'] = buildReturnObj(p5Item.return);
81+
}
82+
83+
if (p5Item.itemtype === 'method') {
84+
if (p5Item.params) {
85+
itemObj['params'] = buildParamsObj(p5Item.params);
86+
}
87+
if (p5Item.overloads) {
88+
itemObj = getOverloads(p5Item, itemObj);
89+
}
90+
}
91+
return itemObj;
92+
}
93+
94+
function buildReturnObj(returns) {
95+
return returns.type + ': ' + getText(returns.description);
96+
}
97+
98+
function buildParamsObj(params) {
99+
var paramsObj = {};
100+
101+
params.forEach(p => {
102+
var descr = p.type;
103+
if (p.description) {
104+
descr += ': ';
105+
}
106+
if ('optional' in p && p['optional']) {
107+
descr += ' (Optional) ';
108+
}
109+
descr += p.description;
110+
paramsObj[p.name] = getText(descr);
111+
});
112+
return paramsObj;
113+
}
114+
115+
function getOverloads(p5Item, itemObj) {
116+
p5Item.overloads.forEach(o => {
117+
if (o.params) {
118+
var moreParams = buildParamsObj(o.params);
119+
if (itemObj.params) {
120+
for (var p in moreParams) {
121+
if (!(p in itemObj.params)) {
122+
itemObj['params'][p] = moreParams[p];
123+
}
124+
}
125+
} else {
126+
itemObj['params'] = moreParams;
127+
}
128+
}
129+
});
130+
return itemObj;
131+
}
132+
133+
// returns the 'clean' version of the input text
134+
function getText(str) {
135+
return str
136+
.trim()
137+
.replace(/<p>|<\/p>|<br>/g, '')
138+
.replace(/\n|\s+/g, ' ');
139+
}
140+
141+
// returns an array containing the 'clean' versions of the text in the <p> tags of the input text
142+
function getParagraphs(text) {
143+
return text
144+
.trim()
145+
.replace(/<\/p>|<br>/g, '')
146+
.replace(/\n|\s+/g, ' ')
147+
.split(/<p>/)
148+
.filter(x => x.length > 0);
149+
}
150+
151+
module.exports = getenJSON;

0 commit comments

Comments
 (0)