mirror of
https://github.com/home-assistant/frontend.git
synced 2025-05-15 23:48:43 +00:00
181 lines
5.0 KiB
JavaScript
181 lines
5.0 KiB
JavaScript
import fs from "fs/promises";
|
|
import gulp from "gulp";
|
|
import path from "path";
|
|
import mapStream from "map-stream";
|
|
import transform from "gulp-json-transform";
|
|
import { LokaliseApi } from "@lokalise/node-api";
|
|
import JSZip from "jszip";
|
|
|
|
const inDir = "translations";
|
|
const inDirFrontend = `${inDir}/frontend`;
|
|
const inDirBackend = `${inDir}/backend`;
|
|
const srcMeta = "src/translations/translationMetadata.json";
|
|
const encoding = "utf8";
|
|
|
|
function hasHtml(data) {
|
|
return /<[a-z][\s\S]*>/i.test(data);
|
|
}
|
|
|
|
function recursiveCheckHasHtml(file, data, errors, recKey) {
|
|
Object.keys(data).forEach(function (key) {
|
|
if (typeof data[key] === "object") {
|
|
const nextRecKey = recKey ? `${recKey}.${key}` : key;
|
|
recursiveCheckHasHtml(file, data[key], errors, nextRecKey);
|
|
} else if (hasHtml(data[key])) {
|
|
errors.push(`HTML found in ${file.path} at key ${recKey}.${key}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
function checkHtml() {
|
|
const errors = [];
|
|
|
|
return mapStream(function (file, cb) {
|
|
const content = file.contents;
|
|
let error;
|
|
if (content) {
|
|
if (hasHtml(String(content))) {
|
|
const data = JSON.parse(String(content));
|
|
recursiveCheckHasHtml(file, data, errors);
|
|
if (errors.length > 0) {
|
|
error = errors.join("\r\n");
|
|
}
|
|
}
|
|
}
|
|
cb(error, file);
|
|
});
|
|
}
|
|
|
|
function convertBackendTranslations(data, _file) {
|
|
const output = { component: {} };
|
|
if (!data.component) {
|
|
return output;
|
|
}
|
|
Object.keys(data.component).forEach((domain) => {
|
|
if (!("entity_component" in data.component[domain])) {
|
|
return;
|
|
}
|
|
output.component[domain] = { entity_component: {} };
|
|
Object.keys(data.component[domain].entity_component).forEach((key) => {
|
|
output.component[domain].entity_component[key] =
|
|
data.component[domain].entity_component[key];
|
|
});
|
|
});
|
|
return output;
|
|
}
|
|
|
|
gulp.task("convert-backend-translations", function () {
|
|
return gulp
|
|
.src([`${inDirBackend}/*.json`])
|
|
.pipe(transform((data, file) => convertBackendTranslations(data, file)))
|
|
.pipe(gulp.dest(inDirBackend));
|
|
});
|
|
|
|
gulp.task("check-translations-html", function () {
|
|
return gulp
|
|
.src([`${inDirFrontend}/*.json`, `${inDirBackend}/*.json`])
|
|
.pipe(checkHtml());
|
|
});
|
|
|
|
gulp.task("check-all-files-exist", async function () {
|
|
const file = await fs.readFile(srcMeta, { encoding });
|
|
const meta = JSON.parse(file);
|
|
const writings = [];
|
|
Object.keys(meta).forEach((lang) => {
|
|
writings.push(
|
|
fs.writeFile(`${inDirFrontend}/${lang}.json`, JSON.stringify({}), {
|
|
flag: "wx",
|
|
}),
|
|
fs.writeFile(`${inDirBackend}/${lang}.json`, JSON.stringify({}), {
|
|
flag: "wx",
|
|
})
|
|
);
|
|
});
|
|
await Promise.allSettled(writings);
|
|
});
|
|
|
|
const lokaliseProjects = {
|
|
backend: "130246255a974bd3b5e8a1.51616605",
|
|
frontend: "3420425759f6d6d241f598.13594006",
|
|
};
|
|
|
|
gulp.task("fetch-lokalise", async function () {
|
|
let apiKey;
|
|
try {
|
|
apiKey =
|
|
process.env.LOKALISE_TOKEN ||
|
|
(await fs.readFile(".lokalise_token", { encoding }));
|
|
} catch {
|
|
throw new Error(
|
|
"An Administrator Lokalise API token is required to download the latest set of translations. Place your token in a new file `.lokalise_token` in the repo root directory."
|
|
);
|
|
}
|
|
const lokaliseApi = new LokaliseApi({ apiKey });
|
|
|
|
const mkdirPromise = Promise.all([
|
|
fs.mkdir(inDirFrontend, { recursive: true }),
|
|
fs.mkdir(inDirBackend, { recursive: true }),
|
|
]);
|
|
|
|
await Promise.all(
|
|
Object.entries(lokaliseProjects).map(([project, projectId]) =>
|
|
lokaliseApi
|
|
.files()
|
|
.download(projectId, {
|
|
format: "json",
|
|
original_filenames: false,
|
|
replace_breaks: false,
|
|
json_unescaped_slashes: true,
|
|
export_empty_as: "skip",
|
|
})
|
|
.then((download) => fetch(download.bundle_url))
|
|
.then((response) => {
|
|
if (response.status === 200 || response.status === 0) {
|
|
return response.arrayBuffer();
|
|
}
|
|
throw new Error(response.statusText);
|
|
})
|
|
.then(JSZip.loadAsync)
|
|
.then(async (contents) => {
|
|
await mkdirPromise;
|
|
return Promise.all(
|
|
Object.keys(contents.files).map(async (filename) => {
|
|
const file = contents.file(filename);
|
|
if (!file) {
|
|
// no file, probably a directory
|
|
return Promise.resolve();
|
|
}
|
|
return file
|
|
.async("nodebuffer")
|
|
.then((content) =>
|
|
fs.writeFile(
|
|
path.join(
|
|
inDir,
|
|
project,
|
|
filename.split("/").splice(-1)[0]
|
|
),
|
|
content,
|
|
{ flag: "w", encoding }
|
|
)
|
|
);
|
|
})
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
console.error(err);
|
|
throw err;
|
|
})
|
|
)
|
|
);
|
|
});
|
|
|
|
gulp.task(
|
|
"download-translations",
|
|
gulp.series(
|
|
"fetch-lokalise",
|
|
"convert-backend-translations",
|
|
"check-translations-html",
|
|
"check-all-files-exist"
|
|
)
|
|
);
|