cordova-plugin-localization-string
Version:
Cordova Plugin for handling localization strings on InfoPlist.strings and Localizable.strings on iOS, strings.xml on Android
178 lines (155 loc) • 4.41 kB
JavaScript
var fs = require("fs");
var path = require("path");
var mkdirp = require("mkdirp").mkdirp;
var _ = require("underscore");
var xml2js = require("xml2js");
var utils = require("./utils");
function fileExists(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
return false;
}
}
module.exports = function (context) {
return utils.getTargetLang(context).then(function (languages) {
var promisesToRun = [];
languages.forEach(function (lang) {
// read the json file
// var langJson = require(lang.path);
var langJson = JSON.parse(fs.readFileSync(lang.path, "utf8"));
// check the locales to write to
var localeLangs = [];
//
if (_.has(langJson, "locale") && _.has(langJson.locale, "android")) {
// iterate the locales
_.forEach(langJson.locale.android, function (aLocale) {
localeLangs.push(aLocale);
});
} else {
// use the default lang from the filename, for example "en" in en.json
localeLangs.push(lang.lang);
}
_.forEach(localeLangs, function (localeLang) {
var stringXmlFilePath = getLocalStringXmlPath(context, localeLang);
var parser = new xml2js.Parser();
var stringXmlJson;
if (!fileExists(stringXmlFilePath)) {
stringXmlJson = {
resources: {
string: [],
},
};
promisesToRun.push(
processResult(context, localeLang, langJson, stringXmlJson)
);
} else {
promisesToRun.push(
new Promise(function (resolve, reject) {
// lets read from strings.xml into json
fs.readFile(stringXmlFilePath, function (err, data) {
if (err) {
return reject(err);
}
parser.parseString(data, function (err, result) {
if (err) {
return reject(err);
}
stringXmlJson = result;
// initialize xmlJson to have strings
if (
!_.has(stringXmlJson, "resources") ||
!_.has(stringXmlJson.resources, "string")
) {
stringXmlJson.resources = {
string: [],
};
}
processResult(
context,
localeLang,
langJson,
stringXmlJson
).then(resolve, reject);
});
});
})
);
}
});
});
return Promise.all(promisesToRun);
});
};
function getLocalStringXmlPath(context, lang) {
var resPath = getResPath(context);
var defaultLocale = getDefaultLocale();
return path.normalize(
path.join(
resPath,
"values" + (lang !== defaultLocale ? "-" + lang : ""),
"strings.xml"
)
);
}
function getResPath(context) {
var locations = context
.requireCordovaModule("cordova-lib/src/platforms/platforms")
.getPlatformApi("android").locations;
return (
(locations && locations.res) ||
path.join(context.opts.projectRoot, "platforms/android/res")
);
}
function getDefaultLocale() {
var config = fs.readFileSync("config.xml").toString();
var matches = config.match(
new RegExp('<widget[^>]*?defaultlocale="(.*?)"[\\s\\S]*?>', "i")
);
return (matches && matches[1]) || "en";
}
// process the modified xml and write to file
function processResult(context, lang, langJson, stringXmlJson) {
var mapObj = {};
// create a map to the actual string
_.forEach(stringXmlJson.resources.string, function (val) {
if (_.has(val, "$") && _.has(val["$"], "name")) {
mapObj[val["$"].name] = val;
}
});
var langJsonToProcess = _.extend(
{},
langJson.config_android,
langJson.app,
langJson.app_android
);
// now iterate through langJsonToProcess
_.forEach(langJsonToProcess, function (val, key) {
// positional string format is in Mac OS X format. change to android format
val = val.replace(/\$@/gi, "$s");
val = val.replace(/'/gi, "\\'");
if (_.has(mapObj, key)) {
// mapObj contains key. replace key
mapObj[key]["_"] = val;
} else {
// add by inserting
stringXmlJson.resources.string.push({
_: val,
$: { name: key },
});
}
});
// save to disk
var filePath = getLocalStringXmlPath(context, lang);
var langDir = path.dirname(filePath);
return mkdirp(langDir).then(function () {
fs.writeFileSync(filePath, buildXML(stringXmlJson));
console.log("Localization saved:", filePath);
});
function buildXML(obj) {
var builder = new xml2js.Builder();
builder.options.renderOpts.indent = "\t";
var x = builder.buildObject(obj);
return x.toString();
}
}