UNPKG

cordova-plugin-localization-string

Version:

Cordova Plugin for handling localization strings on InfoPlist.strings and Localizable.strings on iOS, strings.xml on Android

251 lines (221 loc) 6.81 kB
var fs = require("fs"); var path = require("path"); var mkdirp = require("mkdirp").mkdirp; var _ = require("underscore"); var xcode = require("xcode"); var utils = require("./utils"); var iosProjFolder; var iosPbxProjPath; function jsonToDotStrings(jsonObj) { var returnString = ""; _.forEach(jsonObj, function (val, key) { returnString += '"' + key + '" = "' + val + '";\n'; }); return returnString; } function getProjectName() { // Valid matches // '<name>Application one</name>', // '<name short="App1">Application one</name>', // '<name xmlns:widget="http://www.w3.org/ns/widgets">Application one</name>', // '<name >Application one</name>', // `<name // >Application one</name>`, // // Invalid matches // '<name2>Application one</name>', // '<namefoo>Application one</name>', // '<name!!>Application one</name>', const regExpression = "<name(?=[\\s>])[^>]*>(.*?)</name>"; var config = fs.readFileSync("config.xml").toString(); var matches = config.match(new RegExp(regExpression, "i")); return (matches && matches[1]) || null; } function initIosDir() { if (!iosProjFolder || !iosPbxProjPath) { var projectName = getProjectName(); iosProjFolder = "platforms/ios/" + projectName; iosPbxProjPath = "platforms/ios/" + projectName + ".xcodeproj/project.pbxproj"; } } function getTargetIosDir() { initIosDir(); return iosProjFolder; } function getXcodePbxProjPath() { initIosDir(); return iosPbxProjPath; } function writeStringFile(plistStringJsonObj, lang, fileName, bundle) { var lProjPath = getTargetIosDir() + "/Resources/" + (bundle ? bundle + "/" : "") + lang + ".lproj"; mkdirp(lProjPath).then(function () { var stringToWrite = jsonToDotStrings(plistStringJsonObj); fs.writeFileSync(path.join(lProjPath, fileName), stringToWrite); }); } function writeLocalisationFieldsToXcodeProj(filePaths, groupName, proj) { var fileRefSection = proj.pbxFileReferenceSection(); var fileRefValues = _.values(fileRefSection); if (filePaths.length > 0) { var groupKey = proj.findPBXVariantGroupKey({ name: groupName }); if (!groupKey) { // findPBXVariantGroupKey with name InfoPlist.strings not found. creating new group var localizableStringVarGroup = proj.addLocalizationVariantGroup(groupName); groupKey = localizableStringVarGroup.fileRef; } filePaths.forEach(function (path) { var results = _.find(fileRefValues, function (o) { return ( _.isObject(o) && _.has(o, "path") && o.path.replace(/['"]+/g, "") === path ); }); if (_.isUndefined(results)) { // not found in pbxFileReference yet proj.addResourceFile( "Resources/" + path, { variantGroup: true }, groupKey ); } }); } } module.exports = function (context) { var infoPlistPaths = []; var localizableStringsPaths = []; var settingsBundlePaths = []; var appShortcutsPaths = []; return utils.getTargetLang(context).then(function (languages) { 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, "ios")) { // iterate the locales _.forEach(langJson.locale.ios, 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) { if (_.has(langJson, "config_ios")) { // do processing for appname into plist var plistString = langJson.config_ios; if (!_.isEmpty(plistString)) { writeStringFile(plistString, localeLang, "InfoPlist.strings"); infoPlistPaths.push(localeLang + ".lproj/" + "InfoPlist.strings"); } } // remove APP_NAME and write to Localizable.strings if (_.has(langJson, "app")) { // do processing for appname into plist var localizableStringsJson = langJson.app; // ios specific strings if (_.has(langJson, "app_ios")) { Object.assign(localizableStringsJson, langJson.app_ios); } if (!_.isEmpty(localizableStringsJson)) { writeStringFile( localizableStringsJson, localeLang, "Localizable.strings" ); localizableStringsPaths.push( localeLang + ".lproj/" + "Localizable.strings" ); } } if ( _.has(langJson, "app_shortcuts") && !_.isEmpty(langJson.app_shortcuts) ) { writeStringFile( langJson.app_shortcuts, localeLang, "AppShortcuts.strings" ); appShortcutsPaths.push( localeLang + ".lproj/" + "AppShortcuts.strings" ); } // to create Settings.bundle localizations if (_.has(langJson, "settings_ios")) { var localizableSettingsJson = langJson.settings_ios; if (!_.isEmpty(localizableSettingsJson)) { _.each(localizableSettingsJson, function (value, key) { var settingsFileName = key + ".strings"; var localizableSettingsStringsRoot = value; if (!_.isEmpty(localizableSettingsStringsRoot)) { writeStringFile( localizableSettingsStringsRoot, localeLang, settingsFileName, "Settings.bundle" ); settingsBundlePaths.push( "Settings.bundle" + localeLang + ".lproj/" + settingsFileName ); } }); } } }); }); var pbxProjPath = getXcodePbxProjPath(); var proj = xcode.project(pbxProjPath); return new Promise(function (resolve, reject) { proj.parse(function (error) { if (error) { reject(error); } writeLocalisationFieldsToXcodeProj( infoPlistPaths, "InfoPlist.strings", proj ); writeLocalisationFieldsToXcodeProj( localizableStringsPaths, "Localizable.strings", proj ); writeLocalisationFieldsToXcodeProj( appShortcutsPaths, "AppShortcuts.strings", proj ); fs.writeFileSync(pbxProjPath, proj.writeSync()); console.log( "Pbx project written with localization groups", _.map(languages, "lang") ); var platformPath = path.join( context.opts.projectRoot, "platforms", "ios" ); var projectFilePath = path.join( platformPath, "/cordova/lib/projectFile.js" ); var projectFileExists = fs.existsSync(projectFilePath); // Starting cordova-ios@7.0.0, projectFile.js is not part of the platform folder anymore and has to be grabbed from node_modules var projectFileApi = projectFileExists ? require(projectFilePath) : require("cordova-ios/lib/projectFile"); projectFileApi.purgeProjectFileCache(platformPath); resolve(); }); }); }); };