Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@zeel01
Last active August 2, 2020 21:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeel01/02d4018b09794b20b3f237f949fd959e to your computer and use it in GitHub Desktop.
Save zeel01/02d4018b09794b20b3f237f949fd959e to your computer and use it in GitHub Desktop.
FVTT Module Language Support Counter
// This script can be used to generate an HTML list of modules that support localization
// each entry will have a list of transalations, and each translation will indicate
// how many strings are defined within. For translations that appear to be missing
// strings, a list of missing strings will be created.
//
// It is recommended that you pipe the output of this script into an HTML file to
// be viewed in your browser.
//
// Thanks to KaKaRoTo for his help on this
// You can run the following command from your modules folder:
// GLOB_PATTERN='' node languageCounter.js > languageCounts.html
const path = require("path");
const fs = require("fs-extra"); // npm install fs-extra
const glob = require("glob"); // npm install glob
function globAsync(pattern, options) {
return new Promise((resolve, reject) => {
glob(pattern, options, async (err, files) => {
if (err) reject(err);
else resolve(files);
});
});
}
async function languageCounter() {
let modules;
try {
modules = await globAsync(process.env.GLOB_PATTERN || "*/module.json");
}
catch (e) {
console.error(e);
return;
}
let supported = [];
for (let module of modules) {
try {
let manifest = await fs.readJSON(module);
manifest.ownPath = path.dirname(module);
if (manifest.languages && manifest.languages.length > 0) supported.push(manifest);
}
catch (e) {
console.error(e);
continue;
}
}
supported.sort((a, b) => a.title < b.title ? -1 : 1)
console.log(`<ul>`);
for (let module of supported) {
console.log(`<li>
<span><a href="${module.url}">${module.title}</a> - ${module.author}</span>`);
let languages = [];
let langs = module.languages;
for (let lang of langs) {
let entry = {};
entry.meta = lang;
try {
entry.language = await fs.readJSON(path.resolve(module.ownPath, lang.path));
let reducer = (acc, cur) => (typeof cur[1] !== "object") ? acc : acc + Object.entries(cur[1]).reduce(reducer, Object.keys(cur[1]).length)
entry.stringCount = Object.entries(entry.language).reduce(reducer, Object.keys(entry.language).length);
}
catch (e) {
console.error(e);
entry.language = {};
entry.stringCount = -1;
}
languages.push(entry);
}
languages.sort((a, b) => {
if (a.stringCount > b.stringCount) return -1;
if (a.stringCount < b.stringCount) return 1;
if (a.meta.lang.toLowerCase() == "en") return -1;
if (b.meta.lang.toLowerCase() == "en") return 1;
return 0;
});
for (let entry of languages) {
entry.flat = flatten(entry.language);
}
console.log(`<ul>`);
let first = true;
for (let entry of languages) {
console.log(`<li>${first ? "<strong>":""}${entry.meta.lang.toUpperCase()} - ${entry.meta.name}${first ? "</strong>":""}: ${entry.stringCount < 0 ? "MISSING" : entry.stringCount}`);
if (entry.stringCount > -1 && entry.stringCount < languages[0].stringCount){
console.log(`<details><pre>`);
let diffs = 0;
Object.entries(languages[0].flat).forEach(([key, value]) => {
if (entry.flat[key]) return;
diffs++;
console.log(`"${key}": ${Array.isArray(value)?value.toString():value}`);
});
console.log(`</pre><summary>Differences: ${diffs}</summary></details>`);
}
first = false;
console.log(`</li>`);
}
console.log(`</ul>`);
console.log(`</li>`);
}
console.log(`</ul>`);
}
function flatten(obj) {
let flat = {};
Object.entries(obj).forEach(([key, value]) => {
if (typeof value !== "object" || Array.isArray(value)) return flat[key] = value;
Object.entries(flatten(value)).forEach(([k, v]) => flat[`${key}.${k}`] = v);
});
return flat;
}
languageCounter();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment