diff --git a/examples/siteConfig.js b/examples/siteConfig.js index d8fdaf3373..e599020bb8 100644 --- a/examples/siteConfig.js +++ b/examples/siteConfig.js @@ -79,7 +79,6 @@ const siteConfig = { let languages; if (fs.existsSync("./languages.js")) { languages = require("./languages.js"); - siteConfig["en"] = require("./i18n/en.json"); } else { languages = [ { diff --git a/lib/server/find-strings-plugin.js b/lib/server/find-strings-plugin.js new file mode 100644 index 0000000000..05b93f1c7a --- /dev/null +++ b/lib/server/find-strings-plugin.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +/* find all strings with their descriptions that need to be translated and write + to i18n/en.json file */ + +const fs = require("fs"); + +module.exports = function findStringsPlugin(babel) { + const { types: t } = babel; + + const translationsFile = process.cwd() + "/i18n/en.json"; + let currentTranslations = JSON.parse( + fs.readFileSync(translationsFile, "utf8") + ); + + return { + visitor: { + JSXElement(path) { + if (path.node.openingElement.name.name !== "Translate") { + return; + } + const text = path.node.children[0].value.trim(); + let description; + 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; + } + } + if (!currentTranslations["pages-strings"]) { + currentTranslations["pages-strings"] = {}; + } + currentTranslations["pages-strings"][text + "|" + description] = text; + fs.writeFileSync(translationsFile, JSON.stringify(currentTranslations)); + } + } + }; +}; diff --git a/lib/server/translate-plugin.js b/lib/server/translate-plugin.js new file mode 100644 index 0000000000..845d079dbc --- /dev/null +++ b/lib/server/translate-plugin.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +/* replaces translate tags with calls to translate function */ + +module.exports = function translatePlugin(babel) { + const { types: t } = babel; + + return { + visitor: { + JSXElement(path) { + if (path.node.openingElement.name.name !== "translate") { + return; + } + /* assume translate element only has one child which is the text */ + const text = path.node.children[0].value.trim(); + let description; + 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; + } + } + /* use an expression container if inside a jsxelement */ + if (path.findParent(path => true).node.type === "JSXElement") { + path.replaceWith( + t.jSXExpressionContainer( + t.callExpression(t.identifier("translate"), [ + t.stringLiteral(text + "|" + description) + ]) + ) + ); + } else { + path.replaceWith( + t.callExpression(t.identifier("translate"), [ + t.stringLiteral(text + "|" + description) + ]) + ); + } + } + } + }; +}; diff --git a/lib/server/translation.js b/lib/server/translation.js index 504c602828..b22c092fe4 100644 --- a/lib/server/translation.js +++ b/lib/server/translation.js @@ -73,7 +73,7 @@ function injectContent() { }); let injectedContent = ''; - languages.filter(language => language != 'en').forEach(language => { + languages.forEach(language => { injectedContent += "\nsiteConfig['" + language + diff --git a/lib/server/writeTranslations.js b/lib/server/writeTranslations.js new file mode 100644 index 0000000000..3868d0ff38 --- /dev/null +++ b/lib/server/writeTranslations.js @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +/* 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("./readMetadata.js"); +const path = require("path"); +const shell = require("shelljs"); +const siteConfig = require(CWD + "/siteConfig.js"); + +function writeFileAndCreateFolder(file, content) { + mkdirp.sync(file.replace(new RegExp("/[^/]*$"), "")); + fs.writeFileSync(file, content); +} + +function execute() { + let translations = { + "localized-strings": { + next: "Next", + previous: "Previous" + }, + tagline: siteConfig.tagline, + "pages-strings": {} + }; + + /* look through front matter of docs for titles and categories to translate */ + let files = glob.sync(CWD + "/../docs/en/**"); + files.forEach(file => { + const extension = path.extname(file); + if (extension === ".md" || extension === ".markdown") { + const metadata = readMetadata.extractMetadata( + fs.readFileSync(file, "utf8") + ).metadata; + + translations["localized-strings"][metadata.id] = metadata.title; + translations["localized-strings"][metadata.category] = metadata.category; + } + }); + /* look through header links for text to translate */ + for (let i = 0; i < siteConfig.headerLinksInternal.length; i++) { + translations["localized-strings"][siteConfig.headerLinksInternal[i].text] = + siteConfig.headerLinksInternal[i].text; + } + for (let i = 0; i < siteConfig.headerLinksExternal.length; i++) { + translations["localized-strings"][siteConfig.headerLinksExternal[i].text] = + siteConfig.headerLinksExternal[i].text; + } + writeFileAndCreateFolder(CWD + "/i18n/en.json", JSON.stringify(translations)); + + /* go through pages to look for text inside translate tags */ + const plugin = __dirname + "/find-strings-plugin.js"; + files = glob.sync(CWD + "/pages/en/**"); + files.forEach(file => { + const extension = path.extname(file); + if (extension === ".js") { + shell.exec( + `babel ${file} --plugins=${plugin} --presets=react > /dev/null` + ); + } + }); +} + +module.exports = execute; diff --git a/package.json b/package.json index 7d5441e459..45440ab8f2 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "examples": "./lib/copy-examples.js" }, "dependencies": { + "babel-cli": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-register": "^6.24.1", "classnames": "^2.2.5", @@ -17,10 +18,6 @@ "request": "^2.81.0", "shelljs": "^0.7.8" }, - "devDependencies": { - "babel-cli": "^6.24.1", - "babel-preset-react": "^6.24.1" - }, "name": "docusaurus", "version": "1.0.0-alpha.12", "bin": {