Skip to content

Instantly share code, notes, and snippets.

@ngocvantran
Last active June 8, 2022 04:17
Show Gist options
  • Save ngocvantran/96c6f3dacc9931d9bcdcb4d5bc68c2d8 to your computer and use it in GitHub Desktop.
Save ngocvantran/96c6f3dacc9931d9bcdcb4d5bc68c2d8 to your computer and use it in GitHub Desktop.
i18n extract
"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));
});
};
const I18nextExtractor = require('./I18nextExtractor');
const baseConfig = {
// Webpack config here
plugins: [
new WebpackPreBuildPlugin(function() {
I18nextExtractor({
// Your options here
});
}),,
// Other webpack plugins, if needed here
]
}
@johnfelipe
Copy link

how can add this for extract into my REACT app?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment