Move locale files under api/runtime components

This commit is contained in:
Nick O'Leary
2015-11-21 23:12:39 +00:00
parent 88dc202db2
commit d2be7f8c8f
9 changed files with 63 additions and 66 deletions

View File

@@ -34,6 +34,7 @@ var comms = require("./comms");
var auth = require("./auth");
var needsPermission = auth.needsPermission;
var i18n;
var log;
var adminApp;
var nodeApp;
@@ -50,6 +51,7 @@ var errorHandler = function(err,req,res,next) {
function init(server,runtime) {
var settings = runtime.settings;
i18n = runtime.i18n;
log = runtime.log;
if (settings.httpNodeRoot !== false) {
nodeApp = express();
@@ -127,8 +129,9 @@ function init(server,runtime) {
}
}
function start() {
comms.start();
return when.resolve();
return i18n.registerMessageCatalog("editor",path.resolve(path.join(__dirname,"locales")),"editor.json").then(function(){
comms.start();
});
}
function stop() {
comms.stop();

View File

@@ -13,20 +13,52 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var fs = require('fs');
var path = require('path');
var i18n;
var supportedLangs = [];
var apiLocalDir = path.resolve(path.join(__dirname,"locales"));
var initSupportedLangs = function() {
fs.readdir(apiLocalDir, function(err,files) {
if(!err) {
supportedLangs = files;
}
});
}
function determineLangFromHeaders(acceptedLanguages){
var lang = i18n.defaultLang;
acceptedLanguages = acceptedLanguages || [];
for (var i=0;i<acceptedLanguages.length;i++){
if (supportedLangs.indexOf(acceptedLanguages[i]) !== -1){
lang = acceptedLanguages[i];
break;
// check the language without the country code
} else if (supportedLangs.indexOf(acceptedLanguages[i].split("-")[0]) !== -1) {
lang = acceptedLanguages[i].split("-")[0];
break;
}
}
return lang;
}
module.exports = {
init: function(runtime) {
i18n = runtime.i18n;
initSupportedLangs();
},
get: function(req,res) {
var namespace = req.params[0];
namespace = namespace.replace(/\.json$/,"");
var lang = i18n.determineLangFromHeaders(req.acceptsLanguages() || []);
var lang = determineLangFromHeaders(req.acceptsLanguages() || []);
var prevLang = i18n.i.lng();
i18n.i.setLng(lang, function(){
var catalog = i18n.catalog(namespace,lang);
res.json(catalog||{});
});
i18n.i.setLng(prevLang);
}
},
determineLangFromHeaders: determineLangFromHeaders
}

View File

@@ -0,0 +1,207 @@
{
"common": {
"label": {
"name": "Name",
"ok": "Ok",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close"
}
},
"workspace": {
"defaultName": "Sheet __number__",
"renameSheet": "Rename sheet",
"confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here"
},
"menu": {
"label": {
"sidebar": {
"sidebar": "Sidebar",
"show": "Toggle Sidebar"
},
"displayStatus": "Display Node Status",
"displayConfig": "Configuration Nodes",
"import": "Import",
"export": "Export",
"clipboard": "Clipboard",
"library": "Library",
"subflows": "Subflows",
"createSubflow": "Create Subflow",
"selectionToSubflow": "Selection to Subflow",
"flows": "Tabs",
"add": "Add",
"rename": "Rename",
"delete": "Delete",
"keyboardShortcuts": "Keyboard Shortcuts",
"login": "Login",
"logout": "Logout"
}
},
"user": {
"loggedInAs": "Logged in as __name__",
"login": "Login",
"loginFailed": "Login failed"
},
"notification": {
"warning": "<strong>Warning</strong>: __message__",
"warnings": {
"undeployedChanges": "node has undeployed changes",
"nodeActionDisabled": "node actions disabled within subflow"
},
"error": "<strong>Error</strong>: __message__",
"errors": {
"lostConnection": "Lost connection to server",
"cannotAddSubflowToItself": "Cannot add subflow to itself",
"cannotAddCircularReference": "Cannot add subflow - circular reference detected"
}
},
"clipboard": {
"nodes": "Nodes:",
"selectNodes": "Select the text above and copy to the clipboard.",
"pasteNodes": "Paste nodes here",
"importNodes": "Import nodes",
"exportNodes": "Export nodes to clipboard",
"importUnrecognised": "Imported unrecognised type:",
"importUnrecognised_plural": "Imported unrecognised types:",
"nodeCopied": "__count__ node copied",
"nodeCopied_plural": "__count__ nodes copied",
"invalidFlow": "Invalid flow: __message__"
},
"deploy": {
"deploy": "Deploy",
"full": "Full",
"fullDesc": "Deploys everything in the workspace",
"modifiedFlows": "Modified Flows",
"modifiedFlowsDesc": "Only deploys flows that contain changed nodes",
"modifiedNodes": "Modified Nodes",
"modifiedNodesDesc": "Only deploys nodes that have changed",
"successfulDeploy": "Successfully Deployed",
"errors": {
"noResponse": "no response from server"
},
"confirm": {
"button": {
"confirm": "Confirm deploy",
"cancel": "Cancel"
},
"undeployedChanges": "You have undeployed changes.\n\nLeaving this page will lose these changes.",
"improperlyConfigured": "The workspace contains some nodes that are not properly configured:",
"unknown": "The workspace contains some unknown node types:",
"unusedConfig": "The workspace contains some unused configuration nodes:",
"confirm": "Are you sure you want to deploy?"
}
},
"subflow": {
"editSubflow": "Edit flow __name__",
"edit": "Edit flow",
"subflowInstances": "There is __count__ instance of this subflow",
"subflowInstances_plural": "There are __count__ instances of this subflow",
"editSubflowProperties": "edit properties",
"input": "inputs:",
"output": "outputs:",
"deleteSubflow": "delete subflow",
"info": "Description",
"format":"markdown format",
"errors": {
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
"multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection"
}
},
"editor": {
"configEdit": "edit",
"configAdd": "add",
"configDelete": "Delete",
"nodesUse": "__count__ node uses this config",
"nodesUse_plural": "__count__ nodes use this config",
"addNewConfig": "Add new __type__ config node",
"editConfig": "Edit __type__ config node",
"addNewType": "Add new __type__...",
"errors": {
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it"
}
},
"keyboard": {
"selectAll": "Select all nodes",
"selectAllConnected": "Select all connected nodes",
"addRemoveNode": "Add/remove node from selection",
"deleteSelected": "Delete selected nodes or link",
"importNode": "Import nodes",
"exportNode": "Export selected nodes",
"toggleSidebar": "Toggle sidebar",
"deleteNode": "Delete selected nodes or link",
"copyNode": "Copy selected nodes",
"cutNode": "Cut selected nodes",
"pasteNode": "Paste nodes"
},
"library": {
"openLibrary": "Open Library...",
"saveToLibrary": "Save to Library...",
"typeLibrary": "__type__ library",
"unnamedType": "Unnamed __type__",
"saveToLibrary": "Save to Library",
"exportToLibrary": "Export nodes to library",
"dialogSaveOverwrite": "A __libraryType__ called __libraryName__ already exists. Overwrite?",
"invalidFilename": "Invalid filename",
"savedNodes": "Saved nodes",
"savedType": "Saved __type__",
"saveFailed": "Save failed: __message__",
"filename": "Filename",
"folder": "Folder",
"filenamePlaceholder": "file",
"fullFilenamePlaceholder": "a/b/file",
"folderPlaceholder": "a/b",
"breadcrumb": "Library"
},
"palette": {
"noInfo": "no information available",
"filter": "filter nodes",
"label": {
"subflows": "subflows",
"input": "input",
"output": "output",
"function": "function",
"social": "social",
"storage": "storage",
"analysis": "analysis",
"advanced": "advanced"
},
"event": {
"nodeAdded": "Node added to palette:",
"nodeAdded_plural": "Nodes added to palette",
"nodeRemoved": "Node removed from palette:",
"nodeRemoved_plural": "Nodes removed from palette:",
"nodeEnabled": "Node enabled:",
"nodeEnabled_plural": "Nodes enabled:",
"nodeDisabled": "Node disabled:",
"nodeDisabled_plural": "Nodes disabled:"
}
},
"sidebar": {
"info": {
"name": "Information",
"label": "info",
"node": "Node",
"type": "Type",
"id": "ID",
"subflow": "Subflow",
"instances": "Instances",
"properties": "Properties",
"blank": "blank",
"arrayItems": "__count__ items"
},
"config": {
"name": "Configuration nodes",
"label": "config",
"local": "on this flow",
"global": "on all flows",
"none": "none",
"subflows": "subflows",
"flows": "flows"
}
}
}

View File

@@ -16,6 +16,7 @@
var when = require("when");
var comms = require("./comms");
var locales = require("./locales");
var redNodes;
var log;
var i18n;
@@ -33,7 +34,7 @@ module.exports = {
log.audit({event: "nodes.list.get"},req);
res.json(redNodes.getNodeList());
} else {
var lang = i18n.determineLangFromHeaders(req.acceptsLanguages());
var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
log.audit({event: "nodes.configs.get"},req);
res.send(redNodes.getNodeConfigs(lang));
}
@@ -126,7 +127,7 @@ module.exports = {
res.status(404).end();
}
} else {
var lang = i18n.determineLangFromHeaders(req.acceptsLanguages());
var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
result = redNodes.getNodeConfig(id,lang);
if (result) {
log.audit({event: "nodes.config.get",id:id},req);

View File

@@ -20,19 +20,9 @@ var path = require("path");
var fs = require("fs");
var defaultLang = "en-US";
var supportedLangs = [];
var resourceMap = {
"runtime": {
basedir: path.resolve(__dirname+"/../../locales"),
file:"runtime.json"
},
"editor": {
basedir: path.resolve(__dirname+"/../../locales"),
file: "editor.json"
}
}
var resourceCache = {}
var resourceMap = {};
var resourceCache = {};
function registerMessageCatalog(namespace,dir,file) {
return when.promise(function(resolve,reject) {
@@ -43,19 +33,6 @@ function registerMessageCatalog(namespace,dir,file) {
});
}
var initSupportedLangs = function() {
return when.promise(function(resolve,reject) {
fs.readdir(resourceMap.editor.basedir, function(err,files) {
if(err) {
reject(err);
} else {
supportedLangs = files;
resolve();
}
});
});
}
function mergeCatalog(fallback,catalog) {
for (var k in fallback) {
if (fallback.hasOwnProperty(k)) {
@@ -102,21 +79,17 @@ function init() {
i18n.backend(MessageFileLoader);
i18n.init({
ns: {
namespaces: ["runtime","editor"],
namespaces: [],
defaultNs: "runtime"
},
fallbackLng: ['en-US']
fallbackLng: [defaultLang]
},function() {
initSupportedLangs().then(function() {
resolve();
});
resolve();
});
});
}
function getCatalog(namespace,lang) {
//console.log("+",namespace,lang);
//console.log(resourceCache[namespace][lang]);
var result = null;
if (resourceCache.hasOwnProperty(namespace)) {
result = resourceCache[namespace][lang];
@@ -130,32 +103,15 @@ function getCatalog(namespace,lang) {
}
}
}
//console.log(result);
return result;
}
function determineLangFromHeaders(acceptedLanguages){
var lang = "en-US";
acceptedLanguages = acceptedLanguages || [];
for (var i=0;i<acceptedLanguages.length;i++){
if (supportedLangs.indexOf(acceptedLanguages[i]) !== -1){
lang = acceptedLanguages[i];
break;
// check the language without the country code
} else if (supportedLangs.indexOf(acceptedLanguages[i].split("-")[0]) !== -1) {
lang = acceptedLanguages[i].split("-")[0];
break;
}
}
return lang;
}
var obj = module.exports = {
init: init,
registerMessageCatalog: registerMessageCatalog,
catalog: getCatalog,
i: i18n,
determineLangFromHeaders: determineLangFromHeaders
defaultLang:defaultLang
}
obj['_'] = function() {

View File

@@ -51,6 +51,9 @@ function getVersion() {
function start() {
return i18n.init()
.then(function() {
return i18n.registerMessageCatalog("runtime",path.resolve(path.join(__dirname,"locales")),"runtime.json")
})
.then(function() { return storage.init(settings)})
.then(function() { return settings.load(storage)})
.then(function() {

View File

@@ -0,0 +1,124 @@
{
"runtime": {
"welcome": "Welcome to Node-RED",
"version": "__component__ version: __version__",
"paths": {
"settings": "Settings file : __path__"
}
},
"server": {
"loading": "Loading palette nodes",
"errors": "Failed to register __count__ node type",
"errors_plural": "Failed to register __count__ node types",
"errors-help": "Run with -v for details",
"missing-modules": "Missing node modules:",
"removing-modules": "Removing modules from config",
"added-types": "Added node types:",
"removed-types": "Removed node types:",
"install": {
"invalid": "Invalid module name",
"installing": "Installing module: __name__",
"installed": "Installed module: __name__",
"install-failed": "Install failed",
"install-failed-long": "Installation of module __name__ failed:",
"install-failed-not-found": "$t(install-failed-long) module not found",
"uninstalling": "Uninstalling module: __name__",
"uninstall-failed": "Uninstall failed",
"uninstall-failed-long": "Uninstall of module __name__ failed:",
"uninstalled": "Uninstalled module: __name__"
},
"unable-to-listen": "Unable to listen on __listenpath__",
"port-in-use": "Error: port in use",
"uncaught-exception": "Uncaught Exception:",
"admin-ui-disabled": "Admin UI disabled",
"now-running": "Server now running at __listenpath__",
"failed-to-start": "Failed to start server:",
"headless-mode": "Running in headless mode",
"httpadminauth-deprecated": "use of httpAdminAuth is deprecated. Use adminAuth instead"
},
"api": {
"flows": {
"error-save": "Error saving flows: __message__",
"error-reload": "Error reloading flows: __message__"
},
"library": {
"error-load-entry": "Error loading library entry '__path__': __message__",
"error-save-entry": "Error saving library entry '__path__': __message__",
"error-load-flow": "Error loading flow '__path__': __message__",
"error-save-flow": "Error saving flow '__path__': __message__"
},
"nodes": {
"enabled": "Enabled node types:",
"disabled": "Disabled node types:",
"error-enable": "Failed to enable node:"
}
},
"comms": {
"error": "Communication channel error: __message__",
"error-server": "Communication server error: __message__",
"error-send": "Communication send error: __message__"
},
"settings": {
"not-available": "Settings not available",
"property-read-only": "Property '__prop__' is read-only"
},
"nodes": {
"credentials": {
"error":"Error loading credentials: __message__",
"not-registered": "Credential type '__type__' is not registered"
},
"flows": {
"registered-missing": "Missing type registered: __type__",
"error": "Error loading flows: __message__",
"starting-modified-nodes": "Starting modified nodes",
"starting-modified-flows": "Starting modified flows",
"starting-flows": "Starting flows",
"started-modified-nodes": "Started modified nodes",
"started-modified-flows": "Started modified flows",
"started-flows": "Started flows",
"stopping-modified-nodes": "Stopping modified nodes",
"stopping-modified-flows": "Stopping modified flows",
"stopping-flows": "Stopping flows",
"stopped-modified-nodes": "Stopped modified nodes",
"stopped-modified-flows": "Stopped modified flows",
"stopped-flows": "Stopped flows",
"stopped": "Stopped",
"missing-types": "Waiting for missing types to be registered:",
"missing-type-provided": " - __type__ (provided by npm module __module__)",
"missing-type-install-1": "To install any of these missing modules, run:",
"missing-type-install-2": "in the directory:"
},
"flow": {
"unknown-type": "Unknown type: __type__",
"missing-types": "missing types",
"error-loop": "Message exceeded maximum number of catches"
},
"index": {
"unrecognised-id": "Unrecognised id: __id__",
"type-in-use": "Type in use: __msg__",
"unrecognised-module": "Unrecognised module: __module__"
},
"registry": {
"localfilesystem": {
"module-not-found": "Cannot find module '__module__'"
}
}
},
"storage": {
"index": {
"forbidden-flow-name": "forbidden flow name"
},
"localfilesystem": {
"user-dir": "User directory : __path__",
"flows-file": "Flows file : __path__",
"create": "Creating new flow file"
}
}
}