#!/usr/bin/env node /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /* generate the i18n/en.json file */ const CWD = process.cwd(); const fs = require("fs-extra"); const mkdirp = require("mkdirp"); const glob = require("glob"); const readMetadata = require("./server/readMetadata.js"); const path = require("path"); const siteConfig = require(CWD + "/siteConfig.js"); const babylon = require("babylon"); const traverse = require("babel-traverse").default; const sidebars = require(CWD + "/sidebars.json"); let currentTranslations = { "localized-strings": {}, "pages-strings": {} }; if (fs.existsSync(path)) { currentTranslations = JSON.parse( fs.readFileSync(CWD + "/i18n/en.json", "utf8") ); } function writeFileAndCreateFolder(file, content) { mkdirp.sync(file.replace(new RegExp("/[^/]*$"), "")); fs.writeFileSync(file, content); } function execute() { console.log("Extracting translateable strings from files..."); let translations = { "localized-strings": { next: "Next", previous: "Previous", tagline: siteConfig.tagline }, "pages-strings": {} }; // look through markdown headers of docs for titles and categories to translate let files = glob.sync(CWD + "/../" + readMetadata.getDocsPath() + "/**"); files.forEach(file => { const extension = path.extname(file); if (extension === ".md" || extension === ".markdown") { let res; try { res = readMetadata.processMetadata(file); } catch (e) { console.error(e); process.exit(1); } if (!res) { return; } const metadata = res.metadata; translations["localized-strings"][metadata.localized_id] = metadata.title; if (metadata.sidebar_label) { translations["localized-strings"][metadata.sidebar_label] = metadata.sidebar_label; } } }); // look through header links for text to translate siteConfig.headerLinks.forEach(link => { if (link.label) { translations["localized-strings"][link.label] = link.label; } }); // find sidebar category titles to translate Object.keys(sidebars).forEach(sb => { const categories = sidebars[sb]; Object.keys(categories).forEach(category => { translations["localized-strings"][category] = category; }); }); files = glob.sync(CWD + "/versioned_sidebars/*"); files.forEach(file => { if (!file.endsWith("-sidebars.json")) { if (file.endsWith("-sidebar.json")) { console.warn(`Skipping ${file}. Make sure your sidebar filenames follow this format: 'version-VERSION-sidebars.json'.`); } return; } let sidebarContent; try { sidebarContent = JSON.parse(fs.readFileSync(file, "utf8")); } catch (e) { console.error(`Could not parse ${file} into json. ${e}`); process.exit(1); } Object.keys(sidebarContent).forEach(sb => { const categories = sidebarContent[sb]; Object.keys(categories).forEach(category => { translations["localized-strings"][category] = category; }); }); }); // go through pages to look for text inside translate tags files = glob.sync(CWD + "/pages/en/**"); files.forEach(file => { const extension = path.extname(file); if (extension === ".js") { const ast = babylon.parse(fs.readFileSync(file, "utf8"), { plugins: ["jsx"] }); traverse(ast, { enter(path) { if ( path.node.type === "JSXElement" && path.node.openingElement.name.name === "translate" ) { const text = path.node.children[0].value .trim() .replace(/\s+/g, " "); let description = "no description given"; const attributes = path.node.openingElement.attributes; for (let i = 0; i < attributes.length; i++) { if (attributes[i].name.name === "desc") { description = attributes[i].value.value; } } translations["pages-strings"][text + "|" + description] = text; } } }); } }); // Manually add 'Help Translate' to en.json translations["pages-strings"][ "Help Translate|recruit community translators for your project" ] = "Help Translate"; translations["pages-strings"][ "Edit this Doc|recruitment message asking to edit the doc source" ] = "Edit"; translations["pages-strings"][ "Translate this Doc|recruitment message asking to translate the docs" ] = "Translate"; translations["pages-strings"] = Object.assign( translations["pages-strings"], currentTranslations["pages-strings"] ); translations["localized-strings"] = Object.assign( translations["localized-strings"], currentTranslations["localized-strings"] ); writeFileAndCreateFolder( CWD + "/i18n/en.json", JSON.stringify( Object.assign( { _comment: "This file is auto-generated by write-translations.js" }, translations ), null, 2 ) ); } execute(); module.exports = execute;