From 788454051ce3148c38299616f1bfba3ba78783b1 Mon Sep 17 00:00:00 2001 From: Joe Uhren Date: Sun, 16 Jun 2024 18:58:12 -0600 Subject: [PATCH] Add preliminary plugin support -Plugins can now be enabled via settings.json after dropping the plugin files into the new plugins directory -Enabling plugins will allow extending the normal functionality of the explorer with new database collections, menus, pages and apis + open up a new url for data to be sent from the plugin to the explorer -A new plugins section was added to the settings with a definition for the generic-snapshots plugin -Locale strings are now loaded and shared out via the settings so there is generally no more need to explicitly include the locale.js file -The locale object has been updated to localization within the explorer -A number of new locale strings have been added and their values replaced with the locale string within the explorer -Added plugin support verbiage and a link to the generic-snapshots crowdfunding task to the README --- README.md | 4 +- app.js | 226 +++++++++++++++-- lib/database.js | 94 ++++++-- lib/explorer.js | 103 ++++---- lib/locale.js | 479 ++++++++++++++++++++----------------- lib/nodeapi.js | 4 +- lib/settings.js | 116 +++++---- locale/en.json | 55 ++++- plugins/delete.me | 1 + public/css/style.scss | 4 +- routes/index.js | 49 +++- scripts/compile_css.js | 4 +- scripts/create_backup.js | 12 +- scripts/delete_database.js | 23 +- scripts/prestart.js | 7 +- scripts/restore_backup.js | 47 ++-- scripts/stop_explorer.js | 2 +- scripts/sync.js | 40 +++- scripts/update_explorer.js | 19 +- settings.json.template | 78 +++--- views/address.pug | 30 +-- views/block.pug | 48 ++-- views/claim_address.pug | 8 +- views/error.pug | 6 +- views/index.pug | 26 +- views/info.pug | 58 +++-- views/layout.pug | 127 ++++++---- views/market.pug | 82 +++---- views/masternodes.pug | 10 +- views/movement.pug | 18 +- views/network.pug | 22 +- views/orphans.pug | 22 +- views/reward.pug | 36 +-- views/richlist.pug | 36 +-- views/tx.pug | 62 ++--- 35 files changed, 1213 insertions(+), 745 deletions(-) create mode 100644 plugins/delete.me diff --git a/README.md b/README.md index 2576f6c0..0cbc4162 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Written in node.js and mongodb, eIquidus is the most stable, secure, customizabl Exor accepts targeted donations in an effort to crowdfund various feature and improvement requests for the block explorer and other Exor-related projects. [Browse the list of unfunded tasks](https://exor.io/tasklist/hide-completed/hide-funded/show-unfunded/) and send Exor coins to the correct funding address to help meet the funding goal for tasks that you would like to see developed. Once the funding goal is met, Exor developers will begin work on the task asap and will remain a top priority until completed. If you are a software developer and would like to work on funded tasks in exchange for payment in EXOR, please get in touch with us using one of the [Developer Contact](#developer-contact) links below. +**NEW:** Preliminary plugin support has been added. Help support the first plugin proposal for automatic snapshot creation. More info: [https://exor.io/task/181/b371d98f6217f2f533b3a0c9fedce7b200571c4f/](https://exor.io/task/181/b371d98f6217f2f533b3a0c9fedce7b200571c4f/) + ### Premium Support All code in this project is open source and available free-of-charge under the BSD-3-Clause license. If you require assistance setting up an explorer for your coin, or are interested in hiring a developer to incorporate custom changes for your explorer, you may contact the developer using the [Developer Contact](#developer-contact) links below. @@ -980,7 +982,7 @@ You can support us via one of the following options: ### License -Copyright (c) 2019-2023, The Exor Community
+Copyright (c) 2019-2024, The Exor Community
Copyright (c) 2017, The Chaincoin Community
Copyright (c) 2015, Iquidus Technology
Copyright (c) 2015, Luke Williams
diff --git a/app.js b/app.js index 1637e0a7..3a290279 100644 --- a/app.js +++ b/app.js @@ -9,10 +9,11 @@ var express = require('express'), routes = require('./routes/index'), lib = require('./lib/explorer'), db = require('./lib/database'), - package_metadata = require('./package.json'), - locale = require('./lib/locale'); + package_metadata = require('./package.json'); var app = express(); var apiAccessList = []; +var viewPaths = [path.join(__dirname, 'views')] +var pluginRoutes = []; const { exec } = require('child_process'); // pass wallet rpc connection info to nodeapi @@ -63,8 +64,88 @@ if (settings.webserver.cors.enabled == true) { }); } +// loop through all plugins defined in the settings +settings.plugins.allowed_plugins.forEach(function (plugin) { + // check if this plugin is enabled + if (plugin.enabled) { + const pluginName = (plugin.plugin_name == null ? '' : plugin.plugin_name); + + // check if the plugin exists in the plugins directory + if (db.fs.existsSync(`./plugins/${pluginName}`)) { + // check if the plugin's local_plugin_settings file exists + if (db.fs.existsSync(`./plugins/${pluginName}/lib/local_plugin_settings.js`)) { + // load the local_plugin_settings.js file from the plugin + let localPluginSettings = require(`./plugins/${pluginName}/lib/local_plugin_settings`); + + // loop through all local plugin settings + Object.keys(localPluginSettings).forEach(function(key, index, map) { + // check if this is a known setting type that should be brought into the main settings + if (key.endsWith('_page') && typeof localPluginSettings[key] === 'object' && localPluginSettings[key]['enabled'] == true) { + // this is a page setting + // add the page_id to the page setting + localPluginSettings[key].page_id = key; + + // add the menu item title to the page setting + localPluginSettings[key].menu_title = localPluginSettings['localization'][`${key}_menu_title`]; + + // check if there is already a page for this plugin + if (plugin.pages == null) { + // initialize the pages array + plugin.pages = []; + } + + // add this page setting to the main plugin data + plugin['pages'].push(localPluginSettings[key]); + } else if (key == 'public_apis') { + // this is a collection of new apis + // check if there is an ext section + if (localPluginSettings[key]['ext'] != null) { + // loop through all ext apis for this plugin + Object.keys(localPluginSettings[key]['ext']).forEach(function(extKey, extIndex, extMap) { + // add the name of the api into the object + localPluginSettings[key]['ext'][extKey]['api_name'] = extKey; + + // loop through all parameters for this api and replace them in the description string if applicable + for (let p = 0; p < localPluginSettings[key]['ext'][extKey]['api_parameters'].length; p++) + localPluginSettings['localization'][`${extKey}_description`] = localPluginSettings['localization'][`${extKey}_description`].replace(new RegExp(`\\{${(p + 1)}}`, 'g'), localPluginSettings[key]['ext'][extKey]['api_parameters'][p]['parameter_name']); + + // add the localized api description into the object + localPluginSettings[key]['ext'][extKey]['api_desc'] = localPluginSettings['localization'][`${extKey}_description`]; + }); + } + + // copy the entire public_apis section from the plugin into the main settings + plugin.public_apis = localPluginSettings[key]; + } + }); + } + + // check if the plugin's routes/index.js file exists + if (db.fs.existsSync(`./plugins/${pluginName}/routes/index.js`)) { + // get the plugin routes and save them to an array + pluginRoutes.push(require(`./plugins/${pluginName}/routes/index`)); + + // check if the plugin has a views directory + if (db.fs.existsSync(`./plugins/${pluginName}/views`)) { + // get the list of files in the views directory + const files = db.fs.readdirSync(`./plugins/${pluginName}/views`); + + // filter the list of files to check if any have the .pug extension + const pugFiles = files.filter(file => path.extname(file) === '.pug'); + + // check if the plugin has 1 or more views + if (pugFiles.length > 0) { + // add this plugins view path to the list of view paths + viewPaths.push(path.resolve(`./plugins/${pluginName}/views`)); + } + } + } + } + } +}); + // view engine setup -app.set('views', path.join(__dirname, 'views')); +app.set('views', viewPaths); app.set('view engine', 'pug'); var default_favicon = ''; @@ -95,6 +176,11 @@ app.use(express.static(path.join(__dirname, 'public'))); app.use('/api', nodeapi.app); app.use('/', routes); +// loop through all plugin routes and add them to the app +pluginRoutes.forEach(function (r) { + app.use('/', r); +}); + // post method to claim an address using verifymessage functionality app.post('/claim', function(req, res) { // validate captcha if applicable @@ -227,6 +313,101 @@ function validate_captcha(captcha_enabled, data, cb) { } } +// post method to receive data from a plugin +app.post('/plugin-request', function(req, res) { + const pluginLockName = 'plugin'; + + // check if another plugin request is already running + if (lib.is_locked([pluginLockName], true) == true) + res.json({'status': 'failed', 'error': true, 'message': `Another plugin request is already running..`}); + else { + // create a new plugin lock before checking the rest of the locks to minimize problems with running scripts at the same time + lib.create_lock(pluginLockName); + + // check the backup, restore and delete locks since those functions would be problematic when updating data + if (lib.is_locked(['backup', 'restore', 'delete'], true) == true) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Another script has locked the database..`}); + } else { + // all lock tests passed. OK to run plugin request + + let dataObject = {}; + + try { + // attempt to parse the POST data field into a JSON object + dataObject = JSON.parse(req.body.data); + } catch { + // do nothing. errors will be handled below + } + + // check if the dataObject was populated + if (dataObject == null || JSON.stringify(dataObject) === '{}') { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': 'POST data is missing or not in the correct format'}); + } else { + // check if the plugin secret code is correct and if the coin name was specified + if (dataObject.plugin_data == null || settings.plugins.plugin_secret_code != dataObject.plugin_data.secret_code) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': 'Secret code is missing or incorrect'}); + } else if (dataObject.plugin_data.coin_name == null || dataObject.plugin_data.coin_name == '') { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': 'Coin name is missing'}); + } else { + const tableData = dataObject.table_data; + + // check if the table_data seems valid + if (tableData == null || !Array.isArray(tableData)) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `table_data from POST data is missing or empty`}); + } else { + const pluginName = (dataObject.plugin_data.plugin_name == null ? '' : dataObject.plugin_data.plugin_name); + const pluginObj = settings.plugins.allowed_plugins.find(item => item.plugin_name === pluginName && pluginName != ''); + + // check if the requested plugin was found in the settings + if (pluginObj == null) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Plugin '${pluginName}' is not defined in settings`}); + } else { + // check if the requested plugin is enabled + if (!pluginObj.enabled) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Plugin '${pluginName}' is not enabled`}); + } else { + // check if the plugin exists in the plugins directory + if (!db.fs.existsSync(`./plugins/${pluginName}`)) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Plugin '${pluginName}' is not installed in the plugins directory`}); + } else { + // check if the plugin's server_functions file exists + if (!db.fs.existsSync(`./plugins/${pluginName}/lib/server_functions.js`)) { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Plugin '${pluginName}' is missing the /lib/server_functions.js file`}); + } else { + // load the server_functions.js file from the plugin + const serverFunctions = require(`./plugins/${pluginName}/lib/server_functions`); + + // check if the process_plugin_request function exists + if (typeof serverFunctions.process_plugin_request !== 'function') { + lib.remove_lock(pluginLockName); + res.json({'status': 'failed', 'error': true, 'message': `Plugin '${pluginName}' is missing the process_plugin_request function`}); + } else { + // call the process_plugin_request function to process the new table data + serverFunctions.process_plugin_request(dataObject.plugin_data.coin_name, tableData, settings.sync.update_timeout, function(response) { + lib.remove_lock(pluginLockName); + res.json(response); + }); + } + } + } + } + } + } + } + } + } + } +}); + // extended apis app.use('/ext/getmoneysupply', function(req, res) { // check if the getmoneysupply api is enabled @@ -237,7 +418,7 @@ app.use('/ext/getmoneysupply', function(req, res) { res.end((stats && stats.supply ? stats.supply.toString() : '0')); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getaddress/:hash', function(req, res) { @@ -288,7 +469,7 @@ app.use('/ext/getaddress/:hash', function(req, res) { }); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/gettx/:txid', function(req, res) { @@ -343,7 +524,7 @@ app.use('/ext/gettx/:txid', function(req, res) { } }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getbalance/:hash', function(req, res) { @@ -357,7 +538,7 @@ app.use('/ext/getbalance/:hash', function(req, res) { res.send({ error: 'address not found.', hash: req.params.hash }); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getdistribution', function(req, res) { @@ -371,7 +552,7 @@ app.use('/ext/getdistribution', function(req, res) { }); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getcurrentprice', function(req, res) { @@ -384,7 +565,7 @@ app.use('/ext/getcurrentprice', function(req, res) { res.send(p_ext); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getbasicstats', function(req, res) { @@ -408,7 +589,7 @@ app.use('/ext/getbasicstats', function(req, res) { } }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getlasttxs/:min', function(req, res) { @@ -461,7 +642,7 @@ app.use('/ext/getlasttxs/:min', function(req, res) { } }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getaddresstxs/:address/:start/:length', function(req, res) { @@ -533,7 +714,7 @@ app.use('/ext/getaddresstxs/:address/:start/:length', function(req, res) { } }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); function get_connection_and_block_counts(get_data, cb) { @@ -581,7 +762,7 @@ app.use('/ext/getsummary', function(req, res) { difficulty = difficulty['proof-of-stake']; } - if (hashrate == 'There was an error. Check your console.') + if (hashrate == `${settings.localization.ex_error}: ${settings.localization.check_console}`) hashrate = 0; let mn_total = 0; @@ -618,7 +799,7 @@ app.use('/ext/getsummary', function(req, res) { }); } } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getnetworkpeers', function(req, res) { @@ -649,7 +830,7 @@ app.use('/ext/getnetworkpeers', function(req, res) { res.json(peers); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); // get the list of masternodes from local collection @@ -668,7 +849,7 @@ app.use('/ext/getmasternodelist', function(req, res) { res.send(masternodes); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); // returns a list of masternode reward txs for a single masternode address from a specific block height @@ -694,7 +875,7 @@ app.use('/ext/getmasternoderewards/:hash/:since', function(req, res) { res.send({error: "failed to retrieve masternode rewards", hash: req.params.hash, since: req.params.since}); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); // returns the total masternode rewards received for a single masternode address from a specific block height @@ -709,7 +890,7 @@ app.use('/ext/getmasternoderewardstotal/:hash/:since', function(req, res) { res.send({error: "failed to retrieve masternode rewards", hash: req.params.hash, since: req.params.since}); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); // get the list of orphans from local collection @@ -742,7 +923,7 @@ app.use('/ext/getorphanlist/:start/:length', function(req, res) { res.json({"data": data, "recordsTotal": count, "recordsFiltered": count}); }); } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); // get the last updated date for a particular section @@ -765,7 +946,7 @@ app.use('/ext/getlastupdated/:section', function(req, res) { res.send({error: 'Cannot find last updated date'}); } } else - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); }); app.use('/ext/getnetworkchartdata', function(req, res) { @@ -785,7 +966,7 @@ app.use('/system/restartexplorer', function(req, res, next) { res.end(); } else { // show the error page - var err = new Error('Not Found'); + var err = new Error(settings.localization.error_not_found); err.status = 404; next(err); } @@ -934,7 +1115,7 @@ settings.api_page.public_apis.rpc.getmasternodelist = { "enabled": false }; // locals app.set('explorer_version', package_metadata.version); -app.set('locale', locale); +app.set('localization', settings.localization); app.set('coin', settings.coin); app.set('network_history', settings.network_history); app.set('shared_pages', settings.shared_pages); @@ -956,6 +1137,7 @@ app.set('labels', settings.labels); app.set('default_coingecko_ids', settings.default_coingecko_ids); app.set('api_cmds', settings.api_cmds); app.set('blockchain_specific', settings.blockchain_specific); +app.set('plugins', settings.plugins); // determine panel offset based on which panels are enabled var paneltotal = 5; diff --git a/lib/database.js b/lib/database.js index 1fbb848a..d2703dc7 100644 --- a/lib/database.js +++ b/lib/database.js @@ -13,7 +13,6 @@ var mongoose = require('mongoose'), ClaimAddress = require('../models/claimaddress'), lib = require('./explorer'), settings = require('./settings'), - locale = require('./locale'), fs = require('fs'); function find_address(hash, caseSensitive, cb) { @@ -130,7 +129,7 @@ function get_market_data(market, coin_symbol, pair_symbol, cb) { if (fs.existsSync('./lib/markets/' + market + '.js')) { exMarket = require('./markets/' + market); - exMarket.get_data({coin: coin_symbol, exchange: pair_symbol, api_error_msg: locale.mkt_unexpected_api_data}, function(err, obj) { + exMarket.get_data({coin: coin_symbol, exchange: pair_symbol, api_error_msg: settings.localization.mkt_unexpected_api_data}, function(err, obj) { return cb(err, obj); }); } else @@ -248,7 +247,7 @@ function init_markets(cb) { // check if exchange trading pair exists in the market collection if (!exists) { // exchange doesn't exist in the market collection so add a default definition now - console.log('No %s[%s] entry found. Creating new entry now..', market, split_pair[0] + '/' + split_pair[1]); + console.log(`${settings.localization.creating_initial_entry.replace('{1}', `${market}[${split_pair[0]}/${split_pair[1]}]`)}.. ${settings.localization.please_wait}..`); module.exports.create_market(split_pair[0], split_pair[1], market, function() { pairCounter++; @@ -343,7 +342,7 @@ function init_heavy(cb) { if (settings.blockchain_specific.heavycoin.enabled == true) { module.exports.check_heavy(settings.coin.name, function(exists) { if (exists == false) { - console.log('No heavycoin entry found. Creating new entry now..'); + console.log(`${settings.localization.creating_initial_entry.replace('{1}', 'heavycoin')}.. ${settings.localization.please_wait}..`); module.exports.create_heavy(settings.coin.name, function() { return cb(); }); @@ -412,6 +411,68 @@ function init_claimaddress(coin, cb) { }); } +function init_plugins(coin, cb) { + // check if there are any defined plugins in the settings + if (settings.plugins.allowed_plugins != null && settings.plugins.allowed_plugins.length > 0) { + let checkedPlugins = 0; + + // loop through all plugins defined in the settings + settings.plugins.allowed_plugins.forEach(function (plugin) { + // check if this plugin is enabled + if (!plugin.enabled) { + checkedPlugins++; + + if (checkedPlugins == settings.plugins.allowed_plugins.length) + return cb(); + } else { + const pluginName = (plugin.plugin_name == null ? '' : plugin.plugin_name); + + // check if the plugin exists in the plugins directory + if (!fs.existsSync(`./plugins/${pluginName}`)) { + console.log(`WARNING: Plugin '${pluginName}' is not installed in the plugins directory`); + + checkedPlugins++; + + if (checkedPlugins == settings.plugins.allowed_plugins.length) + return cb(); + } else { + // check if the plugin's server_functions file exists + if (!fs.existsSync(`./plugins/${pluginName}/lib/server_functions.js`)) { + console.log(`WARNING: Plugin '${pluginName}' is missing the /lib/server_functions.js file`); + + checkedPlugins++; + + if (checkedPlugins == settings.plugins.allowed_plugins.length) + return cb(); + } else { + // load the server_functions.js file from the plugin + const serverFunctions = require(`../plugins/${pluginName}/lib/server_functions`); + + // check if the plugin_load function exists + if (typeof serverFunctions.plugin_load !== 'function') { + console.log(`WARNING: Plugin '${pluginName}' is missing the plugin_load function`); + + checkedPlugins++; + + if (checkedPlugins == settings.plugins.allowed_plugins.length) + return cb(); + } else { + // call the plugin_load function to initialize the plugin + serverFunctions.plugin_load(coin, function() { + checkedPlugins++; + + if (checkedPlugins == settings.plugins.allowed_plugins.length) + return cb(); + }); + } + } + } + } + }); + } else + return cb(); +} + // find masternode by txid and function find_masternode(txhash, addr, cb) { Masternode.findOne({ txhash: txhash, addr: addr }).then((masternode) => { @@ -660,7 +721,7 @@ module.exports = { }); newStats.save().then(() => { - console.log("Initial stats entry created for %s", coin); + console.log(`${settings.localization.entry_created_successfully.replace('{1}', 'stats').replace('{2}', coin)}`); return cb(); }).catch((err) => { console.log(err); @@ -1014,7 +1075,7 @@ module.exports = { }); newMarkets.save().then(() => { - console.log("Initial market entry created for %s[%s]", market, coin_symbol + '/' + pair_symbol); + console.log(`${settings.localization.entry_created_successfully.replace('{1}', 'market').replace('{2}', `${market}[${coin_symbol}/${pair_symbol}]`)}`); return cb(); }).catch((err) => { console.log(err); @@ -1054,7 +1115,7 @@ module.exports = { }); newRichlist.save().then(() => { - console.log("Initial richlist entry created for %s", coin); + console.log(`${settings.localization.entry_created_successfully.replace('{1}', 'richlist').replace('{2}', coin)}`); return cb(); }).catch((err) => { console.log(err); @@ -1096,7 +1157,7 @@ module.exports = { }); newHeavy.save().then(() => { - console.log("Initial heavycoin entry created for %s", coin); + console.log(`${settings.localization.entry_created_successfully.replace('{1}', 'heavycoin').replace('{2}', coin)}`); return cb(); }).catch((err) => { console.log(err); @@ -1879,7 +1940,7 @@ module.exports = { }, initialize_data_startup: function(cb) { - console.log('Initializing database.. Please wait...'); + console.log(`${settings.localization.initializing_database}.. ${settings.localization.please_wait}..`); // check if stats collection is initialized module.exports.check_stats(settings.coin.name, function(stats_exists) { @@ -1887,7 +1948,7 @@ module.exports = { // determine if stats collection already exists if (stats_exists == false) { - console.log('No stats entry found. Creating new entry now..'); + console.log(`${settings.localization.creating_initial_entry.replace('{1}', 'stats')}.. ${settings.localization.please_wait}..`); skip = false; } @@ -1909,7 +1970,7 @@ module.exports = { // determine if richlist collection already exists if (richlist_exists == false) { - console.log('No richlist entry found. Creating new entry now..'); + console.log(`${settings.localization.creating_initial_entry.replace('{1}', 'richlist')}.. ${settings.localization.please_wait}..`); skip = false; } @@ -1919,9 +1980,12 @@ module.exports = { init_heavy(function() { // check and initialize the claimaddress collection init_claimaddress(settings.coin.name, function() { - // finished initializing startup data - console.log('Database initialization complete'); - return cb(); + // initialize all enabled plugins + init_plugins(settings.coin.name, function() { + // finished initializing startup data + console.log('Database initialization complete'); + return cb(); + }); }); }); }); @@ -1951,7 +2015,7 @@ module.exports = { save_tx: function(txid, blockheight, block, cb) { lib.get_rawtransaction(txid, function(tx) { - if (tx && tx != 'There was an error. Check your console.') { + if (tx && tx != `${settings.localization.ex_error}: ${settings.localization.check_console}`) { lib.prepare_vin(tx, function(vin, tx_type_vin) { lib.prepare_vout(tx.vout, txid, vin, ((!settings.blockchain_specific.zksnarks.enabled || typeof tx.vjoinsplit === 'undefined' || tx.vjoinsplit == null) ? [] : tx.vjoinsplit), function(vout, nvin, tx_type_vout) { lib.syncLoop(nvin.length, function (loop) { diff --git a/lib/explorer.js b/lib/explorer.js index d3e9d383..df6838bb 100644 --- a/lib/explorer.js +++ b/lib/explorer.js @@ -1,7 +1,6 @@ var request = require('postman-request'), async = require('async'), settings = require('./settings'), - locale = require('./locale'), Address = require('../models/address'); var base_server = 'http://127.0.0.1:' + settings.webserver.port + "/"; @@ -12,7 +11,7 @@ const client = new onode.Client(settings.wallet); const rpc_queue = async.queue((task_params, cb) => { client.cmd([task_params], function(err, response) { if (err) - return cb('There was an error. Check your console.'); + return cb(`${settings.localization.ex_error}: ${settings.localization.check_console}`); else return cb(response); }); @@ -206,7 +205,7 @@ module.exports = { // get data from wallet via rpc cmd rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb('-'); var net_hash = null; @@ -234,7 +233,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') { + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) { // return a blank value return cb('-'); } else { @@ -273,7 +272,7 @@ module.exports = { // get data from wallet via rpc cmd rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb('-'); // check if the response has a value if (response) { @@ -290,7 +289,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') { + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) { // return a blank value return cb('-'); } else { @@ -316,7 +315,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -326,7 +325,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -345,7 +344,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -355,7 +354,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -374,7 +373,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -384,7 +383,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -405,7 +404,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(normalizeMasternodeCount(response)); @@ -415,7 +414,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(normalizeMasternodeCount(body)); @@ -438,7 +437,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -448,7 +447,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -467,7 +466,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -477,7 +476,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -496,7 +495,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -506,7 +505,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -525,7 +524,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -535,7 +534,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -554,7 +553,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -564,7 +563,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -583,7 +582,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -593,7 +592,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -612,7 +611,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -622,7 +621,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -641,7 +640,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -651,7 +650,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -670,7 +669,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -680,7 +679,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -699,7 +698,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -709,7 +708,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -728,7 +727,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -738,7 +737,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -760,7 +759,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -770,7 +769,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -789,7 +788,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -799,7 +798,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -900,7 +899,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -910,7 +909,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -928,7 +927,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (!response || !response.moneysupply || response == 'There was an error. Check your console.') + if (!response || !response.moneysupply || response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response.moneysupply); @@ -938,7 +937,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (!body || !body.moneysupply ||body == 'There was an error. Check your console.') + if (!body || !body.moneysupply || body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body.moneysupply); @@ -961,7 +960,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (!response || !response.total_amount || response == 'There was an error. Check your console.') + if (!response || !response.total_amount || response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response.total_amount); @@ -971,7 +970,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (!body || !body.total_amount ||body == 'There was an error. Check your console.') + if (!body || !body.total_amount || body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body.total_amount); @@ -989,7 +988,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (!response || !response.moneysupply || response == 'There was an error. Check your console.') + if (!response || !response.moneysupply || response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response.moneysupply); @@ -999,7 +998,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (!body || !body.moneysupply ||body == 'There was an error. Check your console.') + if (!body || !body.moneysupply || body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body.moneysupply); @@ -1024,7 +1023,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -1034,7 +1033,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); @@ -1053,7 +1052,7 @@ module.exports = { if (settings.api_cmds.use_rpc) { rpcCommand([{method:cmd.method, parameters: cmd.parameters}], function(response) { // check if an error msg was received from the rpc server - if (response == 'There was an error. Check your console.') + if (response == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(response); @@ -1063,7 +1062,7 @@ module.exports = { request({uri: uri, json: true}, function (error, response, body) { // check if an error msg was received from the web api server - if (body == 'There was an error. Check your console.') + if (body == `${settings.localization.ex_error}: ${settings.localization.check_console}`) return cb(null); else return cb(body); diff --git a/lib/locale.js b/lib/locale.js index 5df0937c..beaeb62d 100644 --- a/lib/locale.js +++ b/lib/locale.js @@ -3,218 +3,270 @@ * this information to the other modules */ -var fs = require("fs"); -var jsonminify = require("jsonminify"); -var settings = require("./settings"); - -// global -exports.difficulty = "Difficulty", -exports.network = "Network", -exports.masternodecount = "Masternodes", -exports.height = "Height", -exports.timestamp = "Timestamp", -exports.size = "Size", -exports.transactions = "Transactions", -exports.total_sent = "Total Sent", -exports.total_received = "Total Received", -exports.confirmations = "Confirmations", -exports.total = "Total", -exports.total_top_100 = "Top 1-100 Total", -exports.bits = "Bits", -exports.nonce = "Nonce", -exports.new_coins = "New Coins", -exports.proof_of_stake = "PoS", -exports.hidden_address = "Hidden Address", -exports.hidden_sender = "Hidden Sender", -exports.hidden_recipient = "Hidden Recipient", -exports.unknown_address = "Unknown Address", -exports.unknown_sender = "Unknown Sender", -exports.unknown_recipient = "Unknown Recipient", -exports.last_updated = "Last Updated", -exports.initial_index_alert = "Blockchain data is currently being synchronized. You may browse the site during this time, but keep in mind that data may not yet be fully accurate and some functionality may not work until synchronization is complete.", - -// menu items -exports.menu_explorer = "Explorer", -exports.menu_api = "API", -exports.menu_markets = "Markets", -exports.menu_richlist = "Rich List", -exports.menu_reward = "Reward", -exports.menu_movement = "Movement", -exports.menu_node = "Nodes", -exports.menu_network = "Network", -exports.menu_claim_address = "Claim Address", -exports.menu_orphans = "Orphaned Blocks", - -// explorer view -exports.ex_title = "{1} Block Explorer", -exports.ex_description = "A listing of all verified {1} transactions", -exports.ex_search_title = "Search", -exports.ex_search_button = "Search", -exports.ex_search_message = "Search by block height, block hash, tx hash or address", -exports.ex_error = "Error", -exports.ex_warning = "Warning", -exports.ex_search_error = "Search found no results.", -exports.ex_latest_transactions = "Latest Transactions", -exports.ex_summary = "Block Summary", -exports.ex_supply = "Coin Supply", -exports.ex_block = "Block", - -// transaction view -exports.tx_title = "{1} Transaction Details", -exports.tx_description = "Viewing tx data from {1} block # {2}", -exports.tx_block_hash = "Block Hash", -exports.tx_recipients = "Recipients", -exports.tx_contributors = "Contributor(s)", -exports.tx_hash = "Tx Hash", -exports.tx_address = "Address", -exports.tx_nonstandard = "NONSTANDARD TX", -exports.view_raw_tx_data = "View Raw Transaction Data", -exports.view_block = "View Block", - -// block view -exports.block_title = "{1} Block Details", -exports.block_description = "Viewing block data from {1} block # {2}", -exports.block_previous = "Previous Block", -exports.block_next = "Next Block", -exports.block_genesis = "GENESIS", -exports.view_raw_block_data = "View Raw Block Data", -exports.view_tx = "View Transaction", - -// error view -exports.error_title = "{1} Block Explorer Error", -exports.error_description = "The page you are looking for cannot be found", -exports.error_description_alt = "An error occurred which prevented the page from loading correctly", - -// address view -exports.a_title = "{1} Wallet Address Details", -exports.a_description = "Viewing balance and transaction data from {1} address {2}", -exports.a_menu_showing = "Showing", -exports.a_menu_txs = "transactions", -exports.a_menu_all = "All", -exports.a_qr = "QR Code", - -// masternode view -exports.mn_title = "{1} Masternodes", -exports.mn_description = "A listing of all masternodes known to be active on the {1} network", -exports.mn_masternode_list = "Masternode List", - -// movement view -exports.move_title = "{1} Coin Movements", -exports.move_description = "A listing of larger movements where {1} or more {2} coins were sent in a single transaction", - -// richlist view -exports.rl_title = "Top {1} Coin Holders", -exports.rl_description = "A listing of the richest {1} wallet addresses and breakdown of the current coin distribution", -exports.rl_received_coins = "Top 100 - Received Coins", -exports.rl_current_balance = "Top 100 - Current Balance", -exports.rl_received = "Received", -exports.rl_balance = "Balance", -exports.rl_wealth = "Wealth Distribution", -exports.rl_top25 = "Top 1-25", -exports.rl_top50 = "Top 26-50", -exports.rl_top75 = "Top 51-75", -exports.rl_top100 = "Top 76-100", -exports.rl_hundredplus = "101+", - -// network view -exports.net_title = "{1} Network Peers", -exports.net_description = "A listing of {1} network peers that have connected to the explorer node in the last 24 hours", -exports.net_addnodes = "Add Nodes", -exports.net_connections = "Connections", -exports.net_address = "Address", -exports.net_protocol = "Protocol", -exports.net_subversion = "Sub-version", -exports.net_country = "Country", - -// api view -exports.api_title = "{1} Public API", -exports.api_description = "A listing of public API endpoints for retrieving {1} coin data from the network without the need for a local wallet", -exports.api_documentation = "API Documentation", -exports.api_calls = "API Calls", -exports.api_getnetworkhashps = "Returns the current network hashrate. (hash/s)", -exports.api_getdifficulty = "Returns the current difficulty.", -exports.api_getconnectioncount = "Returns the number of connections the block explorer has to other nodes.", -exports.api_getmasternodelist = "Returns the complete list of masternodes on the network.", -exports.api_getmasternodecount = "Returns the total number of masternodes on the network.", -exports.api_getvotelist = "Returns the current vote list.", -exports.api_getblockcount = "Returns the number of blocks currently in the block chain.", -exports.api_getblockhash = "Returns the hash of the block at [index]; index 0 is the genesis block.", -exports.api_getblock = "Returns information about the block with the given hash.", -exports.api_getrawtransaction = "Returns raw transaction representation for given transaction id. decrypt can be set to 0(false) or 1(true).", -exports.api_getmaxmoney = 'Returns the maximum possible money supply.', -exports.api_getmaxvote = 'Returns the maximum allowed vote for the current phase of voting.', -exports.api_getvote = 'Returns the current block reward vote setting.', -exports.api_getphase = 'Returns the current voting phase (\'Mint\', \'Limit\' or \'Sustain\').', -exports.api_getreward = 'Returns the current block reward, which has been decided democratically in the previous round of block reward voting.', -exports.api_getsupply = 'Returns the current money supply.', -exports.api_getnextrewardestimate = 'Returns an estimate for the next block reward based on the current state of decentralized voting.', -exports.api_getnextrewardwhenstr = 'Returns a string describing how long until the votes are tallied and the next block reward is computed.', - -// markets view -exports.mkt_title = "{1} Market Details", -exports.mkt_description = "Viewing {1} market data for the {2} exchange", -exports.mkt_hours = "24 hours", -exports.mkt_view_chart = "View 24 hour summary", -exports.mkt_view_summary = "View 24 hour chart", -exports.mkt_no_chart = "Chart data is not available via markets API", -exports.mkt_high = "High", -exports.mkt_low = "Low", -exports.mkt_volume = "Volume", -exports.mkt_top_bid = "Top Bid", -exports.mkt_top_ask = "Top Ask", -exports.mkt_last = "Last Price", -exports.mkt_yesterday = "Yesterday", -exports.mkt_change = "Change", -exports.mkt_sell_orders = "Sell Orders", -exports.mkt_buy_orders = "Buy Orders", -exports.mkt_price = "Price", -exports.mkt_amount = "Amount", -exports.mkt_total = "Total", -exports.mkt_trade_history = "Trade History", -exports.mkt_type = "Type", -exports.mkt_time_stamp = "Time Stamp", -exports.mkt_select = "Market Select", -exports.mkt_unexpected_api_data = "Received unexpected API data response", - -// claim address view -exports.claim_title = "{1} Wallet Address Claim", -exports.claim_description = "Verify ownership of your {1} wallet address and set a custom display name in the explorer", - -// orphans view -exports.orphan_title = "{1} Orphaned Blocks", -exports.orphan_description = "A listing of valid blocks that have been orphaned and do not belong to the main blockchain", -exports.orphan_block_list = "Orphaned Block List", -exports.orphan_block_hash = "Orphaned Block Hash", -exports.orphan_actual_block = "Actual Block", -exports.orphan_prev_block = "Previous Block", -exports.orphan_next_block = "Next Block", -exports.view_orphan = "View Orphaned Block", - -// heavycoin rewards view -exports.heavy_title = "{1} Reward/Voting Details", -exports.heavy_description = "Viewing {1} voting data and coin reward change details", -exports.heavy_reward_voting_info = "Reward/voting information", -exports.heavy_vote = "Vote", -exports.heavy_cap = "Coin Cap", -exports.heavy_phase = "Phase", -exports.heavy_maxvote = "Max Vote", -exports.heavy_reward = "Reward", -exports.heavy_current = "Current Reward", -exports.heavy_estnext = "Est. Next", -exports.heavy_changein = "Reward change in approximately", -exports.heavy_key = "Key", -exports.heavy_lastxvotes = "Last 20 votes", +exports.localization = { + // global + "difficulty": "Difficulty", + "network": "Network", + "masternodecount": "Masternodes", + "height": "Height", + "timestamp": "Timestamp", + "size": "Size", + "transactions": "Transactions", + "total_sent": "Total Sent", + "total_received": "Total Received", + "confirmations": "Confirmations", + "total": "Total", + "total_top_100": "Top 1-100 Total", + "bits": "Bits", + "nonce": "Nonce", + "new_coins": "New Coins", + "proof_of_stake": "PoS", + "hidden_address": "Hidden Address", + "hidden_sender": "Hidden Sender", + "hidden_recipient": "Hidden Recipient", + "unknown_address": "Unknown Address", + "unknown_sender": "Unknown Sender", + "unknown_recipient": "Unknown Recipient", + "last_updated": "Last Updated", + "initial_index_alert": "Blockchain data is currently being synchronized. You may browse the site during this time, but keep in mind that data may not yet be fully accurate and some functionality may not work until synchronization is complete.", + "please_wait": "Please wait", + "creating_initial_entry": "Creating initial {1} entry", + "entry_created_successfully": "Initial {1} entry for {2} created successfully", + "method_disabled": "This method is disabled", + "compiling_css": "Compiling CSS", + "installing_module": "Installing {1} module", + "restoring_backup": "Restoring backup", + "extracting_backup_files": "Extracting backup files", + "explorer_shutting_down": "Explorer shutting down", + "initializing_database": "Initializing database", + "downloading_newest_explorer_code": "Downloading newest explorer code", + "check_outdated_packages": "Checking for outdated packages", + "updating_explorer_packages": "Updating out-of-date explorer packages", + "checking_webserver_running": "Checking if webserver is running", + "reloading_explorer": "Reloading the explorer", + "email_sent_successfully": "Email sent successfully", + "check_console": "Check your console", + "process_aborted": "Process aborted", + "nothing_was_deleted": "Nothing was deleted", + "nothing_was_restored": "Nothing was restored", + + // prompts + "are_you_sure": "Are you sure you want to do this? [y/n]", + "short_yes": "y", + "long_yes": "yes", + + // menu items + "menu_explorer": "Explorer", + "menu_api": "API", + "menu_markets": "Markets", + "menu_richlist": "Rich List", + "menu_reward": "Reward", + "menu_movement": "Movement", + "menu_node": "Nodes", + "menu_network": "Network", + "menu_claim_address": "Claim Address", + "menu_orphans": "Orphaned Blocks", + + // explorer view + "ex_title": "{1} Block Explorer", + "ex_description": "A listing of all verified {1} transactions", + "ex_search_title": "Search", + "ex_search_button": "Search", + "ex_search_message": "Search by block height, block hash, tx hash or address", + "ex_error": "Error", + "ex_warning": "Warning", + "ex_search_error": "Search found no results.", + "ex_latest_transactions": "Latest Transactions", + "ex_summary": "Block Summary", + "ex_supply": "Coin Supply", + "ex_block": "Block", + + // transaction view + "tx_title": "{1} Transaction Details", + "tx_description": "Viewing tx data from {1} block # {2}", + "tx_block_hash": "Block Hash", + "tx_recipients": "Recipients", + "tx_contributors": "Contributor(s)", + "tx_hash": "Tx Hash", + "tx_address": "Address", + "tx_nonstandard": "NONSTANDARD TX", + "view_raw_tx_data": "View Raw Transaction Data", + "view_block": "View Block", + + // block view + "block_title": "{1} Block Details", + "block_description": "Viewing block data from {1} block # {2}", + "block_previous": "Previous Block", + "block_next": "Next Block", + "block_genesis": "GENESIS", + "view_raw_block_data": "View Raw Block Data", + "view_tx": "View Transaction", + + // error view + "error_title": "{1} Block Explorer Error", + "error_description": "The page you are looking for cannot be found", + "error_description_alt": "An error occurred which prevented the page from loading correctly", + "error_not_found": "Not Found", + + // address view + "a_title": "{1} Wallet Address Details", + "a_description": "Viewing balance and transaction data from {1} address {2}", + "a_menu_showing": "Showing", + "a_menu_txs": "transactions", + "a_menu_all": "All", + "a_qr": "QR Code", + + // masternode view + "mn_title": "{1} Masternodes", + "mn_description": "A listing of all masternodes known to be active on the {1} network", + "mn_masternode_list": "Masternode List", + + // movement view + "move_title": "{1} Coin Movements", + "move_description": "A listing of larger movements where {1} or more {2} coins were sent in a single transaction", + + // richlist view + "rl_title": "Top {1} Coin Holders", + "rl_description": "A listing of the richest {1} wallet addresses and breakdown of the current coin distribution", + "rl_received_coins": "Top 100 - Received Coins", + "rl_current_balance": "Top 100 - Current Balance", + "rl_received": "Received", + "rl_balance": "Balance", + "rl_wealth": "Wealth Distribution", + "rl_top25": "Top 1-25", + "rl_top50": "Top 26-50", + "rl_top75": "Top 51-75", + "rl_top100": "Top 76-100", + "rl_hundredplus": "101+", + + // network view + "net_title": "{1} Network Peers", + "net_description": "A listing of {1} network peers that have connected to the explorer node in the last 24 hours", + "net_addnodes": "Add Nodes", + "net_connections": "Connections", + "net_address": "Address", + "net_protocol": "Protocol", + "net_subversion": "Sub-version", + "net_country": "Country", + + // api view + "api_title": "{1} Public API", + "api_description": "A listing of public API endpoints for retrieving {1} coin data from the network without the need for a local wallet", + "api_documentation": "API Documentation", + "api_calls": "API Calls", + "api_getnetworkhashps": "Returns the current network hashrate. (hash/s)", + "api_getdifficulty": "Returns the current difficulty.", + "api_getconnectioncount": "Returns the number of connections the block explorer has to other nodes.", + "api_getmasternodelist": "Returns the complete list of masternodes on the network.", + "api_getmasternodecount": "Returns the total number of masternodes on the network.", + "api_getvotelist": "Returns the current vote list.", + "api_getblockcount": "Returns the number of blocks currently in the block chain.", + "api_getblockhash": "Returns the hash of the block at [index]; index 0 is the genesis block.", + "api_getblock": "Returns information about the block with the given hash.", + "api_getrawtransaction": "Returns raw transaction representation for given transaction id. decrypt can be set to 0(false) or 1(true).", + "api_getmaxmoney": 'Returns the maximum possible money supply.', + "api_getmaxvote": 'Returns the maximum allowed vote for the current phase of voting.', + "api_getvote": 'Returns the current block reward vote setting.', + "api_getphase": 'Returns the current voting phase (\'Mint\', \'Limit\' or \'Sustain\').', + "api_getreward": 'Returns the current block reward, which has been decided democratically in the previous round of block reward voting.', + "api_getsupply": 'Returns the current money supply.', + "api_getnextrewardestimate": 'Returns an estimate for the next block reward based on the current state of decentralized voting.', + "api_getnextrewardwhenstr": 'Returns a string describing how long until the votes are tallied and the next block reward is computed.', + + // markets view + "mkt_title": "{1} Market Details", + "mkt_description": "Viewing {1} market data for the {2} exchange", + "mkt_hours": "24 hours", + "mkt_view_chart": "View 24 hour summary", + "mkt_view_summary": "View 24 hour chart", + "mkt_no_chart": "Chart data is not available via markets API", + "mkt_high": "High", + "mkt_low": "Low", + "mkt_volume": "Volume", + "mkt_top_bid": "Top Bid", + "mkt_top_ask": "Top Ask", + "mkt_last": "Last Price", + "mkt_yesterday": "Yesterday", + "mkt_change": "Change", + "mkt_sell_orders": "Sell Orders", + "mkt_buy_orders": "Buy Orders", + "mkt_price": "Price", + "mkt_amount": "Amount", + "mkt_total": "Total", + "mkt_trade_history": "Trade History", + "mkt_type": "Type", + "mkt_time_stamp": "Time Stamp", + "mkt_select": "Market Select", + "mkt_unexpected_api_data": "Received unexpected API data response", + + // claim address view + "claim_title": "{1} Wallet Address Claim", + "claim_description": "Verify ownership of your {1} wallet address and set a custom display name in the explorer", + + // orphans view + "orphan_title": "{1} Orphaned Blocks", + "orphan_description": "A listing of valid blocks that have been orphaned and do not belong to the main blockchain", + "orphan_block_list": "Orphaned Block List", + "orphan_block_hash": "Orphaned Block Hash", + "orphan_actual_block": "Actual Block", + "orphan_prev_block": "Previous Block", + "orphan_next_block": "Next Block", + "view_orphan": "View Orphaned Block", + + // heavycoin rewards view + "heavy_title": "{1} Reward/Voting Details", + "heavy_description": "Viewing {1} voting data and coin reward change details", + "heavy_reward_voting_info": "Reward/voting information", + "heavy_vote": "Vote", + "heavy_cap": "Coin Cap", + "heavy_phase": "Phase", + "heavy_maxvote": "Max Vote", + "heavy_reward": "Reward", + "heavy_current": "Current Reward", + "heavy_estnext": "Est. Next", + "heavy_changein": "Reward change in approximately", + "heavy_key": "Key", + "heavy_lastxvotes": "Last 20 votes", + + // sync + "script_launched": "Script launched with pid", + "stopping_sync_process": "Stopping sync process", + "finding_earliest_orphan": "Finding the earliest orphaned blockindex", + "calculating_market_price": "Calculating market price", + "syncing_blocks": "Syncing blocks", + "syncing_peers": "Syncing peers", + "syncing_masternodes": "Syncing masternodes", + "syncing_markets": "Syncing markets", + "checking_blocks": "Checking blocks", + "calculating_tx_count": "Calculating tx count", + "finding_last_blockindex": "Finding last blockindex", + "path_cannot_be_found": "'{1}' cannot be found", + + // settings + "deprecated_setting": "Deprecated setting '{1}' has been mapped to the new location '{2}'. Be sure to make this change in settings.json as the old setting will be removed in a future release", + "unknown_setting": "Unknown setting '{1}' has been ignored", + "missing_setting": "Setting '{1}' is missing. Loading default value", + "continuing_using_defaults": "Continuing using defaults", + "missing_settings_file": "The {1} file is missing", + "error_processing_settings": "There was an error processing the {1} file", + + // locale + "locale_lowercase_req": "Locale strings must start with a lowercase character", + "locale_unknown_string": "Unknown Locale String", + "locale_not_exists": "This setting doesn't exist or was removed" +}; exports.reloadLocale = function reloadLocale(locale) { - // discover where the locale file lives - var localeFilename = "./" + locale; - var localeStr; + const fs = require('fs'); + const jsonminify = require('jsonminify'); + const localeFilename = './' + locale; + let localeStr; try { // read the settings sync localeStr = fs.readFileSync(localeFilename).toString(); } catch(e) { - console.warn('Locale file not found. Continuing using defaults!'); + console.warn(`${exports.localization.missing_settings_file.replace('{1}', locale.split('/')[1])}. ${exports.localization.continuing_using_defaults}`); } var lsettings; @@ -226,7 +278,7 @@ exports.reloadLocale = function reloadLocale(locale) { lsettings = JSON.parse(localeStr); } } catch(e) { - console.error('There was an error processing your locale file: '+e.message); + console.error(`${exports.localization.error_processing_settings.replace('{1}', locale.split('/')[1])}: ${e.message}`); process.exit(1); } @@ -234,17 +286,16 @@ exports.reloadLocale = function reloadLocale(locale) { for (var i in lsettings) { // test if the setting start with a low character if (i.charAt(0).search("[a-z]") !== 0) - console.warn("Settings should start with a low character: '" + i + "'"); + console.warn(`${lsettings.locale_lowercase_req}: '${i}'`); - if (exports[i] !== undefined) { + if (exports.localization[i] !== undefined) { // we know this setting, so we overwrite it - exports[i] = lsettings[i]; + exports.localization[i] = lsettings[i]; } else { - // this setting is unkown, output a warning and throw it away - console.warn("Unknown Setting: '" + i + "'. This setting doesn't exist or it was removed"); + // this setting is unknown. output a warning and discard it + console.warn(`${lsettings.locale_unknown_string}: '${i}'. ${lsettings.locale_not_exists}`); } } -}; -// initially load settings -exports.reloadLocale(settings.locale); \ No newline at end of file + return exports.localization; +}; \ No newline at end of file diff --git a/lib/nodeapi.js b/lib/nodeapi.js index ebb56e0c..0e31ce4e 100644 --- a/lib/nodeapi.js +++ b/lib/nodeapi.js @@ -72,7 +72,7 @@ module.exports = function() { client.cmd(command, function(err, response) { if (err) { console.log(err); - res.send("There was an error. Check your console."); + res.send(`${settings.localization.ex_error}: ${settings.localization.check_console}`); } else { if (typeof response === 'object') res.json(response); @@ -105,7 +105,7 @@ module.exports = function() { // only show disabled msg for outside calls. internal calls should always go through if ((!settings.api_page.enabled || method_enabled == null || !method_enabled) && req.headers.host.indexOf('127.0.0.1') == -1) - res.end('This method is disabled'); + res.end(settings.localization.method_disabled); else if (method == 'getnetworkhashps' && !settings.shared_pages.show_hashrate) { // getnetworkhashps requires show_hashrate to be enabled or else hashrate cannot be returned res.end('-'); diff --git a/lib/settings.js b/lib/settings.js index 17382b41..6b6b71b2 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -2,9 +2,6 @@ * The Settings Module reads the settings out of settings.json and provides this information to the other modules */ -var fs = require("fs"); -var jsonminify = require("jsonminify"); - // locale: Change language definitions. Only English is supported for now exports.locale = "locale/en.json"; @@ -457,11 +454,11 @@ exports.index_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.ex_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.ex_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.ex_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.ex_description" (true/false) "show_description": true }, // transaction_table: a collection of settings that pertain to the transaction table on the index page @@ -490,9 +487,9 @@ exports.block_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.block_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.block_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.block_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.block_description" (true/false) "show_description": true }, // genesis_block: Your coins genesis block hash is used to determine the beginning of the blockchain @@ -524,9 +521,9 @@ exports.transaction_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.tx_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.tx_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.tx_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.tx_description" (true/false) "show_description": true }, // genesis_tx: Your coins genesis transaction hash is used to determine the beginning of the blockchain @@ -550,9 +547,9 @@ exports.address_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.a_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.a_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.a_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.a_description" (true/false) "show_description": true }, // show_sent_received: Determine whether to show Total Sent and Total Received columns at the top of the address page @@ -588,9 +585,9 @@ exports.error_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.error_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.error_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.error_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.error_description" (true/false) "show_description": true } }; @@ -612,11 +609,11 @@ exports.masternodes_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.mn_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.mn_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.mn_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.mn_description" (true/false) "show_description": true }, // masternode_table: a collection of settings that pertain to the masternode table on the masternodes page @@ -644,11 +641,11 @@ exports.movement_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.move_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.move_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.move_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.move_description" (true/false) "show_description": true }, // movement_table: a collection of settings that pertain to the movement table on the movement page @@ -686,11 +683,11 @@ exports.network_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.net_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.net_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.net_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.net_description" (true/false) "show_description": true }, // connections_table: a collection of settings that pertain to the connections table on the network page @@ -758,11 +755,11 @@ exports.richlist_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.rl_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.rl_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.rl_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.rl_description" (true/false) "show_description": true }, // show_current_balance: Determine whether to show the top 100 list of wallet addresses that currently have the most coins in a single wallet (true/false) @@ -813,13 +810,13 @@ exports.markets_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.mkt_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.mkt_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, // show_exchange_url: Determine whether to show an external link to the exchange trading page for the selected pair (true/false) "show_exchange_url": true, - // show_description: Determine whether to show the page description as defined in "locale.mkt_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.mkt_description" (true/false) "show_description": true }, // show_market_dropdown_menu: Determine whether the markets menu in the page header will function as a dropdown or a single-click menu item that opens the default market (true/false) @@ -960,9 +957,9 @@ exports.api_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.api_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.api_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.api_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.api_description" (true/false) "show_description": true }, // show_logo: Determine whether to show the `shared_pages.logo` image at the top of the API Documentation panel or not @@ -1201,9 +1198,9 @@ exports.claim_address_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.claim_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.claim_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.claim_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.claim_description" (true/false) "show_description": true }, // show_header_menu: Show/hide the "Claim Address" header menu item (true/false) @@ -1233,11 +1230,11 @@ exports.orphans_page = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.orphan_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.orphan_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.orphan_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.orphan_description" (true/false) "show_description": true }, // orphans_table: a collection of settings that pertain to the orphans table on the orphans page @@ -1426,11 +1423,11 @@ exports.blockchain_specific = { "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.reward_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.reward_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.reward_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.reward_description" (true/false) "show_description": true } }, @@ -1534,12 +1531,27 @@ exports.blockchain_specific = { } }; +// plugins: A collection of settings that pertain to extended functionality from external plugins that support explorer integration +exports.plugins = { + // plugin_secret_code: A secret code that will be received from all plugins to validate the plugin data request before modifying local database data + // NOTE: This is used as an internal password for your own plugins that can be run on different servers to validate that plugin data being received by the explorer is coming from you and not from a malicious user + // This code should be a random set of numbers, letters and special characters that cannot be easily guessed that must also match the plugin_secret_code in all plugin external.settings.json files + // WARNING: Be sure to change the default secret code as it is only a sample and will be the first code that malicious users try to use to manipulate your explorer's data + "plugin_secret_code": "SJs2=&r^ScLGLgTaNm7#74=s?48zf*4+vm5S", + // allowed_plugins: A collection of settings that pertain to the list of plugins allowed to be used with this explorer instance + // You can add as many plugins as necessary in the following format: [ { "plugin_name": "new_plugin_1", "enabled": "true" }, { "plugin_name": "new_plugin_2", "enabled": "false" } ] + // NOTE: Plugins enabled here must also have the actual plugin downloaded into the explorer's /plugins directory with the same name as the plugin_name specified here or they will be ignored + "allowed_plugins": [] +}; + exports.loadSettings = function loadSettings() { - var settings_filename = "./settings.json"; - var settings; - var json_settings; - // define an exception list of setting json paths (period separated) that do not have defaults and should not throw 'unknown setting' errors - var exceptions = ['labels']; + const fs = require('fs'); + const path = require('path'); + const jsonminify = require('jsonminify'); + const filename = `${path.parse(path.basename(__filename)).name}.json`; + const settings_filename = `./${filename}`; + let settings; + let json_settings; // check if the settings.json file exists if (fs.existsSync(settings_filename)) { @@ -1547,10 +1559,10 @@ exports.loadSettings = function loadSettings() { // read settings.json into a string variable settings = fs.readFileSync(settings_filename).toString(); } catch(e) { - console.warn('The settings.json file is missing. Continuing using defaults.'); + console.warn(`${exports.localization.missing_settings_file.replace('{1}', settings_filename.split('/')[1])}. ${exports.localization.continuing_using_defaults}`); } } else - console.warn('The settings.json file is missing. Continuing using defaults.'); + console.warn(`${exports.localization.missing_settings_file.replace('{1}', settings_filename.split('/')[1])}. ${exports.localization.continuing_using_defaults}`); try { // check if the settings string was populated @@ -1561,7 +1573,7 @@ exports.loadSettings = function loadSettings() { json_settings = JSON.parse(settings); } } catch(e) { - console.error('There was an error processing your settings.json file: ' + e.message); + console.error(`${exports.localization.error_processing_settings.replace('{1}', settings_filename.split('/')[1])}: ${e.message}`); process.exit(1); } @@ -1948,6 +1960,9 @@ exports.loadSettings = function loadSettings() { json_settings = fix_deprecated_setting(json_settings, 'shared_pages.page_header.network_charts.difficulty_chart.line_color', 'shared_pages.page_header.network_charts.difficulty_chart.pow_line_color'); json_settings = fix_deprecated_setting(json_settings, 'shared_pages.page_header.network_charts.difficulty_chart.fill_color', 'shared_pages.page_header.network_charts.difficulty_chart.pow_fill_color'); + // define an exception list of setting json paths (period separated) that do not have defaults and should not throw 'unknown setting' errors + let exceptions = ['labels']; + // loop through all settings from the settings.json file for (var current_setting in json_settings) { // merge settings from settings.json with the defaults from settings.js @@ -1955,7 +1970,7 @@ exports.loadSettings = function loadSettings() { } // re-initialize the exceptions list - exceptions = ['loadSettings']; + exceptions = ['loadSettings', 'reloadLocale', 'localization']; // loop through the loaded/default settings (settings.js) to look for missing settings for (var current_setting in exports) { @@ -1982,7 +1997,7 @@ fix_deprecated_setting = function(json_settings, old_path, new_path) { // set the new setting to the value of the old setting eval('json_settings' + fix_object_path(new_path) + ' = ' + JSON.stringify(setting_value)); // show warning msg - console.warn("Deprecated setting '" + old_path + "' has been mapped to the new location '" + new_path + "'. Be sure to make this change in settings.json as the old setting will be removed in a future release."); + console.warn(exports.localization.deprecated_setting.replace('{1}', old_path).replace('{2}', new_path)); } } @@ -2021,7 +2036,7 @@ merge_settings = function(json_settings, exceptions, current_setting, path) { if (Object.byString(exports, path) == null) { // this setting object does not exist in settings.js // show warning msg - console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed."); + console.warn(exports.localization.unknown_setting.replace('{1}', path)); } else { // the object exists in the loaded settings // check if the object is an array or is one of the exceptions @@ -2044,13 +2059,13 @@ merge_settings = function(json_settings, exceptions, current_setting, path) { if (Object.byString(exports, path) == null) { // this setting property does not exist in settings.js // show warning msg - console.warn("Unknown setting '" + path + "' has been ignored. This setting doesn't exist or was removed."); + console.warn(exports.localization.unknown_setting.replace('{1}', path)); } else { // the property exists in the loaded settings // get the settings.json value var setting_value = Object.byString(json_settings, path); // overwrite the property value with the value from settings.json - eval('exports' + fix_object_path(path) + ' = ' + (typeof setting_value === "string" ? '"' : '') + setting_value + (typeof setting_value === "string" ? '"' : '')); + eval('exports' + fix_object_path(path) + ' = ' + JSON.stringify(setting_value)); } } } @@ -2067,7 +2082,7 @@ check_missing_settings = function(json_settings, exceptions, current_setting, pa if (exceptions.indexOf(path) == -1) { // this is not one of the exceptions // show warning msg - console.warn("setting '" + path + "' is missing. Loading default value."); + console.warn(exports.localization.missing_setting.replace('{1}', path)); } } else { // the object exists in the json settings @@ -2086,7 +2101,7 @@ check_missing_settings = function(json_settings, exceptions, current_setting, pa if (exceptions.indexOf(path) == -1) { // this is not one of the exceptions // show warning msg - console.warn("setting '" + path + "' is missing. Loading default value."); + console.warn(exports.localization.missing_setting.replace('{1}', path)); } } } @@ -2112,5 +2127,14 @@ Object.byString = function(o, s) { return o; } +// load the locale file +const locale = require('./locale'); + +// add the reloadLocale function to the settings exports +exports.reloadLocale = locale.reloadLocale; + +// populate locale strings +exports.localization = exports.reloadLocale(exports.locale); + // populate settings exports.loadSettings(); \ No newline at end of file diff --git a/locale/en.json b/locale/en.json index 5d1ee86c..d9046473 100644 --- a/locale/en.json +++ b/locale/en.json @@ -25,6 +25,31 @@ "unknown_recipient": "Unknown Recipient", "last_updated": "Last Updated", "initial_index_alert": "Blockchain data is currently being synchronized. You may browse the site during this time, but keep in mind that data may not yet be fully accurate and some functionality may not work until synchronization is complete.", + "please_wait": "Please wait", + "creating_initial_entry": "Creating initial {1} entry", + "entry_created_successfully": "Initial {1} entry for {2} created successfully", + "method_disabled": "This method is disabled", + "compiling_css": "Compiling CSS", + "installing_module": "Installing {1} module", + "restoring_backup": "Restoring backup", + "extracting_backup_files": "Extracting backup files", + "explorer_shutting_down": "Explorer shutting down", + "initializing_database": "Initializing database", + "downloading_newest_explorer_code": "Downloading newest explorer code", + "check_outdated_packages": "Checking for outdated packages", + "updating_explorer_packages": "Updating out-of-date explorer packages", + "checking_webserver_running": "Checking if webserver is running", + "reloading_explorer": "Reloading the explorer", + "email_sent_successfully": "Email sent successfully", + "check_console": "Check your console", + "process_aborted": "Process aborted", + "nothing_was_deleted": "Nothing was deleted", + "nothing_was_restored": "Nothing was restored", + + // prompts + "are_you_sure": "Are you sure you want to do this? [y/n]", + "short_yes": "y", + "long_yes": "yes", // menu items "menu_explorer": "Explorer", @@ -77,6 +102,7 @@ "error_title": "{1} Block Explorer Error", "error_description": "The page you are looking for cannot be found", "error_description_alt": "An error occurred which prevented the page from loading correctly", + "error_not_found": "Not Found", // address view "a_title": "{1} Wallet Address Details", @@ -196,5 +222,32 @@ "heavy_estnext": "Est. Next", "heavy_changein": "Reward change in approximately", "heavy_key": "Key", - "heavy_lastxvotes": "Last 20 votes" + "heavy_lastxvotes": "Last 20 votes", + + // sync + "script_launched": "Script launched with pid", + "stopping_sync_process": "Stopping sync process", + "finding_earliest_orphan": "Finding the earliest orphaned blockindex", + "calculating_market_price": "Calculating market price", + "syncing_blocks": "Syncing blocks", + "syncing_peers": "Syncing peers", + "syncing_masternodes": "Syncing masternodes", + "syncing_markets": "Syncing markets", + "checking_blocks": "Checking blocks", + "calculating_tx_count": "Calculating tx count", + "finding_last_blockindex": "Finding last blockindex", + "path_cannot_be_found": "'{1}' cannot be found", + + // settings + "deprecated_setting": "Deprecated setting '{1}' has been mapped to the new location '{2}'. Be sure to make this change in settings.json as the old setting will be removed in a future release", + "unknown_setting": "Unknown setting '{1}' has been ignored", + "missing_setting": "Setting '{1}' is missing. Loading default value", + "continuing_using_defaults": "Continuing using defaults", + "missing_settings_file": "The {1} file is missing", + "error_processing_settings": "There was an error processing the {1} file", + + // locale + "locale_lowercase_req": "Locale strings must start with a lowercase character", + "locale_unknown_string": "Unknown Locale String", + "locale_not_exists": "This setting doesn't exist or was removed" } \ No newline at end of file diff --git a/plugins/delete.me b/plugins/delete.me new file mode 100644 index 00000000..887153fa --- /dev/null +++ b/plugins/delete.me @@ -0,0 +1 @@ +This file is used to ensure the plugins folder syncs with git. It's safe to delete this file. \ No newline at end of file diff --git a/public/css/style.scss b/public/css/style.scss index 11cba3da..a4f6c7d0 100644 --- a/public/css/style.scss +++ b/public/css/style.scss @@ -1664,11 +1664,11 @@ div[data-overlayscrollbars-viewport="scrollbarHidden"] > .navbar-nav > li#market } } -#showClaimInstructions { +.instructions { color: #ffffff; } -#showClaimInstructions:hover { +.instructions:hover { color: #efefef; } diff --git a/routes/index.js b/routes/index.js index bcf5ba2f..7b4f3a24 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,6 @@ var express = require('express'), router = express.Router(), settings = require('../lib/settings'), - locale = require('../lib/locale'), db = require('../lib/database'), lib = require('../lib/explorer'); @@ -100,7 +99,7 @@ function get_block_data_from_wallet(block, res, orphan) { var i = loop.iteration(); lib.get_rawtransaction(block.tx[i], function(tx) { - if (tx && tx != 'There was an error. Check your console.') { + if (tx && tx != `${settings.localization.ex_error}: ${settings.localization.check_console}`) { lib.prepare_vin(tx, function(vin, tx_type_vin) { lib.prepare_vout(tx.vout, block.tx[i], vin, ((!settings.blockchain_specific.zksnarks.enabled || typeof tx.vjoinsplit === 'undefined' || tx.vjoinsplit == null) ? [] : tx.vjoinsplit), function(vout, nvin, tx_type_vout) { lib.calculate_total(vout, function(total) { @@ -138,7 +137,7 @@ function get_theme_hash() { function route_get_block(res, blockhash) { lib.get_block(blockhash, function (block) { - if (block && block != 'There was an error. Check your console.') { + if (block && block != `${settings.localization.ex_error}: ${settings.localization.check_console}`) { if (blockhash == settings.block_page.genesis_block) send_block_data(res, block, null, 'Genesis Block', null); else if (block.confirmations == -1) { @@ -159,7 +158,7 @@ function route_get_block(res, blockhash) { var height = blockhash; lib.get_blockhash(height, function(hash) { - if (hash && hash != 'There was an error. Check your console.') + if (hash && hash != `${settings.localization.ex_error}: ${settings.localization.check_console}`) res.redirect('/block/' + hash); else route_get_txlist(res, 'Block not found: ' + blockhash); @@ -192,7 +191,7 @@ function route_get_tx(res, txid) { lib.calculate_total(rvout, function(total) { if (!rtx.confirmations > 0) { lib.get_block(rtx.blockhash, function(block) { - if (block && block != 'There was an error. Check your console.') { + if (block && block != `${settings.localization.ex_error}: ${settings.localization.check_console}`) { var utx = { txid: rtx.txid, vin: rvin, @@ -219,7 +218,7 @@ function route_get_tx(res, txid) { if (!rtx.blockheight && rtx.blockhash) { // blockheight not found so look up the block lib.get_block(rtx.blockhash, function(block) { - if (block && block != 'There was an error. Check your console.') { + if (block && block != `${settings.localization.ex_error}: ${settings.localization.check_console}`) { // create the tx object before rendering var utx = { txid: rtx.txid, @@ -339,8 +338,31 @@ router.get('/', function(req, res) { }); router.get('/info', function(req, res) { + let pluginApisExt = []; + // ensure api page is enabled if (settings.api_page.enabled == true) { + // loop through all plugins defined in the settings + settings.plugins.allowed_plugins.forEach(function (plugin) { + // check if this plugin is enabled + if (plugin.enabled) { + // check if this plugin has a public_apis section + if (plugin.public_apis != null) { + // check if there is an ext section + if (plugin.public_apis.ext != null) { + // loop through all ext apis for this plugin + Object.keys(plugin.public_apis.ext).forEach(function(key, index, map) { + // check if this api is enabled + if (plugin.public_apis.ext[key].enabled == true) { + // add this api into the list of ext apis for plugins + pluginApisExt.push(plugin.public_apis.ext[key]); + } + }); + } + } + } + }); + // load the api page res.render( 'info', @@ -351,7 +373,8 @@ router.get('/info', function(req, res) { customHash: get_custom_hash(), styleHash: get_style_hash(), themeHash: get_theme_hash(), - page_title_prefix: settings.coin.name + ' Public API' + page_title_prefix: settings.coin.name + ' Public API', + pluginApisExt: pluginApisExt } ); } else { @@ -417,7 +440,7 @@ router.get('/markets/:market/:coin_symbol/:pair_symbol', function(req, res) { customHash: get_custom_hash(), styleHash: get_style_hash(), themeHash: get_theme_hash(), - page_title_prefix: locale.mkt_title.replace('{1}', marketdata.market_name + ' (' + marketdata.coin + '/' + marketdata.exchange + ')') + page_title_prefix: settings.localization.mkt_title.replace('{1}', marketdata.market_name + ' (' + marketdata.coin + '/' + marketdata.exchange + ')') } ); }); @@ -622,7 +645,7 @@ router.get('/orphans', function(req, res) { customHash: get_custom_hash(), styleHash: get_style_hash(), themeHash: get_theme_hash(), - page_title_prefix: locale.orphan_title.replace('{1}', settings.coin.name) + page_title_prefix: settings.localization.orphan_title.replace('{1}', settings.coin.name) } ); }); @@ -645,7 +668,7 @@ router.post('/search', function(req, res) { res.redirect('/tx/' + tx.txid); else { lib.get_block(query, function(block) { - if (block && block != 'There was an error. Check your console.') + if (block && block != `${settings.localization.ex_error}: ${settings.localization.check_console}`) res.redirect('/block/' + query); else { // check wallet for transaction @@ -654,7 +677,7 @@ router.post('/search', function(req, res) { res.redirect('/tx/' + tx.txid); else { // search found nothing so display the tx list page with an error msg - route_get_txlist(res, locale.ex_search_error + query ); + route_get_txlist(res, settings.localization.ex_search_error + query ); } }); } @@ -668,10 +691,10 @@ router.post('/search', function(req, res) { res.redirect('/address/' + address.a_id); else { lib.get_blockhash(query, function(hash) { - if (hash && hash != 'There was an error. Check your console.') + if (hash && hash != `${settings.localization.ex_error}: ${settings.localization.check_console}`) res.redirect('/block/' + hash); else - route_get_txlist(res, locale.ex_search_error + query); + route_get_txlist(res, settings.localization.ex_search_error + query); }); } }); diff --git a/scripts/compile_css.js b/scripts/compile_css.js index 919fea69..92056c23 100644 --- a/scripts/compile_css.js +++ b/scripts/compile_css.js @@ -6,6 +6,7 @@ const style_min_filename = 'style.min.css' const custom_filename = 'custom.scss'; const custom_min_filename = 'custom.min.css' const theme_selector_template_text = `$theme-name: "replace";`; +const settings = require('../lib/settings'); let compile_theme_css = false; let compile_custom_css = false; let theme_name = ''; @@ -15,7 +16,6 @@ if (!fs.existsSync(`${css_path}${theme_selector_filename}`)) { // theme file doesn't exist, so it is necessary to compile the css compile_theme_css = true; } else { - const settings = require('../lib/settings'); const last_theme = fs.readFileSync(`${css_path}${theme_selector_filename}`, 'utf-8'); theme_name = settings.shared_pages.theme; @@ -56,7 +56,7 @@ if (!fs.existsSync(`${css_path}${custom_min_filename}`)) { // check if it necessary to compile any css files if (compile_theme_css || compile_custom_css) { - console.log('Compiling CSS.. Please wait..'); + console.log(`${settings.localization.compiling_css}.. ${settings.localization.please_wait}..`); const sass = require('sass'); diff --git a/scripts/create_backup.js b/scripts/create_backup.js index 6bf7f545..95a15147 100644 --- a/scripts/create_backup.js +++ b/scripts/create_backup.js @@ -3,9 +3,10 @@ const path = require('path'); const lib = require('../lib/explorer'); const archiveSuffix = '.bak'; const backupLockName = 'backup'; -var backupPath = path.join(path.dirname(__dirname), 'backups'); -var backupFilename; -var lockCreated = false; +const settings = require('../lib/settings'); +let backupPath = path.join(path.dirname(__dirname), 'backups'); +let backupFilename; +let lockCreated = false; // exit function used to cleanup lock before finishing script function exit(exitCode) { @@ -60,12 +61,11 @@ if (!fs.existsSync(path.join(backupPath, `${backupFilename}${archiveSuffix}`))) // ensure the lock will be deleted on exit lockCreated = true; // check all other possible locks since backups should not run at the same time that data is being changed - if (lib.is_locked(['restore', 'delete', 'index', 'markets', 'peers', 'masternodes']) == false) { + if (lib.is_locked(['restore', 'delete', 'index', 'markets', 'peers', 'masternodes', 'plugin']) == false) { // all tests passed. OK to run backup - console.log("Script launched with pid: " + process.pid); + console.log(`${settings.localization.script_launched }: ${process.pid}`); const { exec } = require('child_process'); - const settings = require('../lib/settings'); const randomDirectoryName = Math.random().toString(36).substring(2, 15) + Math.random().toString(23).substring(2, 5); // execute backup diff --git a/scripts/delete_database.js b/scripts/delete_database.js index 4afa64bd..6a7c2340 100644 --- a/scripts/delete_database.js +++ b/scripts/delete_database.js @@ -1,8 +1,9 @@ const lib = require('../lib/explorer'); const readline = require('readline'); const deleteLockName = 'delete'; -var lockCreated = false; -var preserveClaimAddressNames = false; +const settings = require('../lib/settings'); +let lockCreated = false; +let preserveClaimAddressNames = false; // exit function used to cleanup lock before finishing script function exit(mongoose, exitCode) { @@ -84,17 +85,14 @@ function delete_prompt(cb) { } // prompt for deleting explorer database - rl.question('Are you sure you want to do this? [y/n]: ', function (deleteAnswer) { + rl.question(`${settings.localization.are_you_sure}: `, function (deleteAnswer) { // stop prompting rl.close(); // determine if the explorer database should be deleted - switch (deleteAnswer) { - case 'y': - case 'Y': - case 'yes': - case 'YES': - case 'Yes': + switch ((deleteAnswer == null ? '' : deleteAnswer).toLowerCase()) { + case settings.localization.short_yes: + case settings.localization.long_yes: return cb(true); break; default: @@ -152,7 +150,7 @@ if (lib.is_locked([deleteLockName]) == false) { // ensure the lock will be deleted on exit lockCreated = true; - var lock_list = ['backup', 'restore', 'markets', 'peers', 'masternodes']; + var lock_list = ['backup', 'restore', 'markets', 'peers', 'masternodes', 'plugin']; // do not check the index lock if this is called from the reindex process if (process.argv[2] == null || process.argv[2] != 'reindex') { @@ -165,9 +163,8 @@ if (lib.is_locked([deleteLockName]) == false) { // suppress the pid message when doing a reindex if (process.argv[2] == null || process.argv[2] != 'reindex') - console.log("Script launched with pid: " + process.pid); + console.log(`${settings.localization.script_launched }: ${process.pid}`); - const settings = require('../lib/settings'); const mongoose = require('mongoose'); const dbString = `mongodb://${encodeURIComponent(settings.dbsettings.user)}:${encodeURIComponent(settings.dbsettings.password)}@${settings.dbsettings.address}:${settings.dbsettings.port}/${settings.dbsettings.database}`; @@ -231,7 +228,7 @@ if (lib.is_locked([deleteLockName]) == false) { exit(mongoose, 1); }); } else { - console.log('Process aborted. Nothing was deleted.'); + console.log(`${settings.localization.process_aborted}. ${settings.localization.nothing_was_deleted}.`); exit(null, 2); } }); diff --git a/scripts/prestart.js b/scripts/prestart.js index 72dc71c6..b854f07a 100644 --- a/scripts/prestart.js +++ b/scripts/prestart.js @@ -1,3 +1,4 @@ +const settings = require('../lib/settings'); const minNodeVersionMajor = '16'; const minNodeVersionMinor = '20'; const minNodeVersionRevision = '1'; @@ -54,7 +55,7 @@ function check_arguments_passed(cb) { // check if the cmd result contains an @ symbol if (splitResponse[1].indexOf('@') == -1) { - console.log('Installing pm2 module.. Please wait..'); + console.log(`${settings.localization.installing_module.replace('{1}', 'pm2')}.. ${settings.localization.please_wait}..`); // install pm2 exec(`npm install pm2@latest${(isWinOS ? ' -g' : '')}`, (err, stdout, stderr) => { @@ -73,7 +74,7 @@ function check_arguments_passed(cb) { // check if the cmd result contains an @ symbol if (splitResponse[1].indexOf('@') == -1) { - console.log('Installing forever module.. Please wait..'); + console.log(`${settings.localization.installing_module.replace('{1}', 'forever')}.. ${settings.localization.please_wait}..`); // install forever exec('npm install forever', (err, stdout, stderr) => { @@ -133,7 +134,7 @@ check_arguments_passed(function(pidName, node_env) { } } - // Setting the NODE_ENV variable is more easily done from here seeing at the syntax changes slightly depending on operating system + // setting the NODE_ENV variable is more easily done from here seeing at the syntax changes slightly depending on operating system execSync(`${(process.platform == 'win32' ? 'set' : 'export')} NODE_ENV=${node_env} && pm2 ${startOrReload} ./bin/instance -i 0 -n explorer -p "./tmp/pm2.pid" --node-args="--stack-size=10000" --update-env`, {stdio : 'inherit'}); break; case 'forever': diff --git a/scripts/restore_backup.js b/scripts/restore_backup.js index afca2e01..0bd14e94 100644 --- a/scripts/restore_backup.js +++ b/scripts/restore_backup.js @@ -4,7 +4,9 @@ const lib = require('../lib/explorer'); const archiveSuffix = '.bak'; const oldArchiveSuffix = '.tar.gz'; const restoreLockName = 'restore'; +const tarModule = 'tar'; const defaultBackupPath = path.join(path.dirname(__dirname), 'backups'); +const settings = require('../lib/settings'); var lockCreated = false; // exit function used to cleanup lock before finishing script @@ -55,10 +57,10 @@ function check_module_directory_exists(dirName, cb) { if (!fs.existsSync(`./node_modules/${dirName}`)) { const { exec } = require('child_process'); - console.log('Installing tar package.. Please wait..'); + console.log(`${settings.localization.installing_module.replace('{1}', tarModule)}.. ${settings.localization.please_wait}..`); // install tar module - exec('npm install tar', (err, stdout, stderr) => { + exec(`npm install ${tarModule}`, (err, stdout, stderr) => { // always return true for now without checking results return cb(true); }); @@ -80,7 +82,7 @@ function drop_collection(mongoose, colName, cb) { }); } -function delete_database(mongoose, settings, cb) { +function delete_database(mongoose, cb) { const dbString = `mongodb://${encodeURIComponent(settings.dbsettings.user)}:${encodeURIComponent(settings.dbsettings.password)}@${settings.dbsettings.address}:${settings.dbsettings.port}/${settings.dbsettings.database}`; console.log('Connecting to database..'); @@ -126,10 +128,10 @@ function delete_database(mongoose, settings, cb) { }); } -function restore_backup(mongoose, settings, backupPath, extractedPath, gZip) { +function restore_backup(mongoose, backupPath, extractedPath, gZip) { const { exec } = require('child_process'); - console.log('Restoring backup.. Please wait..'); + console.log(`${settings.localization.restoring_backup}.. ${settings.localization.please_wait}..`); // restore mongo database from backup const restoreProcess = exec(`mongorestore --host="${settings.dbsettings.address}" --port="${settings.dbsettings.port}" --username="${settings.dbsettings.user}" --password="${settings.dbsettings.password}" --authenticationDatabase="${settings.dbsettings.database}" ${(gZip ? `--gzip --archive="${backupPath}"` : `"${extractedPath}"`)}`); @@ -204,17 +206,14 @@ if (process.argv[2] != null && process.argv[2] != '') { console.log('You are about to delete the current eIquidus database and restore from backup.'); // prompt for restoring explorer database - rl.question('Are you sure you want to do this? [y/n]: ', function (restoreAnswer) { + rl.question(`${settings.localization.are_you_sure}: `, function (restoreAnswer) { // stop prompting rl.close(); // determine if the explorer database should be restored - switch (restoreAnswer) { - case 'y': - case 'Y': - case 'yes': - case 'YES': - case 'Yes': + switch ((restoreAnswer == null ? '' : restoreAnswer).toLowerCase()) { + case settings.localization.short_yes: + case settings.localization.long_yes: // check if the "restore backup" process is already running if (lib.is_locked([restoreLockName]) == false) { // create a new restore lock before checking the rest of the locks to minimize problems with running scripts at the same time @@ -222,11 +221,9 @@ if (process.argv[2] != null && process.argv[2] != '') { // ensure the lock will be deleted on exit lockCreated = true; // check all other possible locks since restoring backups should not run at the same time that data is being changed - if (lib.is_locked(['backup', 'delete', 'index', 'markets', 'peers', 'masternodes']) == false) { + if (lib.is_locked(['backup', 'delete', 'index', 'markets', 'peers', 'masternodes', 'plugin']) == false) { // all tests passed. OK to run restore - console.log("Script launched with pid: " + process.pid); - - const settings = require('../lib/settings'); + console.log(`${settings.localization.script_launched }: ${process.pid}`); // check if this is a tar.gz (older explorer backup format) if (!backupPath.endsWith(oldArchiveSuffix)) { @@ -234,19 +231,19 @@ if (process.argv[2] != null && process.argv[2] != '') { // newer backup format (.bak) // delete all collections from existing database - delete_database(mongoose, settings, function(retVal) { + delete_database(mongoose, function(retVal) { if (retVal) { // move on to the restore process - restore_backup(mongoose, settings, backupPath, backupPath, true); + restore_backup(mongoose, backupPath, backupPath, true); } }); } else { // older backup format (.tar.gz) // check if the tar module is already installed - check_module_directory_exists('tar', function(retVal) { - const tar = require('tar'); + check_module_directory_exists(tarModule, function(retVal) { + const tar = require(tarModule); - console.log('Extracting backup files.. Please wait..'); + console.log(`${settings.localization.extracting_backup_files}.. ${settings.localization.please_wait}..`); // extract the backup archive tar.x({ file: backupPath, cwd: defaultBackupPath, gzip: true }, function() { @@ -257,10 +254,10 @@ if (process.argv[2] != null && process.argv[2] != '') { const mongoose = require('mongoose'); // delete all collections from existing database - delete_database(mongoose, settings, function(retVal) { + delete_database(mongoose, function(retVal) { if (retVal) { // move on to the restore process - restore_backup(mongoose, settings, backupPath, extractedPath, false); + restore_backup(mongoose, backupPath, extractedPath, false); } }); } else { @@ -291,13 +288,13 @@ if (process.argv[2] != null && process.argv[2] != '') { break; default: - console.log('Process aborted. Nothing was restored.'); + console.log(`${settings.localization.process_aborted}. ${settings.localization.nothing_was_restored}.`); exit(null, 2); } }); } else { // backup does not exist - console.log(`${backupPath} cannot be found`); + console.log(settings.localization.path_cannot_be_found.replace('{1}', backupPath)); exit(null, 2); } } else { diff --git a/scripts/stop_explorer.js b/scripts/stop_explorer.js index 3128577c..b3f66c99 100644 --- a/scripts/stop_explorer.js +++ b/scripts/stop_explorer.js @@ -47,7 +47,7 @@ if (validate_port(settings.webserver.port) == true) { // send a kill signal to the process that is currently using the explorer's server port exec(killcmd, (err, stdout, stderr) => { // show shutdown msg - console.log('Explorer shutting down... Please wait...'); + console.log(`${settings.localization.explorer_shutting_down}.. ${settings.localization.please_wait}..`); process.exit(0); }); } else { diff --git a/scripts/sync.js b/scripts/sync.js index 55c6481d..680f9402 100644 --- a/scripts/sync.js +++ b/scripts/sync.js @@ -17,13 +17,13 @@ var stopSync = false; // prevent stopping of the sync script to be able to gracefully shut down process.on('SIGINT', () => { - console.log('Stopping sync process.. Please wait..'); + console.log(`${settings.localization.stopping_sync_process}.. ${settings.localization.please_wait}..`); stopSync = true; }); // prevent killing of the sync script to be able to gracefully shut down process.on('SIGTERM', () => { - console.log('Stopping sync process.. Please wait..'); + console.log(`${settings.localization.stopping_sync_process}.. ${settings.localization.please_wait}..`); stopSync = true; }); @@ -513,7 +513,7 @@ function update_orphans(orphan_index, orphan_current, last_blockindex, timeout, function get_earliest_orphan_block(orphan_index, orphan_current, last_blockindex, cb) { // check if it is necessary to search for orphan data if (orphan_index == null || orphan_index == 0) { - console.log('Finding the earliest orphaned blockindex.. Please wait..'); + console.log(`${settings.localization.finding_earliest_orphan}.. ${settings.localization.please_wait}..`); Tx.aggregate([ { $match: { @@ -1023,7 +1023,7 @@ function get_market_price(market_array) { const coingecko = require('../lib/apis/coingecko'); const currency = lib.get_market_currency_code(); - console.log('Calculating market price.. Please wait..'); + console.log(`${settings.localization.calculating_market_price}.. ${settings.localization.please_wait}..`); // get the market price from coingecko api coingecko.get_market_prices(coingecko_id, currency, settings.markets_page.coingecko_api_key, function (err, last_price, last_usd_price) { @@ -1050,7 +1050,7 @@ function get_market_price(market_array) { }); } else { // coingecko api returned an error - console.log(`Error: ${err}`); + console.log(`${settings.localization.ex_error}: ${err}`); exit(1); } }); @@ -1060,7 +1060,7 @@ function get_market_price(market_array) { } }); } else { - console.log('Calculating market price.. Please wait..'); + console.log(`${settings.localization.calculating_market_price}.. ${settings.localization.please_wait}..`); // get the list of coins from coingecko coingecko_coin_list_api(market_array, function (coin_err, coin_list) { @@ -1350,10 +1350,24 @@ if (lib.is_locked([database]) == false) { // check the backup, restore and delete locks since those functions would be problematic when updating data if (lib.is_locked(['backup', 'restore', 'delete']) == false) { // all tests passed. OK to run sync - console.log("Script launched with pid: " + process.pid); - - if (mode == 'update') - console.log(`Syncing ${(database == 'index' ? 'blocks' : database)}.. Please wait..`); + console.log(`${settings.localization.script_launched }: ${process.pid}`); + + if (mode == 'update') { + switch (database) { + case 'index': + console.log(`${settings.localization.syncing_blocks}.. ${settings.localization.please_wait}..`); + break; + case 'peers': + console.log(`${settings.localization.syncing_peers}.. ${settings.localization.please_wait}..`); + break; + case 'masternodes': + console.log(`${settings.localization.syncing_masternodes}.. ${settings.localization.please_wait}..`); + break; + default: // markets + console.log(`${settings.localization.syncing_markets}.. ${settings.localization.please_wait}..`); + break; + } + } var dbString = 'mongodb://' + encodeURIComponent(settings.dbsettings.user); dbString = dbString + ':' + encodeURIComponent(settings.dbsettings.password); @@ -1396,7 +1410,7 @@ if (lib.is_locked([database]) == false) { db.update_db(settings.coin.name, function(stats) { // check if stats returned properly if (stats !== false) { - console.log('Checking blocks.. Please wait..'); + console.log(`${settings.localization.checking_blocks}.. ${settings.localization.please_wait}..`); update_tx_db(settings.coin.name, block_start, stats.count, stats.txes, settings.sync.check_timeout, 1, function() { // check if the script stopped prematurely @@ -1466,7 +1480,7 @@ if (lib.is_locked([database]) == false) { db.update_db(settings.coin.name, function(stats) { // check if stats returned properly if (stats !== false) { - console.log('Calculating tx count.. Please wait..'); + console.log(`${settings.localization.calculating_tx_count}.. ${settings.localization.please_wait}..`); // Resetting the transaction counter requires a single lookup on the txes collection to find all txes that have a positive or zero total and 1 or more vout Tx.find({'total': {$gte: 0}, 'vout': { $gte: { $size: 1 }}}).countDocuments().then((count) => { @@ -1493,7 +1507,7 @@ if (lib.is_locked([database]) == false) { db.update_db(settings.coin.name, function(stats) { // check if stats returned properly if (stats !== false) { - console.log('Finding last blockindex.. Please wait..'); + console.log(`${settings.localization.finding_last_blockindex}.. ${settings.localization.please_wait}..`); // Resetting the last blockindex counter requires a single lookup on the txes collection to find the last indexed blockindex Tx.find({}, {blockindex:1, _id:0}).sort({blockindex: -1}).limit(1).exec().then((tx) => { diff --git a/scripts/update_explorer.js b/scripts/update_explorer.js index 1dc73752..70a267ec 100644 --- a/scripts/update_explorer.js +++ b/scripts/update_explorer.js @@ -1,8 +1,8 @@ const { execSync } = require('child_process'); const fs = require('fs'); const argument = (process.argv[2] != null && process.argv[2] != '' && (process.argv[2] == 'explorer-only' || process.argv[2] == 'dependencies-only') ? process.argv[2] : ''); - -var reloadWebserver = false; +const settings = require('../lib/settings'); +let reloadWebserver = false; function exit() { console.log('Explorer update complete'); @@ -33,7 +33,7 @@ if (argument == '' || argument == 'explorer-only') { var commit = fs.readFileSync('./.git/refs/heads/master'); // update to newest explorer source - console.log('Downloading newest explorer code.. Please wait..\n'); + console.log(`${settings.localization.downloading_newest_explorer_code}.. ${settings.localization.please_wait}..\n`); try { console.log('Git response:'); @@ -71,7 +71,7 @@ if (argument == '' || argument == 'dependencies-only') { // check for outdated packages try { - console.log((argument == 'dependencies-only' ? '' : '\n') +'Checking for outdated packages.. Please wait..'); + console.log(`${(argument == 'dependencies-only' ? '' : '\n')}${settings.localization.check_outdated_packages}.. ${settings.localization.please_wait}..`); execSync('npm outdated'); // all packages are up-to-date @@ -86,7 +86,7 @@ if (argument == '' || argument == 'dependencies-only') { // check if there were any outdated packages if (outdatedPkgs != null) { // update npm modules to latest versions according to package.json rules - console.log('Updating out-of-date explorer packages.. Please wait..\n'); + console.log(`${settings.localization.updating_explorer_packages}.. ${settings.localization.please_wait}..\n`); execSync('npm update'); // check for outdated packages (again) @@ -108,7 +108,7 @@ if (argument == '' || argument == 'dependencies-only') { // check if the web server should be reloaded if (reloadWebserver == true) { - console.log('Checking if webserver is running.. Please wait..\n'); + console.log(`${settings.localization.checking_webserver_running}.. ${settings.localization.please_wait}..\n`); const path = require('path'); const lib = require('../lib/explorer'); @@ -136,7 +136,7 @@ if (reloadWebserver == true) { if (pidActive == true) { // compile css and initialize database init_database(function() { - console.log('\nReloading the explorer.. Please wait..\n'); + console.log(`\n${settings.localization.reloading_explorer}.. ${settings.localization.please_wait}..\n`); // reload pm2 using the zero-downtime reload function execSync(`pm2 reload explorer`, {stdio : 'inherit'}); @@ -158,7 +158,7 @@ if (reloadWebserver == true) { if (pidActive == true) { // compile css and initialize database init_database(function() { - console.log('\nReloading the explorer.. Please wait..\n'); + console.log(`\n${settings.localization.reloading_explorer}.. ${settings.localization.please_wait}..\n`); // reload forever using the restart function execSync(`forever restart explorer`, {stdio : 'inherit'}); @@ -171,7 +171,6 @@ if (reloadWebserver == true) { }); } else { const request = require('postman-request'); - const settings = require('../lib/settings'); // try executing the restart explorer api request({uri: `http://localhost:${settings.webserver.port}/system/restartexplorer`, timeout: 1000}, function (error, response, summary) { @@ -184,7 +183,7 @@ if (reloadWebserver == true) { } else { // compile css and initialize database init_database(function() { - console.log('\nReloading the explorer.. Please wait..\n'); + console.log(`\n${settings.localization.reloading_explorer}.. ${settings.localization.please_wait}..\n`); // finish the script exit(); diff --git a/settings.json.template b/settings.json.template index d5a2e92f..30b43c6f 100644 --- a/settings.json.template +++ b/settings.json.template @@ -541,11 +541,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.ex_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.ex_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.ex_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.ex_description" (true/false) "show_description": true }, // transaction_table: a collection of settings that pertain to the transaction table on the index page @@ -574,9 +574,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.block_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.block_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.block_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.block_description" (true/false) "show_description": true }, // genesis_block: Your coins genesis block hash is used to determine the beginning of the blockchain @@ -608,9 +608,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.tx_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.tx_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.tx_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.tx_description" (true/false) "show_description": true }, // genesis_tx: Your coins genesis transaction hash is used to determine the beginning of the blockchain @@ -634,9 +634,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.a_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.a_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.a_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.a_description" (true/false) "show_description": true }, // show_sent_received: Determine whether to show Total Sent and Total Received columns at the top of the address page @@ -672,9 +672,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.error_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.error_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.error_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.error_description" (true/false) "show_description": true } }, @@ -696,11 +696,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.mn_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.mn_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.mn_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.mn_description" (true/false) "show_description": true }, // masternode_table: a collection of settings that pertain to the masternode table on the masternodes page @@ -728,11 +728,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.move_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.move_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.move_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.move_description" (true/false) "show_description": true }, // movement_table: a collection of settings that pertain to the movement table on the movement page @@ -770,11 +770,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.net_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.net_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.net_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.net_description" (true/false) "show_description": true }, // connections_table: a collection of settings that pertain to the connections table on the network page @@ -842,11 +842,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.rl_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.rl_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.rl_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.rl_description" (true/false) "show_description": true }, // show_current_balance: Determine whether to show the top 100 list of wallet addresses that currently have the most coins in a single wallet (true/false) @@ -897,13 +897,13 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.mkt_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.mkt_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, // show_exchange_url: Determine whether to show an external link to the exchange trading page for the selected pair (true/false) "show_exchange_url": true, - // show_description: Determine whether to show the page description as defined in "locale.mkt_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.mkt_description" (true/false) "show_description": true }, // show_market_dropdown_menu: Determine whether the markets menu in the page header will function as a dropdown or a single-click menu item that opens the default market (true/false) @@ -1044,9 +1044,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.api_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.api_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.api_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.api_description" (true/false) "show_description": true }, // show_logo: Determine whether to show the `shared_pages.logo` image at the top of the API Documentation panel or not @@ -1285,9 +1285,9 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.claim_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.claim_title" (true/false) "show_title": true, - // show_description: Determine whether to show the page description as defined in "locale.claim_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.claim_description" (true/false) "show_description": true }, // show_header_menu: Show/hide the "Claim Address" header menu item (true/false) @@ -1317,11 +1317,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.orphan_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.orphan_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.orphan_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.orphan_description" (true/false) "show_description": true }, // orphans_table: a collection of settings that pertain to the orphans table on the orphans page @@ -1543,11 +1543,11 @@ "page_header": { // show_img: Determine whether to show the page title image defined in the "shared_pages.page_header.page_title_image" setting (true/false) "show_img": true, - // show_title: Determine whether to show the page title as defined in "locale.reward_title" (true/false) + // show_title: Determine whether to show the page title as defined in "localization.reward_title" (true/false) "show_title": true, // show_last_updated: Determine whether to show a label below the page title with the last updated date (true/false) "show_last_updated": true, - // show_description: Determine whether to show the page description as defined in "locale.reward_description" (true/false) + // show_description: Determine whether to show the page description as defined in "localization.reward_description" (true/false) "show_description": true } }, @@ -1649,5 +1649,27 @@ // NOTE: Enabling this feature will require a full reindex of the blockchain data "enabled": false } + }, + + // plugins: A collection of settings that pertain to extended functionality from external plugins that support explorer integration + "plugins": { + // plugin_secret_code: A secret code that will be received from all plugins to validate the plugin data request before modifying local database data + // NOTE: This is used as an internal password for your own plugins that can be run on different servers to validate that plugin data being received by the explorer is coming from you and not from a malicious user + // This code should be a random set of numbers, letters and special characters that cannot be easily guessed that must also match the plugin_secret_code in all plugin external.settings.json files + // WARNING: Be sure to change the default secret code as it is only a sample and will be the first code that malicious users try to use to manipulate your explorer's data + "plugin_secret_code": "SJs2=&r^ScLGLgTaNm7#74=s?48zf*4+vm5S", + // allowed_plugins: A collection of settings that pertain to the list of plugins allowed to be used with this explorer instance + // You can add as many plugins as necessary in the following format: [ { "plugin_name": "new_plugin_1", "enabled": "true" }, { "plugin_name": "new_plugin_2", "enabled": "false" } ] + // NOTE: Plugins enabled here must also have the actual plugin downloaded into the explorer's /plugins directory with the same name as the plugin_name specified here or they will be ignored + "allowed_plugins": [ + { + // plugin_name: The name of the plugin which must exactly match the name of the plugin folder name inside the explorer /plugins directory + "plugin_name": "generic-snapshots", + // enabled: Enable/disable the plugin + // If set to true, the plugin will be used to extend the explorer functionality and accept incoming http requests to modify explorer data + // If set to false, all features and functionality of the plugin will be completely disabled + "enabled": false + } + ] } } \ No newline at end of file diff --git a/views/address.pug b/views/address.pug index ad5ac6a1..e9e7bd45 100644 --- a/views/address.pug +++ b/views/address.pug @@ -69,7 +69,7 @@ block content var vin = data[3]; //variables for better readability var balance = data[4].toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); //variables for better readability var balanceParts = balance.split('.'); - $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); + $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); $("td:eq(1)", row).html('' + txhash + '').addClass('breakWord d-none d-md-table-cell'); var amount = 0; var updown = ''; @@ -137,21 +137,21 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.address_page.page_header.show_title == true - h3#page-title #{settings.locale.a_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.a_title.replace('{1}', settings.coin.name)} if settings.address_page.page_header.show_description == true if settings.address_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=settings.locale.a_description.replace('{1}', settings.coin.name).replace('{2}', (address.a_id == 'hidden_address' ? settings.locale.hidden_address : (address.a_id == 'unknown_address' ? settings.locale.unknown_address : address.a_id))) + .sub-page-header.text-muted=settings.localization.a_description.replace('{1}', settings.coin.name).replace('{2}', (address.a_id == 'hidden_address' ? settings.localization.hidden_address : (address.a_id == 'unknown_address' ? settings.localization.unknown_address : address.a_id))) else - .sub-page-header.text-muted=settings.locale.a_description.replace('{1}', settings.coin.name).replace('{2}', (address.a_id == 'hidden_address' ? settings.locale.hidden_address : (address.a_id == 'unknown_address' ? settings.locale.unknown_address : address.a_id))) + .sub-page-header.text-muted=settings.localization.a_description.replace('{1}', settings.coin.name).replace('{2}', (address.a_id == 'hidden_address' ? settings.localization.hidden_address : (address.a_id == 'unknown_address' ? settings.localization.unknown_address : address.a_id))) .cardSpacer.clearfix .card.card-default.border-0.card-address-summary.cardSpacer .card-header(style='position:relative;') if settings.claim_address_page.enabled == false || claim_name == null || claim_name == '' if address.a_id == 'hidden_address' - strong #{settings.locale.hidden_address} + strong #{settings.localization.hidden_address} else if address.a_id == 'unknown_address' - strong #{settings.locale.unknown_address} + strong #{settings.localization.unknown_address} else strong #{address.a_id} else @@ -167,15 +167,15 @@ block content table#address-summary.table.table-bordered.table-striped.summary-table.mobile-border-right(style='border-top:0;margin-top:0 !important;') thead tr(class=theadClasses) - th.text-center #{settings.locale.rl_balance} + th.text-center #{settings.localization.rl_balance} span.small.fw-normal (#{settings.coin.symbol}) if settings.address_page.show_sent_received == true - th.text-center #{settings.locale.total_sent} + th.text-center #{settings.localization.total_sent} span.small.fw-normal (#{settings.coin.symbol}) if settings.address_page.show_sent_received == true - th.text-center #{settings.locale.total_received} + th.text-center #{settings.localization.total_received} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.a_qr} + th.text-center #{settings.localization.a_qr} tbody tr td.text-center.addr-summary #{balanceParts[0]}. @@ -190,15 +190,15 @@ block content img.qrcode(src='/qr/' + address.a_id) .card.card-default.border-0.cardSpacer .card-header - strong #{settings.locale.ex_latest_transactions} + strong #{settings.localization.ex_latest_transactions} table#address-txs.table.table-bordered.table-striped.table-paging.table-hover.mobile-border-right thead tr(class=theadClasses) th.d-table-cell.d-md-none - th.d-none.d-md-table-cell #{settings.locale.tx_hash} - th.text-center #{settings.locale.mkt_amount} + th.d-none.d-md-table-cell #{settings.localization.tx_hash} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.rl_balance} + th.text-center #{settings.localization.rl_balance} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.timestamp} + th.text-center #{settings.localization.timestamp} tbody \ No newline at end of file diff --git a/views/block.pug b/views/block.pug index 4174b71d..fe4dccee 100644 --- a/views/block.pug +++ b/views/block.pug @@ -36,7 +36,7 @@ block content button.btn-close(type='button', data-bs-dismiss='alert') .cardSpacer span.fa-solid.fa-triangle-exclamation(style='margin-right:5px') - strong=settings.locale.ex_warning + strong=settings.localization.ex_warning div="This is an orphaned block" if settings.block_page.page_header.show_img == true || settings.block_page.page_header.show_title == true || settings.block_page.page_header.show_description == true #page-header-container(style='align-items:' + (settings.block_page.page_header.show_img == true && settings.block_page.page_header.show_title == true && settings.block_page.page_header.show_description == true ? 'flex-start' : 'center')) @@ -45,45 +45,45 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.block_page.page_header.show_title == true - h3#page-title #{settings.locale.block_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.block_title.replace('{1}', settings.coin.name)} if settings.block_page.page_header.show_description == true if settings.block_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=settings.locale.block_description.replace('{1}', settings.coin.name).replace('{2}', block.height) + .sub-page-header.text-muted=settings.localization.block_description.replace('{1}', settings.coin.name).replace('{2}', block.height) else - .sub-page-header.text-muted=settings.locale.block_description.replace('{1}', settings.coin.name).replace('{2}', block.height) + .sub-page-header.text-muted=settings.localization.block_description.replace('{1}', settings.coin.name).replace('{2}', block.height) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header div(style='display: flex;flex-wrap: wrap;') if block.previousblockhash != null a(href='/block/' + block.previousblockhash) - span.fa-solid.fa-chevron-left.block-last(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.block_previous, style='color: var(--bs-body-color);') - strong.d-none.d-md-block #{settings.locale.tx_block_hash}: #{block.hash} - strong.d-block.d-md-none #{settings.locale.ex_summary} + span.fa-solid.fa-chevron-left.block-last(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.block_previous, style='color: var(--bs-body-color);') + strong.d-none.d-md-block #{settings.localization.tx_block_hash}: #{block.hash} + strong.d-block.d-md-none #{settings.localization.ex_summary} else - strong.d-none.d-md-block(style='margin-left:10px;') #{settings.locale.tx_block_hash}: #{block.hash} - strong.d-block.d-md-none(style='margin-left:10px;') #{settings.locale.ex_summary} + strong.d-none.d-md-block(style='margin-left:10px;') #{settings.localization.tx_block_hash}: #{block.hash} + strong.d-block.d-md-none(style='margin-left:10px;') #{settings.localization.ex_summary} if block.nextblockhash != null a(href='/block/' + block.nextblockhash) - span.fa-solid.fa-chevron-right.block-next(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.block_next, style='color: var(--bs-body-color);') + span.fa-solid.fa-chevron-right.block-next(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.block_next, style='color: var(--bs-body-color);') if settings.api_page.public_apis.rpc.getblock.enabled == true - a.d-none.d-md-block(href='/api/getblock?hash=' + block.hash, style='margin-left:auto;', data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.view_raw_block_data) + a.d-none.d-md-block(href='/api/getblock?hash=' + block.hash, style='margin-left:auto;', data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.view_raw_block_data) span.fa-solid.fa-circle-info(style='color: var(--bs-body-color);') table#block-summary.table.table-bordered.summary-table.bottom-border-0.single-row-table(style='border-top:0;margin-top:0 !important;') thead tr(class=theadClasses) - th.text-center #{settings.locale.height} - th.text-center #{settings.locale.difficulty} + th.text-center #{settings.localization.height} + th.text-center #{settings.localization.difficulty} if settings.block_page.multi_algorithm.show_algo == true th.text-center='Algorithm' - th.text-center #{settings.locale.confirmations} + th.text-center #{settings.localization.confirmations} if settings.blockchain_specific.heavycoin.enabled == true th.text-center Vote - th.text-center #{settings.locale.size} (kB) - th.text-center #{settings.locale.bits} - th.text-center #{settings.locale.nonce} - th.text-center #{settings.locale.timestamp} + th.text-center #{settings.localization.size} (kB) + th.text-center #{settings.localization.bits} + th.text-center #{settings.localization.nonce} + th.text-center #{settings.localization.timestamp} tbody - var difficulty = Number(block.difficulty).toLocaleString('en',{'minimumFractionDigits':4,'maximumFractionDigits':4,'useGrouping':true}); - var splitDifficulty = difficulty.split('.'); @@ -111,25 +111,25 @@ block content span#timestampCol if block.hash == settings.block_page.genesis_block .alert.alert-info(role='alert', style='text-align:center;') - strong #{settings.locale.block_genesis} + strong #{settings.localization.block_genesis} else .card.card-default.border-0 .card-header - strong #{settings.locale.ex_latest_transactions} + strong #{settings.localization.ex_latest_transactions} table.table.table-bordered.table-striped.table-hover.summary-table.mobile-border-right thead tr(class=theadClasses) th.text-center.d-table-cell.d-md-none - th.d-none.d-md-table-cell #{settings.locale.tx_hash} - th.text-center #{settings.locale.tx_recipients} - th.text-center #{settings.locale.mkt_amount} + th.d-none.d-md-table-cell #{settings.localization.tx_hash} + th.text-center #{settings.localization.tx_recipients} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) tbody each txn in txs tr td.text-center.d-table-cell.d-md-none a(href='/tx/' + txn.txid) - span.fa-regular.fa-eye(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.view_tx) + span.fa-regular.fa-eye(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.view_tx) td.d-none.d-md-table-cell a.breakWord(href='/tx/' + txn.txid) #{txn.txid} td.text-center #{txn.vout.length} diff --git a/views/claim_address.pug b/views/claim_address.pug index 866ddefe..2ed225ca 100644 --- a/views/claim_address.pug +++ b/views/claim_address.pug @@ -144,19 +144,19 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.claim_address_page.page_header.show_title == true - h3#page-title #{settings.locale.claim_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.claim_title.replace('{1}', settings.coin.name)} if settings.claim_address_page.page_header.show_description == true if settings.claim_address_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=settings.locale.claim_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.claim_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.claim_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.claim_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header strong Claim Wallet Address .card-body - a#showClaimInstructions.badge.bg-primary(href='#claimInstructions', style='font-size:100%;margin-bottom:15px;', data-bs-toggle='collapse' role='button' aria-expanded='false' aria-controls='claimInstructions') + a#showClaimInstructions.instructions.badge.bg-primary(href='#claimInstructions', style='font-size:100%;margin-bottom:15px;', data-bs-toggle='collapse' role='button' aria-expanded='false' aria-controls='claimInstructions') i.fa-solid.fa-angle-up(style='margin-right:5px;') span Show claim instructions div#claimInstructions.collapse diff --git a/views/error.pug b/views/error.pug index 5b14604e..a389da17 100644 --- a/views/error.pug +++ b/views/error.pug @@ -14,12 +14,12 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.error_page.page_header.show_title == true - h3#page-title=settings.locale.error_title.replace('{1}', settings.coin.name) + h3#page-title=settings.localization.error_title.replace('{1}', settings.coin.name) if settings.error_page.page_header.show_description == true if settings.error_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=(error.status == null ? settings.locale.error_description_alt : settings.locale.error_description) + .sub-page-header.text-muted=(error.status == null ? settings.localization.error_description_alt : settings.localization.error_description) else - .sub-page-header.text-muted=(error.status == null ? settings.locale.error_description_alt : settings.locale.error_description) + .sub-page-header.text-muted=(error.status == null ? settings.localization.error_description_alt : settings.localization.error_description) .cardSpacer.clearfix h2=(error.status == null ? '' : error.status + ' ') + message \ No newline at end of file diff --git a/views/index.pug b/views/index.pug index c47c7e78..eaeca416 100644 --- a/views/index.pug +++ b/views/index.pug @@ -72,7 +72,7 @@ block content var timestamp = data[5]; var offset = 0; - $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); + $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); $("td:eq(1)", row).html('' + blockindex + ''); $("td:eq(2)", row).html('' + txhash + '').addClass("text-center breakWord d-none d-md-table-cell"); $("td:eq(3)", row).html(outputs).addClass("text-center d-none d-sm-table-cell"); @@ -136,7 +136,7 @@ block content button.btn-close(type='button', data-bs-dismiss='alert') .cardSpacer span.fa-solid.fa-circle-exclamation(style='margin-right:5px') - strong #{settings.locale.ex_error} + strong #{settings.localization.ex_error} div #{error} .col-md-12.cardSpacer if settings.index_page.page_header.show_img == true || settings.index_page.page_header.show_title == true || settings.index_page.page_header.show_last_updated == true || settings.index_page.page_header.show_description == true @@ -146,27 +146,27 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.index_page.page_header.show_title == true - h3#page-title #{settings.locale.ex_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.ex_title.replace('{1}', settings.coin.name)} if settings.index_page.page_header.show_last_updated == true if settings.index_page.page_header.show_title != true && settings.index_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.index_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.index_page.page_header.show_description == true if settings.index_page.page_header.show_title != true && settings.index_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.ex_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.ex_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.ex_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.ex_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header - strong #{settings.locale.ex_latest_transactions} + strong #{settings.localization.ex_latest_transactions} table#recent-table.table.table-bordered.table-striped.table-paging.table-hover - var theadClasses = []; if settings.shared_pages.table_header_bgcolor != null && settings.shared_pages.table_header_bgcolor != '' @@ -174,12 +174,12 @@ block content thead tr(class=theadClasses) th.d-table-cell.d-md-none - th.text-center #{settings.locale.ex_block} - th.text-center.d-none.d-md-table-cell #{settings.locale.tx_hash} - th.text-center.d-none.d-sm-table-cell #{settings.locale.tx_recipients} - th.text-center #{settings.locale.mkt_amount} + th.text-center #{settings.localization.ex_block} + th.text-center.d-none.d-md-table-cell #{settings.localization.tx_hash} + th.text-center.d-none.d-sm-table-cell #{settings.localization.tx_recipients} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) if settings.block_page.multi_algorithm.show_algo == true th.text-center="Algorithm" - th.text-center #{settings.locale.timestamp} + th.text-center #{settings.localization.timestamp} tbody.text-center \ No newline at end of file diff --git a/views/info.pug b/views/info.pug index 11e4c978..99cdc85b 100644 --- a/views/info.pug +++ b/views/info.pug @@ -14,26 +14,26 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.api_page.page_header.show_title == true - h3#page-title #{settings.locale.api_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.api_title.replace('{1}', settings.coin.name)} if settings.api_page.page_header.show_description == true if settings.api_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=settings.locale.api_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.api_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.api_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.api_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0 .card-header - strong #{settings.locale.api_documentation} + strong #{settings.localization.api_documentation} .card-body if settings.api_page.show_logo == true img(src=settings.shared_pages.logo, style='margin:0;height:128px;') hr - var hide_rpc_api_section = !(settings.api_page.public_apis.rpc.getdifficulty.enabled == true && settings.api_cmds['getdifficulty'] != null && settings.api_cmds['getdifficulty'] != '') && !(settings.api_page.public_apis.rpc.getconnectioncount.enabled == true && settings.api_cmds['getconnectioncount'] != null && settings.api_cmds['getconnectioncount'] != '') && !(settings.api_page.public_apis.rpc.getblockcount.enabled == true && settings.api_cmds['getblockcount'] != null && settings.api_cmds['getblockcount'] != '') && !(settings.api_page.public_apis.rpc.getblockhash.enabled == true && settings.api_cmds['getblockhash'] != null && settings.api_cmds['getblockhash'] != '') && !(settings.api_page.public_apis.rpc.getblock.enabled == true && settings.api_cmds['getblock'] != null && settings.api_cmds['getblock'] != '') && !(settings.api_page.public_apis.rpc.getrawtransaction.enabled == true && settings.api_cmds['getrawtransaction'] != null && settings.api_cmds['getrawtransaction'] != '') && !(settings.api_page.public_apis.rpc.getnetworkhashps.enabled == true && settings.shared_pages.show_hashrate == true && settings.api_cmds['getnetworkhashps'] != null && settings.api_cmds['getnetworkhashps'] != '') && !(settings.api_page.public_apis.rpc.getvotelist.enabled == true && settings.api_cmds['getvotelist'] != null && settings.api_cmds['getvotelist'] != '') && !(settings.api_page.public_apis.rpc.getmasternodecount.enabled == true && settings.api_cmds['getmasternodecount'] != null && settings.api_cmds['getmasternodecount'] != '') && (!settings.blockchain_specific.heavycoin.enabled || (!(settings.blockchain_specific.heavycoin.public_apis.getmaxmoney.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getmaxmoney'] != null && settings.blockchain_specific.heavycoin.api_cmds['getmaxmoney'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getmaxvote.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getmaxvote'] != null && settings.blockchain_specific.heavycoin.api_cmds['getmaxvote'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getvote.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getvote'] != null && settings.blockchain_specific.heavycoin.api_cmds['getvote'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getphase.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getphase'] != null && settings.blockchain_specific.heavycoin.api_cmds['getphase'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getreward.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getreward'] != null && settings.blockchain_specific.heavycoin.api_cmds['getreward'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getsupply.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getsupply'] != null && settings.blockchain_specific.heavycoin.api_cmds['getsupply'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getnextrewardestimate.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardestimate'] != null && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardestimate'] != '') && !(settings.blockchain_specific.heavycoin.public_apis.getnextrewardwhenstr.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardwhenstr'] != null && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardwhenstr'] != ''))); - - var hide_ext_api_section = !settings.api_page.public_apis.ext.getmoneysupply.enabled && !settings.api_page.public_apis.ext.getdistribution.enabled && !settings.api_page.public_apis.ext.getaddress.enabled && !settings.api_page.public_apis.ext.getaddresstxs.enabled && !settings.api_page.public_apis.ext.gettx.enabled && !settings.api_page.public_apis.ext.getbalance.enabled && !settings.api_page.public_apis.ext.getlasttxs.enabled && !settings.api_page.public_apis.ext.getcurrentprice.enabled && !settings.api_page.public_apis.ext.getnetworkpeers.enabled && !settings.api_page.public_apis.ext.getbasicstats.enabled && !settings.api_page.public_apis.ext.getsummary.enabled && !(settings.api_page.public_apis.ext.getmasternodelist.enabled && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != '') && !settings.api_page.public_apis.ext.getmasternoderewards.enabled && !settings.api_page.public_apis.ext.getmasternoderewardstotal.enabled; + - var hide_ext_api_section = !settings.api_page.public_apis.ext.getmoneysupply.enabled && !settings.api_page.public_apis.ext.getdistribution.enabled && !settings.api_page.public_apis.ext.getaddress.enabled && !settings.api_page.public_apis.ext.getaddresstxs.enabled && !settings.api_page.public_apis.ext.gettx.enabled && !settings.api_page.public_apis.ext.getbalance.enabled && !settings.api_page.public_apis.ext.getlasttxs.enabled && !settings.api_page.public_apis.ext.getcurrentprice.enabled && !settings.api_page.public_apis.ext.getnetworkpeers.enabled && !settings.api_page.public_apis.ext.getbasicstats.enabled && !settings.api_page.public_apis.ext.getsummary.enabled && !(settings.api_page.public_apis.ext.getmasternodelist.enabled && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != '') && !settings.api_page.public_apis.ext.getmasternoderewards.enabled && !settings.api_page.public_apis.ext.getmasternoderewardstotal.enabled && pluginApisExt.length == 0; - var market_currency = (settings.markets_page.market_price == 'COINGECKO' ? (settings.markets_page.coingecko_currency == null || settings.markets_page.coingecko_currency == '' ? '' : settings.markets_page.coingecko_currency) : (settings.markets_page.default_exchange.trading_pair != null && settings.markets_page.default_exchange.trading_pair.indexOf('/') > -1 ? settings.markets_page.default_exchange.trading_pair.split('/')[1] : '')).toUpperCase(); if !hide_rpc_api_section - h3 #{settings.locale.api_calls} + h3 #{settings.localization.api_calls} p em Return data from coind ul @@ -42,42 +42,42 @@ block content p div.fw-bold getdifficulty div - em #{settings.locale.api_getdifficulty} + em #{settings.localization.api_getdifficulty} a(href='/api/getdifficulty') #{address}/api/getdifficulty if settings.api_page.public_apis.rpc.getconnectioncount.enabled == true && settings.api_cmds['getconnectioncount'] != null && settings.api_cmds['getconnectioncount'] != '' li p div.fw-bold getconnectioncount div - em #{settings.locale.api_getconnectioncount} + em #{settings.localization.api_getconnectioncount} a(href='/api/getconnectioncount') #{address}/api/getconnectioncount if settings.api_page.public_apis.rpc.getblockcount.enabled == true && settings.api_cmds['getblockcount'] != null && settings.api_cmds['getblockcount'] != '' li p div.fw-bold getblockcount div - em #{settings.locale.api_getblockcount} + em #{settings.localization.api_getblockcount} a(href='/api/getblockcount') #{address}/api/getblockcount if settings.api_page.public_apis.rpc.getblockhash.enabled == true && settings.api_cmds['getblockhash'] != null && settings.api_cmds['getblockhash'] != '' li p div.fw-bold getblockhash [index] div - em #{settings.locale.api_getblockhash} + em #{settings.localization.api_getblockhash} a(href='/api/getblockhash?index=' + settings.api_page.sample_data.blockindex) #{address}/api/getblockhash?index=#{settings.api_page.sample_data.blockindex} if settings.api_page.public_apis.rpc.getblock.enabled == true && settings.api_cmds['getblock'] != null && settings.api_cmds['getblock'] != '' li p div.fw-bold getblock [hash] div - em #{settings.locale.api_getblock} + em #{settings.localization.api_getblock} a(href='/api/getblock?hash=' + settings.api_page.sample_data.blockhash) #{address}/api/getblock?hash=#{settings.api_page.sample_data.blockhash} if settings.api_page.public_apis.rpc.getrawtransaction.enabled == true && settings.api_cmds['getrawtransaction'] != null && settings.api_cmds['getrawtransaction'] != '' li p div.fw-bold getrawtransaction [txid] [decrypt] div - em #{settings.locale.api_getrawtransaction} + em #{settings.localization.api_getrawtransaction} div a(href='/api/getrawtransaction?txid=' + settings.api_page.sample_data.txhash + '&decrypt=0') #{address}/api/getrawtransaction?txid=#{settings.api_page.sample_data.txhash}&decrypt=0 div @@ -87,21 +87,21 @@ block content p div.fw-bold getnetworkhashps div - em #{settings.locale.api_getnetworkhashps} + em #{settings.localization.api_getnetworkhashps} a(href='/api/getnetworkhashps') #{address}/api/getnetworkhashps if settings.api_page.public_apis.rpc.getvotelist.enabled == true && settings.api_cmds['getvotelist'] != null && settings.api_cmds['getvotelist'] != '' li p div.fw-bold getvotelist div - em #{settings.locale.api_getvotelist} + em #{settings.localization.api_getvotelist} a(href='/api/getvotelist') #{address}/api/getvotelist if settings.api_page.public_apis.rpc.getmasternodecount.enabled == true && settings.api_cmds['getmasternodecount'] != null && settings.api_cmds['getmasternodecount'] != '' li p div.fw-bold getmasternodecount div - em #{settings.locale.api_getmasternodecount} + em #{settings.localization.api_getmasternodecount} a(href='/api/getmasternodecount') #{address}/api/getmasternodecount if settings.blockchain_specific.heavycoin.enabled == true if settings.blockchain_specific.heavycoin.public_apis.getmaxmoney.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getmaxmoney'] != null && settings.blockchain_specific.heavycoin.api_cmds['getmaxmoney'] != '' @@ -109,56 +109,56 @@ block content p div.fw-bold getmaxmoney div - em #{settings.locale.api_getmaxmoney} + em #{settings.localization.api_getmaxmoney} a(href='/api/getmaxmoney') #{address}/api/getmaxmoney if settings.blockchain_specific.heavycoin.public_apis.getmaxvote.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getmaxvote'] != null && settings.blockchain_specific.heavycoin.api_cmds['getmaxvote'] != '' li p div.fw-bold getmaxvote div - em #{settings.locale.api_getmaxvote} + em #{settings.localization.api_getmaxvote} a(href='/api/getmaxvote') #{address}/api/getmaxvote if settings.blockchain_specific.heavycoin.public_apis.getvote.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getvote'] != null && settings.blockchain_specific.heavycoin.api_cmds['getvote'] != '' li p div.fw-bold getvote div - em #{settings.locale.api_getvote} + em #{settings.localization.api_getvote} a(href='/api/getvote') #{address}/api/getvote if settings.blockchain_specific.heavycoin.public_apis.getphase.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getphase'] != null && settings.blockchain_specific.heavycoin.api_cmds['getphase'] != '' li p div.fw-bold getphase div - em #{settings.locale.api_getphase} + em #{settings.localization.api_getphase} a(href='/api/getphase') #{address}/api/getphase if settings.blockchain_specific.heavycoin.public_apis.getreward.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getreward'] != null && settings.blockchain_specific.heavycoin.api_cmds['getreward'] != '' li p div.fw-bold getreward div - em #{settings.locale.api_getreward} + em #{settings.localization.api_getreward} a(href='/api/getreward') #{address}/api/getreward if settings.blockchain_specific.heavycoin.public_apis.getsupply.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getsupply'] != null && settings.blockchain_specific.heavycoin.api_cmds['getsupply'] != '' li p div.fw-bold getsupply div - em #{settings.locale.api_getsupply} + em #{settings.localization.api_getsupply} a(href='/api/getsupply') #{address}/api/getsupply if settings.blockchain_specific.heavycoin.public_apis.getnextrewardestimate.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardestimate'] != null && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardestimate'] != '' li p div.fw-bold getnextrewardestimate div - em #{settings.locale.api_getnextrewardestimate} + em #{settings.localization.api_getnextrewardestimate} a(href='/api/getnextrewardestimate') #{address}/api/getnextrewardestimate if settings.blockchain_specific.heavycoin.public_apis.getnextrewardwhenstr.enabled == true && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardwhenstr'] != null && settings.blockchain_specific.heavycoin.api_cmds['getnextrewardwhenstr'] != '' li p div.fw-bold getnextrewardwhenstr div - em #{settings.locale.api_getnextrewardwhenstr} + em #{settings.localization.api_getnextrewardwhenstr} a(href='/api/getnextrewardwhenstr') #{address}/api/getnextrewardwhenstr hr if !hide_ext_api_section @@ -251,7 +251,7 @@ block content p div.fw-bold getmasternodelist div - em #{settings.locale.api_getmasternodelist} + em #{settings.localization.api_getmasternodelist} a(href='/ext/getmasternodelist') #{address}/ext/getmasternodelist if settings.api_page.public_apis.ext.getmasternoderewards.enabled == true li @@ -267,6 +267,16 @@ block content div em Returns the total number of coins earned in masternode rewards for address [hash] that arrived after block height [since] a(href='/ext/getmasternoderewardstotal/' + settings.api_page.sample_data.address + '/' + settings.api_page.sample_data.blockindex) #{address}/ext/getmasternoderewardstotal/#{settings.api_page.sample_data.address}/#{settings.api_page.sample_data.blockindex} + each extApi in pluginApisExt + li + p + - var api_path = '' + each apiParam in extApi.api_parameters + - api_path += (api_path == '' ? '/ext/' + extApi.api_name : '') + '/' + apiParam.parameter_name + div.fw-bold #{extApi.api_name}#{(api_path == null || api_path == '' ? '' : ' (' + api_path + ')')} + div + em #{extApi.api_desc} + a(href=extApi.api_url_sample) #{address}#{extApi.api_url_sample} hr h3 Linking (GET) p diff --git a/views/layout.pug b/views/layout.pug index 27ba20f3..f2afd654 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -4,7 +4,7 @@ html(lang='en') meta(charset='UTF-8') meta(name='viewport' content='width=device-width, initial-scale=1') meta(http-equiv='Content-Language', content='en') - title=(page_title_prefix == null || page_title_prefix == '' ? settings.locale.error_title.replace('{1}', settings.coin.name) : page_title_prefix) + ' - ' + settings.shared_pages.page_title + title=(page_title_prefix == null || page_title_prefix == '' ? settings.localization.error_title.replace('{1}', settings.coin.name) : page_title_prefix) + ' - ' + settings.shared_pages.page_title if settings.shared_pages.favicons.favicon32 != '' link(rel='icon', href='/' + settings.shared_pages.favicons.favicon32, sizes='32x32') if settings.shared_pages.favicons.favicon128 != '' @@ -137,12 +137,25 @@ html(lang='en') if settings.blockchain_specific.heavycoin.reward_page.show_difficulty_chart == true - showDifficultyChart = true default - if settings.error_page.show_panels == true - - showPanels = true - if settings.error_page.show_nethash_chart == true - - showNethashChart = true - if settings.error_page.show_difficulty_chart == true - - showDifficultyChart = true + - var found_plugin = false + each plugin in settings.plugins.allowed_plugins + if plugin != null && plugin.enabled == true && plugin.pages != null && plugin.pages.length > 0 + each pg in plugin.pages + if pg.enabled == true && pg.page_id == active + - found_plugin = true + if pg.show_panels == true + - showPanels = true + if pg.show_nethash_chart == true + - showNethashChart = true + if pg.show_difficulty_chart == true + - showDifficultyChart = true + if !found_plugin + if settings.error_page.show_panels == true + - showPanels = true + if settings.error_page.show_nethash_chart == true + - showNethashChart = true + if settings.error_page.show_difficulty_chart == true + - showDifficultyChart = true if active == 'markets' || active == 'richlist' || active == 'reward' || (settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true))) script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js') if active == 'markets' @@ -311,18 +324,18 @@ html(lang='en') } } function getNetworkPanel() { - return '
#{settings.locale.network} ' + getNetHashUnits() + '
'; + return '
#{settings.localization.network} ' + getNetHashUnits() + '
'; } function getDifficultyPanel() { let difficultyType=''; if ('#{settings.shared_pages.difficulty}' == 'Hybrid') difficultyType+='
'; - return '
#{settings.locale.difficulty}
'; + return '
#{settings.localization.difficulty}
'; } function getMasternodesPanel() { - return '
#{settings.locale.masternodecount}
'; + return '
#{settings.localization.masternodecount}
'; } function getCoinSupplyPanel() { - return `
#{settings.locale.ex_supply} (${"#{settings.coin.symbol}".replace(/"/g, '"')})
`; + return `
#{settings.localization.ex_supply} (${"#{settings.coin.symbol}".replace(/"/g, '"')})
`; } function getPricePanel() { return '
Price (#{market_currency})
'; @@ -1150,12 +1163,12 @@ html(lang='en') li#home.nav-item a.nav-link(href='/') span.fa-solid.fa-cubes - span.margin-left-5 #{settings.locale.menu_explorer} + span.margin-left-5 #{settings.localization.menu_explorer} if settings.blockchain_specific.heavycoin.enabled == true && settings.blockchain_specific.heavycoin.reward_page.enabled == true li#reward.nav-item a.nav-link(href='/reward') span.fa-solid.fa-star - span.margin-left-5 #{settings.locale.menu_reward} + span.margin-left-5 #{settings.localization.menu_reward} if settings.masternodes_page.enabled == true li#masternodes.nav-item a.nav-link(href='/masternodes') @@ -1165,23 +1178,23 @@ html(lang='en') li#movement.nav-item a.nav-link(href='/movement') span.fa-regular.fa-money-bill-1 - span.margin-left-5 #{settings.locale.menu_movement} + span.margin-left-5 #{settings.localization.menu_movement} if settings.network_page.enabled == true li#network.nav-item a.nav-link(href='/network') span.fa-solid.fa-network-wired - span.margin-left-5 #{settings.locale.menu_network} + span.margin-left-5 #{settings.localization.menu_network} if settings.richlist_page.enabled == true li#richlist.nav-item a.nav-link(href='/richlist') span.fa-brands.fa-btc - span.margin-left-5 #{settings.locale.menu_richlist} + span.margin-left-5 #{settings.localization.menu_richlist} if settings.markets_page.enabled == true if settings.markets_page.show_market_dropdown_menu == true && settings.market_count > 1 li#markets.dropdown.nav-item a.nav-link.dropdown-toggle(data-bs-toggle='dropdown', href='#') span.fa-solid.fa-chart-line - span.margin-left-5 #{settings.locale.menu_markets} + span.margin-left-5 #{settings.localization.menu_markets} div.navbar(class=dropdownClasses) each mkt in settings.market_data if mkt != null && mkt.id != null @@ -1205,22 +1218,30 @@ html(lang='en') li#markets.nav-item a.nav-link(href='/markets/' + settings.markets_page.default_exchange.exchange_name + '/' + settings.markets_page.default_exchange.trading_pair) span.fa-solid.fa-chart-line - span.margin-left-5 #{settings.locale.menu_markets} + span.margin-left-5 #{settings.localization.menu_markets} if settings.api_page.enabled == true li#info.nav-item a.nav-link(href='/info') span.fa-solid.fa-circle-info - span.margin-left-5 #{settings.locale.menu_api} + span.margin-left-5 #{settings.localization.menu_api} if settings.claim_address_page.show_header_menu == true && settings.claim_address_page.enabled == true li#claim-address.nav-item a.nav-link(href='/claim') span.fa-regular.fa-address-card - span.margin-left-5 #{settings.locale.menu_claim_address} + span.margin-left-5 #{settings.localization.menu_claim_address} if settings.orphans_page.enabled == true li#orphans.nav-item a.nav-link(href='/orphans') span.fa-regular.fa-rectangle-xmark - span.margin-left-5 #{settings.locale.menu_orphans} + span.margin-left-5 #{settings.localization.menu_orphans} + each plugin in settings.plugins.allowed_plugins + if plugin != null && plugin.enabled == true && plugin.pages != null && plugin.pages.length > 0 + each pg in plugin.pages + if pg.enabled == true && pg.show_header_menu == true + li.nav-item(id=pg.page_id) + a.nav-link(href='/' + pg.route_suffix) + span(class=pg.menu_fontawesome_class) + span.margin-left-5=pg.menu_title if settings.shared_pages.page_header.search.enabled == true && settings.shared_pages.page_header.search.position.toString().toLowerCase() == 'inside-header' span#search-header-span(alt='Search', title='Search', data-bs-toggle='tooltip', data-bs-placement='left') button#search-header-button(data-bs-toggle='collapse', data-bs-target='#search-navbar-collapse') @@ -1230,8 +1251,8 @@ html(lang='en') div.navbar-nav.align-items-lg-center.search-box-custom(style='width:100%;') form.form-inline.col-12.d-flex.justify-content-center(method='post', action='/search') div.input-group.input-group-md.search-for(style='width:100%;') - input.form-control(type='text', name='search', placeholder=settings.locale.ex_search_message) - button.btn.btn-success.btn-sm(type='submit') #{settings.locale.ex_search_button} + input.form-control(type='text', name='search', placeholder=settings.localization.ex_search_message) + button.btn.btn-success.btn-sm(type='submit') #{settings.localization.ex_search_button} else header#main-header-side.side-header.navbar(class=headerClasses) div#inner-header-side.navbar.navbar-expand-lg @@ -1254,8 +1275,8 @@ html(lang='en') div.navbar-nav.align-items-lg-center.search-box-custom(style='width:100%;') form.form-inline.col-12.d-flex.justify-content-center(method='post', action='/search') div.input-group.input-group-md.search-for(style='width:100%;') - input.form-control(type='text', name='search', placeholder=settings.locale.ex_search_message) - button.btn.btn-success.btn-sm(type='submit') #{settings.locale.ex_search_button} + input.form-control(type='text', name='search', placeholder=settings.localization.ex_search_message) + button.btn.btn-success.btn-sm(type='submit') #{settings.localization.ex_search_button} div#body-container(class=bodyContainerClasses) if settings.shared_pages.page_header.menu == 'side' div#side-nav-bar.navbar(class=sideBarClasses) @@ -1264,41 +1285,41 @@ html(lang='en') li#sidebar-offcanvas-close.nav-item.text-end a.nav-link.d-inline(href='#', alt='Close Menu', title='Close Menu', data-bs-toggle='tooltip', data-bs-placement='right') span.fa-2xl.fa-regular.fa-rectangle-xmark(type='button', data-bs-dismiss='offcanvas' aria-label='Close') - li#home.nav-item(alt=settings.locale.menu_explorer, title=settings.locale.menu_explorer, data-bs-toggle='tooltip', data-bs-placement='right') + li#home.nav-item(alt=settings.localization.menu_explorer, title=settings.localization.menu_explorer, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/') span.nav-icon.fa-solid.fa-cubes - span.margin-left-5 #{settings.locale.menu_explorer} + span.margin-left-5 #{settings.localization.menu_explorer} if settings.blockchain_specific.heavycoin.enabled == true && settings.blockchain_specific.heavycoin.reward_page.enabled == true - li#reward.nav-item(alt=settings.locale.menu_reward, title=settings.locale.menu_reward, data-bs-toggle='tooltip', data-bs-placement='right') + li#reward.nav-item(alt=settings.localization.menu_reward, title=settings.localization.menu_reward, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/reward') span.nav-icon.fa-solid.fa-star - span.margin-left-5 #{settings.locale.menu_reward} + span.margin-left-5 #{settings.localization.menu_reward} if settings.masternodes_page.enabled == true li#masternodes.nav-item(alt="Masternodes", title="Masternodes", data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/masternodes') span.nav-icon.fa-solid.fa-share-nodes span.margin-left-5 Masternodes if settings.movement_page.enabled == true - li#movement.nav-item(alt=settings.locale.menu_movement, title=settings.locale.menu_movement, data-bs-toggle='tooltip', data-bs-placement='right') + li#movement.nav-item(alt=settings.localization.menu_movement, title=settings.localization.menu_movement, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/movement') span.nav-icon.fa-regular.fa-money-bill-1 - span.margin-left-5 #{settings.locale.menu_movement} + span.margin-left-5 #{settings.localization.menu_movement} if settings.network_page.enabled == true - li#network.nav-item(alt=settings.locale.menu_network, title=settings.locale.menu_network, data-bs-toggle='tooltip', data-bs-placement='right') + li#network.nav-item(alt=settings.localization.menu_network, title=settings.localization.menu_network, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/network') span.nav-icon.fa-solid.fa-network-wired - span.margin-left-5 #{settings.locale.menu_network} + span.margin-left-5 #{settings.localization.menu_network} if settings.richlist_page.enabled == true - li#richlist.nav-item(alt=settings.locale.menu_richlist, title=settings.locale.menu_richlist, data-bs-toggle='tooltip', data-bs-placement='right') + li#richlist.nav-item(alt=settings.localization.menu_richlist, title=settings.localization.menu_richlist, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/richlist') span.nav-icon.fa-brands.fa-btc - span.margin-left-5 #{settings.locale.menu_richlist} + span.margin-left-5 #{settings.localization.menu_richlist} if settings.markets_page.enabled == true if settings.markets_page.show_market_dropdown_menu == true && settings.market_count > 1 - li#markets.dropend.nav-item.side-market-menu(alt=settings.locale.menu_markets, title=settings.locale.menu_markets, data-bs-toggle='tooltip', data-bs-placement='right') + li#markets.dropend.nav-item.side-market-menu(alt=settings.localization.menu_markets, title=settings.localization.menu_markets, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link.dropdown-toggle(href='#') span.nav-icon.fa-solid.fa-chart-line - span.margin-left-5 #{settings.locale.menu_markets} + span.margin-left-5 #{settings.localization.menu_markets} div#side-market-menu.navbar(class=dropdownClasses) each mkt in settings.market_data if mkt != null && mkt.id != null @@ -1319,25 +1340,33 @@ html(lang='en') span #{mkt.name} span.small.fw-normal (#{pair.pair}) else - li#markets.nav-item(alt=settings.locale.menu_markets, title=settings.locale.menu_markets, data-bs-toggle='tooltip', data-bs-placement='right') + li#markets.nav-item(alt=settings.localization.menu_markets, title=settings.localization.menu_markets, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/markets/' + settings.markets_page.default_exchange.exchange_name + '/' + settings.markets_page.default_exchange.trading_pair) span.nav-icon.fa-solid.fa-chart-line - span.margin-left-5 #{settings.locale.menu_markets} + span.margin-left-5 #{settings.localization.menu_markets} if settings.api_page.enabled == true - li#info.nav-item(alt=settings.locale.menu_api, title=settings.locale.menu_api, data-bs-toggle='tooltip', data-bs-placement='right') + li#info.nav-item(alt=settings.localization.menu_api, title=settings.localization.menu_api, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/info') span.nav-icon.fa-solid.fa-circle-info - span.margin-left-5 #{settings.locale.menu_api} + span.margin-left-5 #{settings.localization.menu_api} if settings.claim_address_page.show_header_menu == true && settings.claim_address_page.enabled == true - li#claim-address.nav-item(alt=settings.locale.menu_claim_address, title=settings.locale.menu_claim_address, data-bs-toggle='tooltip', data-bs-placement='right') + li#claim-address.nav-item(alt=settings.localization.menu_claim_address, title=settings.localization.menu_claim_address, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/claim') span.nav-icon.fa-regular.fa-address-card - span.margin-left-5 #{settings.locale.menu_claim_address} + span.margin-left-5 #{settings.localization.menu_claim_address} if settings.orphans_page.enabled == true - li#orphans.nav-item(alt=settings.locale.menu_orphans, title=settings.locale.menu_orphans, data-bs-toggle='tooltip', data-bs-placement='right') + li#orphans.nav-item(alt=settings.localization.menu_orphans, title=settings.localization.menu_orphans, data-bs-toggle='tooltip', data-bs-placement='right') a.nav-link(href='/orphans') span.nav-icon.fa-regular.fa-rectangle-xmark - span.margin-left-5 #{settings.locale.menu_orphans} + span.margin-left-5 #{settings.localization.menu_orphans} + each plugin in settings.plugins.allowed_plugins + if plugin != null && plugin.enabled == true && plugin.pages != null && plugin.pages.length > 0 + each pg in plugin.pages + if pg.enabled == true && pg.show_header_menu == true + li.nav-item(id=pg.page_id, alt=pg.menu_title, title=pg.menu_title, data-bs-toggle='tooltip', data-bs-placement='right') + a.nav-link(href='/' + pg.route_suffix) + span.nav-icon(class=pg.menu_fontawesome_class) + span.margin-left-5=pg.menu_title div#side-offcanvas.offcanvas.offcanvas-start(tabindex='-1') div.offcanvas-body.navbar(class=sideBarClasses) div#main-container(class=mainContainerClasses) @@ -1347,8 +1376,8 @@ html(lang='en') .alert.alert-warning .cardSpacer span.fa-solid.fa-triangle-exclamation(style='margin-right:5px;') - strong #{settings.locale.ex_warning} - div #{settings.locale.initial_index_alert} + strong #{settings.localization.ex_warning} + div #{settings.localization.initial_index_alert} if showPanels == true || (settings.shared_pages.page_header.search.enabled == true && settings.shared_pages.page_header.search.position.toString().toLowerCase() == 'below-header') .col-lg-12 if showPanels == true @@ -1377,8 +1406,8 @@ html(lang='en') div#search-row.row.text-center form.form-inline.col-12.d-flex.justify-content-center(method='post', action='/search') #index-search.form-group.d-flex.justify-content-center - input.form-control(type='text', name='search', placeholder=settings.locale.ex_search_message, style='min-width:80%;margin-right:5px;') - button.btn.btn-success(type='submit') #{settings.locale.ex_search_button} + input.form-control(type='text', name='search', placeholder=settings.localization.ex_search_message, style='min-width:80%;margin-right:5px;') + button.btn.btn-success(type='submit') #{settings.localization.ex_search_button} if settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true)) .container .row.align-items-start diff --git a/views/market.pug b/views/market.pug index 2d4c221f..22b3c2bd 100644 --- a/views/market.pug +++ b/views/market.pug @@ -91,16 +91,16 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.markets_page.page_header.show_title == true - h3#page-title !{settings.locale.mkt_title.replace('{1}', marketdata.market_name + ' (' + marketdata.coin + '/' + marketdata.exchange + ')')} + h3#page-title !{settings.localization.mkt_title.replace('{1}', marketdata.market_name + ' (' + marketdata.coin + '/' + marketdata.exchange + ')')} if settings.markets_page.page_header.show_last_updated == true if settings.markets_page.page_header.show_title != true && settings.markets_page.page_header.show_description != true && (settings.markets_page.page_header.show_exchange_url != true && marketdata.url != null && marketdata.url != '') #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.markets_page.page_header.show_description == true || (settings.markets_page.page_header.show_exchange_url == true && marketdata.url != null && marketdata.url != '') ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.markets_page.page_header.show_exchange_url == true && marketdata.url != null && marketdata.url != '' if settings.markets_page.page_header.show_title != true && settings.markets_page.page_header.show_last_updated != true && settings.markets_page.page_header.show_description != true @@ -117,16 +117,16 @@ block content if settings.markets_page.page_header.show_description == true if settings.markets_page.page_header.show_title != true && settings.markets_page.page_header.show_last_updated != true && (settings.markets_page.page_header.show_exchange_url != true && marketdata.url != null && marketdata.url != '') #page-title-container - .sub-page-header.text-muted=settings.locale.mkt_description.replace('{1}', marketdata.coin + '/' + marketdata.exchange).replace('{2}', marketdata.market_name) + .sub-page-header.text-muted=settings.localization.mkt_description.replace('{1}', marketdata.coin + '/' + marketdata.exchange).replace('{2}', marketdata.market_name) else - .sub-page-header.text-muted=settings.locale.mkt_description.replace('{1}', marketdata.coin + '/' + marketdata.exchange).replace('{2}', marketdata.market_name) + .sub-page-header.text-muted=settings.localization.mkt_description.replace('{1}', marketdata.coin + '/' + marketdata.exchange).replace('{2}', marketdata.market_name) .cardSpacer.clearfix if settings.markets_page.show_market_select == true && settings.market_count > 1 .row .col-md-12.cardSpacer .card.card-default.border-0 .card-header - strong #{settings.locale.mkt_select} + strong #{settings.localization.mkt_select} .card-body ul.nav.nav-pills each mkt in settings.market_data @@ -288,45 +288,45 @@ block content img.align-top.market-logo(src='data:image/png;base64,' + marketdata.market_logo, title=marketdata.market_name + ' Logo', alt=marketdata.market_name + ' Logo') strong #{marketdata.market_name} span.small.fw-normal (#{marketdata.coin}/#{marketdata.exchange}) - strong - #{settings.locale.mkt_hours} + strong - #{settings.localization.mkt_hours} if marketdata.data.chartdata == null || marketdata.data.chartdata == 'null' || marketdata.data.chartdata == '' || marketdata.data.chartdata == '[]' - span.fa-solid.fa-chart-line.float-end.view-chart-disabled.market-toggle(style='cursor: pointer;color: var(--bs-body-color);', data-bs-toggle='tooltip', data-bs-placement='bottom', title=settings.locale.mkt_no_chart) + span.fa-solid.fa-chart-line.float-end.view-chart-disabled.market-toggle(style='cursor: pointer;color: var(--bs-body-color);', data-bs-toggle='tooltip', data-bs-placement='bottom', title=settings.localization.mkt_no_chart) table#market-summary.table.table-bordered.bottom-border-0.summary-table.single-row-table(style='border-top:0;margin-top:0 !important;') thead tr(class=theadClasses) if marketdata.data.summary != null if marketdata.data.summary.high != null - th.text-center #{settings.locale.mkt_high} + th.text-center #{settings.localization.mkt_high} if marketdata.data.summary.low != null - th.text-center #{settings.locale.mkt_low} + th.text-center #{settings.localization.mkt_low} if marketdata.data.summary.volume != null - th.text-center #{settings.locale.mkt_volume} + th.text-center #{settings.localization.mkt_volume} span.small.fw-normal (#{marketdata.coin}) if marketdata.data.summary.volume_btc != null - th.text-center #{settings.locale.mkt_volume} + th.text-center #{settings.localization.mkt_volume} span.small.fw-normal (#{marketdata.exchange}) if marketdata.data.summary.bid != null - th.text-center #{settings.locale.mkt_top_bid} + th.text-center #{settings.localization.mkt_top_bid} if marketdata.data.summary.ask != null - th.text-center #{settings.locale.mkt_top_ask} + th.text-center #{settings.localization.mkt_top_ask} if marketdata.data.summary.last != null - th.text-center #{settings.locale.mkt_last} + th.text-center #{settings.localization.mkt_last} if marketdata.data.summary.prev != null - th.text-center #{settings.locale.mkt_yesterday} + th.text-center #{settings.localization.mkt_yesterday} if marketdata.data.summary.change != null || (marketdata.data.summary.last != null && marketdata.data.summary.prev != null) - th.text-center #{settings.locale.mkt_change} + th.text-center #{settings.localization.mkt_change} else - th.text-center #{settings.locale.mkt_high} - th.text-center #{settings.locale.mkt_low} - th.text-center #{settings.locale.mkt_volume} + th.text-center #{settings.localization.mkt_high} + th.text-center #{settings.localization.mkt_low} + th.text-center #{settings.localization.mkt_volume} span.small.fw-normal (#{marketdata.coin}) - th.text-center #{settings.locale.mkt_volume} + th.text-center #{settings.localization.mkt_volume} span.small.fw-normal (#{marketdata.exchange}) - th.text-center #{settings.locale.mkt_top_bid} - th.text-center #{settings.locale.mkt_top_ask} - th.text-center #{settings.locale.mkt_last} - th.text-center #{settings.locale.mkt_yesterday} - th.text-center #{settings.locale.mkt_change} + th.text-center #{settings.localization.mkt_top_bid} + th.text-center #{settings.localization.mkt_top_ask} + th.text-center #{settings.localization.mkt_last} + th.text-center #{settings.localization.mkt_yesterday} + th.text-center #{settings.localization.mkt_change} tbody tr if marketdata.data.summary != null @@ -410,7 +410,7 @@ block content .card-header if marketdata.market_logo != null && marketdata.market_logo != '' img.align-top.market-logo(src='data:image/png;base64,' + marketdata.market_logo, title=marketdata.market_name + ' Logo', alt=marketdata.market_name + ' Logo') - strong #{marketdata.market_name} - #{marketdata.coin}/#{marketdata.exchange} - #{settings.locale.mkt_hours} + strong #{marketdata.market_name} - #{marketdata.coin}/#{marketdata.exchange} - #{settings.localization.mkt_hours} .card-body canvas#chart(style='height:300px;') .row @@ -419,15 +419,15 @@ block content .card-header(style='border-bottom-width:1px;') if marketdata.market_logo != null && marketdata.market_logo != '' img.align-top.market-logo(src='data:image/png;base64,' + marketdata.market_logo, title=marketdata.market_name + ' Logo', alt=marketdata.market_name + ' Logo') - strong(style='color:var(--bs-body-color)') #{settings.locale.mkt_buy_orders} + strong(style='color:var(--bs-body-color)') #{settings.localization.mkt_buy_orders} table#buy-orders.table.table-striped.table-bordered.table-hover.order-table.bottom-border-0 thead tr(class=theadClasses) - th.text-center #{settings.locale.mkt_price} + th.text-center #{settings.localization.mkt_price} span.small.fw-normal (#{marketdata.exchange}) - th.text-center #{settings.locale.mkt_amount} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{marketdata.coin}) - th.text-center #{settings.locale.mkt_total} + th.text-center #{settings.localization.mkt_total} span.small.fw-normal (#{marketdata.exchange}) tbody if marketdata.data.buys != null @@ -453,15 +453,15 @@ block content .card-header(style='border-bottom-width:1px;') if marketdata.market_logo != null && marketdata.market_logo != '' img.align-top.market-logo(src='data:image/png;base64,' + marketdata.market_logo, title=marketdata.market_name + ' Logo', alt=marketdata.market_name + ' Logo') - strong(style='color:var(--bs-body-color)') #{settings.locale.mkt_sell_orders} + strong(style='color:var(--bs-body-color)') #{settings.localization.mkt_sell_orders} table#sell-orders.table.table-striped.table-bordered.table-hover.order-table.bottom-border-0 thead tr(class=theadClasses) - th.text-center #{settings.locale.mkt_price} + th.text-center #{settings.localization.mkt_price} span.small.fw-normal (#{marketdata.exchange}) - th.text-center #{settings.locale.mkt_amount} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{marketdata.coin}) - th.text-center #{settings.locale.mkt_total} + th.text-center #{settings.localization.mkt_total} span.small.fw-normal (#{marketdata.exchange}) tbody if marketdata.data.sells != null @@ -488,17 +488,17 @@ block content .card-header if marketdata.market_logo != null && marketdata.market_logo != '' img.align-top.market-logo(src='data:image/png;base64,' + marketdata.market_logo, title=marketdata.market_name + ' Logo', alt=marketdata.market_name + ' Logo') - strong #{settings.locale.mkt_trade_history} + strong #{settings.localization.mkt_trade_history} table#history-table.table.table-hover.table-bordered.table-striped.table-paging(cellspacing='0') thead tr(class=theadClasses) - th.text-center #{settings.locale.mkt_price} + th.text-center #{settings.localization.mkt_price} span.small.fw-normal (#{marketdata.exchange}) - th.text-center #{settings.locale.mkt_amount} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{marketdata.coin}) - th.text-center #{settings.locale.mkt_total} + th.text-center #{settings.localization.mkt_total} span.small.fw-normal (#{marketdata.exchange}) - th.text-center #{settings.locale.mkt_time_stamp} + th.text-center #{settings.localization.mkt_time_stamp} tbody if marketdata.data.history != null each order in marketdata.data.history @@ -537,5 +537,5 @@ block content button.btn-close(type='button', data-bs-dismiss='alert') .cardSpacer span.fa-solid.fa-circle-exclamation(style='margin-right:5px') - strong #{marketdata.market_name} #{settings.locale.ex_error} + strong #{marketdata.market_name} #{settings.localization.ex_error} div This market has no data to display. \ No newline at end of file diff --git a/views/masternodes.pug b/views/masternodes.pug index 9017a44a..4a4607db 100644 --- a/views/masternodes.pug +++ b/views/masternodes.pug @@ -200,23 +200,23 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.masternodes_page.page_header.show_title == true - h3#page-title #{settings.locale.mn_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.mn_title.replace('{1}', settings.coin.name)} if settings.masternodes_page.page_header.show_last_updated == true if settings.masternodes_page.page_header.show_title != true && settings.masternodes_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.masternodes_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.masternodes_page.page_header.show_description == true if settings.masternodes_page.page_header.show_title != true && settings.masternodes_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.mn_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.mn_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.mn_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.mn_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header diff --git a/views/movement.pug b/views/movement.pug index 85ccc9be..37d2bce4 100644 --- a/views/movement.pug +++ b/views/movement.pug @@ -69,7 +69,7 @@ block content var amountStr = amountParts[0] + '.' + amountParts[1] + ''; var timestamp = data[5]; //variables for better readability var total = ""; - $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); + $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); $("td:eq(1)", row).html('' + txhash + '').addClass('breakWord d-none d-md-table-cell'); $("td:eq(2)", row).html(total).addClass('text-center'); $("td:eq(3)", row).html('' + format_unixtime(timestamp) + '').addClass('text-center'); @@ -126,23 +126,23 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.movement_page.page_header.show_title == true - h3#page-title #{settings.locale.move_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.move_title.replace('{1}', settings.coin.name)} if settings.movement_page.page_header.show_last_updated == true if settings.movement_page.page_header.show_title != true && settings.movement_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.movement_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.movement_page.page_header.show_description == true if settings.movement_page.page_header.show_title != true && settings.movement_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.move_description.replace('{1}', settings.movement_page.movement_table.min_amount).replace('{2}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.move_description.replace('{1}', settings.movement_page.movement_table.min_amount).replace('{2}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.move_description.replace('{1}', settings.movement_page.movement_table.min_amount).replace('{2}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.move_description.replace('{1}', settings.movement_page.movement_table.min_amount).replace('{2}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header @@ -154,8 +154,8 @@ block content thead tr(class=theadClasses) th.d-table-cell.d-md-none - th.d-none.d-md-table-cell #{settings.locale.tx_hash} - th.text-center #{settings.locale.mkt_amount} + th.d-none.d-md-table-cell #{settings.localization.tx_hash} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.timestamp} + th.text-center #{settings.localization.timestamp} tbody \ No newline at end of file diff --git a/views/network.pug b/views/network.pug index c940af93..167f7a7b 100644 --- a/views/network.pug +++ b/views/network.pug @@ -286,41 +286,41 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.network_page.page_header.show_title == true - h3#page-title #{settings.locale.net_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.net_title.replace('{1}', settings.coin.name)} if settings.network_page.page_header.show_last_updated == true if settings.network_page.page_header.show_title != true && settings.network_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.network_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.network_page.page_header.show_description == true if settings.network_page.page_header.show_title != true && settings.network_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.net_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.net_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.net_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.net_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix ul.nav.nav-tabs(role='tablist') li.nav-item(role='presentation') - a.nav-link.active(href='#connections', aria-controls='connections', role='tab', data-bs-toggle='tab') #{settings.locale.net_connections} + a.nav-link.active(href='#connections', aria-controls='connections', role='tab', data-bs-toggle='tab') #{settings.localization.net_connections} li.nav-item(role='presentation') - a.nav-link(href='#addnodes', aria-controls='addnodes', role='tab', data-bs-toggle='tab') #{settings.locale.net_addnodes} + a.nav-link(href='#addnodes', aria-controls='addnodes', role='tab', data-bs-toggle='tab') #{settings.localization.net_addnodes} .tab-content #connections.container.tab-pane.active(style='margin-top:0;border-top:0;') .card.card-default.border-0 table#connections-table.table.table-bordered.table-striped.table-paging.table-hover.mobile-border-right thead tr(class=theadClasses) - th.text-center #{settings.locale.net_address} + th.text-center #{settings.localization.net_address} if settings.network_page.connections_table.port_filter != '-1' th.text-center='Port' - th.text-center #{settings.locale.net_protocol} - th.text-center #{settings.locale.net_subversion} - th.text-center #{settings.locale.net_country} + th.text-center #{settings.localization.net_protocol} + th.text-center #{settings.localization.net_subversion} + th.text-center #{settings.localization.net_country} tbody.text-center #addnodes.container.tab-pane(style='margin-top:0;border-top:0;') .card.card-default.border-0 diff --git a/views/orphans.pug b/views/orphans.pug index 79ea8f6f..b2643a06 100644 --- a/views/orphans.pug +++ b/views/orphans.pug @@ -47,7 +47,7 @@ block content var good_blockhash = data[2]; var prev_blockhash = data[3]; var next_blockhash = data[4]; - $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); + $("td:eq(0)", row).html('').addClass('text-center d-table-cell d-md-none'); $("td:eq(1)", row).html('' + orphan_blockhash + '').addClass('breakWord d-none d-md-table-cell'); $("td:eq(2)", row).html('' + blockindex.toString() + '').addClass('text-center'); $("td:eq(3)", row).html('' + (blockindex - 1).toString() + '').addClass('text-center'); @@ -88,27 +88,27 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.orphans_page.page_header.show_title == true - h3#page-title #{settings.locale.orphan_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.orphan_title.replace('{1}', settings.coin.name)} if settings.orphans_page.page_header.show_last_updated == true if settings.orphans_page.page_header.show_title != true && settings.orphans_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.orphans_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.orphans_page.page_header.show_description == true if settings.orphans_page.page_header.show_title != true && settings.orphans_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.orphan_description + .sub-page-header.text-muted=settings.localization.orphan_description else - .sub-page-header.text-muted=settings.locale.orphan_description + .sub-page-header.text-muted=settings.localization.orphan_description .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header - strong=settings.locale.orphan_block_list + strong=settings.localization.orphan_block_list table#orphans-table.table.table-bordered.table-striped.table-paging.table-hover.mobile-border-right - var theadClasses = []; if settings.shared_pages.table_header_bgcolor != null && settings.shared_pages.table_header_bgcolor != '' @@ -116,8 +116,8 @@ block content thead tr(class=theadClasses) th.d-table-cell.d-md-none - th.d-none.d-md-table-cell #{settings.locale.orphan_block_hash} - th.text-center #{settings.locale.orphan_actual_block} - th.text-center #{settings.locale.orphan_prev_block} - th.text-center #{settings.locale.orphan_next_block} + th.d-none.d-md-table-cell #{settings.localization.orphan_block_hash} + th.text-center #{settings.localization.orphan_actual_block} + th.text-center #{settings.localization.orphan_prev_block} + th.text-center #{settings.localization.orphan_next_block} tbody \ No newline at end of file diff --git a/views/reward.pug b/views/reward.pug index 7fb43b21..67b2083d 100644 --- a/views/reward.pug +++ b/views/reward.pug @@ -41,27 +41,27 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.blockchain_specific.heavycoin.reward_page.page_header.show_title == true - h3#page-title #{settings.locale.heavy_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.heavy_title.replace('{1}', settings.coin.name)} if settings.blockchain_specific.heavycoin.reward_page.page_header.show_last_updated == true if settings.blockchain_specific.heavycoin.reward_page.page_header.show_title != true && settings.blockchain_specific.heavycoin.reward_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.blockchain_specific.heavycoin.reward_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.blockchain_specific.heavycoin.reward_page.page_header.show_description == true if settings.blockchain_specific.heavycoin.reward_page.page_header.show_title != true && settings.blockchain_specific.heavycoin.reward_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.heavy_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.heavy_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.heavy_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.heavy_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .card.card-default.border-0.card-address-reward .card-header(style='position:relative;') - strong #{settings.locale.heavy_reward_voting_info} + strong #{settings.localization.heavy_reward_voting_info} span.small.fw-normal (#{settings.coin.symbol}) table#reward-summary.table.table-bordered.table-striped.summary-table.single-row-table(style='border-top:0;border-bottom:0;margin-top:0 !important;') - var theadClasses = []; @@ -69,14 +69,14 @@ block content - theadClasses.push('table-' + settings.shared_pages.table_header_bgcolor); thead tr(class=theadClasses) - th.text-center #{settings.locale.ex_supply} + th.text-center #{settings.localization.ex_supply} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.heavy_cap} + th.text-center #{settings.localization.heavy_cap} span.small.fw-normal (#{settings.coin.symbol}) - th.text-center #{settings.locale.heavy_phase} - th.text-center #{settings.locale.heavy_maxvote} - th.text-center #{settings.locale.heavy_reward} - th.text-center #{settings.locale.heavy_estnext} + th.text-center #{settings.localization.heavy_phase} + th.text-center #{settings.localization.heavy_maxvote} + th.text-center #{settings.localization.heavy_reward} + th.text-center #{settings.localization.heavy_estnext} tbody - var supplyValue = Number(heavy.supply).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var splitSupply = supplyValue.split('.'); @@ -128,25 +128,25 @@ block content } }; new Chart(ctx, { type: 'doughnut', data: data, options: options }); - h5 #{settings.locale.heavy_changein} + h5 #{settings.localization.heavy_changein} h5 =heavy.nextin form table.table tbody tr - th #{settings.locale.heavy_key} + th #{settings.localization.heavy_key} td tr - th #{settings.locale.heavy_vote} + th #{settings.localization.heavy_vote} td div(style="width:20px;height:20px;background-color:#428bca") tr - th #{settings.locale.heavy_current} + th #{settings.localization.heavy_current} td div(style="width:20px;height:20px;background-color:#222") tr - th #{settings.locale.heavy_estnext} + th #{settings.localization.heavy_estnext} td div(style="width:20px;height:20px;background-color:rgba(92,184,92,1.0)") .col-md-9 @@ -154,7 +154,7 @@ block content .card-body div.text-center .div - strong #{settings.locale.heavy_lastxvotes} + strong #{settings.localization.heavy_lastxvotes} .div canvas.d-inline(id="lastVotes", width="800", height="300", style="margin-left:-30px;margin-top:30px;max-width:800px;") script. diff --git a/views/richlist.pug b/views/richlist.pug index 99a58d13..91fd11cc 100644 --- a/views/richlist.pug +++ b/views/richlist.pug @@ -73,23 +73,23 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.richlist_page.page_header.show_title == true - h3#page-title #{settings.locale.rl_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.rl_title.replace('{1}', settings.coin.name)} if settings.richlist_page.page_header.show_last_updated == true if settings.richlist_page.page_header.show_title != true && settings.richlist_page.page_header.show_description != true #page-title-container .sub-page-header - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate else .sub-page-header(style='margin-bottom:' + (settings.richlist_page.page_header.show_description == true ? '5' : '0') + 'px') - span.fw-bold=settings.locale.last_updated + ':' + span.fw-bold=settings.localization.last_updated + ':' span.text-muted#lastUpdatedDate if settings.richlist_page.page_header.show_description == true if settings.richlist_page.page_header.show_title != true && settings.richlist_page.page_header.show_last_updated != true #page-title-container - .sub-page-header.text-muted=settings.locale.rl_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.rl_description.replace('{1}', settings.coin.name) else - .sub-page-header.text-muted=settings.locale.rl_description.replace('{1}', settings.coin.name) + .sub-page-header.text-muted=settings.localization.rl_description.replace('{1}', settings.coin.name) .cardSpacer.clearfix .row(style='margin-left:0;margin-right:0;') if settings.richlist_page.show_current_balance == true || settings.richlist_page.show_received_coins == true @@ -98,10 +98,10 @@ block content ul.nav.nav-tabs(role='tablist') if settings.richlist_page.show_current_balance == true li.nav-item(role='presentation') - a(class='nav-link' + (settings.richlist_page.show_current_balance == true ? ' active' : ''), href='#balance', aria-controls='balance', role='tab', data-bs-toggle='tab') #{settings.locale.rl_current_balance} + a(class='nav-link' + (settings.richlist_page.show_current_balance == true ? ' active' : ''), href='#balance', aria-controls='balance', role='tab', data-bs-toggle='tab') #{settings.localization.rl_current_balance} if settings.richlist_page.show_received_coins == true li.nav-item(role='presentation') - a(class='nav-link' + (!settings.richlist_page.show_current_balance ? ' active' : ''), href='#received', aria-controls='received', role='tab', data-bs-toggle='tab') #{settings.locale.rl_received_coins} + a(class='nav-link' + (!settings.richlist_page.show_current_balance ? ' active' : ''), href='#received', aria-controls='received', role='tab', data-bs-toggle='tab') #{settings.localization.rl_received_coins} .tab-content if settings.richlist_page.show_current_balance == true #balance(class='container tab-pane' + (settings.richlist_page.show_current_balance == true ? ' active' : ''), style='margin-top:0;') @@ -111,8 +111,8 @@ block content tr(class=theadClasses) th.text-center span.fa-solid.fa-flag-checkered - th #{settings.locale.tx_address} - th.text-center #{settings.locale.rl_balance} + th #{settings.localization.tx_address} + th.text-center #{settings.localization.rl_balance} span.small.fw-normal (#{settings.coin.symbol}) th.text-center % tbody @@ -144,8 +144,8 @@ block content tr(class=theadClasses) th.text-center span.fa-solid.fa-flag-checkered - th #{settings.locale.tx_address} - th.text-center #{settings.locale.rl_received} + th #{settings.localization.tx_address} + th.text-center #{settings.localization.rl_received} span.small.fw-normal (#{settings.coin.symbol}) tbody - var count = 0; @@ -169,7 +169,7 @@ block content if settings.richlist_page.wealth_distribution.show_distribution_table == true #summary-panel.card.card-default.border-0(style='margin-top:' + (settings.richlist_page.show_current_balance == true || settings.richlist_page.show_received_coins == true ? '34' : '0') + 'px;') .card-header - strong #{settings.locale.rl_wealth} + strong #{settings.localization.rl_wealth} table.table.table-hover.table-bordered.summary-table.right-border-0(style='margin-bottom:0;') thead tr(class=theadClasses) @@ -181,7 +181,7 @@ block content tr td.fw-bold div.float-start.wealth-dist-color-box(style=('background-color:' + settings.richlist_page.wealth_distribution.colors[0] + ';')) - span #{settings.locale.rl_top25} + span #{settings.localization.rl_top25} - var total = Number(dista.total).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = parseFloat(dista.percent).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); @@ -193,7 +193,7 @@ block content tr td.fw-bold div.float-start.wealth-dist-color-box(style=('background-color:' + settings.richlist_page.wealth_distribution.colors[1] + ';')) - span #{settings.locale.rl_top50} + span #{settings.localization.rl_top50} - var total = Number(distb.total).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = parseFloat(distb.percent).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); @@ -205,7 +205,7 @@ block content tr td.fw-bold div.float-start.wealth-dist-color-box(style=('background-color:' + settings.richlist_page.wealth_distribution.colors[2] + ';')) - span #{settings.locale.rl_top75} + span #{settings.localization.rl_top75} - var total = Number(distc.total).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = parseFloat(distc.percent).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); @@ -217,7 +217,7 @@ block content tr td.fw-bold div.float-start.wealth-dist-color-box(style=('background-color:' + settings.richlist_page.wealth_distribution.colors[3] + ';')) - span #{settings.locale.rl_top100} + span #{settings.localization.rl_top100} - var total = Number(distd.total).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = parseFloat(distd.percent).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); @@ -228,7 +228,7 @@ block content span.decimal #{percentParts[1]} tr.text-end td.fw-bold - span #{settings.locale.total_top_100} + span #{settings.localization.total_top_100} - var total = Number(parseFloat(dista.total) + parseFloat(distb.total) + parseFloat(distc.total) + parseFloat(distd.total)).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = (parseFloat(dista.percent)+parseFloat(distb.percent)+parseFloat(distc.percent)+parseFloat(distd.percent)).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); @@ -264,7 +264,7 @@ block content span.decimal #{percentParts[1]} tr.text-end td.fw-bold - span #{settings.locale.total} + span #{settings.localization.total} - var total = Number(parseFloat(dista.total) + parseFloat(distb.total) + parseFloat(distc.total) + parseFloat(distd.total) + parseFloat(diste.total) + (settings.richlist_page.burned_coins.include_burned_coins_in_distribution == true && burned != null && burned > 0 ? burned / 100000000 : 0)).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var totalParts = total.split("."); - var percent = (parseFloat(dista.percent) + parseFloat(distb.percent) + parseFloat(distc.percent) + parseFloat(distd.percent) + parseFloat(diste.percent) + parseFloat((settings.richlist_page.burned_coins.include_burned_coins_in_distribution == true && burned != null && burned > 0 ? ((burned / 100000000) / stats.supply) * 100 : 0))).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':2,'useGrouping':false}); diff --git a/views/tx.pug b/views/tx.pug index 2ddd8960..dc244760 100644 --- a/views/tx.pug +++ b/views/tx.pug @@ -23,7 +23,7 @@ block content button.btn-close(type='button', data-bs-dismiss='alert') .cardSpacer span.fa-solid.fa-triangle-exclamation(style='margin-right:5px') - strong=settings.locale.ex_warning + strong=settings.localization.ex_warning div="This is an orphaned transaction" if settings.transaction_page.page_header.show_img == true || settings.transaction_page.page_header.show_title == true || settings.transaction_page.page_header.show_description == true #page-header-container(style='align-items:' + (settings.transaction_page.page_header.show_img == true && settings.transaction_page.page_header.show_title == true && settings.transaction_page.page_header.show_description == true ? 'flex-start' : 'center')) @@ -32,35 +32,35 @@ block content img#header-img(src=(settings.shared_pages.page_header.page_title_image == null || settings.shared_pages.page_header.page_title_image.image_path == null || settings.shared_pages.page_header.page_title_image.image_path == '' ? '/img/page-title-img.png' : settings.shared_pages.page_header.page_title_image.image_path)) #page-title-container if settings.transaction_page.page_header.show_title == true - h3#page-title #{settings.locale.tx_title.replace('{1}', settings.coin.name)} + h3#page-title #{settings.localization.tx_title.replace('{1}', settings.coin.name)} if settings.transaction_page.page_header.show_description == true if settings.transaction_page.page_header.show_title != true #page-title-container - .sub-page-header.text-muted=settings.locale.tx_description.replace('{1}', settings.coin.name).replace('{2}', tx.blockindex) + .sub-page-header.text-muted=settings.localization.tx_description.replace('{1}', settings.coin.name).replace('{2}', tx.blockindex) else - .sub-page-header.text-muted=settings.locale.tx_description.replace('{1}', settings.coin.name).replace('{2}', tx.blockindex) + .sub-page-header.text-muted=settings.localization.tx_description.replace('{1}', settings.coin.name).replace('{2}', tx.blockindex) .cardSpacer.clearfix .card.card-default.border-0.cardSpacer .card-header - strong=settings.locale.tx_hash + ': ' + tx.txid + strong=settings.localization.tx_hash + ': ' + tx.txid if settings.api_page.public_apis.rpc.getrawtransaction.enabled == true a.d-none.d-md-inline(href=`/api/getrawtransaction?txid=${tx.txid}&decrypt=1`, style='color: var(--bs-body-color);') - span.fa-solid.fa-circle-info.float-end(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.view_raw_tx_data) + span.fa-solid.fa-circle-info.float-end(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.view_raw_tx_data) table#tx-table.table.table-bordered.table-striped.summary-table.mobile-border-right thead tr(class=theadClasses) th.text-center.d-table-cell.d-md-none - th.d-none.d-md-table-cell #{settings.locale.tx_block_hash} + th.d-none.d-md-table-cell #{settings.localization.tx_block_hash} if settings.transaction_page.show_op_return == true th='OP_RETURN' - th.text-center #{settings.locale.confirmations} - th.text-center #{settings.locale.timestamp} + th.text-center #{settings.localization.confirmations} + th.text-center #{settings.localization.timestamp} tbody - var confirms = (blockcount - tx.blockindex + 1); tr td.text-center.d-table-cell.d-md-none a(href='/block/' + tx.blockhash) - span.fa-regular.fa-eye(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.locale.view_block) + span.fa-regular.fa-eye(data-bs-toggle='tooltip', data-bs-placement='top', title=settings.localization.view_block) td.d-none.d-md-table-cell a.breakWord(href='/block/' + tx.blockhash) #{tx.blockhash} if settings.transaction_page.show_op_return == true @@ -75,28 +75,28 @@ block content span#timestampCol if tx.vout.length < 1 .alert.alert-info.text-center(role='alert', style='margin-bottom:0;') - strong #{settings.locale.tx_nonstandard} + strong #{settings.localization.tx_nonstandard} else .row .col-md-6.cardSpacer .card.card-default.border-0 .card-header - strong #{settings.locale.tx_contributors} + strong #{settings.localization.tx_contributors} span.fa-solid.fa-arrow-right.float-end.d-none.d-md-block table.table.table-bordered.table-striped.table-hover.summary-table.mobile-border-right thead tr(class=theadClasses) - th #{settings.locale.tx_address} + th #{settings.localization.tx_address} if (tx.vin.length > 0) if tx.vin[0].addresses != 'coinbase' - th.text-center #{settings.locale.mkt_amount} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) tbody if tx.vin.length > 0 each address in tx.vin if address.addresses == 'coinbase' tr.table-info.text-center - td #{settings.locale.new_coins} + td #{settings.localization.new_coins} else - var ramount = Number(address.amount / 100000000).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var ramountParts = ramount.split('.'); @@ -112,29 +112,29 @@ block content else if address.addresses == 'hidden_address' if settings.address_page.enable_hidden_address_view == true a.breakWord(href='/address/hidden_address') - =settings.locale.hidden_sender + =settings.localization.hidden_sender else - =settings.locale.hidden_sender + =settings.localization.hidden_sender else if settings.address_page.enable_unknown_address_view == true a.breakWord(href='/address/unknown_address') - =settings.locale.unknown_sender + =settings.localization.unknown_sender else - =settings.locale.unknown_sender + =settings.localization.unknown_sender td.table-danger.text-center #{ramountParts[0]}. span.decimal #{ramountParts[1]} else tr.table-info.text-center - td.bottom-border-1 #{settings.locale.proof_of_stake} + td.bottom-border-1 #{settings.localization.proof_of_stake} .col-md-6.cardSpacer .card.card-default.border-0 .card-header - strong #{settings.locale.tx_recipients} + strong #{settings.localization.tx_recipients} table.table.table-bordered.table-striped.table-hover.summary-table.mobile-border-right thead tr(class=theadClasses) - th #{settings.locale.tx_address} - th.text-center #{settings.locale.mkt_amount} + th #{settings.localization.tx_address} + th.text-center #{settings.localization.mkt_amount} span.small.fw-normal (#{settings.coin.symbol}) tbody each address in tx.vout @@ -157,15 +157,15 @@ block content if address.addresses == 'hidden_address' if settings.address_page.enable_hidden_address_view == true a.breakWord(href='/address/hidden_address') - =settings.locale.hidden_recipient + =settings.localization.hidden_recipient else - =settings.locale.hidden_recipient + =settings.localization.hidden_recipient else if settings.address_page.enable_unknown_address_view == true a.breakWord(href='/address/unknown_address') - =settings.locale.unknown_recipient + =settings.localization.unknown_recipient else - =settings.locale.unknown_recipient + =settings.localization.unknown_recipient td.table-success.text-center #{ramountParts[0]}. span.decimal #{ramountParts[1]} else @@ -173,15 +173,15 @@ block content if address.addresses == 'hidden_address' if settings.address_page.enable_hidden_address_view == true a.breakWord(href='/address/hidden_address') - =settings.locale.hidden_recipient + =settings.localization.hidden_recipient else - =settings.locale.hidden_recipient + =settings.localization.hidden_recipient else if settings.address_page.enable_unknown_address_view == true a.breakWord(href='/address/unknown_address') - =settings.locale.unknown_recipient + =settings.localization.unknown_recipient else - =settings.locale.unknown_recipient + =settings.localization.unknown_recipient else - var ramount = Number(address.amount / 100000000).toLocaleString('en',{'minimumFractionDigits':2,'maximumFractionDigits':8,'useGrouping':true}); - var ramountParts = ramount.split('.');