Skip to content

Commit

Permalink
MDL-76331 editor_tiny: Generate all langstrings
Browse files Browse the repository at this point in the history
This change renames the generator and has it generate the language
strings for all available languages for easier import into AMOS.
  • Loading branch information
andrewnicols committed Nov 17, 2022
1 parent 205a6c1 commit 6ee0d6a
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 21 deletions.
17 changes: 10 additions & 7 deletions lib/editor/tiny/readme_moodle.md
Expand Up @@ -43,23 +43,23 @@

## Update procedure for included TinyMCE translations

1. Visit https://www.tiny.cloud/get-tiny/language-packages/ and download a translation which has been fully translated, for example the German translation.
2. If you did not download the German translation, update the final line of `tools/getOriginals.mjs` to the language code for the relevant translation.
1. Visit https://www.tiny.cloud/get-tiny/language-packages/ and download the "TinyMCE 6 All languages" zip file.
2. Check the list of languages and confirm that the German translation is still at 100%. If not, then make a note of a language which is.
3. Unzip the translation into a new directory:

```
```bash
langdir=`mktemp -d`
cd "${langdir}"
unzip path/to/de.zip
unzip path/to/langs.zip
```

4. Run the translation tool:

```
node "${MOODLEDIR}/tools/getOriginals.mjs"
```bash
node "${MOODLEDIR}/tools/createLangStrings.mjs"
```

This will generate two files
This will generate a language file for each available Language, as well as a `tinystrings.json`, and a `strings.php` which will be used in the subsequent steps.

5. Copy the `tinystrings.json` file into the Moodle directory

Expand All @@ -75,9 +75,12 @@
```

7. Commit changes
8. If required, the remaining language strings can be fed into AMOS.

---

**Note:** A set of language files are also generated for all supported translations and may be submitted to AMOS if desired.

**Note:** You will need to manually check for any Moodle-updated language strings as part of this change (for example any from the en_fixes).

---
Expand Up @@ -13,23 +13,28 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

import {readFile, writeFile} from 'fs/promises';
import {readdir, readFile, writeFile, mkdir} from 'fs/promises';
import {join as joinPath} from 'path';

const fullyTranslatedLanguage = 'de';
const maxStringIdentifierLength = 90;

const readStringsFromLanguages = async (language) => {
const fileContent = await readFile(`./langs/${language}.js`, 'utf-8');

const translations = [];
let translations = {};
const tinymce = {
addI18n: (language, strings) => {
translations.push(...(Object.keys(strings)));
translations = strings;
},
};

eval(fileContent);

return translations.sort();
return Object.keys(translations).sort().reduce((sortedTranslations, key) => {
sortedTranslations[key] = translations[key];
return sortedTranslations;
}, {});
};

const getStringMap = (strings) => {
Expand All @@ -41,7 +46,7 @@ const getStringMap = (strings) => {
.replaceAll(/\{(\d)\}/g, '$1')
.replaceAll('#', 'hash')
.replaceAll(/[^a-z0-9_\-\.]/g, '')
;
;

if (stringKey === '') {
throw new Error(`The calculated key for '${string}' was empty`);
Expand Down Expand Up @@ -77,17 +82,58 @@ const getStringMap = (strings) => {
return stringMap;
};

const getPhpStrings = (stringMap) => Object.entries(stringMap).map(([stringKey, stringValue]) => {
return `$string['${stringKey}'] = '${stringValue.replace("'", "\\\'")}';`
}).join("\n");

const getPhpStrings = (stringMap, translatedStrings) => Object.entries(stringMap).map(([stringKey, englishString]) => {
if (translatedStrings[englishString].length === 0) {
return null;
}
return `$string['${stringKey}'] = '${translatedStrings[englishString].replaceAll("'", "\\\'")}';`
})
.filter((value) => value !== null)
.join("\n");

const storeEnglishStrings = async(stringMap) => {
const englishStrings = Object.entries(stringMap).map(([stringKey, stringValue]) => {
return `$string['${stringKey}'] = '${stringValue.replace("'", "\\\'")}';`
}).join("\n");
await writeFile('./strings.php', englishStrings + "\n");
await writeFile('./tinystrings.json', JSON.stringify(stringMap, null, ' '));
}

const constructTranslationFile = async(language) => {
const constructTranslationFile = async(language, englishStringMap = null) => {
const strings = await readStringsFromLanguages(language);
const stringMap = getStringMap(strings);
console.log(`Generating translation data for ${language} with ${Object.keys(strings).length} strings`);
const stringMap = englishStringMap === null ? getStringMap(Object.keys(strings)) : englishStringMap;

await writeFile('./strings.php', getPhpStrings(stringMap) + "\n");
await writeFile('./tinystrings.json', JSON.stringify(stringMap, null, ' '));
const langDir = joinPath('lang', language);
await mkdir(langDir, {recursive: true});

const fileContent = `<?php
${getPhpStrings(stringMap, strings)}
`;

await writeFile(joinPath(langDir, `editor_tiny.php`), fileContent);

return {
strings,
stringMap,
};
};

constructTranslationFile('de');
const constructTranslationFiles = async() => {
const {stringMap} = await constructTranslationFile(fullyTranslatedLanguage);
storeEnglishStrings(stringMap);

readdir('./langs/').then((files) => {
files.forEach(async(file) => {
const langIdent = file.replace('.js', '');
if (langIdent === fullyTranslatedLanguage) {
// This language is already done.
return;
}
await constructTranslationFile(langIdent, stringMap);
});
});
}

constructTranslationFiles();

0 comments on commit 6ee0d6a

Please sign in to comment.