Last active
June 8, 2022 04:17
-
-
Save ngocvantran/96c6f3dacc9931d9bcdcb4d5bc68c2d8 to your computer and use it in GitHub Desktop.
i18n extract
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
const fs = require('fs'); | |
const _ = require('lodash'); | |
const path = require('path'); | |
const readdirp = require('readdirp'); | |
const Parser = require('i18next-scanner').Parser; | |
const WebpackPreBuildPlugin = require('pre-build-webpack'); | |
const {i18nextToPo, i18nextToPot} = require('i18next-conv'); | |
const charsMap = { | |
'a': 'ààà', 'b': 'ƀ', 'c': 'ç', 'd': 'ð', 'e': 'ééé', 'f': 'ƒ', 'g': 'ĝ', 'h': 'ĥ', 'i': 'îîî', 'l': 'ļ', 'k': 'ķ', 'j': 'ĵ', 'm': 'ɱ', | |
'n': 'ñ', 'o': 'ôôô', 'p': 'þ', 'q': 'ǫ', 'r': 'ŕ', 's': 'š', 't': 'ţ', 'u': 'ûûû', 'v': 'ṽ', 'w': 'ŵ', 'x': 'ẋ', 'y': 'ý', 'z': 'ž', | |
'A': 'ÀÀÀ', 'B': 'Ɓ', 'C': 'Ç', 'D': 'Ð', 'E': 'ÉÉÉ', 'F': 'Ƒ', 'G': 'Ĝ', 'H': 'Ĥ', 'I': 'ÎÎÎ', 'L': 'Ļ', 'K': 'Ķ', 'J': 'Ĵ', 'M': 'Ṁ', | |
'N': 'Ñ', 'O': 'ÔÔÔ', 'P': 'Þ', 'Q': 'Ǫ', 'R': 'Ŕ', 'S': 'Š', 'T': 'Ţ', 'U': 'ÛÛÛ', 'V': 'Ṽ', 'W': 'Ŵ', 'X': 'Ẋ', 'Y': 'Ý', 'Z': 'Ž' | |
}; | |
module.exports = function(options) { | |
options = _.defaults(options, { | |
src: 'src', // Root folder to search for files to extract | |
dest: 'translations', // Folder to write extracted POT file | |
language: 'en', // Lanugage of templates and js files | |
ns: 'translation', // Namespace for created translation file | |
pseudo: null, // Set to a language code (qps-PLOC) to generate pseudo translation file, | |
filename: '{{ns}}.{{language}}.{{ext}}', // Output file name format | |
attr: ['t'], // Template file attributes to detect source text | |
func: ['i18next.t', 'i18n.t'], // JS method to detect source text | |
project: null, // Project name for POT file header | |
roots: [], // Property names to nest generated pseudo json file | |
count: "{{count}}", // Count value used for plurals | |
}); | |
let parser = new Parser({ | |
attr: { | |
list: options.attr | |
}, | |
func: { | |
list: options.func | |
}, | |
nsSeparator: false, | |
keySeparator: false, | |
defaultNs: options.ns, | |
}); | |
readdirp({ | |
root: options.src, | |
entryType: 'files' | |
}, function(file) { | |
let fullPath = file.fullPath; | |
let extension = path.extname(fullPath).toLowerCase(); | |
switch (extension) { | |
case '.html': | |
case '.htm': | |
let template = fs.readFileSync(fullPath, 'utf-8'); | |
parser.parseAttrFromString(template); | |
break; | |
case '.js': | |
case '.ts': | |
let script = fs.readFileSync(fullPath, 'utf-8'); | |
parser.parseFuncFromString(script); | |
break; | |
} | |
}, function() { | |
let translations = parser.get()[options.language][options.ns]; | |
delete translations['']; | |
let potPath = path.join( | |
options.dest, | |
options.filename | |
.replace('{{ns}}', options.ns) | |
.replace('{{language}}', options.language) | |
.replace('{{ext}}', 'pot')); | |
let potDir = path.dirname(potPath); | |
if (!fs.existsSync(potDir)) | |
fs.mkdirSync(potDir); | |
// Converts JSON to POT | |
let convertOpts = { | |
language: options.language, | |
project: options.project, | |
}; | |
i18nextToPot(options.language, JSON.stringify(translations), convertOpts) | |
.then(function(result) { | |
fs.writeFileSync(potPath, result); | |
}); | |
if (!options.pseudo) | |
return; | |
// Pseudo translation | |
let pseudoPath = path.join( | |
options.dest, | |
options.filename | |
.replace('{{ns}}', options.ns) | |
.replace('{{language}}', options.pseudo) | |
.replace('{{ext}}', 'json')); | |
let pseudoDir = path.dirname(pseudoPath); | |
if (!fs.existsSync(pseudoDir)) | |
fs.mkdirSync(pseudoDir); | |
// Create pseudo translations | |
let countHolder = Math.round(Math.random() * 10000).toString(); | |
Object.keys(translations).forEach(function(key) { | |
let translated = ''; | |
let msgid = key.replace(options.count, countHolder); | |
for (let i = 0; i < msgid.length; i++) { | |
let alternatives = charsMap[msgid[i]]; | |
if (!alternatives) { | |
translated += msgid[i]; | |
continue; | |
} | |
translated += alternatives[i % alternatives.length]; | |
} | |
translations[key] = translated | |
.replace(countHolder, options.count); | |
}); | |
// Nest translations in requested roots | |
if (options.roots) { | |
for (let i = options.roots.length - 1; i >= 0; i--) { | |
let temp = translations; | |
translations = {}; | |
translations[options.roots[i]] = temp; | |
} | |
} | |
// Write to file | |
fs.writeFileSync(pseudoPath, | |
JSON.stringify(translations, null, 2)); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const I18nextExtractor = require('./I18nextExtractor'); | |
const baseConfig = { | |
// Webpack config here | |
plugins: [ | |
new WebpackPreBuildPlugin(function() { | |
I18nextExtractor({ | |
// Your options here | |
}); | |
}),, | |
// Other webpack plugins, if needed here | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how can add this for extract into my REACT app?