+ Mailtrain – {{#translate}}the best newsletter app{{/translate}} +
+``` + +### Managing Translations + +* Translations are loaded from Gettext MO files. In order to generate such files you need a Gettext translations editor. [POEdit](https://poedit.net/) is a great choice. + +* To create the translation catalog run `grunt` from command line. This fetches all translatable strings from JavaScript and Handlebars files and merges these into the translation catalog located at */languages/mailtrain.pot* + +* To add a new language use this catalog file as a source. Once you want to update your translation file from the updated catalog, select "Catalogue" -> "Update from POT file..." in POEdit and select mailtrain.pot. This will merge all the new translations from the POT file to your PO file. + + *If you have saved the PO file in [./languages](./languages) then POEdit should auto generate required MO file whenever you hit save for the PO file. + +* Once you have a correct MO file in the languages folder, edit Mailtrain config and set ["language" option](https://github.com/Mailtrain-org/mailtrain/blob/ba8bd1212335cb9bd7ba094beb7b5400f35cae6c/config/default.toml#L30-L31) to your language name. If the value is "et" then Mailtrain loads translations from ./languages/et.mo + +> **NB!** For now translation settings are global, so if you have set a translation in config then this applies to all users. An user can't select another translation than the default even if there is a translation file. This is because current Mailtrain code does not provide request context to functions and the functions generating strings do not know which language to use. + +## License + + * Versions 1.22.0 and up **GPL-V3.0** + * Versions 1.21.0 and up: **EUPL-1.1** + * Versions 1.19.0 and up: **MIT** + * Up to versions 1.18.0 **GPL-V3.0** diff --git a/index.js b/index.js index 565119fa..9428aaf4 100644 --- a/index.js +++ b/index.js @@ -4,15 +4,25 @@ * Module dependencies. */ -let config = require('config'); -let log = require('npmlog'); -let app = require('./app'); -let http = require('http'); -let sender = require('./services/sender'); -let importer = require('./services/importer'); -let verpServer = require('./services/verp-server'); -let testServer = require('./services/test-server'); -let dbcheck = require('./lib/dbcheck'); +const config = require('config'); +const log = require('npmlog'); +const app = require('./app'); +const http = require('http'); +const https = require('https'); +const fs = require('fs'); +const fork = require('child_process').fork; +const triggers = require('./services/triggers'); +const importer = require('./services/importer'); +const verpServer = require('./services/verp-server'); +const testServer = require('./services/test-server'); +const postfixBounceServer = require('./services/postfix-bounce-server'); +const tzupdate = require('./services/tzupdate'); +const feedcheck = require('./services/feedcheck'); +const dbcheck = require('./lib/dbcheck'); +const tools = require('./lib/tools'); +const reportProcessor = require('./lib/report-processor'); +const executor = require('./lib/executor'); +const privilegeHelpers = require('./lib/privilege-helpers'); let port = config.www.port; let host = config.www.host; @@ -25,11 +35,15 @@ log.level = config.log.level; app.set('port', port); /** - * Create HTTP server. + * Create HTTP/HTTPS server. */ -let server = http.createServer(app); - +let server = (!config.www.https) ? http.createServer(app) : https.createServer({ + cert: fs.readFileSync(config.www.cert), + key: fs.readFileSync(config.www.key), + ca: config.www.ca ? fs.readFileSync(config.www.ca) : undefined, + dhparams: config.www.dhparams ? fs.readFileSync(config.www.dhparams) : undefined +}, app); // Check if database needs upgrading before starting the server dbcheck(err => { @@ -64,35 +78,78 @@ server.on('error', err => { } }); +function spawnSenders(callback) { + let processes = Math.max(Number(config.queue.processes) || 1, 1); + let spawned = 0; + let returned = false; + + if (processes > 1 && !config.redis.enabled) { + log.error('Queue', '%s processes requested but Redis is not enabled, spawning 1 process', processes); + processes = 1; + } + + let spawnSender = function () { + if (spawned >= processes) { + if (!returned) { + returned = true; + return callback(); + } + return false; + } + + let child = fork(__dirname + '/services/sender.js', []); + let pid = child.pid; + tools.workers.add(child); + + child.on('close', (code, signal) => { + spawned--; + tools.workers.delete(child); + log.error('Child', 'Sender process %s exited with %s', pid, code || signal); + // Respawn after 5 seconds + setTimeout(() => spawnSender(), 5 * 1000).unref(); + }); + + spawned++; + setImmediate(spawnSender); + }; + + spawnSender(); +} + server.on('listening', () => { let addr = server.address(); let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; log.info('Express', 'WWW server listening on %s', bind); // start additional services - testServer(() => { - verpServer(() => { - importer(() => { - sender(() => { - log.info('Service', 'All services started'); - if (config.group) { - try { - process.setgid(config.group); - log.info('Service', 'Changed group to "%s" (%s)', config.group, process.getgid()); - } catch (E) { - log.info('Service', 'Failed changed group to "%s"', config.group); - } - } - if (config.user) { - try { - process.setuid(config.user); - log.info('Service', 'Changed user to "%s" (%s)', config.user, process.getuid()); - } catch (E) { - log.info('Service', 'Failed changed user to "%s"', config.user); - } - } + function startNextServices() { + testServer(() => { + verpServer(() => { + + privilegeHelpers.dropRootPrivileges(); + + tzupdate(() => { + importer(() => { + triggers(() => { + spawnSenders(() => { + feedcheck(() => { + postfixBounceServer(() => { + reportProcessor.init(() => { + log.info('Service', 'All services started'); + }); + }); + }); + }); + }); + }); }); }); }); - }); + } + + if (config.reports && config.reports.enabled === true) { + executor.spawn(startNextServices); + } else { + startNextServices(); + } }); diff --git a/languages/de_DE.mo b/languages/de_DE.mo new file mode 100644 index 00000000..419808d4 Binary files /dev/null and b/languages/de_DE.mo differ diff --git a/languages/de_DE.po b/languages/de_DE.po new file mode 100644 index 00000000..b5f10985 --- /dev/null +++ b/languages/de_DE.po @@ -0,0 +1,4700 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-04 00:45+0200\n" +"PO-Revision-Date: 2018-03-07 14:12+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: views/archive/layout.hbs:1 views/layout.hbs:1 +msgid "Self hosted email newsletter app" +msgstr "Selbst gehostete Newsletter-App" + +#: views/blacklist.hbs:1 views/campaigns/blacklisted.hbs:1 +#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1 +#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1 +#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1 +#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1 +#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1 +#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1 +#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1 +#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1 +#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1 +#: views/lists/fields/fields.hbs:1 views/lists/forms/create.hbs:1 +#: views/lists/forms/edit.hbs:1 views/lists/forms/forms.hbs:1 +#: views/lists/lists.hbs:1 views/lists/segments/create.hbs:1 +#: views/lists/segments/edit.hbs:1 views/lists/segments/rule-configure.hbs:1 +#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1 +#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1 +#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1 +#: views/lists/subscription/import-failed.hbs:1 +#: views/lists/subscription/import-preview.hbs:1 +#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1 +#: views/report-templates/create.hbs:1 views/report-templates/edit.hbs:1 +#: views/report-templates/report-templates.hbs:1 +#: views/reports/create-select-template.hbs:1 views/reports/create.hbs:1 +#: views/reports/edit.hbs:1 views/reports/output.hbs:1 +#: views/reports/reports.hbs:1 views/reports/view.hbs:1 views/settings.hbs:1 +#: views/templates/create.hbs:1 views/templates/edit.hbs:1 +#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1 +#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1 +#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1 +#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1 +#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169 +msgid "Home" +msgstr "Home" + +#: views/blacklist.hbs:2 views/blacklist.hbs:3 views/layout.hbs:7 +#: views/lists/subscription/edit.hbs:15 +msgid "Blacklist" +msgstr "Blacklist" + +#: views/blacklist.hbs:4 views/users/api.hbs:55 +msgid "Add email to blacklist" +msgstr "E-Mail Adresse zur Blacklist hinzufügen" + +#: views/blacklist.hbs:5 +msgid "Add" +msgstr "Hinzufügen" + +#: views/blacklist.hbs:6 +msgid "Email" +msgstr "E-Mail" + +#: views/campaigns/blacklisted.hbs:2 views/campaigns/bounced.hbs:2 +#: views/campaigns/campaigns.hbs:2 views/campaigns/campaigns.hbs:7 +#: views/campaigns/clicked.hbs:2 views/campaigns/complained.hbs:2 +#: views/campaigns/create-rss.hbs:2 views/campaigns/create-triggered.hbs:2 +#: views/campaigns/create.hbs:2 views/campaigns/delivered.hbs:2 +#: views/campaigns/edit-rss.hbs:2 views/campaigns/edit-triggered.hbs:2 +#: views/campaigns/edit.hbs:2 views/campaigns/opened.hbs:2 +#: views/campaigns/unsubscribed.hbs:2 views/campaigns/upload-attachment.hbs:2 +#: views/campaigns/view.hbs:2 lib/tools.js:126 routes/campaigns.js:35 +msgid "Campaigns" +msgstr "Kampagnen" + +#: views/campaigns/blacklisted.hbs:3 views/campaigns/blacklisted.hbs:4 +msgid "Blacklisted info" +msgstr "Blacklisted info" + +#: views/campaigns/blacklisted.hbs:5 views/campaigns/bounced.hbs:5 +#: views/campaigns/clicked.hbs:5 views/campaigns/complained.hbs:5 +#: views/campaigns/delivered.hbs:5 views/campaigns/edit-rss.hbs:5 +#: views/campaigns/edit-triggered.hbs:5 views/campaigns/edit.hbs:5 +#: views/campaigns/opened.hbs:5 views/campaigns/unsubscribed.hbs:5 +#: views/campaigns/upload-attachment.hbs:6 +msgid "View campaign" +msgstr "Kampagne ansehen" + +#: views/campaigns/blacklisted.hbs:6 +msgid "Subscribers who blacklisted by global blacklist:" +msgstr "Abonnenten, die von der globalen Blacklist aufgelistet wurden:" + +#: views/campaigns/blacklisted.hbs:7 views/campaigns/bounced.hbs:7 +#: views/campaigns/clicked.hbs:15 views/campaigns/complained.hbs:7 +#: views/campaigns/delivered.hbs:7 views/campaigns/opened.hbs:9 +#: views/campaigns/unsubscribed.hbs:7 +#: views/lists/subscription/import-failed.hbs:8 views/lists/view.hbs:19 +#: views/triggers/triggered.hbs:6 +msgid "Address" +msgstr "Adresse" + +#: views/campaigns/blacklisted.hbs:8 views/campaigns/bounced.hbs:8 +#: views/campaigns/clicked.hbs:16 views/campaigns/complained.hbs:8 +#: views/campaigns/delivered.hbs:8 views/campaigns/opened.hbs:10 +#: views/campaigns/unsubscribed.hbs:8 views/lists/subscription/add.hbs:6 +#: views/lists/subscription/edit.hbs:7 +#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:20 +#: views/subscription/partials/subscription-custom-fields.hbs:3 +#: views/triggers/triggered.hbs:7 +msgid "First Name" +msgstr "Vorname" + +#: views/campaigns/blacklisted.hbs:9 views/campaigns/bounced.hbs:9 +#: views/campaigns/clicked.hbs:17 views/campaigns/complained.hbs:9 +#: views/campaigns/delivered.hbs:9 views/campaigns/opened.hbs:11 +#: views/campaigns/unsubscribed.hbs:9 views/lists/subscription/add.hbs:7 +#: views/lists/subscription/edit.hbs:8 +#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:21 +#: views/subscription/partials/subscription-custom-fields.hbs:4 +#: views/triggers/triggered.hbs:8 +msgid "Last Name" +msgstr "Nachname" + +#: views/campaigns/blacklisted.hbs:10 +msgid "Reason" +msgstr "Grund" + +#: views/campaigns/blacklisted.hbs:11 +msgid "Time" +msgstr "Zeit" + +#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4 +msgid "Bounced info" +msgstr "Bounced Info" + +#: views/campaigns/bounced.hbs:6 +msgid "Subscribers who bounced and were unsubscribed:" +msgstr "Abonnenten, die bounced und abgemeldet wurden:" + +#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10 +#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10 +msgid "SMTP response" +msgstr "SMTP Antwort" + +#: views/campaigns/bounced.hbs:11 +msgid "Bounce time" +msgstr "Bounce Zeitpunkt" + +#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:25 +#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4 +#: views/campaigns/create.hbs:27 +msgid "Create Campaign" +msgstr "Kampagne erstellen" + +#: views/campaigns/campaigns.hbs:4 +msgid "Regular Campaign" +msgstr "Normale Kampagne" + +#: views/campaigns/campaigns.hbs:5 +msgid "RSS Campaign" +msgstr "RSS-Kampagne" + +#: views/campaigns/campaigns.hbs:6 +msgid "Triggered Campaign" +msgstr "Trigger-Kampagne" + +#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6 +#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5 +#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9 +#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:73 +#: views/lists/create.hbs:5 views/lists/edit.hbs:6 +#: views/lists/fields/fields.hbs:6 views/lists/forms/forms.hbs:6 +#: views/lists/lists.hbs:5 views/lists/segments/segments.hbs:6 +#: views/report-templates/partials/report-template-fields.hbs:1 +#: views/report-templates/report-templates.hbs:10 +#: views/reports/partials/report-fields.hbs:1 +#: views/reports/partials/report-fields.hbs:5 +#: views/reports/partials/report-fields.hbs:9 views/reports/reports.hbs:6 +#: views/templates/templates.hbs:5 views/triggers/triggers.hbs:5 +msgid "Name" +msgstr "Name" + +#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8 +#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7 +#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11 +#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:74 +#: views/lists/create.hbs:7 views/lists/edit.hbs:10 +#: views/lists/forms/edit.hbs:9 views/lists/forms/forms.hbs:7 +#: views/lists/lists.hbs:8 views/mosaico/editor.hbs:3 +#: views/partials/merge-tag-reference.hbs:4 +#: views/report-templates/partials/report-template-fields.hbs:3 +#: views/report-templates/report-templates.hbs:11 +#: views/reports/partials/report-fields.hbs:3 +#: views/reports/partials/report-fields.hbs:6 views/reports/reports.hbs:8 +#: views/templates/create.hbs:9 views/templates/edit.hbs:8 +#: views/templates/templates.hbs:6 views/triggers/create.hbs:7 +#: views/triggers/edit.hbs:8 views/triggers/triggers.hbs:7 +msgid "Description" +msgstr "Beschreibung" + +#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:75 +#: views/lists/view.hbs:22 views/lists/view.hbs:30 +#: views/triggers/triggers.hbs:6 +msgid "Status" +msgstr "Status" + +#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:76 +#: views/lists/view.hbs:23 views/lists/view.hbs:24 +#: views/report-templates/report-templates.hbs:12 +#: views/reports/partials/report-fields.hbs:7 views/reports/reports.hbs:9 +msgid "Created" +msgstr "Erstellt" + +#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4 +msgid "Link info" +msgstr "Link Info" + +#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:63 +msgid "URL" +msgstr "URL" + +#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:64 +msgid "Clicks" +msgstr "Klicks" + +#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:65 +msgid "% of clicks" +msgstr "% der Klicks" + +#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:66 +msgid "% of messages" +msgstr "% der Nachrichten" + +#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:69 +msgid "Aggregated clicks" +msgstr "Aggregierte Klicks" + +#: views/campaigns/clicked.hbs:11 +msgid "Subscribers who clicked on a link:" +msgstr "Abonnenten welche einen Link geklickt haben:" + +#: views/campaigns/clicked.hbs:12 +msgid "Subscribers who clicked on this link:" +msgstr "Abonnenten welche diesen Link geklickt haben:" + +#: views/campaigns/clicked.hbs:13 views/campaigns/opened.hbs:7 +msgid "Stats by country" +msgstr "Statistik: Land" + +#: views/campaigns/clicked.hbs:14 views/campaigns/opened.hbs:8 +msgid "Stats by device type" +msgstr "Statistik: Gerätetyp" + +#: views/campaigns/clicked.hbs:18 +msgid "First click time" +msgstr "Erste Klickzeit" + +#: views/campaigns/clicked.hbs:19 +msgid "Click count" +msgstr "Anzahl Klicks" + +#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4 +msgid "Complained info" +msgstr "Beschwerde Info" + +#: views/campaigns/complained.hbs:6 +msgid "Subscribers who complained and were unsubscribed:" +msgstr "Abonnenten welche sich beschwert haben und deabonniert wurden:" + +#: views/campaigns/complained.hbs:11 +msgid "Complain time" +msgstr "Zeitpunkt der Beschwerde" + +#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4 +#: views/campaigns/create-rss.hbs:20 +msgid "Create RSS Campaign" +msgstr "RSS-Kampagne erstellen" + +#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6 +msgid "" +"RSS campaign sets up a tracker against selected RSS feed address. Whenever a " +"new entry is found from this feed it is sent to selected list as an email " +"message." +msgstr "" +"Eine RSS-Kampagne setzt einen Tracker auf den gewählten RSS-Feed. Wenn ein " +"neuer Eintrag in diesem Feed gefunden wird, wird er als E-Mail an die " +"ausgewählte Liste gesendet." + +#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6 +#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9 +#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11 +msgid "Campaign Name" +msgstr "Kampagnen Name" + +#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8 +#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11 +#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13 +#: views/lists/create.hbs:8 views/lists/edit.hbs:11 +#: views/report-templates/partials/report-template-fields.hbs:4 +#: views/reports/partials/report-fields.hbs:4 views/templates/create.hbs:11 +#: views/templates/edit.hbs:10 views/triggers/create.hbs:9 +#: views/triggers/edit.hbs:10 +msgid "HTML is allowed" +msgstr "HTML ist erlaubt" + +#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9 +#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12 +#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14 +#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6 +#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12 +#: views/triggers/triggers.hbs:8 +msgid "List" +msgstr "Liste" + +#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10 +#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:10 +#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13 +#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15 +#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28 +#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10 +#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10 +#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11 +#: views/lists/subscription/import-preview.hbs:5 +#: views/reports/partials/report-select-template.hbs:2 +#: views/subscription/partials/subscription-custom-fields.hbs:9 +#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7 +#: views/triggers/create.hbs:17 views/triggers/create.hbs:20 +#: views/triggers/create.hbs:22 views/triggers/create.hbs:26 +#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22 +#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28 +msgid "Select" +msgstr "Bitte wählen" + +#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11 +#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14 +#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16 +#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11 +#: views/triggers/edit.hbs:13 +msgid "subscribers" +msgstr "Abonnenten" + +#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15 +msgid "RSS Feed Url" +msgstr "RSS Feed URL" + +#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16 +msgid "" +"New entries from this RSS URL are sent out to list subscribers as email " +"messages" +msgstr "" +"Neue Beiträge dieser RSS URL werden den Abonnenten als E-Mail-Nachrichten " +"zugestellt" + +#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:18 +#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18 +#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17 +#: views/campaigns/view.hbs:12 +msgid "Email \"from name\"" +msgstr "E-Mail \"von Name\"" + +#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:19 +#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19 +#: views/campaigns/edit-triggered.hbs:17 views/campaigns/edit.hbs:18 +#: views/settings.hbs:23 +msgid "This is the name your emails will come from" +msgstr "Dies ist der Absendername Ihrer E-Mails" + +#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:20 +#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20 +#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19 +#: views/campaigns/view.hbs:13 +msgid "Email \"from\" address" +msgstr "E-Mail \"von Adresse\"" + +#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:21 +#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19 +#: views/settings.hbs:25 +msgid "This is the address people will send replies to" +msgstr "Dies ist die Reply-To Adresse" + +#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:24 +#: views/campaigns/create.hbs:28 views/campaigns/edit-rss.hbs:22 +#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:27 +msgid "Disable opened tracking" +msgstr "Deaktiviere das Tracking beim Öffnen der E-Mail (Zählpixel)" + +#: views/campaigns/create-rss.hbs:20 views/campaigns/create-triggered.hbs:25 +#: views/campaigns/create.hbs:29 views/campaigns/edit-rss.hbs:23 +#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:28 +msgid "Disable clicked tracking" +msgstr "Deaktiviere das Tracking beim Klicken von Links" + +#: views/campaigns/create-triggered.hbs:3 +#: views/campaigns/create-triggered.hbs:4 +msgid "Create Triggered Campaign" +msgstr "Trigger-Kampagne erstellen" + +#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12 +#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7 +#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33 +#: views/reports/reports.hbs:7 views/templates/create.hbs:13 +msgid "Template" +msgstr "Vorlage" + +#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:13 +msgid "Select a template:" +msgstr "Vorlage auswählen:" + +#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:15 +msgid "Selecting a template creates a campaign specific copy from it" +msgstr "" +"Wenn Sie eine Vorlage auswählen, wird eine Kopie nur für diese Kampagne erstellt" + +#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:16 +msgid "Or alternatively use an URL as the message content source:" +msgstr "" +"Oder alternativ können Sie eine URL als Quelle für den E-Mail Inhalt verwenden:" + +#: views/campaigns/create-triggered.hbs:17 views/campaigns/create.hbs:17 +#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28 +msgid "" +"If a message is sent then this URL will be POSTed to using Merge Tags as " +"POST body. Use this if you want to generate the HTML message yourself" +msgstr "" +"Wenn eine Nachricht gesendet wird, wird diese URL per POST Request " +"aufgerufen mit den Merge-Tags als POST-Body. Verwenden Sie diese Funktion, " +"wenn Sie die HTML-Nachricht selbst generieren möchten" + +#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:24 +#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23 +#: views/campaigns/view.hbs:15 +msgid "Email \"subject line\"" +msgstr "E-Mail Betreffzeile" + +#: views/campaigns/create-triggered.hbs:23 views/campaigns/create.hbs:25 +#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24 +#: views/settings.hbs:27 +msgid "Keep it relevant and non-spammy" +msgstr "Halten Sie den Inhalt relevant und frei von Spam" + +#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20 +msgid "" +"This is the address people will send replies to unless reply-to address is " +"set" +msgstr "" +"Dies ist die Adresse, an welche Antworten gesendet werden, ausser die " +"Kampagnenspezifische \"reply-to\" Adresse ist definiert" + +#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21 +#: views/campaigns/view.hbs:14 +msgid "Email \"reply-to\" address" +msgstr "E-Mail \"reply-to\" Adresse" + +#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22 +msgid "If set, this is the address people will send replies to" +msgstr "" +"Falls gesetzt, ist dies die Adresse an welche E-Mail-Antworten gesendet " +"werden" + +#: views/campaigns/create.hbs:26 views/campaigns/edit.hbs:25 +msgid "Custom unsubscribe (URL)" +msgstr "Benutzerdefiniertes Deabonnement (URL)" + +#: views/campaigns/create.hbs:27 views/campaigns/edit.hbs:26 +msgid "Set a custom unsubscribe url" +msgstr "Geben Sie eine eigene URL an, die den Abonnenten zum Abmelden angezeigt wird" + +#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4 +msgid "Delivered info" +msgstr "Zustellungs Info" + +#: views/campaigns/delivered.hbs:6 +msgid "Subscribers who received the message and did not bounce/unsubscribe:" +msgstr "" +"Abonnenten, welche die Nachricht erfolgreich erhalten (kein \"bounce\") und " +"nicht deabonniert haben:" + +#: views/campaigns/delivered.hbs:11 +msgid "Delivery time" +msgstr "Zugestellt am" + +#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4 +msgid "Edit RSS Campaign" +msgstr "RSS-Kampagne bearbeiten" + +#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8 +#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6 +msgid "General Settings" +msgstr "Allgemeine Einstellungen" + +#: views/campaigns/edit-rss.hbs:17 +msgid "" +"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post " +"content. Additionally you can use any valid merge tag as well." +msgstr "" +"Verwenden Sie den speziellen Merge-Tag [RSS ENTRY], um die Position für den " +"RSS-Beitrag zu markieren. Zusätzlich können Sie auch alle gültigen Merge-" +"Tags verwenden." + +#: views/campaigns/edit-rss.hbs:23 views/campaigns/edit-triggered.hbs:26 +#: views/campaigns/edit.hbs:34 +msgid "Delete Campaign" +msgstr "Kampagne löschen" + +#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27 +#: views/campaigns/edit.hbs:35 views/lists/edit.hbs:17 +#: views/lists/fields/edit.hbs:39 views/lists/forms/edit.hbs:29 +#: views/lists/forms/forms.hbs:12 views/lists/segments/edit.hbs:14 +#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:18 +#: views/reports/edit.hbs:6 views/settings.hbs:99 views/templates/edit.hbs:12 +#: views/triggers/edit.hbs:30 views/users/account.hbs:18 +msgid "Update" +msgstr "Aktualisieren" + +#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4 +msgid "Edit Triggered Campaign" +msgstr "Trigger-Kampagne bearbeiten" + +#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6 +#: routes/forms.js:143 +msgid "General" +msgstr "Generell" + +#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26 +msgid "Template Settings" +msgstr "Vorlagen Einstellungen" + +#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27 +msgid "Template URL" +msgstr "Vorlagen URL" + +#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4 +#: views/campaigns/upload-attachment.hbs:3 +#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3 +msgid "Edit Campaign" +msgstr "Kampagne bearbeiten" + +#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:29 +msgid "Attachments" +msgstr "Anhänge" + +#: views/campaigns/edit.hbs:30 +msgid "File" +msgstr "Datei" + +#: views/campaigns/edit.hbs:31 +msgid "Size" +msgstr "Grösse" + +#: views/campaigns/edit.hbs:32 views/campaigns/view.hbs:68 +#: views/lists/fields/fields.hbs:12 views/lists/forms/forms.hbs:9 +#: views/lists/view.hbs:33 +msgid "No data available in table" +msgstr "Keine Daten verfügbar in dieser Tabelle" + +#: views/campaigns/edit.hbs:33 views/campaigns/upload-attachment.hbs:4 +msgid "Add Attachment" +msgstr "Datei hinzufügen" + +#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4 +msgid "Opened info" +msgstr "Öffnungs Info" + +#: views/campaigns/opened.hbs:6 +msgid "Subscribers who opened this message:" +msgstr "Abonnenten, die diese Nachricht geöffnet haben:" + +#: views/campaigns/opened.hbs:12 +msgid "First open" +msgstr "Erstmals geöffnet" + +#: views/campaigns/opened.hbs:13 +msgid "Opened count" +msgstr "Anzahl Öffnungen" + +#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4 +msgid "Unsubscribed info" +msgstr "Deabonnement Info" + +#: views/campaigns/unsubscribed.hbs:6 +msgid "Subscribers who unsubscribed:" +msgstr "Abonnenten welche deabonnierten:" + +#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:28 +#: views/lists/subscription/import.hbs:10 routes/lists.js:202 +msgid "Unsubscribed" +msgstr "Deabonniert" + +#: views/campaigns/upload-attachment.hbs:7 +msgid "Upload" +msgstr "Hochladen" + +#: views/campaigns/view.hbs:4 +msgid "Overview" +msgstr "Übersicht" + +#: views/campaigns/view.hbs:5 +msgid "Links" +msgstr "Links" + +#: views/campaigns/view.hbs:7 +msgid "Feed URL" +msgstr "Feed URL" + +#: views/campaigns/view.hbs:8 +msgid "Last check" +msgstr "Letzter check" + +#: views/campaigns/view.hbs:9 +msgid "Not yet checked" +msgstr "Noch nicht geprüft" + +#: views/campaigns/view.hbs:10 +msgid "activate campaign to start checking feed for new messages" +msgstr "" +"Aktivieren Sie die Kampagne, um die Überprüfung des Feeds auf neue " +"Nachrichten zu starten" + +#: views/campaigns/view.hbs:11 +msgid "RSS status" +msgstr "RSS Status" + +#: views/campaigns/view.hbs:16 +msgid "Preview campaign as" +msgstr "Kampagnen Vorschau als" + +#: views/campaigns/view.hbs:17 +msgid "Add new test user" +msgstr "Neuen Testbenutzer hinzufügen" + +#: views/campaigns/view.hbs:18 +msgid "No test users yet, create one here" +msgstr "Noch keine Testbenutzer vorhanden, erstellen Sie einen hier" + +#: views/campaigns/view.hbs:19 +msgid "Go" +msgstr "Los" + +#: views/campaigns/view.hbs:20 lib/models/triggers.js:26 +msgid "Delivered" +msgstr "Zugestellt" + +#: views/campaigns/view.hbs:21 +msgid "List subscribers who received this message" +msgstr "Abonnenten dieser Liste, die diese Nachricht erhalten haben" + +#: views/campaigns/view.hbs:22 +msgid "Blacklisted" +msgstr "Blacklisted" + +#: views/campaigns/view.hbs:23 +msgid "List subscribers who blacklisted by global blacklist" +msgstr "Abonnenten, die von der globalen Blacklist aufgelistet wurden" + +#: views/campaigns/view.hbs:24 routes/lists.js:202 +msgid "Bounced" +msgstr "Bounced" + +#: views/campaigns/view.hbs:25 +msgid "List subscribers who bounced" +msgstr "Bounced Listen Abonnenten" + +#: views/campaigns/view.hbs:26 +msgid "Complaints" +msgstr "Beschwerden" + +#: views/campaigns/view.hbs:27 +msgid "List subscribers who complained for this message" +msgstr "Abonnenten, die sich über diese Nachricht beschwert haben" + +#: views/campaigns/view.hbs:29 +msgid "List subscribers who unsubscribed after this message" +msgstr "Abonnenten, die sich nach dieser Nachricht abgemeldet haben" + +#: views/campaigns/view.hbs:30 +msgid "Opened" +msgstr "Geöffnet" + +#: views/campaigns/view.hbs:31 +msgid "List subscribers who opened this message" +msgstr "Abonnenten, die diese Nachricht geöffnet haben" + +#: views/campaigns/view.hbs:32 +msgid "Clicked" +msgstr "Geklickt" + +#: views/campaigns/view.hbs:33 views/campaigns/view.hbs:70 +msgid "List subscribers who clicked on a link" +msgstr "Abonnenten, die auf einen Link geklickt haben" + +#: views/campaigns/view.hbs:34 +msgid "" +"Are you sure? This action would start sending messages to the selected list" +msgstr "" +"Sind Sie sicher? Diese Aktion wird mit dem Senden von Nachrichten an die " +"ausgewählte Liste beginnen" + +#: views/campaigns/view.hbs:35 +msgid "Delay sending" +msgstr "Senden verzögern" + +#: views/campaigns/view.hbs:36 +msgid "hours" +msgstr "Stunden" + +#: views/campaigns/view.hbs:37 +msgid "minutes" +msgstr "Minuten" + +#: views/campaigns/view.hbs:38 +msgid "Send to subscribers:" +msgstr "An Abonnenten senden:" + +#: views/campaigns/view.hbs:39 +msgid "Are you sure? This action would reset scheduling" +msgstr "Sind Sie sicher? Diese Aktion wird die Terminierung zurücksetzen" + +#: views/campaigns/view.hbs:40 +msgid "Cancel" +msgstr "Abbrechen" + +#: views/campaigns/view.hbs:41 +msgid "Sending scheduled" +msgstr "Senden geplant" + +#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:54 +msgid "Pause" +msgstr "Pause" + +#: views/campaigns/view.hbs:43 routes/campaigns.js:253 +msgid "Sending" +msgstr "Am senden" + +#: views/campaigns/view.hbs:44 views/campaigns/view.hbs:48 +msgid "" +"Are you sure? This action would resume sending messages to the selected list" +msgstr "" +"Sind Sie sicher? Diese Aktion wird das Senden von E-Mails an die " +"ausgewählte Liste fortsetzen" + +#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49 +msgid "Are you sure? This action would reset all stats about current progress" +msgstr "" +"Sind Sie sicher? Diese Aktion würde alle Statistiken über den aktuellen " +"Fortschritt zurücksetzen" + +#: views/campaigns/view.hbs:46 +msgid "Resume" +msgstr "Fortsetzen" + +#: views/campaigns/view.hbs:47 views/campaigns/view.hbs:51 +msgid "Reset" +msgstr "Zurücksetzen" + +#: views/campaigns/view.hbs:50 +msgid "Continue" +msgstr "Weiter" + +#: views/campaigns/view.hbs:52 +msgid "" +"All messages sent! Hit \"Continue\" if you you want to send this campaign to " +"new subscribers" +msgstr "" +"Alle E-Mails gesendet! Klicken Sie auf \"Weiter\", wenn Sie diese Kampagne " +"an neue Abonnenten senden möchten" + +#: views/campaigns/view.hbs:53 +msgid "" +"Are you sure? This action would pause sending new entries in RSS feed as " +"email messages to the selected list" +msgstr "" +"Sind Sie sicher? Diese Aktion wird das Senden neuer Einträge des RSS-Feed " +"als E-Mail-Nachrichten an die ausgewählte Liste pausieren" + +#: views/campaigns/view.hbs:55 views/campaigns/view.hbs:59 +msgid "Campaign status:" +msgstr "Kampagnen Status:" + +#: views/campaigns/view.hbs:56 +msgid "ACTIVE" +msgstr "AKTIV" + +#: views/campaigns/view.hbs:57 +msgid "" +"Are you sure? This action would start sending new entries in RSS feed as " +"email messages to the selected list" +msgstr "" +"Sind Sie sicher? Diese Aktion würde neue RSS Feed Einträge als E-Mail-" +"Nachrichten der ausgewählten Liste zustellen" + +#: views/campaigns/view.hbs:58 +msgid "Activate" +msgstr "Aktivieren" + +#: views/campaigns/view.hbs:60 +msgid "INACTIVE" +msgstr "INAKTIV" + +#: views/campaigns/view.hbs:61 +msgid "" +"This is a triggered campaign. Messages are only sent to subscribers that hit " +"some trigger that invokes this campaign" +msgstr "" +"Dies ist eine Trigger-Kampagne. Nachrichten werden nur an Abonnenten " +"gesendet, die einen Trigger auslösen, der diese Kampagne aufruft" + +#: views/campaigns/view.hbs:62 +msgid "see more" +msgstr "mehr anzeigen" + +#: views/campaigns/view.hbs:67 +msgid "List subscribers who clicked this link" +msgstr "Abonnenten dieser Liste, die diesen Link geklickt haben" + +#: views/campaigns/view.hbs:71 +msgid "" +"Clicks are counted as unique subscribers that clicked on a specific link or " +"on any link (in aggregated view)" +msgstr "" +"Klicks werden als eindeutige Abonnenten gezählt, die auf einen bestimmten " +"Link oder auf irgendeinen Link geklickt haben (in der aggregierter Ansicht)" + +#: views/campaigns/view.hbs:72 +msgid "" +"If a new entry is found from campaign feed a new subcampaign is created of " +"that entry and it will be listed here" +msgstr "" +"Wenn ein neuer Eintrag aus dem Kampagnen-Feed gefunden wird, wird eine neue " +"Unterkampagne von diesem Eintrag erstellt und hier aufgelistet" + +#: views/emails/password-reset-html.hbs:1 +#: views/emails/password-reset-text.hbs:1 +msgid "Change your password" +msgstr "Ändern Sie Ihr Passwort" + +#: views/emails/password-reset-html.hbs:2 +#: views/emails/password-reset-text.hbs:2 +msgid "We have received a password change request for your Mailtrain account:" +msgstr "" +"Wir haben eine Anforderung zur Passwortänderungs für Ihr Mailtrain-Konto erhalten:" + +#: views/emails/password-reset-html.hbs:3 +#: views/emails/password-reset-text.hbs:3 +msgid "Reset password" +msgstr "Passwort zurücksetzen" + +#: views/emails/password-reset-html.hbs:4 +#: views/emails/password-reset-text.hbs:4 +msgid "" +"If you did not ask to change your password, then you can ignore this email " +"and your password will not be changed." +msgstr "" +"Wenn Sie Ihr Passwort nicht ändern wollen, können Sie diese E-" +"Mail einfach ignorieren." + +#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3 +#: views/emails/stationery-text.hbs:3 +msgid "Preferences" +msgstr "Persönliche Einstellungen" + +#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4 +#: views/emails/stationery-text.hbs:4 views/lists/subscription/edit.hbs:16 +#: views/subscription/partials/subscription-unsubscribe-form.hbs:2 +#: views/subscription/web-manage.mjml.hbs:3 +#: views/subscription/web-unsubscribe.mjml.hbs:1 +#: views/subscription/web-unsubscribe.mjml.hbs:3 routes/forms.js:213 +#: routes/lists.js:284 +msgid "Unsubscribe" +msgstr "Newsletter abbestellen" + +#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5 +#: views/emails/stationery-text.hbs:5 +msgid "View this email in your browser" +msgstr "E-Mail im Browser ansehen" + +#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1 +msgid "Hey [FIRST_NAME/Customer]," +msgstr "Hallo [FIRST_NAME/Customer]," + +#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2 +msgid "Cheers," +msgstr "Viele Grüße," + +#: views/index.hbs:1 +msgid "List Management" +msgstr "Listen Management" + +#: views/index.hbs:2 +msgid "" +"Mailtrain allows you to easily manage even very large lists. Million " +"subscribers? Not a problem. You can add subscribers manually, through the " +"API or import from a CSV file. All lists come with support for custom fields " +"and merge tags as well." +msgstr "" +"Mailtrain ermöglicht es Ihnen, auch sehr große Listen zu verwalten. Millionen von " +"Abonnenten? Kein Problem. Sie können Abonnenten manuell über die API " +"hinzufügen oder aus einer CSV-Datei importieren. Für alle Listen können " +"zusätzliche Datenfelder und Merge Tags genutzt werden." + +#: views/index.hbs:3 views/index.hbs:7 views/index.hbs:10 views/index.hbs:13 +#: views/index.hbs:16 views/index.hbs:19 views/index.hbs:22 views/index.hbs:25 +#: views/index.hbs:28 +msgid "Show more" +msgstr "Zeige mehr" + +#: views/index.hbs:4 views/lists/fields/create.hbs:3 +#: views/lists/fields/edit.hbs:3 views/lists/fields/fields.hbs:3 +#: views/lists/fields/fields.hbs:5 views/lists/view.hbs:6 +msgid "Custom Fields" +msgstr "Zusätzliche Datenfelder" + +#: views/index.hbs:5 +msgid "" +"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. " +"Every custom field can be included in the generated newsletters through " +"merge tags." +msgstr "" +"Textfelder, Nummern, Dropdowns oder Checkboxen, Mailtrain bietet all das. " +"Jedes zusätzliche Feld kann in den generierten Newslettern über " +"Merge-Tags eingebunden werden." + +#: views/index.hbs:6 +msgid "Mailtrain also supports custom forms." +msgstr "Mailtrain bietet auch benutzerdefinierte Formulare." + +#: views/index.hbs:8 +msgid "List Segmentation" +msgstr "Listen Segmentierung" + +#: views/index.hbs:9 +msgid "" +"Send messages only to list subscribers that match predefined segmentation " +"rules. No need to create separate lists with small differences." +msgstr "" +"Senden Sie nur Nachrichten an Abonnenten, welche die vordefinierten " +"Segmentierungsregeln erfüllen. Es besteht keine Notwendigkeit, separate " +"Listen mit kleinen Unterschieden zu erstellen." + +#: views/index.hbs:11 +msgid "RSS Campaigns" +msgstr "RSS-Kampagnen" + +#: views/index.hbs:12 +msgid "" +"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed " +"then Mailtrain auto-generates a new campaign using entry data as message " +"contents and sends it to selected subscribers." +msgstr "" +"Mailtrain kann RSS-Feeds verfolgen und bei neuen Einträgen automatisch " +"eine neue Kampagne mit dem RSS-Beitrag als Nachrichteninhalt an die " +"ausgewählte Liste senden." + +#: views/index.hbs:14 +msgid "GPG Encryption" +msgstr "GPG Verschlüsselung" + +#: views/index.hbs:15 +msgid "" +"If a list has a custom field for a GPG Public Key set then subscribers can " +"upload their GPG public key to receive encrypted messages from the list." +msgstr "" +"Wenn für eine Liste ein benutzerdefiniertes Feld für den GPG-Public-Key " +"vorhanden ist, können Abonnenten ihren GPG-Public-Key hochladen, um " +"alle E-Mails verschlüsselt zu erhalten." + +#: views/index.hbs:17 +msgid "Click Stats" +msgstr "Klick Statistik" + +#: views/index.hbs:18 +msgid "" +"After a campaign is sent, check individual click statistics for every link " +"included in the message." +msgstr "" +"Nachdem eine Kampagne gesendet wurde, sind Klick-Statistiken für jeden in " +"der E-Mail-Nachricht enthaltener Link verfügbar." + +#: views/index.hbs:20 +msgid "Template Editors" +msgstr "Vorlagen Editoren" + +#: views/index.hbs:21 +msgid "" +"Mailtrain ships with GrapeJS and Mosaico built in, two advanced template " +"editors. Mailtrain also offers a code editor if you prefer to handcraft the " +"HTML yourself." +msgstr "" +"Mailtrain beinhaltet GrapeJS und Mosaico, zwei Programme zum Bearbeiten der " +"E-Mail-Vorlagen. Natürlich bietet Mailtrain auch einen Code-Editor, sofern " +"Sie den HTML Code selber erstellen möchten." + +#: views/index.hbs:23 +msgid "Send via Any Provider" +msgstr "Sende mit beliebigen Anbietern" + +#: views/index.hbs:24 +msgid "" +"Mailtrain recommends SendPulse even though you " +"can use any provider that supports SMTP protocol to send out your " +"newsletters. Bounce and complaints handling via webhooks is supported for " +"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA." +msgstr "" +"Mailtrain empfiehlt SendPulse, obwohl Sie " +"jeden Provider verwenden können, der das SMTP-Protokoll unterstützt, um Ihre " +"Newsletter zu versenden. Bounce- und Reklamationsabwicklung werden über " +"Webhooks für SES, SparkPost, SendGrid und Mailgun unterstützt, auch für " +"Postfix und ZoneMTA." + +#: views/index.hbs:26 lib/tools.js:130 +msgid "Automation" +msgstr "Automatisierung" + +#: views/index.hbs:27 +msgid "" +"Define automation triggers to send specific messages when a user activates " +"the trigger." +msgstr "" +"Definieren Sie Automatisierungs-Trigger, um bestimmte Nachrichten zu senden, " +"wenn ein Benutzer den Trigger aktiviert." + +#: views/index.hbs:29 +msgid "Donate to Author" +msgstr "Dem Autor spenden" + +#: views/index.hbs:30 +msgid "Mailtrain is available under GPLv3 license and completely open source." +msgstr "Mailtrain ist unter GPLv3 Lizenz verfügbar und komplett offen." + +#: views/index.hbs:31 +msgid "" +"If you really like Mailtrain or your business benefits from it financially " +"then I would really appreciate a small donation to keep the Mailtrain " +"development engines running. You can either use Bitcoin or PayPal for " +"donations. My Bitcoin wallet is" +msgstr "" +"Wenn Sie Mailtrain wirklich mögen oder Ihr Geschäft davon finanziell " +"profitiert, würde ich eine kleine Spende sehr schätzen, um die Mailtrain-" +"Entwicklung am laufen zu halten. Sie können entweder per Bitcoin oder PayPal " +"spenden. Meine Bitcoin Adresse ist" + +#: views/index.hbs:32 +msgid "Or Donate Using Paypal" +msgstr "Oder spenden Sie mit PayPal" + +#: views/index.hbs:33 +msgid "Official Mailtrain Partners" +msgstr "Offizielle Mailtrain Partner" + +#: views/index.hbs:34 +msgid "" +"A reliable SMTP server, easy integration, and 12,000 messages a month free" +msgstr "" +"Ein zuverlässiger SMTP-Server, einfache Integration und 12.000 Nachrichten " +"pro Monat kostenlos" + +#: views/index.hbs:35 +msgid "Free, open source mail server solution" +msgstr "Kostenlose, Open Source Mail Server Lösung" + +#: views/layout.hbs:2 +msgid "Toggle navigation" +msgstr "Navigation umschalten" + +#: views/layout.hbs:3 +msgid "Wiki" +msgstr "Wiki" + +#: views/layout.hbs:4 +msgid "Blog" +msgstr "Blog" + +#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3 +msgid "Account" +msgstr "Account" + +#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3 +msgid "Settings" +msgstr "Einstellungen" + +#: views/layout.hbs:8 views/users/api.hbs:2 views/users/api.hbs:3 +msgid "API" +msgstr "API" + +#: views/layout.hbs:9 +msgid "Log out" +msgstr "Abmelden" + +#: views/layout.hbs:10 views/users/forgot.hbs:2 views/users/login.hbs:2 +#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2 +msgid "Sign in" +msgstr "Anmelden" + +#: views/layout.hbs:11 +msgid "Self Hosted Newsletter App Built on Top of Nodemailer" +msgstr "Selbst gehostete Newsletter-App basierend auf Nodemailer" + +#: views/layout.hbs:12 views/layout.hbs:14 +msgid "Source on GitHub" +msgstr "Quellcode auf Github" + +#: views/layout.hbs:13 +msgid "Subscribe to Our Newsletter" +msgstr "Abonnieren Sie unseren Newsletter" + +#: views/lists/create.hbs:2 views/lists/edit.hbs:2 +#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2 +#: views/lists/fields/fields.hbs:2 views/lists/forms/create.hbs:2 +#: views/lists/forms/edit.hbs:2 views/lists/forms/forms.hbs:2 +#: views/lists/lists.hbs:2 views/lists/lists.hbs:4 +#: views/lists/segments/create.hbs:2 views/lists/segments/edit.hbs:2 +#: views/lists/segments/rule-configure.hbs:2 +#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2 +#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2 +#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2 +#: views/lists/subscription/import-failed.hbs:2 +#: views/lists/subscription/import-preview.hbs:2 +#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2 +#: lib/tools.js:118 routes/lists.js:59 +msgid "Lists" +msgstr "Listen" + +#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:10 +#: views/lists/lists.hbs:3 +msgid "Create List" +msgstr "Liste erstellen" + +#: views/lists/create.hbs:6 views/lists/edit.hbs:7 +msgid "List Name" +msgstr "Name der Liste" + +#: views/lists/create.hbs:9 views/lists/edit.hbs:15 +msgid "Allow public users to subscribe themselves" +msgstr "Allen erlauben, diese Liste selbst zu abonnieren" + +#: views/lists/create.hbs:11 views/lists/edit.hbs:17 +msgid "Unsubscription" +msgstr "Deabonnement" + +#: views/lists/create.hbs:12 views/lists/edit.hbs:18 +msgid "Select how an unsuscription request by subscriber is handled." +msgstr "" +"Wählen Sie, welche Schritte zum Abmelden von der Liste notwendig sein sollen." + +#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:8 +msgid "Edit List" +msgstr "Liste bearbeiten" + +#: views/lists/edit.hbs:5 +msgid "View List" +msgstr "Liste ansehen" + +#: views/lists/edit.hbs:8 +msgid "List ID" +msgstr "Listen ID" + +#: views/lists/edit.hbs:9 +msgid "This is the list ID displayed to the subscribers" +msgstr "Diese Listen ID wird den Abonnenten dargestellt" + +#: views/lists/edit.hbs:12 +msgid "Custom Form" +msgstr "Benutzerdefiniertes Formular" + +#: views/lists/edit.hbs:13 views/lists/forms/forms.hbs:11 +msgid "Default Mailtrain Form" +msgstr "Standard Mailtrain Formular" + +#: views/lists/edit.hbs:14 +msgid "" +"The custom form used for this list. You can create a form here." +msgstr "" +"Das Standard-Formular dieser Liste. Wenn Sie ein benutzerdefiniertes Formular " +"erstellen möchten, klicken Sie hier." + +#: views/lists/edit.hbs:19 +msgid "Unsubscribe Header" +msgstr "Deabonnement Header" + +#: views/lists/edit.hbs:20 +msgid "Do not send List-Unsubscribe headers" +msgstr "Sende keine Header zum Abmelden von der Liste" + +#: views/lists/edit.hbs:16 +msgid "Delete List" +msgstr "Liste löschen" + +#: views/lists/fields/create.hbs:4 +msgid "Create Field" +msgstr "Feld erstellen" + +#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4 +msgid "Create Custom Field" +msgstr "zusäzliches Feld erstellen" + +#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7 +#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8 +msgid "Field Name" +msgstr "Feldnamen" + +#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9 +msgid "Field Type" +msgstr "Feldtyp" + +#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10 +#: lib/models/fields.js:17 +msgid "Text" +msgstr "Text" + +#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11 +#: lib/models/fields.js:21 +msgid "Number" +msgstr "Nummer" + +#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12 +#: lib/models/fields.js:18 +msgid "Website" +msgstr "Webseite" + +#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13 +#: lib/models/fields.js:20 +msgid "GPG Public Key" +msgstr "GPG Public Key" + +#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14 +#: lib/models/fields.js:19 +msgid "Multi-line text" +msgstr "Mehrzeiliger Text" + +#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15 +msgid "JSON" +msgstr "JSON" + +#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16 +msgid "Date" +msgstr "Datum" + +#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17 +msgid "Date (MM/DD/YYYY)" +msgstr "Datum (MM/DD/YYYY)" + +#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18 +#: lib/models/fields.js:26 +msgid "Date (DD/MM/YYYY)" +msgstr "Datum (DD/MM/YYYY)" + +#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19 +msgid "Birthday" +msgstr "Geburtstag" + +#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20 +#: lib/models/fields.js:27 +msgid "Birthday (MM/DD)" +msgstr "Geburtstag (MM/DD)" + +#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21 +#: lib/models/fields.js:28 +msgid "Birthday (DD/MM)" +msgstr "Geburtstag (DD/MM)" + +#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22 +msgid "Grouped" +msgstr "Gruppiert" + +#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23 +msgid "Drop Downs" +msgstr "Dropdown" + +#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24 +#: lib/models/fields.js:22 +msgid "Radio Buttons" +msgstr "Radio Buttons" + +#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25 +#: lib/models/fields.js:23 +msgid "Checkboxes" +msgstr "Checkboxen" + +#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26 +msgid "Option for a group value" +msgstr "Option für einen Gruppenwert" + +#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27 +msgid "Group" +msgstr "Gruppe" + +#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29 +msgid "Required for group options" +msgstr "Erforderlich für Gruppenoptionen" + +#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30 +#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36 +#: views/lists/fields/fields.hbs:9 +msgid "Default merge tag value" +msgstr "Standard Wert für Merge-Tag" + +#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34 +msgid "" +"For group elements like checkboxes you can control the appearance of the " +"merge tag with an optional template. The template uses handlebars syntax and " +"you can find all values from{{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+"Für Gruppenelemente wie Checkboxen können Sie das Aussehen des Merge-Tags "
+"mit einer optionalen Vorlage steuern. Die Vorlage verwendet die Handlebars-"
+"Syntax und Sie können alle Werte des {{values}} Array finden, "
+"zB {{#each}} {{this}} {{/each}}. Wenn die Vorlage nicht "
+"definiert ist, werden mehrere Werte mit Kommas verbunden. Sie können diese "
+"Vorlage auch verwenden, um JSON-Werte zu rendern (wenn das JSON ein Array "
+"ist, dann ist das Array als values verfügbar, ansonsten können "
+"Sie direkt auf die JSON-Keys zugreifen)."
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Sichtbar"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Feld hinzufügen"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Feld bearbeiten"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr "Zusätzliches Feld bearbeiten"
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr "Zurück zu den Feldern"
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/mosaico/editor.hbs:2 views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr "Merge-Tag"
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr "Merge-Tag"
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr "Fügen Sie diesen Tag Ihrem Inhalt hinzu:"
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Feld löschen"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:26
+#: views/report-templates/partials/report-template-fields.hbs:5
+msgid "Type"
+msgstr "Typ"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/forms/edit.hbs:22 views/lists/forms/forms.hbs:8
+#: views/lists/segments/segments.hbs:8 views/lists/segments/view.hbs:12
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:276
+#: routes/campaigns.js:568 routes/campaigns.js:657 routes/campaigns.js:706
+#: routes/lists.js:166 routes/lists.js:253 routes/report-templates.js:51
+#: routes/templates.js:170 routes/triggers.js:297
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: views/lists/forms/create.hbs:3 views/lists/forms/edit.hbs:3
+#: views/lists/forms/forms.hbs:3 views/lists/forms/forms.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Forms"
+msgstr "Benutzerdefinierte Formulare"
+
+#: views/lists/forms/create.hbs:4
+msgid "Create Form"
+msgstr "Formular erstellen"
+
+#: views/lists/forms/create.hbs:5 views/lists/forms/forms.hbs:4
+msgid "Create Custom Form"
+msgstr "Benutzerdefiniertes Formular erstellen"
+
+#: views/lists/forms/create.hbs:6 views/lists/forms/create.hbs:7
+#: views/lists/forms/edit.hbs:7 views/lists/forms/edit.hbs:8
+msgid "Form Name"
+msgstr "Formular-Name"
+
+#: views/lists/forms/create.hbs:8
+msgid "Add Form"
+msgstr "Formular hinzufügen"
+
+#: views/lists/forms/edit.hbs:4
+msgid "Edit Form"
+msgstr "Formular bearbeiten"
+
+#: views/lists/forms/edit.hbs:5
+msgid "Edit Custom Form"
+msgstr "Formular bearbeiten"
+
+#: views/lists/forms/edit.hbs:6
+msgid "Back to forms"
+msgstr "Zurück zu Formulare"
+
+#: views/lists/forms/edit.hbs:10
+msgid "Optional comments about this form"
+msgstr "Optionale Kommentare zu diesem Formular"
+
+#: views/lists/forms/edit.hbs:11
+msgid "Form Preview"
+msgstr "Formular Vorschau"
+
+#: views/lists/forms/edit.hbs:12
+msgid ""
+"Note: These links are solely for a quick preview. If you submit a preview "
+"form you'll get redirected to the list's default form."
+msgstr ""
+"Hinweis: Diese Links dienen ausschließlich der Vorschau. Wenn Sie ein "
+"Vorschau-Formlar absenden, werden Sie auf das Standardformular der Liste "
+"umgeleitet."
+
+#: views/lists/forms/edit.hbs:13 views/lists/subscription/add.hbs:16
+#: views/subscription/mail-unsubscribe-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-unsubscribe-confirmed-text.hbs:4 routes/forms.js:157
+#: routes/lists.js:284
+msgid "Subscribe"
+msgstr "Abonnieren"
+
+#: views/lists/forms/edit.hbs:14
+msgid "Confirm Notice"
+msgstr "Bestätigung erforderlich"
+
+#: views/lists/forms/edit.hbs:15
+msgid "Updated Notice"
+msgstr "Profil aktualisiert"
+
+#: views/lists/forms/edit.hbs:16
+msgid "Unsubscribed Notice"
+msgstr "Abmeldungshinweis"
+
+#: views/lists/forms/edit.hbs:17 routes/forms.js:195
+msgid "Manage"
+msgstr "Verwalten"
+
+#: views/lists/forms/edit.hbs:18
+msgid "Manage Address"
+msgstr "Adresse Verwalten"
+
+#: views/lists/forms/edit.hbs:19
+msgid "Create a test user for additional options"
+msgstr "Erstellen Sie einen Testbenutzer für zusätzliche Optionen"
+
+#: views/lists/forms/edit.hbs:20 views/report-templates/create.hbs:3
+#: views/report-templates/edit.hbs:3
+#: views/report-templates/report-templates.hbs:3 views/templates/create.hbs:2
+#: views/templates/edit.hbs:2 views/templates/templates.hbs:2
+#: views/templates/templates.hbs:4 lib/tools.js:122 routes/templates.js:27
+msgid "Templates"
+msgstr "Vorlagen"
+
+#: views/lists/forms/edit.hbs:21
+msgid "Fields"
+msgstr "Felder"
+
+#: views/lists/forms/edit.hbs:23
+msgid "Form Fields"
+msgstr "Formular Felder"
+
+#: views/lists/forms/edit.hbs:24
+msgid "Fields hidden on subscription page:"
+msgstr "Unsichtbare Felder auf der Anmeldung-Seite:"
+
+#: views/lists/forms/edit.hbs:25
+msgid "Fields shown on subscription page:"
+msgstr "Sichtbare Felder auf der Anmeldung-Seite:"
+
+#: views/lists/forms/edit.hbs:26
+msgid "Fields hidden on preferences page:"
+msgstr "Unsichtbare Felder auf der Profil-Seite:"
+
+#: views/lists/forms/edit.hbs:27
+msgid "Fields shown on preferences page:"
+msgstr "Sichtbare Felder auf der Profil-Seite:"
+
+#: views/lists/forms/edit.hbs:28
+msgid "Delete Form"
+msgstr "Formular löschen"
+
+#: views/lists/forms/forms.hbs:10
+msgid "The default form for this list is:"
+msgstr "Das Standard-Formular für diese Liste ist:"
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7 views/reports/partials/report-fields.hbs:10
+msgid "Subscribers"
+msgstr "Abonnenten"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:7
+#: views/lists/view.hbs:14
+msgid "Segments"
+msgstr "Segmente"
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr "Segment erstellen"
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr "Segmentnamen"
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr "Regel match"
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr "Alle Regeln müssen zutreffen"
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr "Irgendeine Regel kann zutreffen"
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr "Segment hinzufügen"
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:12
+msgid "Edit Segment"
+msgstr "Segment bearbeiten"
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr "Zurück zu Segmente"
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr "Segment löschen"
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Regel erstellen"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Regel"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Wert"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+"Verwenden Sie % für Platzhalterzeichen, z.B. \"%test“, um alle Werte zu "
+"matchen, die mit \"test\" enden"
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr "Exact match verwenden"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr "Range match verwenden"
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr "Relative range match verwenden"
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr "Von"
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr "Tage"
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr "vor heute"
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr "nach heute"
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr "an"
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr "Ausgewählt"
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr "Nicht ausgewählt"
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr "Regel hinzufügen"
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:15
+#: views/reports/create-select-template.hbs:5
+#: views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Weiter"
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr "Regel löschen"
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr "Match"
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:13
+msgid "Segment"
+msgstr "Segment"
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr "Regel match"
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr "Passende Abonnenten"
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr "zeige"
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Abonnent hinzufügen"
+
+#: views/lists/subscription/add.hbs:5
+#: views/subscription/partials/subscription-custom-fields.hbs:1
+#: views/users/account.hbs:7
+msgid "Email Address"
+msgstr "E-Mail-Adresse"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:82 views/settings.hbs:97
+#: views/subscription/partials/subscription-custom-fields.hbs:6
+msgid "Begins with"
+msgstr "Beginnt mit"
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Falls Sie hier einen GPG Public Key einfügen, wird dieser verwendet um E-"
+"Mails an diesen Abonnenten zu verschlüsseln"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Zeitzone"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "Test-Benutzer?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+"Wenn diese Option aktiviert ist, kann dieser Abonnent für die Vorschau von "
+"Kampagnen verwendet werden"
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+"Diese Person wird keine Bestätigungs-E-Mail erhalten. Stellen Sie sicher, "
+"dass Sie die Erlaubnis haben, dieser Person E-Mails zu senden."
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Abonnent bearbeiten"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Zurück zur Liste"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:1
+#: lib/helpers.js:41 lib/models/segments.js:11
+msgid "Email address"
+msgstr "E-Mail-Adresse"
+
+#: views/lists/subscription/edit.hbs:17
+msgid "Delete Subscription"
+msgstr "Abonnement löschen"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Import status"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Fehlgeschlagene Adressen"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid ""
+"Role-based addresses like postmaster@example.com are blocked when importing. "
+"Subscribers with role-based email addresses can join your list using the "
+"subscription form"
+msgstr ""
+"Rollenbasierte Adressen wie postmaster@example.com sind beim Import "
+"gesperrt. Abonnenten mit rollenbasierten E-Mail-Adressen können sich mit dem "
+"Anmeldeformular Ihrer Liste abonnieren."
+
+#: views/lists/subscription/import-failed.hbs:7
+msgid "see here"
+msgstr "sehen Sie hier"
+
+#: views/lists/subscription/import-failed.hbs:9
+msgid "Fail reason"
+msgstr "Fehlerursache"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Abonnenten importieren"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:27
+#: views/users/api.hbs:35 views/users/api.hbs:43 views/users/api.hbs:54
+#: views/users/api.hbs:62 views/users/api.hbs:70
+msgid "Example"
+msgstr "Beispiel"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Import starten"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "CVS Datei"
+
+#: views/lists/subscription/import.hbs:6
+msgid "CSV delimiter"
+msgstr "CSV-Trennzeichen"
+
+#: views/lists/subscription/import.hbs:7
+msgid "Categorize the imported subscribers as"
+msgstr "Kategorisiere die importierten Abonnenten als"
+
+#: views/lists/subscription/import.hbs:8 routes/lists.js:202
+msgid "Subscribed"
+msgstr "Abonniert"
+
+#: views/lists/subscription/import.hbs:9
+msgid "Regular subscriber addresses"
+msgstr "Normale Abonnenten-Adressen"
+
+#: views/lists/subscription/import.hbs:11
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr "Unterdrückte E-Mail-Adressen, die von Ihrer Liste abgemeldet werden"
+
+#: views/lists/subscription/import.hbs:12
+msgid "Check imported emails"
+msgstr "Überprüfe die importierten E-Mail-Adressen"
+
+#: views/lists/subscription/import.hbs:13 views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr "Aktiviert"
+
+#: views/lists/subscription/import.hbs:14 views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr "Deaktiviert"
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Abonnement Formular"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Listen Aktionen"
+
+#: views/lists/view.hbs:9 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr "Trigger erstellen"
+
+#: views/lists/view.hbs:10
+msgid "Add Subscriber"
+msgstr "Abonnent hinzufügen"
+
+#: views/lists/view.hbs:11
+msgid "Import Subscribers"
+msgstr "Abonnenten importieren"
+
+#: views/lists/view.hbs:15
+msgid "Create New Segment"
+msgstr "Neues Segment erstellen"
+
+#: views/lists/view.hbs:16
+msgid "Filter"
+msgstr "Filter"
+
+#: views/lists/view.hbs:17
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+#: views/lists/view.hbs:18
+msgid "Imports"
+msgstr "Importe"
+
+#: views/lists/view.hbs:25 routes/campaigns.js:255 routes/lists.js:296
+msgid "Finished"
+msgstr "Fertig"
+
+#: views/lists/view.hbs:27
+msgid "Added"
+msgstr "Hinzugefügt"
+
+#: views/lists/view.hbs:28
+msgid "Updated"
+msgstr "Aktualisiert"
+
+#: views/lists/view.hbs:29
+msgid "Failed"
+msgstr "Fehlgeschlagen"
+
+#: views/lists/view.hbs:31
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+"Sind Sie sicher? Diese Aktion sollte nur ausgeführt werden, um Probleme mit "
+"hängenden Importen zu lösen"
+
+#: views/lists/view.hbs:32
+msgid "Restart"
+msgstr "Neustart"
+
+#: views/mosaico/editor.hbs:1 views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr "Merge-Tag Referenz"
+
+#: views/mosaico/editor.hbs:4
+msgid "MOSAICO Responsive Email Designer"
+msgstr "MOSAICO Responsive E-Mail-Designer"
+
+#: views/mosaico/editor.hbs:5
+msgid "Sucessfully saved"
+msgstr "Erfolgreich gespeichert"
+
+#: views/mosaico/editor.hbs:6
+msgid "An error occured while saving the document"
+msgstr "Beim Speichern des Dokuments ist ein Fehler aufgetreten"
+
+#: views/mosaico/editor.hbs:7
+msgid "Unsaved changes will be lost. Close now?"
+msgstr "Nicht gespeicherte Änderungen gehen verloren. Jetzt schließen?"
+
+#: views/mosaico/editor.hbs:8 views/mosaico/editor.hbs:9
+msgid "Tags"
+msgstr "Tags"
+
+#: views/partials/codeeditor.hbs:1 views/partials/grapejs.hbs:1
+#: views/partials/mosaico.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Vorlagen-Inhalt (HTML)"
+
+#: views/partials/editor-navbar.hbs:1
+msgid "SAVE"
+msgstr "SPEICHERN"
+
+#: views/partials/editor-navbar.hbs:2
+msgid "SAVING"
+msgstr "AM SPEICHERN"
+
+#: views/partials/editor-navbar.hbs:3
+msgid "CLOSE"
+msgstr "SCHLIESSEN"
+
+#: views/partials/grapejs.hbs:2
+msgid "Open GrapeJS"
+msgstr "GrapeJS öffnen"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "HTML Vorschau anzeigen"
+
+#: views/partials/html-to-text.hbs:1
+msgid ""
+"To extract the text from HTML click here."
+msgstr ""
+"Um den Klartext aus dem HTML Dokument zu extrahieren, klicken Sie hier."
+
+#: views/partials/html-to-text.hbs:2
+msgid ""
+"Please note that your existing plaintext in the field above will be "
+"overwritten. This feature uses the Premailer API, a third party "
+"service. Their Terms of Service and Privacy Policy apply."
+msgstr ""
+"Hierbei wird Ihr bestehender Klartext im Feld oberhalb überschreiben. Diese "
+"Funktion nutzt die Premailer API. Die Verwendung unterliegt "
+"deren AGB und Datenschutzbestimmungen."
+
+#: views/partials/html-to-text.hbs:3
+msgid "An error occurred while talking to the server"
+msgstr "Beim Datenverkehr mit dem Server ist ein Fehler aufgetreten"
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+"Merge-Tags sind Tags, die vor dem Senden der Nachricht ersetzt werden. Das "
+"Format des Merge-Tags lautet wie folgt: [TAG_NAME] oder "
+"[TAG_NAME/fallback] wobei fallback ein optionaler "
+"Textwert ist, der verwendet wird, falls TAG_NAME leer ist."
+
+#: views/partials/modal-carousel.hbs:1
+msgid "{{title}}"
+msgstr "{{title}}"
+
+#: views/partials/mosaico.hbs:2
+msgid "Open Mosaico"
+msgstr "Mosaico öffnen"
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Vorlagen-Inhalt (Klartext)"
+
+#: views/report-templates/create.hbs:2 views/report-templates/edit.hbs:2
+#: views/report-templates/report-templates.hbs:2
+#: views/reports/create-select-template.hbs:2 views/reports/create.hbs:2
+#: views/reports/edit.hbs:2 views/reports/output.hbs:2
+#: views/reports/reports.hbs:2 views/reports/reports.hbs:5
+#: views/reports/view.hbs:2 lib/tools.js:137 routes/reports.js:31
+msgid "Reports"
+msgstr "Reporte"
+
+#: views/report-templates/create.hbs:4 views/report-templates/create.hbs:6
+#: views/report-templates/report-templates.hbs:4 views/templates/create.hbs:3
+#: views/templates/create.hbs:4 views/templates/create.hbs:12
+#: views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Vorlage erstellen"
+
+#: views/report-templates/create.hbs:5 routes/report-templates.js:231
+msgid "Create Report Template"
+msgstr "Report-Vorlage erstellen"
+
+#: views/report-templates/edit.hbs:4 views/templates/edit.hbs:3
+#: views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Vorlage bearbeiten"
+
+#: views/report-templates/edit.hbs:5 routes/report-templates.js:262
+msgid "Edit Report Template"
+msgstr "Report-Vorlage bearbeiten"
+
+#: views/report-templates/edit.hbs:6 views/templates/edit.hbs:11
+msgid "Delete Template"
+msgstr "Vorlage löschen"
+
+#: views/report-templates/edit.hbs:7
+msgid "Update and Stay"
+msgstr "Aktualisieren und bleiben"
+
+#: views/report-templates/edit.hbs:8
+msgid "Update and Leave"
+msgstr "Aktualisieren und verlassen"
+
+#: views/report-templates/partials/report-template-fields.hbs:2
+msgid "Template Name"
+msgstr "Vorlagen-Name"
+
+#: views/report-templates/partials/report-template-fields.hbs:6
+msgid "User selectable fields"
+msgstr "Vom Benutzer wählbare Felder"
+
+#: views/report-templates/partials/report-template-fields.hbs:7
+msgid "Data processing code"
+msgstr "Datenverarbeitungs-Code"
+
+#: views/report-templates/partials/report-template-fields.hbs:8
+msgid "Rendering template"
+msgstr "Render-Vorlage"
+
+#: views/report-templates/report-templates.hbs:5
+msgid "Blank"
+msgstr "Leer"
+
+#: views/report-templates/report-templates.hbs:6
+msgid "All Subscribers"
+msgstr "Alle Abonnenten"
+
+#: views/report-templates/report-templates.hbs:7
+msgid "Grouped Subscribers"
+msgstr "Gruppierte Abonnenten"
+
+#: views/report-templates/report-templates.hbs:8
+msgid "Export List as CSV"
+msgstr "Liste als CSV exportieren"
+
+#: views/report-templates/report-templates.hbs:9 views/reports/reports.hbs:4
+#: routes/report-templates.js:29
+msgid "Report Templates"
+msgstr "Report-Vorlagen"
+
+#: views/reports/create-select-template.hbs:3
+#: views/reports/create-select-template.hbs:4 views/reports/create.hbs:3
+#: views/reports/create.hbs:4 views/reports/create.hbs:5
+#: views/reports/reports.hbs:3 routes/reports.js:81
+msgid "Create Report"
+msgstr "Report erstellen"
+
+#: views/reports/edit.hbs:3 views/reports/edit.hbs:4 routes/reports.js:151
+msgid "Edit Report"
+msgstr "Report bearbeiten"
+
+#: views/reports/edit.hbs:5
+msgid "Delete Report"
+msgstr "Report löschen"
+
+#: views/reports/partials/report-fields.hbs:2
+msgid "Report Name"
+msgstr "Report-Name"
+
+#: views/reports/partials/report-fields.hbs:8
+#: views/reports/partials/report-fields.hbs:11
+msgid ""
+"Select a campaign in the table above by clicking on the respective row "
+"number."
+msgstr ""
+"Wählen Sie eine Kampagne in der obigen Tabelle aus, indem Sie auf die "
+"jeweilige Zeilennummer klicken."
+
+#: views/reports/partials/report-select-template.hbs:1
+msgid "Report Template"
+msgstr "Report-Vorlage"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Service Adresse (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Geben Sie die URL ein, auf welcher dieser Service verfügbar ist"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "Admin E-Mail"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+"Geben Sie hier die E-Mail-Adresse ein, die als \"von\" für Systemmeldungen "
+"verwendet wird"
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr "WYSIWYG Editor deaktivieren"
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr "Wenn markiert zeigt der Editor HTML-Code ohne Vorschau an"
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr "Bestätigungsmeldungen für Abonnements deaktivieren"
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+"Wenn markiert wird keine Bestätigungsnachricht gesendet, die besagt, dass "
+"der Teilnehmer jetzt abonniert oder abgemeldet ist. Dies deaktiviert die "
+"Double-Opt-In-Nachrichten nicht."
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "Tracking ID"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Google-Analytics Tracking-Code"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr "Meldung auf der Startseite"
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr "HTML-Code im Kopfbereich der Startseite"
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr "Kampagnenvorgaben"
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr "Absender Name"
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Absender Name, z.B. Meine grossartige Firma"
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr "Standardadresse"
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr "Kontakt Adresse, z.B. 1234 Hauptstrasse, 01234 Irgendwo, Deutschland"
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr "Standard \"von\" Namen"
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr "Standard \"von\" E-Mail-Adresse"
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr "Standard \"Betreffzeile\""
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr "Standard-Homepage (URL)"
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr ""
+"URL, um die abonnierten Benutzer weiterzuleiten, z.B. http://example.com/"
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr "Mailer-Einstellungen"
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr "Diese Einstellungen sind erforderlich, um E-Mails zu senden"
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr "SMTP"
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr "AWS SES"
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr "SMTP zum Senden der E-Mails verwenden"
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr "Hostname"
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr "Port"
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr "Port, z.B: 465. Automatisch erkannt wenn leer"
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr "Verschlüsseleung"
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr "SMTP Authentifizierung deaktivieren"
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Benutzername"
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr "Benutzername, z.B: myaccount@example.com"
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr "Passwort"
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr "SES API zum Versenden der E-Mails verwenden"
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr "Access Key"
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr "AWS Access Key Id"
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr "Secret Key"
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr "AWS Secret Access Key"
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr "Region"
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr "Am überprüfen"
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr "Mailer-Konfiguration überprüfen"
+
+#: views/settings.hbs:52
+msgid "Don't have an SMTP account yet? Create a free SendPulse account"
+msgstr ""
+"Haben Sie noch kein SMTP-Konto? Erstellen Sie einen kostenloses SendPulse-"
+"Account"
+
+#: views/settings.hbs:53
+msgid "here"
+msgstr "hier"
+
+#: views/settings.hbs:54
+msgid "Advanced Mailer settings"
+msgstr "Erweiterte Mailer-Einstellungen"
+
+#: views/settings.hbs:55
+msgid "Log SMTP transactions"
+msgstr "SMTP-Transaktionen Loggen"
+
+#: views/settings.hbs:56
+msgid "Allow self-signed certificates"
+msgstr "Selbstsignierte Zertifikate zulassen"
+
+#: views/settings.hbs:57
+msgid "Max connections"
+msgstr "Max. Verbindungen"
+
+#: views/settings.hbs:58
+msgid "The count of max connections, eg. 10"
+msgstr "Die Anzahl maximaler Verbindungen, z.B. 10"
+
+#: views/settings.hbs:59
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+"Anzahl der maximalen parallelen Verbindungen zum SMTP-Server (standardmäßig "
+"auf 5). Diese Limite gilt per Sendungsprozess."
+
+#: views/settings.hbs:60
+msgid "Max messages"
+msgstr "Max. Nachrichten"
+
+#: views/settings.hbs:61
+msgid "The count of max messages, eg. 100"
+msgstr "Die Anzahl maximaler Nachrichten, z.B. 100"
+
+#: views/settings.hbs:62
+msgid ""
+"The number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+"Die Anzahl der Nachrichten, die durch eine einzige Verbindung gesendet "
+"werden sollen, bevor die Verbindung geschlossen und wieder geöffnet wird "
+"(standardmäßig 100)"
+
+#: views/settings.hbs:63
+msgid "Throttling"
+msgstr "Throttling"
+
+#: views/settings.hbs:64
+msgid "Messages per hour eg. 1000"
+msgstr "E-Mail-Nachrichten pro Stunde z.B. 1000"
+
+#: views/settings.hbs:65
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+"Maximale Anzahl von E-Mails, die in einer Stunde gesendet werden sollen. "
+"Leer oder 0 bedeutet keine Drosselung. Wenn Ihr Provider eine andere "
+"Geschwindigkeitsbegrenzung (Nachrichten/Minute oder Nachrichten/Sekunde) "
+"verwendet, dann konvertieren Sie diesen Wert in Nachrichten/Stunde (1m/s => "
+"3600m/h). Diese Limite gilt pro Sendungsprozess."
+
+#: views/settings.hbs:66
+msgid "VERP bounce handling"
+msgstr "VERP bounce Handhabung"
+
+#: views/settings.hbs:67
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+"Mailtrain ist in der Lage, VERP-basiertes Routing zu verwenden, um Bounces "
+"zu erkennen. In diesem Fall wird die Nachricht an den Empfänger über eine "
+"benutzerdefinierte VERP-Adresse als Return Path der Nachricht gesendet. Wenn "
+"die Nachricht nicht akzeptiert wird, wird eine Bounce-E-Mail an diese "
+"spezielle VERP-Adresse gesendet und damit ein Bounce erkannt."
+
+#: views/settings.hbs:68
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+"Damit VERP funktioniert, müssen Sie einen DNS MX Record einrichten, der auf "
+"Ihren Mailtrain Hostnamen verweist. Sie müssen auch sicherstellen, dass die "
+"Mailtrain VERP-Schnittstelle von Port 25 Ihres Servers verfügbar ist (Port "
+"25 benötigt normalerweise Root-Benutzerberechtigung). Folglich landen E-"
+"Mails an someuser@verp-hostname auf diesem Server."
+
+#: views/settings.hbs:69
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+"VERP funktioniert in der Regel nur, wenn Sie Ihren eigenen SMTP-Server "
+"verwenden. Reguläre Relay Services (SES, SparkPost, Gmail etc.) neigen dazu, "
+"die VERP-Adresse aus der Nachricht zu entfernen."
+
+#: views/settings.hbs:70
+msgid "Use VERP to catch bounces"
+msgstr "VERP verwenden um bounces zu erfassen"
+
+#: views/settings.hbs:71
+msgid "Server hostname"
+msgstr "Hostname"
+
+#: views/settings.hbs:72
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr "VERP Server Hostname, z.B. bounces.example.com"
+
+#: views/settings.hbs:73
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+"VERP bounce handling Server Hostname. Dieser Hostname wird in der SMTP "
+"envelope FROM Adresse verwendet. Die MX DNS Records sollten auf diesen "
+"Server verweisen"
+
+#: views/settings.hbs:74
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+"VERP Bounce handling Server ist nicht aktiviert. Ändern Sie die Server-"
+"Konfigurationsdatei und starten Sie den Server neu, um ihn zu aktivieren."
+
+#: views/settings.hbs:75
+msgid "GPG Signing"
+msgstr "GPG Signierung"
+
+#: views/settings.hbs:76
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+"Nur verschlüsselte Nachrichten können signiert werden. Abonnenten, die "
+"keinen GPG Public Key in ihrem Profil hinterlegt haben, erhalten normale E-"
+"Mails. Benutzer mit hinterlegtem GPG Key erhalten verschlüsselte Nachrichten "
+"und wenn Sie den Signing Key auch gesetzt haben, werden die Nachrichten mit "
+"diesem Schlüssel signiert."
+
+#: views/settings.hbs:77
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+"Verwenden Sie hier keine sensiblen Keys. Der private Key und Passphrase "
+"werden in der Datenbank nicht verschlüsselt."
+
+#: views/settings.hbs:78
+msgid "Private Key Passphrase"
+msgstr "Private Key Passphrase"
+
+#: views/settings.hbs:79
+msgid "Passphrase for the key if set"
+msgstr "Passwort für den Key falls gesetzt"
+
+#: views/settings.hbs:80
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+"Füllen Sie dies nur aus, wenn Ihr privater Schlüssel mit einer Passphrase "
+"verschlüsselt ist"
+
+#: views/settings.hbs:81
+msgid "GPG Private Key"
+msgstr "GPG Private Key"
+
+#: views/settings.hbs:83
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+"Dieser Wert ist optional. Wenn Sie keinen private Key zur Verfügung stellen "
+"werden GPG verschlüsselte Nachrichten ohne Signierung gesendet."
+
+#: views/settings.hbs:84
+msgid "DKIM Signing by ZoneMTA"
+msgstr "DKIM Signing durch ZoneMTA"
+
+#: views/settings.hbs:85
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+"Wenn Sie ZoneMTA verwenden, kann Mailtrain einen DKIM-Key zur Signierung "
+"aller ausgehenden Nachrichten bereitstellen. Andere Dienste bieten in der "
+"Regel ihre eigenen Mittel an um Ihre E-mails per DKIM zu signieren"
+
+#: views/settings.hbs:86
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+"Verwenden Sie hier keine sensiblen Keys. Der private Key wird in der "
+"Datenbank nicht verschlüsselt."
+
+#: views/settings.hbs:87
+msgid "ZoneMTA DKIM API Key"
+msgstr "ZoneMTA DKIM API Key"
+
+#: views/settings.hbs:88
+msgid "Some secret value"
+msgstr "Ein geheimer Wert"
+
+#: views/settings.hbs:89
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+"Geheimer Wert, der ZoneMTA für die Anforderung von DKIM-"
+"Schlüsselinformationen bekannt ist. Wenn dieser Wert vom Mailtrain-"
+"Installationsskript generiert wurde, können Sie diese Einstellung so "
+"behalten, wie sie ist"
+
+#: views/settings.hbs:90
+msgid "DKIM domain"
+msgstr "DKIM Domain"
+
+#: views/settings.hbs:91
+msgid "Domain name for the DKIM key"
+msgstr "Domain-Name für den DKIM-Key"
+
+#: views/settings.hbs:92
+msgid "Leave blank to use the sender email address domain"
+msgstr "Leer lassen, um die Domain der Sender-E-Mail-Adresse zu verwenden"
+
+#: views/settings.hbs:93 views/settings.hbs:94
+msgid "DKIM key selector"
+msgstr "DKIM Key Selector"
+
+#: views/settings.hbs:95
+msgid "Signing is disabled without a valid selector value"
+msgstr "Signierung ist ohne gültigen Wert deaktiviert"
+
+#: views/settings.hbs:96
+msgid "DKIM Private Key"
+msgstr "DKIM Private Key"
+
+#: views/settings.hbs:98
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+"Dieser Wert ist optional. Wenn Sie keinen privaten Schlüssel bereitstellen, "
+"werden Nachrichten nicht signiert."
+
+#: views/subscription/mail-confirm-html.mjml.hbs:1
+#: views/subscription/mail-confirm-text.hbs:1 routes/subscription.js:551
+msgid "Please Confirm Subscription"
+msgstr "Bitte bestätigen Sie ihr Abonnement"
+
+#: views/subscription/mail-confirm-html.mjml.hbs:2
+#: views/subscription/mail-confirm-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Ja, tragen Sie mich in diese Liste ein"
+
+#: views/subscription/mail-confirm-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Wenn Sie diese E-Mail versehentlich erhalten haben, löschen Sie sie einfach. "
+"Sie werden nicht abonniert, wenn Sie nicht auf den Bestätigungslink oben "
+"klicken."
+
+#: views/subscription/mail-confirm-html.mjml.hbs:4
+#: views/subscription/mail-confirm-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-text.hbs:7
+#: views/subscription/mail-unsubscribe-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-unsubscribe-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "Bei Fragen zu dieser Liste wenden Sie sich bitte an:"
+
+#: views/subscription/mail-confirm-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Wenn Sie diese E-Mail versehentlich erhalten haben, löschen Sie sie einfach. "
+"Sie werden nicht abonniert, es sei denn, Sie klicken auf den "
+"Bestätigungslink oben."
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-subscription-confirmed-text.hbs:1
+#: views/subscription/web-subscribed.mjml.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Abonnement bestätigt"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed"
+msgstr "Ihr Abonnement für unsere Liste wurde bestätigt"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:3
+msgid "If you want to modify your subscription then you can "
+msgstr "Wenn Sie Ihr Abonnement ändern möchten, dann können Sie "
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:4
+msgid "manage your preferences"
+msgstr "Ihre Einstellungen bearbeiten"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-subscription-confirmed-text.hbs:5
+#: views/users/login.hbs:10
+msgid "or"
+msgstr "oder"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:6
+#: views/subscription/mail-subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "diesen Newsletter abbestellen"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:7
+#: views/subscription/web-confirm-notice.mjml.hbs:3
+#: views/subscription/web-subscribed.mjml.hbs:4
+#: views/subscription/web-unsubscribe-notice.mjml.hbs:3
+#: views/subscription/web-updated-notice.mjml.hbs:3
+msgid "Return to our website"
+msgstr "Zurück zu unserer Website"
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:2
+#: views/subscription/web-subscribed.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "Sie wurden erfolgreich in unsere Liste eingetragen."
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Wenn Sie Ihr Abonnement ändern möchten, können Sie:"
+
+#: views/subscription/mail-unsubscribe-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-unsubscribe-confirmed-text.hbs:1
+msgid "You Are Now Unsubscribed"
+msgstr "Sie Sind Nun Abgemeldet"
+
+#: views/subscription/mail-unsubscribe-confirmed-html.mjml.hbs:2
+msgid "We have removed your email address from our list"
+msgstr "Ihre E-Mail-Adresse wurde aus unserer Liste entfernt"
+
+#: views/subscription/mail-unsubscribe-confirmed-html.mjml.hbs:3
+#: views/subscription/mail-unsubscribe-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr ""
+"Wenn Sie sich versehentlich ausgetragen haben, können Sie sich erneut "
+"eintragen:"
+
+#: views/subscription/mail-unsubscribe-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Wir haben Ihre E-Mail-Adresse aus unserer Liste entfernt."
+
+#: views/subscription/partials/subscription-custom-fields.hbs:2
+msgid "want to change it?"
+msgstr "Möchten Sie diese ändern?"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:5
+msgid "Download signature verification key"
+msgstr "Signature-Verification-Key herunterladen"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:7
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+"Fügen Sie hier Ihren GPG-Public Key ein, um Nachrichten zu verschlüsseln, "
+"die an Ihre Adresse gesendet werden"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:8
+msgid "optional"
+msgstr "optional"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:1
+#: views/subscription/partials/subscription-flash-messages.hbs:3
+msgid "Warning!"
+msgstr "Warnung!"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+"Wenn JavaScript nicht aktiviert war, wurde keine Bestätigungs-E-Mail gesendet"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:4
+msgid "JavaScript must be enabled in order for this form to work"
+msgstr "JavaScript muss aktiviert sein, damit dieses Formular funktioniert"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:1
+msgid "Existing Email Address"
+msgstr "Aktuelle E-Mail-Adresse"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:2
+msgid "New Email Address"
+msgstr "Neue E-Mail-Adresse"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:3
+msgid "Your new email address"
+msgstr "Ihre neue E-Mail-Adresse"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:4
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Sie erhalten eine Bestätigungsanforderung an Ihre neue E-Mail-Adresse, die "
+"Sie akzeptieren müssen, bevor Ihre E-Mail tatsächlich geändert wird"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:5
+#: views/subscription/web-manage-address.mjml.hbs:2
+msgid "Update Email Address"
+msgstr "E-Mail-Adresse aktualisieren"
+
+#: views/subscription/partials/subscription-manage-form.hbs:1
+#: views/subscription/web-manage.mjml.hbs:2
+msgid "Update Profile"
+msgstr "Einstellungen aktualisieren"
+
+#: views/subscription/partials/subscription-subscribe-form.hbs:1
+#: views/subscription/web-subscribe.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:1
+msgid "Subscribe to list"
+msgstr "Newsletter abonnieren"
+
+#: views/subscription/web-confirm-notice.mjml.hbs:1
+#: views/subscription/widget-subscribe.hbs:4
+msgid "Almost Finished"
+msgstr "Fast Fertig"
+
+#: views/subscription/web-confirm-notice.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:5
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Wir müssen Ihre E-Mail-Adresse bestätigen. Um den Abo-Prozess abzuschließen, "
+"klicken Sie bitte auf den Link in der E-Mail, die wir Ihnen gerade geschickt "
+"haben."
+
+#: views/subscription/web-manage-address.mjml.hbs:1
+msgid "Update Your Email Address"
+msgstr "E-Mail-Adresse aktualisieren"
+
+#: views/subscription/web-manage.mjml.hbs:1
+msgid "Update Your Preferences"
+msgstr "Einstellungen aktualisieren"
+
+#: views/subscription/web-subscribe.mjml.hbs:1
+msgid "Subscribe to List"
+msgstr "Diese Liste abonnieren"
+
+#: views/subscription/web-subscribed.mjml.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "Danke fürs Abonnieren!"
+
+#: views/subscription/web-unsubscribe-notice.mjml.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Erfolgreich Deabonniert"
+
+#: views/subscription/web-unsubscribe-notice.mjml.hbs:2
+msgid "You have been removed from:"
+msgstr "Sie wurden entfernt von:"
+
+#: views/subscription/web-unsubscribe.mjml.hbs:2
+msgid "Enter your email address to unsubscribe from:"
+msgstr "Geben Sie Ihre E-Mail-Adresse ein, um sich abzumelden von:"
+
+#: views/subscription/web-updated-notice.mjml.hbs:1
+msgid "Profile Updated"
+msgstr "Einstellungen aktualisiert"
+
+#: views/subscription/web-updated-notice.mjml.hbs:2
+msgid "Your profile information has been updated."
+msgstr "Ihre Profilinformationen wurden aktualisiert."
+
+#: views/subscription/widget-subscribe.hbs:2
+msgid "Sending ..."
+msgstr "Am senden …"
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Es sieht so aus, als hätten Sie diese Liste bereits abonniert."
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Vorlagen-Name"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr "Name für diese Vorlage, z.B. Newsletter"
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "HTML Editor"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr "Optionale Kommentare zu dieser Vorlage"
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr "Zurück zu Vorlagen"
+
+#: views/templates/edit.hbs:11
+msgid "Duplicate"
+msgstr "Duplizieren"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr "Automatisierungs-Trigger"
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr "Wählen Sie eine Liste für diesen Trigger"
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr "Trigger-Name"
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr "Name für diesen Trigger, z.B. Inaktive Abonnenten"
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr "Optionale Kommentare zu diesem Trigger"
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr "Trigger-Regel"
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr "Trigger löst aus"
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr "Tage nach:"
+
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Abonnement"
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Ereignis"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Kampagne"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr "Trigger-Aktion"
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr "Kampagne senden"
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr "Trigger bearbeiten"
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr "Zurück zu Triggers"
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr "Trigger ist aktiviert"
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr "Trigger löschen"
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr "Ausgelöst"
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr "Triggered Abonnenten"
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr "Abonnenten, die diesen Trigger ausgelöst haben"
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr "Auslösungszeit"
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr "Trigger"
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr "Ziel-Kampagne"
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr "Anzahl Auslösungen"
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr "Dieses Konto wird über LDAP verwaltet."
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr "Zugehörige E-Mail-Adresse"
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr "Ihre E-Mail-Adresse"
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr ""
+"Diese Adresse wird für die Wiederherstellung des Kontos verwendet, falls Sie "
+"Ihr Passwort vergessen haben"
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr "Passwortänderung"
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+"Sie müssen dieses Formular nur ausfüllen, wenn Sie Ihr aktuelles Passwort "
+"ändern möchten"
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr "Aktuelles Passwort"
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr "Neues Passwort"
+
+#: views/users/account.hbs:16 views/users/reset.hbs:8
+msgid "Confirm Password"
+msgstr "Passwort bestätigen"
+
+#: views/users/account.hbs:17 views/users/reset.hbs:9
+msgid "Confirm New Password"
+msgstr "Neues Passwort bestätigen"
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr ""
+"Sind Sie sicher? Das Zurücksetzen würde das aktuell vorhandene Token "
+"ungültig machen."
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr "Sind Sie sicher?"
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr "Access Token zurücksetzen"
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr "Access Token erstellen"
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr "Persönlicher Access Token:"
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr "Access Token noch nicht erstellt"
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr "Notizen zur API"
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+"API-Antwort ist eine JSON-Struktur mit error und data"
+"code> properties. Wenn die Antwort error einen Wert hat, ist "
+"die Anfrage fehlgeschlagen."
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+"Sie müssen bei der Anfrage einen korrekten Content-Type "
+"definieren. Sie können entweder application/x-www-form-urlencoded"
+"code> für normale Formulardaten oder application/json für eine "
+"JSON-Payload verwenden. Nicht unterstützt wird multipart/form-data"
+"code>."
+
+#: views/users/api.hbs:13
+msgid "Add subscription"
+msgstr "Abonnement hinzufügen"
+
+#: views/users/api.hbs:14
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+"Dieser API-Aufruf fügt entweder ein neues Abonnement hinzu oder aktualisiert "
+"ein bereits vorhandenes Abonnement. Felder, die nicht enthalten sind, "
+"bleiben unverändert. Wenn Sie also nur den Wert LAST_NAME aktualisieren, "
+"bleibt FIRST_NAME für ein bestehendes Abonnement unverändert."
+
+#: views/users/api.hbs:15 views/users/api.hbs:17 views/users/api.hbs:30
+#: views/users/api.hbs:32 views/users/api.hbs:38 views/users/api.hbs:40
+#: views/users/api.hbs:46 views/users/api.hbs:57 views/users/api.hbs:59
+#: views/users/api.hbs:65 views/users/api.hbs:67
+msgid "arguments"
+msgstr "Argumente"
+
+#: views/users/api.hbs:16 views/users/api.hbs:31 views/users/api.hbs:39
+#: views/users/api.hbs:47 views/users/api.hbs:58 views/users/api.hbs:66
+msgid "your personal access token"
+msgstr "Ihr persönlicher Access Token"
+
+#: views/users/api.hbs:18 views/users/api.hbs:33 views/users/api.hbs:41
+msgid "subscriber's email address"
+msgstr "E-Mail-Adresse des Abonnenten"
+
+#: views/users/api.hbs:19 views/users/api.hbs:34 views/users/api.hbs:42
+#: views/users/api.hbs:61 views/users/api.hbs:69
+msgid "required"
+msgstr "erforderlich"
+
+#: views/users/api.hbs:20
+msgid "subscriber's first name"
+msgstr "Vorname des Abonnenten"
+
+#: views/users/api.hbs:21
+msgid "subscriber's last name"
+msgstr "Nachname des Abonnenten"
+
+#: views/users/api.hbs:22
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"Zeitzone des Abonnenten (zB \"Europa/Berlin“, \"PST\" oder \"UTC\"). Falls "
+"nicht gesetzt wird \"UTC\" verwendet."
+
+#: views/users/api.hbs:23
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+"Benutzerdefinierter Feldwert. Verwenden Sie Ja/Nein für Optionsgruppenwerte "
+"(Checkboxen, Radios-Buttons, Dropdowns)"
+
+#: views/users/api.hbs:24
+msgid "Additional POST arguments"
+msgstr "Weitere POST-Argumente"
+
+#: views/users/api.hbs:25
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+"Markieren Sie \"Ja\", wenn Sie sicherstellen möchten, dass die E-Mail als "
+"abonniert markiert ist, auch wenn sie zuvor als abgemeldet markiert wurde. "
+"Wenn die E-Mail-Adresse bereits abbestellt/gesperrt ist, wird der "
+"Abonnementstatus nicht geändert"
+
+#: views/users/api.hbs:26
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+"Markieren Sie \"Ja\", wenn Sie eine Bestätigungs-E-Mail an den Abonnenten "
+"senden möchten, bevor der Abonnent tatsächlich als abonniert markiert wird"
+
+#: views/users/api.hbs:28
+msgid "Remove subscription"
+msgstr "Abonnement entfernen"
+
+#: views/users/api.hbs:29
+msgid "This API call marks a subscription as unsubscribed"
+msgstr "Dieser API-Aufruf markiert ein Abonnement als abbestellt"
+
+#: views/users/api.hbs:36
+msgid "Delete subscription"
+msgstr "Abonnement löschen"
+
+#: views/users/api.hbs:37
+msgid "This API call deletes a subscription"
+msgstr "Dieser API-Aufruf löscht ein Abonnement"
+
+#: views/users/api.hbs:44
+msgid "Get list of blacklisted emails"
+msgstr ""
+
+#: views/users/api.hbs:45
+msgid "This API call get list of blacklisted emails."
+msgstr ""
+
+#: views/users/api.hbs:48
+msgid "Start position"
+msgstr "Startposition"
+
+#: views/users/api.hbs:49
+msgid "optional, default 0"
+msgstr "optional, standard 0"
+
+#: views/users/api.hbs:50
+msgid "limit emails count in response"
+msgstr ""
+
+#: views/users/api.hbs:51
+msgid "optional, default 10000"
+msgstr "optional, standard 10000"
+
+#: views/users/api.hbs:52
+msgid "filter by part of email"
+msgstr ""
+
+#: views/users/api.hbs:53
+msgid "optional, default ''"
+msgstr "optional, standard ''"
+
+#: views/users/api.hbs:56
+msgid "This API call either add emails to blacklist"
+msgstr ""
+
+#: views/users/api.hbs:60 views/users/api.hbs:68
+msgid "email address"
+msgstr "E-Mail-Adresse"
+
+#: views/users/api.hbs:63
+msgid "Delete email from blacklist"
+msgstr "E-Mail aus der Blacklist löschen"
+
+#: views/users/api.hbs:64
+msgid "This API call either delete emails from blacklist"
+msgstr ""
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr "Passwort zurücksetzen"
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr "Ihr Passwort zurücksetzen?"
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr "Accounts werden über LDAP verwaltet."
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr "Passwort zurücksetzen"
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+"Bitte geben Sie den Benutzernamen oder die E-Mail-Adresse an, die Sie bei "
+"der Anmeldung für Ihr Mailtrain-Konto verwendet haben."
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr ""
+"Wir senden Ihnen eine E-Mail, mit der Sie Ihr Passwort zurücksetzen können."
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr "Benutzername oder E-Mail-Adresse"
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr "Verifizierung E-Mail senden"
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Angemeldet bleiben"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "Passwort vergessen?"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr "Wähle Sie Ihr neues Passwort"
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr "Bitte geben Sie ein neues Passwort ein."
+
+#: lib/editor-helpers.js:17 routes/templates.js:95
+msgid "Could not find template with specified ID"
+msgstr "Konnte keine Vorlage mit angegebener ID finden"
+
+#: lib/editor-helpers.js:33 routes/archive.js:145 routes/campaigns.js:131
+#: routes/campaigns.js:284 routes/campaigns.js:379 routes/campaigns.js:427
+#: routes/campaigns.js:467 routes/campaigns.js:844 routes/campaigns.js:867
+#: routes/campaigns.js:886 routes/campaigns.js:908 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr "Konnte keine Kampagne mit dieser ID finden"
+
+#: lib/editor-helpers.js:47 routes/editorapi.js:308
+msgid "Invalid resource type"
+msgstr "Ungültiger Ressourcentyp"
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr "Bad Statuscode %s"
+
+#: lib/helpers.js:32
+msgid "URL that points to the unsubscribe page"
+msgstr "URL, die auf die Abmeldungsseite verweist"
+
+#: lib/helpers.js:35
+msgid "URL that points to the preferences page of the subscriber"
+msgstr ""
+"URL, die auf die Persönliche-Einstellungs-Seite des Teilnehmers verweist"
+
+#: lib/helpers.js:38
+msgid "URL to preview the message in a browser"
+msgstr "URL zur Vorschau der E-Mail im Browser"
+
+#: lib/helpers.js:44 lib/models/segments.js:31
+msgid "First name"
+msgstr "Vorname"
+
+#: lib/helpers.js:47 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Nachname"
+
+#: lib/helpers.js:50
+msgid "Full name (first and last name combined)"
+msgstr "Vollständiger Name (Vor- und Nachname kombiniert)"
+
+#: lib/helpers.js:53
+msgid "Unique ID that identifies the recipient"
+msgstr "Eindeutige ID, die den Empfänger identifiziert"
+
+#: lib/helpers.js:56
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr ""
+"Eindeutige ID, welche die für diese Kampagne verwendete Liste identifiziert"
+
+#: lib/helpers.js:59
+msgid "Unique ID that identifies current campaign"
+msgstr "Eindeutige ID, welche die aktuelle Kampagne identifiziert"
+
+#: lib/helpers.js:67 lib/helpers.js:79
+msgid "content from an RSS entry"
+msgstr "Inhalt aus einem RSS-Eintrag"
+
+#: lib/helpers.js:70
+msgid "RSS entry title"
+msgstr ""
+
+#: lib/helpers.js:73
+msgid "RSS entry date"
+msgstr ""
+
+#: lib/helpers.js:76
+msgid "RSS entry link"
+msgstr ""
+
+#: lib/helpers.js:82
+msgid "RSS entry summary"
+msgstr ""
+
+#: lib/helpers.js:85
+msgid "RSS entry image URL"
+msgstr ""
+
+#: lib/mailer.js:245
+msgid "Invalid mail transport"
+msgstr "Ungültiger Mail-Transport"
+
+#: lib/models/campaigns.js:105 lib/models/campaigns.js:132
+#: lib/models/campaigns.js:205 lib/models/campaigns.js:328
+#: lib/models/campaigns.js:589 lib/models/campaigns.js:721
+msgid "Missing Campaign ID"
+msgstr "Kampagnen-ID fehlt"
+
+#: lib/models/campaigns.js:241
+msgid "Emtpy or too large attahcment"
+msgstr "Leere oder zu große Anhangsdatei"
+
+#: lib/models/campaigns.js:407 lib/models/campaigns.js:598
+msgid "Campaign Name must be set"
+msgstr "Kampagnenname ist erforderlich"
+
+#: lib/models/campaigns.js:411
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr "RSS URL ist erforderlich und muss eine gültige URL sein"
+
+#: lib/models/campaigns.js:567
+msgid "Selected template not found"
+msgstr "Ausgewählte Vorlage nicht gefunden"
+
+#: lib/models/campaigns.js:922
+msgid "Invalid or missing message ID"
+msgstr "Ungültige oder fehlende Nachrichten-ID"
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr "Dropdown-Liste"
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Datum (MM/DD/YYY)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr "JSON-Wert für benutzerdefiniertes Rendering"
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr "Option"
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/forms.js:37 lib/models/lists.js:72 lib/models/lists.js:172
+#: lib/models/lists.js:212 lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:74 lib/models/subscriptions.js:574
+#: lib/models/subscriptions.js:637 lib/models/subscriptions.js:823
+#: lib/models/subscriptions.js:926 lib/models/subscriptions.js:980
+#: lib/models/subscriptions.js:1043 lib/models/subscriptions.js:1086
+msgid "Missing List ID"
+msgstr "Listen-ID fehlt"
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr "Ein Optionsfeld erfordert eine ausgewählte Gruppe"
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr "Feld-ID fehlt"
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr "Feldname ist erforderlich"
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr "Feld nicht gefunden"
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr "Unbekannter Spaltentyp %s"
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr "Spaltenname fehlt"
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr "Listen-ID fehlt"
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr "Die Listen-ID wurde nicht gefunden"
+
+#: lib/models/forms.js:61 lib/models/forms.js:104 lib/models/forms.js:192
+#: lib/models/forms.js:282
+msgid "Missing Form ID"
+msgstr "Formular ID fehlt"
+
+#: lib/models/forms.js:112 lib/models/forms.js:196
+msgid "Form Name must be set"
+msgstr "Formular-Name ist erforderlich"
+
+#: lib/models/forms.js:298
+msgid "Custom form not found"
+msgstr "Formular nicht gefunden"
+
+#: lib/models/links.js:329 routes/campaigns.js:533 routes/campaigns.js:581
+#: routes/campaigns.js:621 routes/campaigns.js:671 services/sender.js:305
+msgid "Campaign not found"
+msgstr "Kampagne nicht gefunden"
+
+#: lib/models/links.js:337 routes/lists.js:177 services/sender.js:312
+msgid "List not found"
+msgstr "Liste nicht gefunden"
+
+#: lib/models/links.js:345
+msgid "Subscription not found"
+msgstr "Abonnement nicht gefunden"
+
+#: lib/models/lists.js:110 lib/models/lists.js:176
+msgid "List Name must be set"
+msgstr "Listennamen ist erforderlich"
+
+#: lib/models/lists.js:241
+msgid "Missing List CID"
+msgstr "Listen CID fehlt"
+
+#: lib/models/report-templates.js:26 lib/models/report-templates.js:70
+#: lib/models/report-templates.js:142
+msgid "Missing report template ID"
+msgstr "Report-Vorlagen-ID fehlt"
+
+#: lib/models/report-templates.js:77
+msgid "Report template name must be set"
+msgstr "Report-Vorlagen-Name ist erforderlich"
+
+#: lib/models/reports.js:39 lib/models/reports.js:109 lib/models/reports.js:187
+msgid "Missing report ID"
+msgstr "Report-ID fehlt"
+
+#: lib/models/reports.js:115
+msgid "Report name must be set"
+msgstr "Report-Name ist erforderlich"
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr "Anmeldungs-Land"
+
+#: lib/models/segments.js:19 lib/models/triggers.js:12
+msgid "Sign up date"
+msgstr "Anmeldungs-Datum"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:16
+msgid "Latest open"
+msgstr "Letzte Öffnung"
+
+#: lib/models/segments.js:27 lib/models/triggers.js:20
+msgid "Latest click"
+msgstr "Letzter Klick"
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr "Segment ID fehlt"
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr "Segment nicht gefunden"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr "%s Tage nach heute"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr "%s Tage vor heute"
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr "heute"
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr "Ungültiger Segment-Regel-Typ"
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr "Ausgewähltes Segment nicht gefunden"
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr "Ungültiger Regel-Typ"
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr "Regel-ID fehlt"
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr "Die Regel wurde nicht gefunden"
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr "Das Segment wurde nicht gefunden"
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr "Ausgewählte Regel nicht gefunden"
+
+#: lib/models/subscriptions.js:148
+msgid "%s: Please Confirm Subscription"
+msgstr "%s: Bitte bestätigen Sie Ihr Abonnement"
+
+#: lib/models/subscriptions.js:258
+msgid "Could not save subscription"
+msgstr "Abonnement konnte nicht gespeichert werden"
+
+#: lib/models/subscriptions.js:441 lib/models/subscriptions.js:471
+msgid "Missing Subscription ID"
+msgstr "Abonnement-ID fehlt"
+
+#: lib/models/subscriptions.js:499
+msgid "Missing Subscription email address"
+msgstr "Abonnement E-Mail Adresse fehlt"
+
+#: lib/models/subscriptions.js:578 lib/models/subscriptions.js:827
+#: lib/models/subscriptions.js:1090
+msgid "Missing subscription ID"
+msgstr "Abonnement-ID fehlt"
+
+#: lib/models/subscriptions.js:641
+msgid "Missing email address"
+msgstr "E-Mail-Adresse fehlt"
+
+#: lib/models/subscriptions.js:930 lib/models/subscriptions.js:984
+#: lib/models/subscriptions.js:1020
+msgid "Missing Import ID"
+msgstr "Import-ID fehlt"
+
+#: lib/models/subscriptions.js:1112
+msgid "Unknown subscription ID"
+msgstr "Unbekannte Abonnement-ID"
+
+#: lib/models/subscriptions.js:1117
+msgid "Nothing seems to be changed"
+msgstr "Nichts scheint sich geändert zu haben"
+
+#: lib/models/subscriptions.js:1131
+msgid "This address is already registered by someone else"
+msgstr "Diese Adresse ist bereits von jemand anderem registriert"
+
+#: lib/models/templates.js:26 lib/models/templates.js:100
+#: lib/models/templates.js:144
+msgid "Missing Template ID"
+msgstr "Vorlagen ID fehlt"
+
+#: lib/models/templates.js:55 lib/models/templates.js:104
+msgid "Template Name must be set"
+msgstr "Vorlagen-Name ist erforderlich"
+
+#: lib/models/triggers.js:29
+msgid "Has Opened"
+msgstr "Hat geöffnet"
+
+#: lib/models/triggers.js:32
+msgid "Has Clicked"
+msgstr "Hat geklickt"
+
+#: lib/models/triggers.js:35
+msgid "Not Opened"
+msgstr "Nicht geöffnet"
+
+#: lib/models/triggers.js:38
+msgid "Not Clicked"
+msgstr "Nicht geklickt"
+
+#: lib/models/triggers.js:175 lib/models/triggers.js:212
+msgid "Missing or invalid list ID"
+msgstr "Fehlende oder ungültige Listen ID"
+
+#: lib/models/triggers.js:179 lib/models/triggers.js:264
+msgid "Days in the past are not allowed"
+msgstr "Tage in der Vergangenheit sind nicht erlaubt"
+
+#: lib/models/triggers.js:183 lib/models/triggers.js:204
+#: lib/models/triggers.js:268 lib/models/triggers.js:289
+msgid "Missing or invalid trigger rule"
+msgstr "Fehlende oder ungültige Trigger-Regel"
+
+#: lib/models/triggers.js:190 lib/models/triggers.js:275
+msgid "Invalid subscription configuration"
+msgstr "Ungültige Abonnement-Konfiguration"
+
+#: lib/models/triggers.js:197 lib/models/triggers.js:282
+msgid "Invalid campaign configuration"
+msgstr "Kampagnen Konfiguration ungültig"
+
+#: lib/models/triggers.js:200 lib/models/triggers.js:285
+msgid "A campaing can not be a target for itself"
+msgstr "Eine Kampagne kann kein Ziel für sich selbst sein"
+
+#: lib/models/triggers.js:233
+msgid "Could not store trigger row"
+msgstr "Trigger-Zeile konnte nicht gespeichert werden"
+
+#: lib/models/triggers.js:250
+msgid "Missing or invalid Trigger ID"
+msgstr "Trigger-ID fehlt oder ist ungültig"
+
+#: lib/models/triggers.js:317
+msgid "Missing Trigger ID"
+msgstr "Trigger-ID fehlt"
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr "Der Benutzer konnte nicht gespeichert werden"
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr "E-Mail-Adresse ist erforderlich"
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr "Fehler beim Überprüfen der Benutzerdaten"
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+"E-Mail-Adresse konnte nicht geändert werden, da ein anderer Benutzer mit "
+"derselben E-Mail-Adresse bereits existiert"
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr "Aktuelles Passwort inkorrekt"
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr "Neues Passwort fehlt"
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr "Passwörter stimmen nicht überein"
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr "Benutzer-ID nicht vorhanden"
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr "Benutzername ist erforderlich"
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr "Mailer Passwort Änderungsanfrage"
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr "Fehlender Benutzername oder Reset-Token"
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Neues Passwort ist ungültig"
+
+#: lib/passport.js:40
+msgid "%s logged out"
+msgstr "%s hat sich abgemeldet"
+
+#: lib/passport.js:53
+msgid "Failed to authenticate user"
+msgstr "Der Benutzer konnte nicht authentifiziert werden"
+
+#: lib/passport.js:69
+msgid "Logged in as %s"
+msgstr "Eingeloggt als %s"
+
+#: lib/passport.js:128
+msgid "Incorrect username or password"
+msgstr "Falscher Benutzername oder Passwort"
+
+#: lib/subscription-mail-helpers.js:39
+msgid "%s: Email Address Already Registered"
+msgstr "%s: Email-Adresse bereits registriert"
+
+#: lib/subscription-mail-helpers.js:49
+msgid "%s: Please Confirm Email Change in Subscription"
+msgstr "%s: Bitte bestätigen Sie die Änderung der Email-Adresse"
+
+#: lib/subscription-mail-helpers.js:69
+msgid "%s: Please Confirm Unsubscription"
+msgstr "%s: Bitte bestätigen Sie die Kündigung des Abonnements"
+
+#: lib/subscription-mail-helpers.js:76
+msgid "%s: Unsubscription Confirmed"
+msgstr "%s: Kündigung des Abonnements bestätigt"
+
+#: lib/tools.js:148
+msgid "Blocked email address \"%s\""
+msgstr "Gesperrte E-Mail-Adresse \"%s\""
+
+#: lib/tools.js:157
+msgid "Invalid email address \"%s\"."
+msgstr "Ungültige E-Mail-Adresse \"%s\"."
+
+#: lib/tools.js:160
+msgid "MX record not found for domain"
+msgstr "MX-Record für die Domäne nicht gefunden"
+
+#: lib/tools.js:163
+msgid "Address domain not found"
+msgstr "Address-Domain nicht gefunden"
+
+#: lib/tools.js:166
+msgid "Address domain name is required"
+msgstr "Address-Domain-Name ist erforderlich"
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:224
+msgid "Not Found"
+msgstr "Nicht gefunden"
+
+#: routes/archive.js:121 services/sender.js:449
+msgid "Received status code %s from %s"
+msgstr "Empfangener Statuscode %s von %s"
+
+#: routes/archive.js:153 routes/campaigns.js:894
+msgid "Attachment not found"
+msgstr "Anhangs-Datei nicht gefunden"
+
+#: routes/blacklist.js:13 routes/campaigns.js:26 routes/editorapi.js:35
+#: routes/fields.js:13 routes/forms.js:16 routes/grapejs.js:13
+#: routes/lists.js:50 routes/mosaico.js:14 routes/report-templates.js:20
+#: routes/reports.js:22 routes/segments.js:13 routes/settings.js:23
+#: routes/templates.js:18 routes/triggers.js:18 routes/users.js:75
+#: routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Sie müssen angemeldet sein, um auf geschützte Inhalte zuzugreifen."
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr "Kampagne konnte nicht erstellt werden"
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr "Die Kampagne “%s” wurde erstellt"
+
+#: routes/campaigns.js:209
+msgid "Campaign settings updated"
+msgstr "Kampagnen-Einstellungen aktualisiert"
+
+#: routes/campaigns.js:211
+msgid "Campaign settings not updated"
+msgstr "Kampagnen-Einstellungen nicht aktualisiert"
+
+#: routes/campaigns.js:227 routes/campaigns.js:744
+msgid "Campaign deleted"
+msgstr "Kampagne gelöscht"
+
+#: routes/campaigns.js:229 routes/campaigns.js:746
+msgid "Could not delete specified campaign"
+msgstr "Die Kampagne konnte nicht gelöscht werden"
+
+#: routes/campaigns.js:248
+msgid "Idling"
+msgstr "Ruhend"
+
+#: routes/campaigns.js:251
+msgid "Scheduled"
+msgstr "Geplant"
+
+#: routes/campaigns.js:257
+msgid "Paused"
+msgstr "Pausiert"
+
+#: routes/campaigns.js:259
+msgid "Inactive"
+msgstr "Inaktiv"
+
+#: routes/campaigns.js:261
+msgid "Active"
+msgstr "Aktiv"
+
+#: routes/campaigns.js:263
+msgid "Other"
+msgstr "Andere"
+
+#: routes/campaigns.js:421
+msgid "Unknown status selector"
+msgstr "Unbekannter Status-Selektor"
+
+#: routes/campaigns.js:762
+msgid "Scheduled sending"
+msgstr "Senden geplant"
+
+#: routes/campaigns.js:764
+msgid "Could not schedule sending"
+msgstr "Versand konnte nicht geplant werden"
+
+#: routes/campaigns.js:776
+msgid "Sending resumed"
+msgstr "Versand wieder aufgenommen"
+
+#: routes/campaigns.js:778
+msgid "Could not resume sending"
+msgstr "Versand konnte nicht fortgesetzt werden"
+
+#: routes/campaigns.js:790
+msgid "Sending reset"
+msgstr "Versand zurückgesetzt"
+
+#: routes/campaigns.js:792
+msgid "Could not reset sending"
+msgstr "Versand konnte nicht zurückgesetzt werden"
+
+#: routes/campaigns.js:804 routes/campaigns.js:832
+msgid "Sending paused"
+msgstr "Versand pausiert"
+
+#: routes/campaigns.js:806 routes/campaigns.js:834
+msgid "Could not pause sending"
+msgstr "Versand konnte nicht pausiert werden"
+
+#: routes/campaigns.js:818
+msgid "Sending activated"
+msgstr "Versand aktiviert"
+
+#: routes/campaigns.js:820
+msgid "Could not activate sending"
+msgstr "Versand konnte nicht aktiviert werden"
+
+#: routes/campaigns.js:855
+msgid "Attachment uploaded"
+msgstr "Anhang hochgeladen"
+
+#: routes/campaigns.js:857
+msgid "Could not store attachment"
+msgstr "Anhang konnte nicht gespeichert werden"
+
+#: routes/campaigns.js:874
+msgid "Attachment deleted"
+msgstr "Anhang gelöscht"
+
+#: routes/campaigns.js:876
+msgid "Could not delete attachment"
+msgstr "Anhang konnte nicht gelöscht werden"
+
+#: routes/editorapi.js:41
+msgid "Invalid editor name"
+msgstr "Ungültiger Editorname"
+
+#: routes/editorapi.js:237 routes/editorapi.js:275
+msgid "Method not supported"
+msgstr "Methode wird nicht unterstützt"
+
+#: routes/editorapi.js:352
+msgid "Invalid resource type or ID"
+msgstr "Ungültiger Ressourcentyp oder ID"
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/forms.js:31 routes/forms.js:63 routes/forms.js:94
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr "Ausgewählte Listen ID nicht gefunden"
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr "Feld konnte nicht erstellt werden"
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr "Ausgewähltes Feld nicht gefunden"
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr "Feld Einstellungen aktualisiert"
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr "Feld Einstellungen nicht aktualisiert"
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr "Benutzerdefiniertes Feld gelöscht"
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr "Das angegebene Feld konnte nicht gelöscht werden"
+
+#: routes/forms.js:78
+msgid "Could not create custom form"
+msgstr "Formular konnte nicht erstellt werden"
+
+#: routes/forms.js:105
+msgid "Selected form not found"
+msgstr "Das Formular wurde nicht gefunden"
+
+#: routes/forms.js:136
+msgid "The plaintext version for this email"
+msgstr "Die Textversion für dieses E-Mail"
+
+#: routes/forms.js:137
+msgid "Custom forms use MJML for formatting"
+msgstr "Formulare verwenden MJML zur formatierung"
+
+#: routes/forms.js:138
+msgid "See the MJML documentation here"
+msgstr ""
+"Die MJML Dokumentation finden Sie hier"
+
+#: routes/forms.js:146
+msgid "Layout"
+msgstr "Layout"
+
+#: routes/forms.js:152
+msgid "Form Input Style"
+msgstr "Formular Input Style"
+
+#: routes/forms.js:154
+msgid ""
+"This CSS stylesheet defines the appearance of form input elements and alerts"
+msgstr ""
+"Dieses CSS-Stylesheet definiert das Aussehen von Formulareingabeelementen "
+"und Warnungen"
+
+#: routes/forms.js:160
+msgid "Web - Subscribe"
+msgstr "Web - Abonnieren"
+
+#: routes/forms.js:165
+msgid "Web - Confirm Notice"
+msgstr "Web - Bestätigung erforderlich"
+
+#: routes/forms.js:170
+msgid "Mail - Confirm Subscription (MJML)"
+msgstr "Mail - Bestätigung erforderlich (MJML)"
+
+#: routes/forms.js:175
+msgid "Mail - Confirm Subscription (Text)"
+msgstr "Mail - Bestätigung erforderlich (Text)"
+
+#: routes/forms.js:180
+msgid "Web - Subscribed Notice"
+msgstr "Web - Notiz: Abonnement bestätigt"
+
+#: routes/forms.js:185
+msgid "Mail - Subscription Confirmed (MJML)"
+msgstr "Mail - Abonnement bestätigt (MJML)"
+
+#: routes/forms.js:190
+msgid "Mail - Subscription Confirmed (Text)"
+msgstr "Mail - Abonnement bestätigt (Text)"
+
+#: routes/forms.js:198
+msgid "Web - Manage Preferences"
+msgstr "Web - Profil bearbeiten"
+
+#: routes/forms.js:203
+msgid "Web - Manage Address"
+msgstr "Web - E-Mail-Adresse bearbeiten"
+
+#: routes/forms.js:208
+msgid "Web - Updated Notice"
+msgstr "Web - Aktualisiert"
+
+#: routes/forms.js:216
+msgid "Web - Unsubscribe"
+msgstr "Web - Abmelden"
+
+#: routes/forms.js:221
+msgid "Web - Unsubscribe Notice"
+msgstr "Web - Abmelden"
+
+#: routes/forms.js:226
+msgid "Mail - Unsubscribe Confirmed (MJML)"
+msgstr "Mail - Abmeldung bestätigt (MJML)"
+
+#: routes/forms.js:231
+msgid "Mail - Unsubscribe Confirmed (Text)"
+msgstr "Mail - Abmeldung bestätigt (Text)"
+
+#: routes/forms.js:269
+msgid "Form settings updated"
+msgstr "Formular-Einstellungen aktualisiert"
+
+#: routes/forms.js:271
+msgid "Form settings not updated"
+msgstr "Formular-Einstellungen nicht aktualisiert"
+
+#: routes/forms.js:287
+msgid "Custom form deleted"
+msgstr "Formular wurde gelöscht"
+
+#: routes/forms.js:289
+msgid "Could not delete specified form"
+msgstr "Das Formular konnte nicht gelöscht werden"
+
+#: routes/index.js:11
+msgid "Self Hosted Newsletter App"
+msgstr "Selbst gehostete Newsletter-App"
+
+#: routes/links.js:39
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr ""
+"Ups, wir konnten keinen Link für die URL finden, die Sie geklickt haben"
+
+#: routes/lists.js:80
+msgid "Could not create list"
+msgstr "Die Liste konnte nicht erstellt werden"
+
+#: routes/lists.js:83
+msgid "List created"
+msgstr "Liste erstellt"
+
+#: routes/lists.js:91 routes/lists.js:267 routes/lists.js:332
+#: routes/lists.js:371 routes/lists.js:440 routes/lists.js:465
+#: routes/lists.js:510 routes/lists.js:532 routes/lists.js:561
+#: routes/lists.js:640 routes/lists.js:697 routes/lists.js:724
+msgid "Could not find list with specified ID"
+msgstr "Die Liste mit angegebener ID konnte nicht gefunden werden"
+
+#: routes/lists.js:118
+msgid "List settings updated"
+msgstr "Listeneinstellungen aktualisiert"
+
+#: routes/lists.js:120
+msgid "List settings not updated"
+msgstr "Listeneinstellungen nicht aktualisiert"
+
+#: routes/lists.js:138
+msgid "List deleted"
+msgstr "Liste gelöscht"
+
+#: routes/lists.js:140
+msgid "Could not delete specified list"
+msgstr "Die Liste konnte nicht gelöscht werden"
+
+#: routes/lists.js:202
+msgid "Unknown"
+msgstr "Unbekannt"
+
+#: routes/lists.js:202
+msgid "Complained"
+msgstr "Beschwert"
+
+#: routes/lists.js:233
+msgid "Invalid key"
+msgstr "Ungültiger Key"
+
+#: routes/lists.js:235
+msgid "Expired key"
+msgstr "Abgelaufener Key"
+
+#: routes/lists.js:237
+msgid "Revoked key"
+msgstr "Widerrufener Key"
+
+#: routes/lists.js:287
+msgid "Initializing"
+msgstr "Initialisierung"
+
+#: routes/lists.js:290
+msgid "Initialized"
+msgstr "Initialisiert"
+
+#: routes/lists.js:293
+msgid "Importing"
+msgstr "Importieren"
+
+#: routes/lists.js:299
+msgid "Errored"
+msgstr "Fehlerhaft"
+
+#: routes/lists.js:377 routes/lists.js:446 routes/lists.js:471
+msgid "Could not find subscriber with specified ID"
+msgstr "Der Abonnent mit angegebenen ID konnte nicht gefunden werden"
+
+#: routes/lists.js:423
+msgid "Could not add subscription"
+msgstr "Das Abonnement konnte nicht hinzugefügt werden"
+
+#: routes/lists.js:428
+msgid "%s was successfully added to your list"
+msgstr "%s wurde Ihrer Liste erfolgreich hinzugefügt"
+
+#: routes/lists.js:430
+msgid "%s was not added to your list"
+msgstr "%s wurde nicht zu Ihrer Liste hinzugefügt"
+
+#: routes/lists.js:452
+msgid "Could not unsubscribe user"
+msgstr "Der Benutzer konnte nicht deabonniert werden"
+
+#: routes/lists.js:455
+msgid "%s was successfully unsubscribed from your list"
+msgstr "%s wurde erfolgreich von Ihrer Liste entfernt"
+
+#: routes/lists.js:475
+msgid "%s was successfully removed from your list"
+msgstr "%s wurde erfolgreich aus Ihrer Liste entfernt"
+
+#: routes/lists.js:487
+msgid "Another subscriber with email address %s already exists"
+msgstr "Ein anderer Abonnent mit der E-Mail-Adresse %s existiert bereits"
+
+#: routes/lists.js:494
+msgid "Subscription settings updated"
+msgstr "Abonnementeinstellungen aktualisiert"
+
+#: routes/lists.js:496
+msgid "Subscription settings not updated"
+msgstr "Abonnementeinstellungen nicht aktualisiert"
+
+#: routes/lists.js:538 routes/lists.js:646 routes/lists.js:682
+#: routes/lists.js:710 routes/lists.js:730
+msgid "Could not find import data with specified ID"
+msgstr "Keine Importdaten für diese ID gefunden"
+
+#: routes/lists.js:569
+msgid "Could not process CSV"
+msgstr "CSV-Datei konnte nicht verarbeitet werden"
+
+#: routes/lists.js:578
+msgid "Could not create importer"
+msgstr "Importer konnte nicht erstellt werden"
+
+#: routes/lists.js:629
+msgid "Empty file"
+msgstr "Leere Datei"
+
+#: routes/lists.js:686
+msgid "Import started"
+msgstr "Import gestartet"
+
+#: routes/lists.js:714
+msgid "Import restarted"
+msgstr "Import neu gestartet"
+
+#: routes/lists.js:797
+msgid "One-step (i.e. no email with confirmation link)"
+msgstr "Ein Schritt ohne Formular (direkt nach dem Klicken auf den Link erfolgt die Abmeldung)"
+
+#: routes/lists.js:803
+msgid ""
+"One-step with unsubscription form (i.e. no email with confirmation link)"
+msgstr ""
+"Ein Schritt mit Formular (nach dem Klick wird ein Formular mit der E-Mail Adresse angezeigt)"
+
+#: routes/lists.js:809
+msgid "Two-step (i.e. an email with confirmation link will be sent)"
+msgstr "Zwei Schritte ohne Formular (direkt nach dem Klick auf den Link wird eine E-Mail mit Bestätigungslink versendet)"
+
+#: routes/lists.js:815
+msgid ""
+"Two-step with unsubscription form (i.e. an email with confirmation link will "
+"be sent)"
+msgstr ""
+"Zwei Schritte mit Formular (nach dem Klick wird ein Formular mit der E-Mail Adresse " "angezeigt, dann wird eine E-Mail mit Bestätigungslink versendet)"
+
+#: routes/lists.js:821
+msgid ""
+"Manual (i.e. unsubscription has to be performed by the list administrator)"
+msgstr ""
+"Manuell (die Abmeldung muss durch den Listen Admin vorgenommen werden)"
+
+#: routes/report-templates.js:246
+msgid "Could not create report template"
+msgstr "Report-Vorlage konnte nicht erstellt werden"
+
+#: routes/report-templates.js:249
+msgid "Report template “%s” created"
+msgstr "Die Report-Vorlage “%s” wurde erstellt"
+
+#: routes/report-templates.js:257
+msgid "Could not find report template with specified ID"
+msgstr "Report-Vorlage mit angegebener ID konnte nicht gefunden werden"
+
+#: routes/report-templates.js:280
+msgid "Report template updated"
+msgstr "Report-Vorlage aktualisiert"
+
+#: routes/report-templates.js:282
+msgid "Report template not updated"
+msgstr "Report-Vorlage wurde nicht aktualisiert"
+
+#: routes/report-templates.js:298
+msgid "Report template deleted"
+msgstr "Report-Vorlage gelöscht"
+
+#: routes/report-templates.js:300
+msgid "Could not delete specified report template"
+msgstr "Die Report-Vorlage konnte nicht gelöscht werden"
+
+#: routes/reports.js:124 routes/reports.js:130
+msgid "Could not create report"
+msgstr "Der Report konnte nicht erstellt werden"
+
+#: routes/reports.js:135
+msgid "Report “%s” created"
+msgstr "Report “%s” erstellt"
+
+#: routes/reports.js:146 routes/reports.js:224 routes/reports.js:239
+#: routes/reports.js:265 routes/reports.js:275
+msgid "Could not find report with specified ID"
+msgstr "Der Report mit dieser ID konnte nicht gefunden werden"
+
+#: routes/reports.js:188 routes/reports.js:194
+msgid "Could not update report"
+msgstr "Der Report konnte nicht aktualisiert werden"
+
+#: routes/reports.js:197
+msgid "Report updated"
+msgstr "Report aktualisiert"
+
+#: routes/reports.js:199
+msgid "Report not updated"
+msgstr "Report nicht aktualisiert"
+
+#: routes/reports.js:212
+msgid "Report deleted"
+msgstr "Report gelöscht"
+
+#: routes/reports.js:214
+msgid "Could not delete specified report"
+msgstr "Der Report konnte nicht gelöscht werden"
+
+#: routes/reports.js:230
+msgid "Could not find report template"
+msgstr "Report-Vorlage konnte nicht gefunden werden"
+
+#: routes/reports.js:260
+msgid "Unknown type of template"
+msgstr "Unbekannter Mime-Type des Template"
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr "Segment konnte nicht erstellt werden"
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr "Segment erstellt"
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr "Ausgewählte Segment-ID wurde nicht gefunden"
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr "Segmenteinstellungen aktualisiert"
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr "Segmenteinstellungen nicht aktualisiert"
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr "Segment gelöscht"
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr "Das angegebene Segment konnte nicht gelöscht werden"
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr "Regel konnte nicht erstellt werden"
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr "Regel erstellt"
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr "Regeleinstellungen aktualisiert"
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr "Regeleinstellungen nicht aktualisiert"
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr "Regel gelöscht"
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr "Die Regel konnte nicht gelöscht werden"
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "TLS verwenden"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "Normalerweise ausgewählt für Port 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "STARTTLS verwenden"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "normalerweise ausgewählt für Port 587 und 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "Keine Verschlüsselung verwenden"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Einstellungen aktualisiert"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Ungültiger Mail Transport Type"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Ungültiger Access Key"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "Ungültige AWS Zugangsdaten"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Verbindung abgelehnt, überprüfen Sie Hostname und Port."
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"Keine Grußnachricht vom Server erhalten. Dies kann bei der Verbindung zu "
+"einem TLS-Port ohne TLS auftreten."
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "Keine Grußnachricht vom Server erhalten."
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Zeitüberschreitung der Verbindung. Überprüfen Sie Ihre Firewall-"
+"Einstellungen, der Ziel-Port ist wahrscheinlich blockiert."
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr ""
+"Authentifizierung nicht akzeptiert, Server erwartet die Verwendung von "
+"STARTTLS."
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr ""
+"Authentifizierung fehlgeschlagen, Benutzername und Passwort überprüfen."
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "Mailer Überprüfung fehlgeschlagen."
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Server antwortete mit: \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr "Mailer-Einstellungen überprüft, bereit zum Senden!"
+
+#: routes/subscription.js:32
+msgid "Not allowed by CORS"
+msgstr "Nicht erlaubt von CORS"
+
+#: routes/subscription.js:50
+msgid "Selected subscription not found"
+msgstr "Ausgewähltes Abonnement nicht gefunden"
+
+#: routes/subscription.js:60 routes/subscription.js:181
+#: routes/subscription.js:266 routes/subscription.js:324
+#: routes/subscription.js:377 routes/subscription.js:429
+#: routes/subscription.js:511 routes/subscription.js:562
+#: routes/subscription.js:638 routes/subscription.js:660
+#: routes/subscription.js:720 routes/subscription.js:744
+#: routes/subscription.js:809
+msgid "Selected list not found"
+msgstr "Ausgewählte Liste nicht gefunden"
+
+#: routes/subscription.js:134
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Abonnement bestätigt"
+
+#: routes/subscription.js:184 routes/subscription.js:514
+msgid "The list does not allow public subscriptions."
+msgstr "Die Liste erlaubt keine öffentlichen Abonnements."
+
+#: routes/subscription.js:493 routes/subscription.js:495
+msgid "Email address not set"
+msgstr "E-Mail-Adresse nicht gesetzt"
+
+#: routes/subscription.js:538
+msgid "Could not store confirmation data"
+msgstr "Die Bestätigungsdaten konnten nicht gespeichert werden"
+
+#: routes/subscription.js:576 routes/subscription.js:675
+#: routes/subscription.js:759
+msgid "Subscription not found from this list"
+msgstr "Abonnement konnte in dieser Liste nicht gefunden werden"
+
+#: routes/subscription.js:735
+msgid "Email address updated, check your mailbox for verification instructions"
+msgstr ""
+"Die E-Mail-Adresse wurde aktualisiert. Bitte überprüfen Sie Ihre Mailbox zur "
+"Bestätigung"
+
+#: routes/subscription.js:858
+msgid "%s: Unsubscribe Confirmed"
+msgstr "%s: Abmeldungen Bestätigt"
+
+#: routes/subscription.js:905 routes/subscription.js:921
+msgid "Public key is not set"
+msgstr "Public-Key ist nicht gesetzt"
+
+#: routes/templates.js:84
+msgid "Could not create template"
+msgstr "Vorlage konnte nicht erstellt werden"
+
+#: routes/templates.js:87
+msgid "Template created"
+msgstr "Vorlage erstellt"
+
+#: routes/templates.js:126
+msgid "Template settings updated"
+msgstr "Vorlageneinstellungen aktualisiert"
+
+#: routes/templates.js:128
+msgid "Template settings not updated"
+msgstr "Template Einstellungen wurden nicht aktualisiert"
+
+#: routes/templates.js:144
+msgid "Template deleted"
+msgstr "Vorlage gelöscht"
+
+#: routes/templates.js:146
+msgid "Could not delete specified template"
+msgstr "Die Vorlage konnte nicht gelöscht werden"
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr "Die ausgewählte Liste konnte nicht gefunden werden"
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr "Trigger konnte nicht erstellt werden"
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr "Trigger “%s” erstellt"
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr "Trigger-Einstellungen aktualisiert"
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr "Trigger-Einstellungen nicht aktualisiert"
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr "Trigger gelöscht"
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr "Der Trigger konnte nicht gelöscht werden"
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr "Der Trigger mit dieser ID konnte nicht gefunden werden"
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr "Trigger nicht gefunden"
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+"Eine E-Mail mit Passwort-Reset-Anweisungen wurde an Ihre E-Mail-Adresse "
+"gesendet, wenn die E-Mail-Adresse auf unserem System existiert."
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr "Unbekanntes oder abgelaufenes Reset-Token"
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "Ihr Passwort wurde erfolgreich geändert"
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr "Benutzerdaten nicht gefunden"
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr "Access Token aktualisiert"
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr "Access Token nicht aktualisiert"
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr "Account-Informationen aktualisiert"
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr "Account-Informationen nicht aktualisiert"
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr "Feed Fehler: %s"
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr "Fand %s neue Kampagnen-Nachrichten im Feed"
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr "Im Feed wurde nichts neues gefunden"
+
+#: services/feedcheck.js:146
+msgid "RSS entry %s"
+msgstr "RSS Eintrag %s"
+
+#: services/importer.js:249
+msgid "Could not access import file"
+msgstr "Auf die Importdatei konnte nicht zugegriffen werden"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr "Unbekannter Trigger-Typ %s"
+
+#~ msgid "Add new custom field"
+#~ msgstr "Neues benutzerdefiniertes Feld hinzufügen"
+
+#~ msgid "field name"
+#~ msgstr "Feldname"
+
+#~ msgid "one of the following types:"
+#~ msgstr "Einer der folgenden Typen:"
+
+#~ msgid ""
+#~ "If the type is 'option' then you also need to specify the parent element "
+#~ "ID"
+#~ msgstr ""
+#~ "Wenn der Typ 'Option' ist, dann müssen Sie auch die übergeordnete Element-"
+#~ "ID angeben"
+
+#~ msgid ""
+#~ "Template for the group element. If not set, then values of the elements "
+#~ "are joined with commas"
+#~ msgstr ""
+#~ "Vorlage für das Gruppenelement. Wenn nicht gesetzt, dann werden die Werte "
+#~ "der Elemente mit Kommas verbunden"
+
+#~ msgid ""
+#~ "if not visible then the subscriber can not view or modify this value at "
+#~ "the profile page"
+#~ msgstr ""
+#~ "Wenn nicht sichtbar, kann der Abonnent diesen Wert auf der Profilseite "
+#~ "weder sehen noch bearbeiten"
+
+#~ msgid "You are now unsubscribed"
+#~ msgstr "Sie sind jetzt aus dieser Liste ausgetragen"
+
+#~ msgid "List management"
+#~ msgstr "Listenverwaltung"
+
+#~ msgid "Custom fields"
+#~ msgstr "Benutzerdefinierte Felder"
+
+#~ msgid "List segmentation"
+#~ msgstr "Listensegmentierung"
+
+#~ msgid "Donate to author"
+#~ msgstr "Spenden willkommen"
+
+#~ msgid "or donate using PayPal"
+#~ msgstr "Oder spenden Sie mit PayPal"
+
+#~ msgid "Click stats"
+#~ msgstr "Klick Statistiken"
+
+#~ msgid "Open source"
+#~ msgstr "Open source"
+
+#~ msgid "Send via any provider"
+#~ msgstr "Senden Sie über jeden Anbieter"
+
+#~ msgid "Trigger based automation"
+#~ msgstr "Triggerbasierte Automatisierung"
+
+#~ msgid "Self hosted newsletter app built on top of Nodemailer"
+#~ msgstr "Selbst gehostete Newsletter-App basierend auf Nodemailer"
+
+#~ msgid "Subscribe to our newsletter"
+#~ msgstr "Abonnieren Sie unseren Newsletter"
+
+#~ msgid "To extract the text from HTML click"
+#~ msgstr "Um den Klartext aus dem HTML Dokument zu extrahieren, klicken Sie"
+
+#~ msgid "Almost finished."
+#~ msgstr "Fast fertig."
+
+#~ msgid "return to our website"
+#~ msgstr "zurück zu unserer Webseite"
+
+#~ msgid "Update your Email Address"
+#~ msgstr "E-Mail-Adresse aktualisieren"
+
+#~ msgid "Update your preferences"
+#~ msgstr "Einstellungen aktualisieren"
+
+#~ msgid ""
+#~ "JavaScript must be enabled in order for the subscription form to work"
+#~ msgstr ""
+#~ "JavaScript muss aktiviert sein, damit das Anmeldeformular funktionieren "
+#~ "kann"
+
+#~ msgid "continue to our website"
+#~ msgstr "weiter zu unserer Webseite"
+
+#~ msgid ""
+#~ "If you really like Mailtrain or your business benefits from it "
+#~ "financially then I would really appreciate a small donation to keep the "
+#~ "Mailtrain development engines running. You can either use Bitcoin or "
+#~ "PayPal for donations. My Bitcoin wallet is "
+#~ "15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM"
+#~ msgstr ""
+#~ "Loren Ipsum it financially then I would really appreciate a small "
+#~ "donation to keep the Mailtrain development engines running. You can "
+#~ "either use Bitcoin or PayPal for donations. My Bitcoin wallet is "
+#~ "15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM"
+
+#~ msgid ""
+#~ "We have received a password change request for your Mailtrain account"
+#~ msgstr ""
+#~ "Wir haben eine Passwortänderungsanfrage für Ihr Mailtrain-Konto erhalten"
+
+#~ msgid "Reset password:"
+#~ msgstr "Passwort zurücksetzen:"
+
+#~ msgid "(optional)"
+#~ msgstr "(optional)"
+
+#~ msgid "–– Select ––"
+#~ msgstr "— Bitte wählen —"
+
+#~ msgid "You have been removed from"
+#~ msgstr "Sie wurden aus dieser Liste ausgetragen:"
+
+#~ msgid "Enter your email address to unsubscribe from"
+#~ msgstr "Geben Sie Ihre E-Mail-Adresse ein, um sich abzumelden von"
+
+#~ msgid "Yes, subscribe me to this list:"
+#~ msgstr "Ja, tragen Sie mich in diese Liste ein:"
+
+#: lib/models/subscriptions.js:910 routes/subscription.js:472
+#: routes/subscription.js:544 routes/subscription.js:580
+#: routes/subscription.js:696 routes/subscription.js:771
+msgid "Subscription not found in this list"
+msgstr "Das Abonnement wurde in dieser Liste nicht gefunden"
+
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:2
+msgid ""
+"We need to confirm your email address. To complete the unsubscription "
+"process, please click the link in the email we just sent you."
+msgstr ""
+"Wir müssen Ihre E-Mail-Adresse bestätigen. Um die Kündigung Ihres Abonnements abzuschließen, "
+"klicken Sie bitte auf den Link in der E-Mail, die wir Ihnen gerade geschickt "
+"haben."
+
+msgid "Please Confirm Unsubscription"
+msgstr "Bitte bestätigen Sie die Kündigung Ihres Abonnements"
+
+msgid "Yes, unsubscribe me from this list"
+msgstr "Ja, ich möchte dieses Abonnement kündigen"
+
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed if you don't click the confirmation link above."
+msgstr ""
+"Wenn Sie diese E-Mail versehentlich erhalten haben, löschen Sie sie einfach. "
+"Ihr Abonnement wird nicht gekündigt, wenn Sie nicht auf den Bestätigungslink oben klicken."
diff --git a/languages/es_ES.mo b/languages/es_ES.mo
new file mode 100644
index 00000000..214acc8a
Binary files /dev/null and b/languages/es_ES.mo differ
diff --git a/languages/es_ES.po b/languages/es_ES.po
new file mode 100644
index 00000000..8abe4590
--- /dev/null
+++ b/languages/es_ES.po
@@ -0,0 +1,4664 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-06-08 10:55+0200\n"
+"PO-Revision-Date: 2017-06-14 15:40+0200\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: es_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.0.2\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+msgid "Self hosted email newsletter app"
+msgstr "Aplicación de boletín de correo electrónico alojado por usted mismo"
+
+#: views/blacklist.hbs:1 views/campaigns/blacklisted.hbs:1
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/forms/create.hbs:1
+#: views/lists/forms/edit.hbs:1 views/lists/forms/forms.hbs:1
+#: views/lists/lists.hbs:1 views/lists/segments/create.hbs:1
+#: views/lists/segments/edit.hbs:1 views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/report-templates/create.hbs:1 views/report-templates/edit.hbs:1
+#: views/report-templates/report-templates.hbs:1
+#: views/reports/create-select-template.hbs:1 views/reports/create.hbs:1
+#: views/reports/edit.hbs:1 views/reports/output.hbs:1
+#: views/reports/reports.hbs:1 views/reports/view.hbs:1 views/settings.hbs:1
+#: views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Inicio"
+
+#: views/blacklist.hbs:2 views/blacklist.hbs:3 views/layout.hbs:7
+#: views/lists/subscription/edit.hbs:15
+msgid "Blacklist"
+msgstr "Lista negra"
+
+#: views/blacklist.hbs:4 views/users/api.hbs:55
+msgid "Add email to blacklist"
+msgstr "Añadir correo a la lista negra"
+
+#: views/blacklist.hbs:5
+msgid "Add"
+msgstr "Añadir"
+
+#: views/blacklist.hbs:6
+msgid "Email"
+msgstr "Correo eléctronico"
+
+#: views/campaigns/blacklisted.hbs:2 views/campaigns/bounced.hbs:2
+#: views/campaigns/campaigns.hbs:2 views/campaigns/campaigns.hbs:7
+#: views/campaigns/clicked.hbs:2 views/campaigns/complained.hbs:2
+#: views/campaigns/create-rss.hbs:2 views/campaigns/create-triggered.hbs:2
+#: views/campaigns/create.hbs:2 views/campaigns/delivered.hbs:2
+#: views/campaigns/edit-rss.hbs:2 views/campaigns/edit-triggered.hbs:2
+#: views/campaigns/edit.hbs:2 views/campaigns/opened.hbs:2
+#: views/campaigns/unsubscribed.hbs:2 views/campaigns/upload-attachment.hbs:2
+#: views/campaigns/view.hbs:2 lib/tools.js:133 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Campañas"
+
+#: views/campaigns/blacklisted.hbs:3 views/campaigns/blacklisted.hbs:4
+msgid "Blacklisted info"
+msgstr "Información de la lista negra"
+
+#: views/campaigns/blacklisted.hbs:5 views/campaigns/bounced.hbs:5
+#: views/campaigns/clicked.hbs:5 views/campaigns/complained.hbs:5
+#: views/campaigns/delivered.hbs:5 views/campaigns/edit-rss.hbs:5
+#: views/campaigns/edit-triggered.hbs:5 views/campaigns/edit.hbs:5
+#: views/campaigns/opened.hbs:5 views/campaigns/unsubscribed.hbs:5
+#: views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Ver campaña"
+
+#: views/campaigns/blacklisted.hbs:6
+msgid "Subscribers who blacklisted by global blacklist:"
+msgstr "Suscriptores que han sido incluidos en la lista negra global:"
+
+#: views/campaigns/blacklisted.hbs:7 views/campaigns/bounced.hbs:7
+#: views/campaigns/clicked.hbs:15 views/campaigns/complained.hbs:7
+#: views/campaigns/delivered.hbs:7 views/campaigns/opened.hbs:9
+#: views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:8 views/lists/view.hbs:19
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Dirección"
+
+#: views/campaigns/blacklisted.hbs:8 views/campaigns/bounced.hbs:8
+#: views/campaigns/clicked.hbs:16 views/campaigns/complained.hbs:8
+#: views/campaigns/delivered.hbs:8 views/campaigns/opened.hbs:10
+#: views/campaigns/unsubscribed.hbs:8 views/lists/subscription/add.hbs:6
+#: views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:20
+#: views/subscription/partials/subscription-custom-fields.hbs:3
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Nombre"
+
+#: views/campaigns/blacklisted.hbs:9 views/campaigns/bounced.hbs:9
+#: views/campaigns/clicked.hbs:17 views/campaigns/complained.hbs:9
+#: views/campaigns/delivered.hbs:9 views/campaigns/opened.hbs:11
+#: views/campaigns/unsubscribed.hbs:9 views/lists/subscription/add.hbs:7
+#: views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:21
+#: views/subscription/partials/subscription-custom-fields.hbs:4
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Apellidos"
+
+#: views/campaigns/blacklisted.hbs:10
+msgid "Reason"
+msgstr "Motivo"
+
+#: views/campaigns/blacklisted.hbs:11
+msgid "Time"
+msgstr "Fecha"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Información del bounce"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Suscriptores que fueron bounce y unsuscritos:"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "Respuesta del SMTP"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Fecha"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:26
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:28
+msgid "Create Campaign"
+msgstr "Crear Campaña"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Campaña normal"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "Campaña de RSS"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr "Campaña encadenada"
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/forms/forms.hbs:6
+#: views/lists/lists.hbs:5 views/lists/segments/segments.hbs:6
+#: views/report-templates/partials/report-template-fields.hbs:1
+#: views/report-templates/report-templates.hbs:10
+#: views/reports/partials/report-fields.hbs:1
+#: views/reports/partials/report-fields.hbs:5
+#: views/reports/partials/report-fields.hbs:9 views/reports/reports.hbs:6
+#: views/templates/templates.hbs:5 views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Nombre"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:74
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10
+#: views/lists/forms/edit.hbs:9 views/lists/forms/forms.hbs:7
+#: views/lists/lists.hbs:8 views/mosaico/editor.hbs:3
+#: views/partials/merge-tag-reference.hbs:4
+#: views/report-templates/partials/report-template-fields.hbs:3
+#: views/report-templates/report-templates.hbs:11
+#: views/reports/partials/report-fields.hbs:3
+#: views/reports/partials/report-fields.hbs:6 views/reports/reports.hbs:8
+#: views/templates/create.hbs:9 views/templates/edit.hbs:8
+#: views/templates/templates.hbs:6 views/triggers/create.hbs:7
+#: views/triggers/edit.hbs:8 views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Descripción"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:75
+#: views/lists/view.hbs:22 views/lists/view.hbs:30
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Estado"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:76
+#: views/lists/view.hbs:23 views/lists/view.hbs:24
+#: views/report-templates/report-templates.hbs:12
+#: views/reports/partials/report-fields.hbs:7 views/reports/reports.hbs:9
+msgid "Created"
+msgstr "Fecha de Creación"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Información del enlace"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:63
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:64
+msgid "Clicks"
+msgstr "Clicks"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:65
+msgid "% of clicks"
+msgstr "% de clicks"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:66
+msgid "% of messages"
+msgstr "% de mensajes"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:69
+msgid "Aggregated clicks"
+msgstr "Clics agregados"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Suscriptores que hicieron click en un enlace:"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Suscriptores que hicieron click en este enlace:"
+
+#: views/campaigns/clicked.hbs:13 views/campaigns/opened.hbs:7
+msgid "Stats by country"
+msgstr "Estadísticas por país"
+
+#: views/campaigns/clicked.hbs:14 views/campaigns/opened.hbs:8
+msgid "Stats by device type"
+msgstr "Estadísticas por dispositivo"
+
+#: views/campaigns/clicked.hbs:18
+msgid "First click time"
+msgstr "Fecha del primer click"
+
+#: views/campaigns/clicked.hbs:19
+msgid "Click count"
+msgstr "Número de clicks"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Información de quejas"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Suscriptores que se quejaron y fueron unsuscritos:"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Fecha de la queja"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:21
+msgid "Create RSS Campaign"
+msgstr "Crear Campaña de RSS"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+"Una campaña RSS detecta los cambios en el Canal RSS configurado. Cuando se "
+"encuentra una nueva entrada de este canal es enviado a la lista seleccionada "
+"como un mensaje de correo electrónico."
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Nombre de la campaña"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/report-templates/partials/report-template-fields.hbs:4
+#: views/reports/partials/report-fields.hbs:4 views/templates/create.hbs:11
+#: views/templates/edit.hbs:10 views/triggers/create.hbs:9
+#: views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "Se permite HTML"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "Lista"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/reports/partials/report-select-template.hbs:2
+#: views/subscription/partials/subscription-custom-fields.hbs:9
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Seleccionar"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "suscriptores"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "RSS Feed URL"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+"Las nuevas entradas de esta dirección de URL de RSS se envían a los "
+"suscriptores de la lista como mensajes de correo electrónico"
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "Email \"en nombre de (from)\""
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit-triggered.hbs:17 views/campaigns/edit.hbs:18
+#: views/settings.hbs:23
+msgid "This is the name your emails will come from"
+msgstr "Este es el nombre con el que se enviaran sus correos electrónicos"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "Correo electrónico \"De/From\""
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:21
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:25
+msgid "This is the address people will send replies to"
+msgstr "Este es el correo al que los contactos responderán"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:26 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:25
+msgid "Disable opened tracking"
+msgstr "Desactivar el seguimiento de Aperturas"
+
+#: views/campaigns/create-rss.hbs:20 views/campaigns/create-triggered.hbs:25
+#: views/campaigns/create.hbs:27 views/campaigns/edit-rss.hbs:23
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26
+msgid "Disable clicked tracking"
+msgstr "Desactivar el seguimiento de Clics"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr "Campaña Trigger creada"
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/reports/reports.hbs:7 views/templates/create.hbs:13
+msgid "Template"
+msgstr "Plantilla"
+
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr "Seleccionar plantilla"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr "Selección de una plantilla para crear una copia de campaña de ella"
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr ""
+"O, alternativamente, utilizar una URL como la fuente de contenido del "
+"mensaje:"
+
+#: views/campaigns/create-triggered.hbs:17 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:26 views/campaigns/edit.hbs:29
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+"Si el mensaje es enviado, se realizará una petición POST a esta URL "
+"utilizando los Merge Tags como parámetros. Utiliza esta opción si quieres "
+"generar el mensaje HTML tu mismo"
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr "Email \"asunto\""
+
+#: views/campaigns/create-triggered.hbs:23 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:27
+msgid "Keep it relevant and non-spammy"
+msgstr "Mantener relevancia y no spam"
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+"Esta es la dirección donde los usuarios enviarán respuestas a menos que "
+"\"mail de respuesta\" sea establecido"
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr "Dirección de correo \"de respuesta\""
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr ""
+"Si se establece, esta es la dirección donde los usuarios enviarán respuestas"
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr "Información tiempo de entrega"
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+"Los suscriptores que recibieron el mensaje y no han sido bounces ni bajas:"
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr "Tiempo de entrega"
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr "Editar Campaña RSS"
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr "Configuración general"
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+"Usar especial tag [RSS_ENTRY] para marcar la posición del contenido del post "
+"RSS. Además puedes utilizas más tags"
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:35
+msgid "Delete Campaign"
+msgstr "Eliminar Camppaña"
+
+#: views/campaigns/edit-rss.hbs:25 views/campaigns/edit-triggered.hbs:28
+#: views/campaigns/edit.hbs:36 views/lists/edit.hbs:20
+#: views/lists/fields/edit.hbs:39 views/lists/forms/edit.hbs:33
+#: views/lists/forms/forms.hbs:12 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:18
+#: views/reports/edit.hbs:6 views/settings.hbs:99 views/templates/edit.hbs:12
+#: views/triggers/edit.hbs:30 views/users/account.hbs:18
+msgid "Update"
+msgstr "Actualizar"
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr "Editar Campaña Activadas"
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+#: routes/forms.js:143
+msgid "General"
+msgstr "General"
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27
+msgid "Template Settings"
+msgstr "Configuración de plantilla"
+
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28
+msgid "Template URL"
+msgstr "URL de la plantilla"
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr "Modificar campaña"
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:30
+msgid "Attachments"
+msgstr "Archivos adjuntos"
+
+#: views/campaigns/edit.hbs:31
+msgid "File"
+msgstr "Archivo"
+
+#: views/campaigns/edit.hbs:32
+msgid "Size"
+msgstr "Tamaño"
+
+#: views/campaigns/edit.hbs:33 views/campaigns/view.hbs:68
+#: views/lists/fields/fields.hbs:12 views/lists/forms/forms.hbs:9
+#: views/lists/view.hbs:33
+msgid "No data available in table"
+msgstr "No hay datos disponibles en la tabla"
+
+#: views/campaigns/edit.hbs:34 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr "Añadir un adjunto"
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr "Información apertura"
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr "Los suscriptores que abrieron este mensaje:"
+
+#: views/campaigns/opened.hbs:12
+msgid "First open"
+msgstr "Primera apertura"
+
+#: views/campaigns/opened.hbs:13
+msgid "Opened count"
+msgstr "Recuento de aperturas"
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr "Información de bajas"
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr "Suscriptores que se han dado de baja"
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:28
+#: views/lists/subscription/import.hbs:10 routes/lists.js:206
+msgid "Unsubscribed"
+msgstr "Dado de baja"
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr "Subir"
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr "Visión de conjunto"
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr "Links"
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr "URL de Feed"
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr "Último control"
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr "No revisado aún"
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr ""
+"Activar la campaña para empezar a comprobar si hay nuevos mensajes de Feed"
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr "Estatus RSS"
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr "Campaña de vista previa como"
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr "Añadir un nuevo usuario de prueba"
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr "Ningún miembro de la prueba aún, crear uno aquí"
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr "Ir"
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:26
+msgid "Delivered"
+msgstr "Entregado"
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr "Lista de Suscriptores que recibieron este boletín"
+
+#: views/campaigns/view.hbs:22
+msgid "Blacklisted"
+msgstr "Lista negra"
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who blacklisted by global blacklist"
+msgstr "Lista de suscriptores que sin lista negra de lista negra mundial"
+
+#: views/campaigns/view.hbs:24 routes/lists.js:206
+msgid "Bounced"
+msgstr "Rebotado"
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who bounced"
+msgstr "Lista de suscriptores que ha rebotado"
+
+#: views/campaigns/view.hbs:26
+msgid "Complaints"
+msgstr "Quejas"
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who complained for this message"
+msgstr "Lista de suscriptores que se ha quejado por este boletín"
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who unsubscribed after this message"
+msgstr "Lista de suscriptores que se han dado de baja tras este boletín"
+
+#: views/campaigns/view.hbs:30
+msgid "Opened"
+msgstr "Aperturas"
+
+#: views/campaigns/view.hbs:31
+msgid "List subscribers who opened this message"
+msgstr "Lista de suscriptores que han abierto este boletín"
+
+#: views/campaigns/view.hbs:32
+msgid "Clicked"
+msgstr "Clics"
+
+#: views/campaigns/view.hbs:33 views/campaigns/view.hbs:70
+msgid "List subscribers who clicked on a link"
+msgstr "Lista de suscriptores que han hecho clic en este boletín"
+
+#: views/campaigns/view.hbs:34
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+"¿Estás seguro? Esta acción empezará a enviar el boletín a la lista "
+"seleccionada"
+
+#: views/campaigns/view.hbs:35
+msgid "Delay sending"
+msgstr "Envío retrasado"
+
+#: views/campaigns/view.hbs:36
+msgid "hours"
+msgstr "horas"
+
+#: views/campaigns/view.hbs:37
+msgid "minutes"
+msgstr "minutos"
+
+#: views/campaigns/view.hbs:38
+msgid "Send to subscribers:"
+msgstr "Enviar a suscriptores:"
+
+#: views/campaigns/view.hbs:39
+msgid "Are you sure? This action would reset scheduling"
+msgstr "¿Estás seguro? Esta acción restablecerá la programación"
+
+#: views/campaigns/view.hbs:40
+msgid "Cancel"
+msgstr "Cancelado"
+
+#: views/campaigns/view.hbs:41
+msgid "Sending scheduled"
+msgstr "Envío programado"
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:54
+msgid "Pause"
+msgstr "Pausa"
+
+#: views/campaigns/view.hbs:43 routes/campaigns.js:253
+msgid "Sending"
+msgstr "Enviando"
+
+#: views/campaigns/view.hbs:44 views/campaigns/view.hbs:48
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+"¿Estás seguro? Esta acción reanudará el envío del boletín a la lista "
+"seleccionada"
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+"¿Estás seguro? Esta acción reiniciará todas las estadísticas de progreso "
+"actual"
+
+#: views/campaigns/view.hbs:46
+msgid "Resume"
+msgstr "Reanudar"
+
+#: views/campaigns/view.hbs:47 views/campaigns/view.hbs:51
+msgid "Reset"
+msgstr "Reiniciar"
+
+#: views/campaigns/view.hbs:50
+msgid "Continue"
+msgstr "Continuar"
+
+#: views/campaigns/view.hbs:52
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+"¡Todos los mensajes han sido enviados! Haz clic en \"Continuar\" si quieres "
+"enviar la campaña a nuevos suscriptores"
+
+#: views/campaigns/view.hbs:53
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"¿Estás seguro? Esta acción pausará el envío de nuevas entradas RSS a la "
+"lista seleccionada"
+
+#: views/campaigns/view.hbs:55 views/campaigns/view.hbs:59
+msgid "Campaign status:"
+msgstr "Estado de la campaña:"
+
+#: views/campaigns/view.hbs:56
+msgid "ACTIVE"
+msgstr "ACTIVO"
+
+#: views/campaigns/view.hbs:57
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"¿Estás seguro? Esta acción empezará el envío del boletín a la lista "
+"seleccionada"
+
+#: views/campaigns/view.hbs:58
+msgid "Activate"
+msgstr "Activar"
+
+#: views/campaigns/view.hbs:60
+msgid "INACTIVE"
+msgstr "INACTIVO"
+
+#: views/campaigns/view.hbs:61
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+"Esta es una campaña encadenada (Trigger). Los boletines son enviados a "
+"suscriptores que han desencadenado alguna acción de esta campaña."
+
+#: views/campaigns/view.hbs:62
+msgid "see more"
+msgstr "ver más"
+
+#: views/campaigns/view.hbs:67
+msgid "List subscribers who clicked this link"
+msgstr "Lista de suscriptores que ha hecho clic en este link"
+
+#: views/campaigns/view.hbs:71
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+"Clics únicos, contados como único suscriptores hace clic en link específico "
+"o en ningún link (vista agregada)"
+
+#: views/campaigns/view.hbs:72
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+"Si una nueva entrada es en la campaña Feed, una nueva subcampaña de esta "
+"entrada es creada y será listada aquí"
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr "Cambiar contraseña"
+
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr ""
+"Hemos recibido una solicitud de cambio de contraseña de su cuenta Mailtrain:"
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr "Restablecer la contraseña"
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+"Si usted no pidió que cambie su contraseña, entonces puede ignorar este "
+"mensaje y no se cambiará la contraseña."
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr "Preferencias"
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/forms/edit.hbs:20
+#: views/lists/subscription/edit.hbs:16
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:2
+#: views/subscription/web-manage.mjml.hbs:3
+#: views/subscription/web-unsubscribe.mjml.hbs:1
+#: views/subscription/web-unsubscribe.mjml.hbs:2 routes/forms.js:223
+#: routes/lists.js:288
+msgid "Unsubscribe"
+msgstr "Darse de baja"
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr "Ver este correo electrónico en su navegador"
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr "Hola [FIRST_NAME/Customer],"
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr "Gracias,"
+
+#: views/index.hbs:1
+msgid "List Management"
+msgstr "Gestión de la lista"
+
+#: views/index.hbs:2
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+"Mailtrain le permite administrar fácilmente listas muy grandes. ¿Millones de "
+"suscriptores? No es un problema. Puede añadir manualmente los suscriptores, "
+"a través de la API o importación de un archivo CSV. Todas las listas vienen "
+"con soporte para los campos personalizados y se fusionan las etiquetas "
+"también."
+
+#: views/index.hbs:3 views/index.hbs:7 views/index.hbs:10 views/index.hbs:13
+#: views/index.hbs:16 views/index.hbs:19 views/index.hbs:22 views/index.hbs:25
+#: views/index.hbs:28
+msgid "Show more"
+msgstr "Mostrar más"
+
+#: views/index.hbs:4 views/lists/fields/create.hbs:3
+#: views/lists/fields/edit.hbs:3 views/lists/fields/fields.hbs:3
+#: views/lists/fields/fields.hbs:5 views/lists/view.hbs:6
+msgid "Custom Fields"
+msgstr "Campos Personalizados"
+
+#: views/index.hbs:5
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+"Mailtrain tiene campos de texto, números, menús desplegables y casillas de "
+"verificación. Cada campo personalizado se puede incluir en los boletines "
+"generados a través de las etiquetas."
+
+#: views/index.hbs:6
+msgid "Mailtrain also supports custom forms."
+msgstr "Mailtrain soporta formularios personalizados también."
+
+#: views/index.hbs:8
+msgid "List Segmentation"
+msgstr "Lista Segmentada"
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+"Enviar mensajes sólo a la lista de suscriptores que cumple las de "
+"segmentación predefinidas. No hay necesidad de crear listas separadas con "
+"pequeñas diferencias."
+
+#: views/index.hbs:11
+msgid "RSS Campaigns"
+msgstr "Campañas RSS"
+
+#: views/index.hbs:12
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+"Configura Mailtrain para seguir el Fedd de RSS y si se detecta una nueva "
+"entrada del feed, Mailtrain generará automáticamente una nueva campaña a "
+"partir de los datos de la entrada como contenido del mensaje y lo enviará a "
+"los suscriptores seleccionados."
+
+#: views/index.hbs:14
+msgid "GPG Encryption"
+msgstr "Cifrado GPG"
+
+#: views/index.hbs:15
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+"Si una lista tiene un campo personalizado para una clave pública GPG "
+"establecida, los suscriptores pueden actualizar su clave pública GPG para "
+"recibir mensajes cifrados de la lista."
+
+#: views/index.hbs:17
+msgid "Click Stats"
+msgstr "Estadísticas de clics"
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+"Tras enviar una campaña, comprobar las estadísticas de clic individuales "
+"para cada enlace incluido en el mensaje."
+
+#: views/index.hbs:20
+msgid "Template Editors"
+msgstr "Editores plantilla"
+
+#: views/index.hbs:21
+msgid ""
+"Mailtrain ships with GrapeJS and Mosaico built in, two advanced template "
+"editors. Mailtrain also offers a code editor if you prefer to handcraft the "
+"HTML yourself."
+msgstr ""
+"Mailtrain envía con los incorporados GrapeJS y Mosaico, dos editores "
+"avanzados de plantillas . Mailtrain también ofrece un editor de código, por "
+"si prefieres modificar HTML."
+
+#: views/index.hbs:23
+msgid "Send via Any Provider"
+msgstr "Enviar a través de cualquier proveedor"
+
+#: views/index.hbs:24
+msgid ""
+"Mailtrain recommends SendPulse even though you "
+"can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+"Mailtrain recomienda SendPulseaunque se puede "
+"utilizar cualquier proveedor que soporte el protocolo SMTP para enviar sus "
+"boletines de noticias. El manejo de rebotes y de quejas a través de WebHooks "
+"es compatible para SES, SparkPost, SendGrid y Mailgun, también para Postfix "
+"y ZoneMTA."
+
+#: views/index.hbs:26 lib/tools.js:137
+msgid "Automation"
+msgstr "Automatización"
+
+#: views/index.hbs:27
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+"Definir los factores desencadenantes de automatización para enviar boletines "
+"específicos cuando un usuario activa el Trigger."
+
+#: views/index.hbs:29
+msgid "Donate to Author"
+msgstr "Donar al autor"
+
+#: views/index.hbs:30
+msgid "Mailtrain is available under GPLv3 license and completely open source."
+msgstr ""
+"Mailtrain está disponible bajo licencia GPLv3 y la fuente es completamente "
+"abierta (Open source)."
+
+#: views/index.hbs:31
+msgid ""
+"If you really like Mailtrain or your business benefits from it financially "
+"then I would really appreciate a small donation to keep the Mailtrain "
+"development engines running. You can either use Bitcoin or PayPal for "
+"donations. My Bitcoin wallet is"
+msgstr ""
+"Si realmente te gusta Mailtrain o su negocio se beneficia de ella "
+"financieramente entonces yo realmente apreciaría una pequeña donación para "
+"mantener los motores de desarrollo Mailtrain. También se puede usar Bitcoin "
+"o PayPal para donaciones. Bitcoin es mi monedero."
+
+#: views/index.hbs:32
+msgid "Or Donate Using Paypal"
+msgstr "O donar usando Paypal"
+
+#: views/index.hbs:33
+msgid "Official Mailtrain Partners"
+msgstr "Socios oficiales de Mailtrain"
+
+#: views/index.hbs:34
+msgid ""
+"A reliable SMTP server, easy integration, and 12,000 messages a month free"
+msgstr ""
+"Un servidor SMTP fiable, de fácil integración y envío de 12.000 mensajes "
+"durante un mes gratis"
+
+#: views/index.hbs:35
+msgid "Free, open source mail server solution"
+msgstr ""
+"Gratis, solución de código abierto (open source) de servidor de correo "
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr "Interruptor de navegación"
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr "Wiki"
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr "Blog"
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr "Cuenta"
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr "Ajustes"
+
+#: views/layout.hbs:8 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr "API"
+
+#: views/layout.hbs:9
+msgid "Log out"
+msgstr "Cerrar sesión"
+
+#: views/layout.hbs:10 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr "Registrarse"
+
+#: views/layout.hbs:11
+msgid "Self Hosted Newsletter App Built on Top of Nodemailer"
+msgstr "Applicación de Newsletter \"autoalojada\" creada en base a Nodemailer?"
+
+#: views/layout.hbs:12 views/layout.hbs:14
+msgid "Source on GitHub"
+msgstr "Fuente en GitHub"
+
+#: views/layout.hbs:13
+msgid "Subscribe to Our Newsletter"
+msgstr "Suscríbete a nuestro boletín"
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/forms/create.hbs:2
+#: views/lists/forms/edit.hbs:2 views/lists/forms/forms.hbs:2
+#: views/lists/lists.hbs:2 views/lists/lists.hbs:4
+#: views/lists/segments/create.hbs:2 views/lists/segments/edit.hbs:2
+#: views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:125 routes/lists.js:59
+msgid "Lists"
+msgstr "Listas"
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:13
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr "Crear lista"
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr "Nombre de Lista"
+
+#: views/lists/create.hbs:9 views/lists/edit.hbs:15
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Suscripción"
+
+#: views/lists/create.hbs:10 views/lists/edit.hbs:16
+msgid "Allow public users to subscribe themselves"
+msgstr "Permitir que los usuarios públicos se suscriban a sí mismos "
+
+#: views/lists/create.hbs:11 views/lists/edit.hbs:17
+msgid "Unsubscription"
+msgstr "Darse de baja"
+
+#: views/lists/create.hbs:12 views/lists/edit.hbs:18
+msgid "Select how an unsuscription request by subscriber is handled."
+msgstr "Seleccionar como el suscriptor maneja la solicitud de baja."
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:8
+msgid "Edit List"
+msgstr "Editar lista"
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr "Ver lista"
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr "ID de lista"
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr "Este es el ID de la lista que se muestra a los suscriptores"
+
+#: views/lists/edit.hbs:12
+msgid "Custom Form"
+msgstr "Formulario personalizado"
+
+#: views/lists/edit.hbs:13 views/lists/forms/forms.hbs:11
+msgid "Default Mailtrain Form"
+msgstr "Formulario por defecto de Mailtrain"
+
+#: views/lists/edit.hbs:14
+msgid ""
+"The custom form used for this list. You can create a form here."
+msgstr ""
+"El formulario personalizado que se utiliza para esta lista. Puedes crear un "
+"formulario aquí ."
+
+#: views/lists/edit.hbs:19
+msgid "Delete List"
+msgstr "Eliminar lista"
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr "Crear campo"
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr "Crear campo personalizado"
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr "Nombre de campo"
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr "Tipo de campo"
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr "Texto"
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr "Número"
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr "Web"
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr "Clave pública GPG"
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr "Texto de varias líneas"
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr "JSON"
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr "Fecha"
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr "Fecha (MM/DD/YYYY)"
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr "Fecha (DD/MM/YYYY)"
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr "Cumpleaños"
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr "Cumpleaños (MM/DD)"
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr "Cumpleaños (DD/MM)"
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr "Agrupado"
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr "Listas deplegables"
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr "Botones Radio "
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr "Checkboxes"
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr "Opción para un valor de grupo"
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr "Grupo"
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr "Requerido para Opciones de Grupo"
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr "Valor de la etiqueta Merge por defecto"
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+"Para los elementos de grupo como checkboxes tu puedes controlar la "
+"apariencia de la etiqueta merge con una plantilla opcional. La plantilla "
+"utiliza la sintaxis Handlebars y se pueden encontrar todos los valores de "
+"{{values}} array, por ejemplo {{#each values}} {{this}} "
+"{{/each}}. Si la plantilla no se define, varios valores se unen con "
+"comas. También puedes utilizar esta plantilla para rederizar valores JSON "
+"(si el JSON es un array, el array es expuesto como values, de "
+"lo contrario puedes acceder directamente a las claves JSON)."
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Visible"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Añadir Campo"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Editar Campo"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr "Editar campo personalizado"
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr "Volver a campos"
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/mosaico/editor.hbs:2 views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr "Etiqueta Merge"
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr "Etiqueta Merge"
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr "Pon esta etiqueta en tu contenido:"
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Eliminar campo"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:26
+#: views/report-templates/partials/report-template-fields.hbs:5
+msgid "Type"
+msgstr "Tipo"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/forms/edit.hbs:26 views/lists/forms/forms.hbs:8
+#: views/lists/segments/segments.hbs:8 views/lists/segments/view.hbs:12
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:276
+#: routes/campaigns.js:568 routes/campaigns.js:657 routes/campaigns.js:706
+#: routes/lists.js:170 routes/lists.js:257 routes/report-templates.js:51
+#: routes/templates.js:170 routes/triggers.js:297
+msgid "Edit"
+msgstr "Editar"
+
+#: views/lists/forms/create.hbs:3 views/lists/forms/edit.hbs:3
+#: views/lists/forms/forms.hbs:3 views/lists/forms/forms.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Forms"
+msgstr "Formularios personalizados"
+
+#: views/lists/forms/create.hbs:4
+msgid "Create Form"
+msgstr "Crear formulario"
+
+#: views/lists/forms/create.hbs:5 views/lists/forms/forms.hbs:4
+msgid "Create Custom Form"
+msgstr "Crear formulario personalizado"
+
+#: views/lists/forms/create.hbs:6 views/lists/forms/create.hbs:7
+#: views/lists/forms/edit.hbs:7 views/lists/forms/edit.hbs:8
+msgid "Form Name"
+msgstr "Nombre de Formulario"
+
+#: views/lists/forms/create.hbs:8
+msgid "Add Form"
+msgstr "Añadir Formulario"
+
+#: views/lists/forms/edit.hbs:4
+msgid "Edit Form"
+msgstr "Editar formulario"
+
+#: views/lists/forms/edit.hbs:5
+msgid "Edit Custom Form"
+msgstr "Editar Formulario personalizado"
+
+#: views/lists/forms/edit.hbs:6
+msgid "Back to forms"
+msgstr "Volver a Formularios"
+
+#: views/lists/forms/edit.hbs:10
+msgid "Optional comments about this form"
+msgstr "Compentarios opcionales sobre el formulario"
+
+#: views/lists/forms/edit.hbs:11
+msgid "Form Preview"
+msgstr "Vista previa del formulario"
+
+#: views/lists/forms/edit.hbs:12
+msgid ""
+"Note: These links are solely for a quick preview. If you submit a preview "
+"form you'll get redirected to the list's default form."
+msgstr ""
+"Nota: Estos enlaces son únicamente para una vista rápida. Si seleccionas la "
+"vista previa de un formulario se te redirecciona a la lista por defecto del "
+"formulario."
+
+#: views/lists/forms/edit.hbs:13 views/lists/subscription/add.hbs:16
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:4
+#: routes/forms.js:157 routes/lists.js:288
+msgid "Subscribe"
+msgstr "Suscribirse"
+
+#: views/lists/forms/edit.hbs:14
+msgid "Confirm Subscription Notice"
+msgstr "Aviso de Confirmación de suscripción"
+
+#: views/lists/forms/edit.hbs:15
+msgid "Confirm Unsubscription Notice"
+msgstr "Aviso de Confirmación de baja"
+
+#: views/lists/forms/edit.hbs:16
+msgid "Subscribed Notice"
+msgstr "Aviso Suscripción"
+
+#: views/lists/forms/edit.hbs:17
+msgid "Updated Notice"
+msgstr "Aviso Actualización"
+
+#: views/lists/forms/edit.hbs:18
+msgid "Unsubscribed Notice"
+msgstr "Aviso Baja"
+
+#: views/lists/forms/edit.hbs:19
+msgid "Manual Unsubscribe Notice"
+msgstr "Aviso Manual de baja"
+
+#: views/lists/forms/edit.hbs:21 routes/forms.js:205
+msgid "Manage"
+msgstr "Gestión"
+
+#: views/lists/forms/edit.hbs:22
+msgid "Manage Address"
+msgstr "Gestión de dirección"
+
+#: views/lists/forms/edit.hbs:23
+msgid "Create a test user for additional options"
+msgstr "Crear un usuario de prueba para opciones adicionales"
+
+#: views/lists/forms/edit.hbs:24 views/report-templates/create.hbs:3
+#: views/report-templates/edit.hbs:3
+#: views/report-templates/report-templates.hbs:3 views/templates/create.hbs:2
+#: views/templates/edit.hbs:2 views/templates/templates.hbs:2
+#: views/templates/templates.hbs:4 lib/tools.js:129 routes/templates.js:27
+msgid "Templates"
+msgstr "Plantillas"
+
+#: views/lists/forms/edit.hbs:25
+msgid "Fields"
+msgstr "Campos"
+
+#: views/lists/forms/edit.hbs:27
+msgid "Form Fields"
+msgstr "Campos de formulario"
+
+#: views/lists/forms/edit.hbs:28
+msgid "Fields hidden on subscription page:"
+msgstr "Campos ocultos de página de suscripción"
+
+#: views/lists/forms/edit.hbs:29
+msgid "Fields shown on subscription page:"
+msgstr "Campos no ocultos de página de suscripción"
+
+#: views/lists/forms/edit.hbs:30
+msgid "Fields hidden on preferences page:"
+msgstr "Campos ocultos de página de preferencias"
+
+#: views/lists/forms/edit.hbs:31
+msgid "Fields shown on preferences page:"
+msgstr "Campos no ocultos de páginas de preferencias"
+
+#: views/lists/forms/edit.hbs:32
+msgid "Delete Form"
+msgstr "Eliminar Formulario"
+
+#: views/lists/forms/forms.hbs:10
+msgid "The default form for this list is:"
+msgstr "El formulario por defecto de esta lista es:"
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7 views/reports/partials/report-fields.hbs:10
+msgid "Subscribers"
+msgstr "Suscriptores"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:7
+#: views/lists/view.hbs:14
+msgid "Segments"
+msgstr "Segmentos"
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr "Crear Segmento"
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr "Nombre del Segmento"
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr "Combinación de reglas"
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr "Todas las reglas deben combinar"
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr "Ninguna regla debe combinar"
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr "Añadir segmento"
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:12
+msgid "Edit Segment"
+msgstr "Editar segmento"
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr "Volver a segmentos"
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr "Eliminar segmento"
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Crear regla"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Regla"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Valor"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+"Usar % para carácter comodín, por ejemplo \"%test\" para combinar todos los "
+"valores que terminen en \"test\""
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr "Usar combinación exacta"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr "Usar rango de combinación"
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr "Usar rango relativo de combinación"
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr "De"
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr "días"
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr "antes de hoy"
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr "después de hoy"
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr "para"
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr "Seleccionado"
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr "No Seleccionado"
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr "Añadir regla"
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:15
+#: views/reports/create-select-template.hbs:5
+#: views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Siguiente"
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr "Eliminar regla"
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr "Combinar"
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:13
+msgid "Segment"
+msgstr "Segmento"
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr "Combinar reglas"
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr "Conjunto de suscriptores"
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr "mostrar"
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Añadir suscriptor"
+
+#: views/lists/subscription/add.hbs:5
+#: views/subscription/partials/subscription-custom-fields.hbs:1
+#: views/users/account.hbs:7
+msgid "Email Address"
+msgstr "Dirección Email"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:82 views/settings.hbs:97
+#: views/subscription/partials/subscription-custom-fields.hbs:6
+msgid "Begins with"
+msgstr "Empieza por"
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Insertar una clave pública GPG que será usada para encriptar mensajes "
+"enviados a este suscriptor"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Zona horaria"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "¿Es un usuario test?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+"Si está marcado, esta suscripción puede ser usada para previsualizar los "
+"boletines"
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+"Esta persona no recibirá correo de confirmación para asegurarse de que tiene "
+"permiso para enviarle boletines."
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Editar suscriptor"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Volver a la lista"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:1
+#: lib/helpers.js:42 lib/models/segments.js:11
+msgid "Email address"
+msgstr "Dirección Email"
+
+#: views/lists/subscription/edit.hbs:17
+msgid "Delete Subscription"
+msgstr "Eliminar suscripción"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Importar estatus"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Direcciones fallidas"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid ""
+"Role-based addresses like postmaster@example.com are blocked when importing. "
+"Subscribers with role-based email addresses can join your list using the "
+"subscription form"
+msgstr ""
+"Direcciones basadas en roles como postmaster@example.com se bloquean cuando "
+"se importan. Los suscriptores con correos electrónicos basados en roles "
+"pueden unirse a la lista utilizando el formulario de suscripción."
+
+#: views/lists/subscription/import-failed.hbs:7
+msgid "see here"
+msgstr "ver aquí"
+
+#: views/lists/subscription/import-failed.hbs:9
+msgid "Fail reason"
+msgstr "Razón fallida"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Importar suscriptores"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:27
+#: views/users/api.hbs:35 views/users/api.hbs:43 views/users/api.hbs:54
+#: views/users/api.hbs:62 views/users/api.hbs:70
+msgid "Example"
+msgstr "Ejemplo"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Empezar importación"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "Archivo CSV"
+
+#: views/lists/subscription/import.hbs:6
+msgid "CSV delimiter"
+msgstr "Delimitador CSV"
+
+#: views/lists/subscription/import.hbs:7
+msgid "Categorize the imported subscribers as"
+msgstr "Categorizar los suscriptores importados como"
+
+#: views/lists/subscription/import.hbs:8 routes/lists.js:206
+msgid "Subscribed"
+msgstr "Suscritos"
+
+#: views/lists/subscription/import.hbs:9
+msgid "Regular subscriber addresses"
+msgstr "Correos de suscriptores regulares"
+
+#: views/lists/subscription/import.hbs:11
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr "Correos suprimidos que serán dados de baja en tu lista"
+
+#: views/lists/subscription/import.hbs:12
+msgid "Check imported emails"
+msgstr "Revisar los correos importados"
+
+#: views/lists/subscription/import.hbs:13 views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr "Activado"
+
+#: views/lists/subscription/import.hbs:14 views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr "Desactivado"
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Formulario de suscripción"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Acciones de Lista"
+
+#: views/lists/view.hbs:9 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr "Crear Trigger"
+
+#: views/lists/view.hbs:10
+msgid "Add Subscriber"
+msgstr "Añadir suscriptor"
+
+#: views/lists/view.hbs:11
+msgid "Import Subscribers"
+msgstr "Importar suscriptores"
+
+#: views/lists/view.hbs:15
+msgid "Create New Segment"
+msgstr "Crear nuevo segmento"
+
+#: views/lists/view.hbs:16
+msgid "Filter"
+msgstr "Filtrar"
+
+#: views/lists/view.hbs:17
+msgid "Subscriptions"
+msgstr "Sucriptores"
+
+#: views/lists/view.hbs:18
+msgid "Imports"
+msgstr "Importaciones"
+
+#: views/lists/view.hbs:25 routes/campaigns.js:255 routes/lists.js:300
+msgid "Finished"
+msgstr "Terminado"
+
+#: views/lists/view.hbs:27
+msgid "Added"
+msgstr "Añadido"
+
+#: views/lists/view.hbs:28
+msgid "Updated"
+msgstr "Actualizado"
+
+#: views/lists/view.hbs:29
+msgid "Failed"
+msgstr "Fallido"
+
+#: views/lists/view.hbs:31
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+"¿Estás seguro? Esta acción sólo será llamada para resolver importaciones "
+"estancadas"
+
+#: views/lists/view.hbs:32
+msgid "Restart"
+msgstr "Reiniciar"
+
+#: views/mosaico/editor.hbs:1 views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr "Etiqueta referencia Merge"
+
+#: views/mosaico/editor.hbs:4
+msgid "MOSAICO Responsive Email Designer"
+msgstr "Diseñador de boletines responsive MOSAICO"
+
+#: views/mosaico/editor.hbs:5
+msgid "Sucessfully saved"
+msgstr "Guardado con éxito"
+
+#: views/mosaico/editor.hbs:6
+msgid "An error occured while saving the document"
+msgstr "Un error ocurrió mientras se guardaban los documentos"
+
+#: views/mosaico/editor.hbs:7
+msgid "Unsaved changes will be lost. Close now?"
+msgstr "Los cambios no guardados se perderán. ¿Cerrar ahora?"
+
+#: views/mosaico/editor.hbs:8 views/mosaico/editor.hbs:9
+msgid "Tags"
+msgstr "Etiquetas"
+
+#: views/partials/codeeditor.hbs:1 views/partials/grapejs.hbs:1
+#: views/partials/mosaico.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Contenido de plantilla (HTML)"
+
+#: views/partials/editor-navbar.hbs:1
+msgid "SAVE"
+msgstr "GUARDAR"
+
+#: views/partials/editor-navbar.hbs:2
+msgid "SAVING"
+msgstr "GUARDANDO"
+
+#: views/partials/editor-navbar.hbs:3
+msgid "CLOSE"
+msgstr "CERRAR"
+
+#: views/partials/grapejs.hbs:2
+msgid "Open GrapeJS"
+msgstr "Abrir GrapeJS"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "Vista previa de Toggle HTML"
+
+#: views/partials/html-to-text.hbs:1
+msgid ""
+"To extract the text from HTML click here."
+msgstr ""
+"Para extraer el texto de HTML, haga clic aquí."
+
+#: views/partials/html-to-text.hbs:2
+msgid ""
+"Please note that your existing plaintext in the field above will be "
+"overwritten. This feature uses the Premailer API, a third party "
+"service. Their Terms of Service and Privacy Policy apply."
+msgstr ""
+"Por favor, tenga en cuenta que el texto plano del campo superior será "
+"sobreescrito. Esta función utiliza Premailer API, como servicio de "
+"terceros. Sus Condiciones de servicio y política de privacidad se aplican."
+
+#: views/partials/html-to-text.hbs:3
+msgid "An error occurred while talking to the server"
+msgstr "Ha ocurrido un error mientras se comunicaba con el servidor"
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+"Merge Tags son etiquetas que son remplazadas antes de enviar el boletín. El "
+"formato de las etiquetas Merge es el siguiente [TAG_NAME] o "
+"[TAG_NAME/fallback] donde fallback es el valor de "
+"un texto opcional usado cuando TAG_NAME está vacío."
+
+#: views/partials/modal-carousel.hbs:1
+msgid "{{title}}"
+msgstr "{{title}}"
+
+#: views/partials/mosaico.hbs:2
+msgid "Open Mosaico"
+msgstr "Abrir Mosaico"
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Contenido de la plantilla (texto plano)"
+
+#: views/report-templates/create.hbs:2 views/report-templates/edit.hbs:2
+#: views/report-templates/report-templates.hbs:2
+#: views/reports/create-select-template.hbs:2 views/reports/create.hbs:2
+#: views/reports/edit.hbs:2 views/reports/output.hbs:2
+#: views/reports/reports.hbs:2 views/reports/reports.hbs:5
+#: views/reports/view.hbs:2 lib/tools.js:144 routes/reports.js:31
+msgid "Reports"
+msgstr "Informes"
+
+#: views/report-templates/create.hbs:4 views/report-templates/create.hbs:6
+#: views/report-templates/report-templates.hbs:4 views/templates/create.hbs:3
+#: views/templates/create.hbs:4 views/templates/create.hbs:12
+#: views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Crear plantilla"
+
+#: views/report-templates/create.hbs:5 routes/report-templates.js:231
+msgid "Create Report Template"
+msgstr "Crear informe de plantilla"
+
+#: views/report-templates/edit.hbs:4 views/templates/edit.hbs:3
+#: views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Editar plantilla"
+
+#: views/report-templates/edit.hbs:5 routes/report-templates.js:262
+msgid "Edit Report Template"
+msgstr "Editar informe de plantilla"
+
+#: views/report-templates/edit.hbs:6 views/templates/edit.hbs:11
+msgid "Delete Template"
+msgstr "Eliminar plantilla"
+
+#: views/report-templates/edit.hbs:7
+msgid "Update and Stay"
+msgstr "Actualizar y permanecer"
+
+#: views/report-templates/edit.hbs:8
+msgid "Update and Leave"
+msgstr "Actualizar y salir"
+
+#: views/report-templates/partials/report-template-fields.hbs:2
+msgid "Template Name"
+msgstr "Nombre de plantilla"
+
+#: views/report-templates/partials/report-template-fields.hbs:6
+msgid "User selectable fields"
+msgstr "Usar campos seleccionables"
+
+#: views/report-templates/partials/report-template-fields.hbs:7
+msgid "Data processing code"
+msgstr "Código de procesamiento de datos"
+
+#: views/report-templates/partials/report-template-fields.hbs:8
+msgid "Rendering template"
+msgstr "Plantilla de renderizado"
+
+#: views/report-templates/report-templates.hbs:5
+msgid "Blank"
+msgstr "Vacío/En blanco"
+
+#: views/report-templates/report-templates.hbs:6
+msgid "All Subscribers"
+msgstr "Todos los suscriptores"
+
+#: views/report-templates/report-templates.hbs:7
+msgid "Grouped Subscribers"
+msgstr "Suscriptores agrupados"
+
+#: views/report-templates/report-templates.hbs:8
+msgid "Export List as CSV"
+msgstr "Exportar lista como CSV"
+
+#: views/report-templates/report-templates.hbs:9 views/reports/reports.hbs:4
+#: routes/report-templates.js:29
+msgid "Report Templates"
+msgstr "Plantillas de informes"
+
+#: views/reports/create-select-template.hbs:3
+#: views/reports/create-select-template.hbs:4 views/reports/create.hbs:3
+#: views/reports/create.hbs:4 views/reports/create.hbs:5
+#: views/reports/reports.hbs:3 routes/reports.js:81
+msgid "Create Report"
+msgstr "Crear informe"
+
+#: views/reports/edit.hbs:3 views/reports/edit.hbs:4 routes/reports.js:151
+msgid "Edit Report"
+msgstr "Editar informe"
+
+#: views/reports/edit.hbs:5
+msgid "Delete Report"
+msgstr "Eliminar informe"
+
+#: views/reports/partials/report-fields.hbs:2
+msgid "Report Name"
+msgstr "Nombre de informe"
+
+#: views/reports/partials/report-fields.hbs:8
+#: views/reports/partials/report-fields.hbs:11
+msgid ""
+"Select a campaign in the table above by clicking on the respective row "
+"number."
+msgstr ""
+"Seleccionar una campaña en la tabla superior haciendo clic en el respectivo "
+"número de columna"
+
+#: views/reports/partials/report-select-template.hbs:1
+msgid "Report Template"
+msgstr "Plantilla informe"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Dirección de servicio (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Introduzca la URL a la que puede acceder este servicio desde"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "Email Admin"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+"Introduce la dirección email que será usada como \"From\" para los envíos"
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr "Desactivar editor WYSIWYG"
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr ""
+"Si está marcado, el editor de mensajes muestra el código HTML sin la vista "
+"previa"
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr "Desactivar los mensajes de confirmación de suscripción"
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+"Si está marcado, no envía mensaje de confirmación que indica que el abonado "
+"está suscrito o dado de baja. Esto no deshabilita dobles mensajes opt-in."
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "ID restreo"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Introduzca un código de seguimiento de Google Analytics"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr "Reconocimiento de portada"
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr "Código HTML es mostrado en la sección de encabezado de la portada"
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr "Fallos en la campaña"
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr "Nombre de Remitente"
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Nombre de Remitente, por ejemplo: Compañía Asombrosa SL."
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr "Dirección por defecto"
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+"Dirección de contacto proporcionada, por ejemplo. Calle lugar cualquiera 1, "
+"Madrid, España"
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr "Nombre \"From\" por defecto"
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr "Email \"From\" por defecto"
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr "\"Asunto\" por defecto"
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr "Home por defecto (URL)"
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr ""
+"URL para redireccionar a los usuarios suscritos, por ejemplo http://example."
+"com/"
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr "Ajustes Remitente"
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr "Estos ajustes son requeridos para enviar boletines"
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr "SMTP"
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr "AWS SES"
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr "Utiliza SMTP para enviar boletines"
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr "Nombre Host"
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr "Puerto"
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr "Puerto, por ejemplo 465. Autodetecta si es vacio"
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr "Codificación"
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr "Desactivar la autenticación SMTP"
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Nombre de usuario"
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr "Nombre de usuario, por ejemplo. nombre@ejemplo.com"
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr "Contraseña"
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr "Utilizar la API de SES para enviar correo"
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr "Clave de acceso"
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr "ID Clave de acceso AWS"
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr "Clave secreta"
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr "Clave de acceso secreta AWS"
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr "Región"
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr "Comprobación"
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr "Compruebe configuración de Remitente"
+
+#: views/settings.hbs:52
+msgid "Don't have an SMTP account yet? Create a free SendPulse account"
+msgstr ""
+"¿No tienes una cuenta SMTP todavía? Crear una cuenta gratuita en SendPulse"
+
+#: views/settings.hbs:53
+msgid "here"
+msgstr "aquí"
+
+#: views/settings.hbs:54
+msgid "Advanced Mailer settings"
+msgstr "Ajustes avanzados de Remitente"
+
+#: views/settings.hbs:55
+msgid "Log SMTP transactions"
+msgstr "Registrar transacciones SMTP"
+
+#: views/settings.hbs:56
+msgid "Allow self-signed certificates"
+msgstr "Permitir certificados con firma propia"
+
+#: views/settings.hbs:57
+msgid "Max connections"
+msgstr "Número máximo de conexiones"
+
+#: views/settings.hbs:58
+msgid "The count of max connections, eg. 10"
+msgstr "Recuento de conexiones máximo, por ejemplo. 10"
+
+#: views/settings.hbs:59
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+"Recuento del número máximo de conexiones simultáneas para hacer frente al "
+"servidor SMTP (por defecto 5). Este límite es por proceso de envío."
+
+#: views/settings.hbs:60
+msgid "Max messages"
+msgstr "Número máximo de mensajes"
+
+#: views/settings.hbs:61
+msgid "The count of max messages, eg. 100"
+msgstr "El recuento de mensajes máximo, por ejemplo. 100"
+
+#: views/settings.hbs:62
+msgid ""
+"The number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+"El número de mensajes a enviar a través de una única conexión antes de la "
+"conexión se cierra y se vuelve a abrir (por defecto 100)"
+
+#: views/settings.hbs:63
+msgid "Throttling"
+msgstr "Regulador "
+
+#: views/settings.hbs:64
+msgid "Messages per hour eg. 1000"
+msgstr "Mensajes por hora, por ejemplo 1000"
+
+#: views/settings.hbs:65
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+"Número máximo de mensajes que se envían en una hora. Dejar en blanco o nulo "
+"sin regulación. Si su proveedor utiliza un límite de velocidad diferente "
+"(mensajes / minuto o mensajes / segundo) a continuación, convertir este "
+"límite en mensajes/hora (1m/s => 3600m/h). Este límite es por proceso de "
+"envío."
+
+#: views/settings.hbs:66
+msgid "VERP bounce handling"
+msgstr "Manejo de rebote VERP"
+
+#: views/settings.hbs:67
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+"Mailtrain es capaz de utilizar el enrutamiento basado VERP para detectar "
+"rebotes. En este caso el mensaje se envía al destinatario mediante una "
+"dirección VERP personalizada como la vía de retorno del mensaje. Si el "
+"mensaje no se acepta un correo electrónico de rebote es enviado a esta "
+"dirección especial VERP y por lo tanto se detecta un rebote."
+
+#: views/settings.hbs:68
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+"ePara obtener el trabajo de VERP, necesitas crear un registro DNS MX que "
+"apunta a su nombre de host Mailtrain. También debe asegurarse de que la "
+"interfaz Mailtrain VERP está disponible desde el puerto 25 del servidor "
+"(puerto 25 por lo general requiere privilegios de usuario root). De esta "
+"manera si alguien trata de enviar un correo electrónico a someuser@verp-"
+"hostname, el correo electrónico debe terminar en este servidor."
+
+#: views/settings.hbs:69
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+"Por lo general VERP sólo funciona si está utilizando su propio servidor "
+"SMTP. Servicios de transmisión regulares (SES, SparkPost, Gmail, etc.) "
+"tienden a eliminar la dirección VERP del mensaje."
+
+#: views/settings.hbs:70
+msgid "Use VERP to catch bounces"
+msgstr "Utilice VERP para rebotes"
+
+#: views/settings.hbs:71
+msgid "Server hostname"
+msgstr "Nombre de Host del servidor"
+
+#: views/settings.hbs:72
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr "El nombre de host del servidor VERP, por ejemplo. bounces.ejemplo.com"
+
+#: views/settings.hbs:73
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+"Nombre de Servidor Host que maneja rebotes VERP. Este nombre de host se "
+"utiliza en el FROM del sobre SMTP y los registros DNS MX deben señalar a "
+"este servidor"
+
+#: views/settings.hbs:74
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+"Servidor Host VERP que maneja rebotes no esta activado. Modifica el archivo "
+"de configuración de tu servidor y reinicia el servidor para activarlo."
+
+#: views/settings.hbs:75
+msgid "GPG Signing"
+msgstr "Firma GPG"
+
+#: views/settings.hbs:76
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+"Sólo los mensajes cifrados pueden ser firmados. Los suscriptores que no han "
+"establecido una clave pública GPG en su perfil de recibirán mensajes de "
+"correo electrónico normales. Los usuarios con claves GPG establecidad, "
+"recibirán mensajes cifrados y si tiene clave de firma también establecida, "
+"los mensajes estarán firmados con esa clave."
+
+#: views/settings.hbs:77
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+"No utilice las teclas susceptibles aquí. La clave privada y la frase de "
+"contraseña no están cifrados en la base de datos."
+
+#: views/settings.hbs:78
+msgid "Private Key Passphrase"
+msgstr "Frase clave privada"
+
+#: views/settings.hbs:79
+msgid "Passphrase for the key if set"
+msgstr "Frase de contraseña para la clave si se establece"
+
+#: views/settings.hbs:80
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+"Sólo rellene esto si su clave privada se cifra con una frase de contraseña"
+
+#: views/settings.hbs:81
+msgid "GPG Private Key"
+msgstr "Clave privada GPG"
+
+#: views/settings.hbs:83
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+"Este valor es opcional. Si usted no proporciona una clave privada GPG los "
+"mensajes cifrados se envían sin firma."
+
+#: views/settings.hbs:84
+msgid "DKIM Signing by ZoneMTA"
+msgstr "Firma DKIM por ZoneMTA"
+
+#: views/settings.hbs:85
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+"Si está utilizando ZoneMTA, Mailtrain puede proporcionar una clave DKIM para "
+"la firma de todos los mensajes salientes. Otros servicios suelen "
+"proporcionar sus propios medios para firmar sus mensajes DKIM"
+
+#: views/settings.hbs:86
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+"No utilice las teclas susceptibles aquí. La clave privada no está cifrada en "
+"la base de datos."
+
+#: views/settings.hbs:87
+msgid "ZoneMTA DKIM API Key"
+msgstr "CLAVE de API DKIM ZoneMTA"
+
+#: views/settings.hbs:88
+msgid "Some secret value"
+msgstr "Algunos valores secretos"
+
+#: views/settings.hbs:89
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+"Valor secreto conocido a ZoneMTA para solicitar información clave DKIM. Si "
+"este valor se genera mediante el script de instalación Mailtrain entonces se "
+"puede mantener como está"
+
+#: views/settings.hbs:90
+msgid "DKIM domain"
+msgstr "dominio DKIM"
+
+#: views/settings.hbs:91
+msgid "Domain name for the DKIM key"
+msgstr "nombre de dominio para la clave DKIM"
+
+#: views/settings.hbs:92
+msgid "Leave blank to use the sender email address domain"
+msgstr ""
+"Dejar en blanco para usar el dominio de dirección de correo electrónico del "
+"remitente"
+
+#: views/settings.hbs:93 views/settings.hbs:94
+msgid "DKIM key selector"
+msgstr "Selector Clave de DKIM"
+
+#: views/settings.hbs:95
+msgid "Signing is disabled without a valid selector value"
+msgstr "Firma está desactivada y sin un valor de selección válido"
+
+#: views/settings.hbs:96
+msgid "DKIM Private Key"
+msgstr "Clave privada DKIM"
+
+#: views/settings.hbs:98
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+"Este valor es opcional. Si usted no proporciona una clave privada a "
+"continuación, los mensajes no se firman."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:1
+#: views/subscription/mail-already-subscribed-text.hbs:1
+#: lib/models/subscriptions.js:171 lib/models/subscriptions.js:892
+msgid "Email address already registered"
+msgstr "Dirección de correo ya registrada"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:2
+#: views/subscription/mail-already-subscribed-text.hbs:2
+msgid ""
+"We have received a subscription request. Your email address is however "
+"already registered."
+msgstr ""
+"Hemos recibido una solicitud de suscripción. Su dirección de correo "
+"electrónico está sin embargo ya registrada."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:3
+#: views/subscription/mail-already-subscribed-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. Your existing "
+"subscription won't be affected."
+msgstr ""
+"Si ha recibido este mensaje por error, simplemente elimínalo. Su "
+"subscripción no se verá afectada."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:3
+msgid "If you want to modify your subscription then you can "
+msgstr "Si desea modificar su suscripción, puedes"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:5
+#: views/subscription/mail-already-subscribed-text.hbs:5
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:4
+msgid "manage your preferences"
+msgstr "administrar tus preferencias"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:6
+#: views/subscription/mail-already-subscribed-text.hbs:6
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-subscription-confirmed-text.hbs:5
+#: views/users/login.hbs:10
+msgid "or"
+msgstr "o"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:7
+#: views/subscription/mail-already-subscribed-text.hbs:7
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:6
+#: views/subscription/mail-subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "darte de baja aquí"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:7
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:3
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:3
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:4
+#: views/subscription/web-subscribed-notice.mjml.hbs:4
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:3
+#: views/subscription/web-updated-notice.mjml.hbs:3
+msgid "Return to our website"
+msgstr "Vuelvea nuestra web"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:9
+#: views/subscription/mail-already-subscribed-text.hbs:8
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:4
+#: views/subscription/mail-confirm-address-change-text.hbs:4
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-subscription-text.hbs:4
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-unsubscription-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-text.hbs:7
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr ""
+"Para preguntas acerca de esta lista, por favor, póngase en contacto con "
+"nosotros en:"
+
+#: views/subscription/mail-already-subscribed-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Si desea modificar su suscripción a continuación, puedes:"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:1
+#: views/subscription/mail-confirm-address-change-text.hbs:1
+msgid "Please Confirm Subscription Address Change"
+msgstr "Por favor, confirma el campo de Dirección de correo de Suscripción"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:2
+#: views/subscription/mail-confirm-address-change-text.hbs:2
+msgid "Yes, subscribe this email address to the list"
+msgstr "Sí, suscribir esta dirección de correo electrónico a la lista"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:3
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Si ha recibido este mensaje por error, simplemente elimínalo. No será "
+"suscrito si no hace clic en el enlace de confirmación anterior."
+
+#: views/subscription/mail-confirm-address-change-text.hbs:3
+#: views/subscription/mail-confirm-subscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Si ha recibido este mensaje por error, simplemente elimínalo. No va a estar "
+"suscrito a menos que haga clic en el enlace de confirmación anterior."
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:1
+#: views/subscription/mail-confirm-subscription-text.hbs:1
+#: views/subscription/mail-confirm-unsubscription-text.hbs:1
+#: routes/subscription.js:431
+msgid "Please Confirm Subscription"
+msgstr "Por favor, confirme la suscripción"
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-subscription-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Sí, suscribirme a la lista"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:1
+msgid "Please Confirm Unsubscription"
+msgstr "Por favor, confirma la baja"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-unsubscription-text.hbs:2
+msgid "Yes, unsubscribe me from this list"
+msgstr "Sí, darme de baja de esta lista"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed if you don't click the confirmation link above."
+msgstr ""
+"Si ha recibido este mensaje por error, simplemente elimínalo. No será dado "
+"de baja si no hace clic en el enlace de confirmación anterior."
+
+#: views/subscription/mail-confirm-unsubscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed unless you click the confirmation link above."
+msgstr ""
+"Si ha recibido este mensaje por error, simplemente elimínalo. No será dado "
+"de baja a menos de hacer clic en el enlace de confirmación anterior."
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-subscription-confirmed-text.hbs:1
+#: views/subscription/web-subscribed-notice.mjml.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Suscripción confirmada"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed"
+msgstr "Su suscripción a nuestra lista ha sido confirmada"
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:2
+#: views/subscription/web-subscribed-notice.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "Su suscripción a nuestra lista ha sido confirmada."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:1
+msgid "You Are Now Unsubscribed"
+msgstr "Tu estás dado de baja ahora"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:2
+msgid "We have removed your email address from our list"
+msgstr "Hemos eliminado su correo electrónico de nuestra lista"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:3
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr "Si te has dado de baja por error, puedes volverte a suscribir en:"
+
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Hemos eliminado su correo electrónico de nuestra lista."
+
+#: views/subscription/partials/subscription-custom-fields.hbs:2
+msgid "want to change it?"
+msgstr "quieres cambiarla?"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:5
+msgid "Download signature verification key"
+msgstr "Descargar clave de verificación de firma"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:7
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+"Inserta tu clave GPG pública aquí para encriptar mensajes enviados a tu "
+"dirección"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:8
+msgid "optional"
+msgstr "opcional"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:1
+#: views/subscription/partials/subscription-flash-messages.hbs:3
+msgid "Warning!"
+msgstr "¡Advertencia!"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+"Si JavaScript no está activada, no se envia ningún mensaje de confirmación"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:4
+msgid "JavaScript must be enabled in order for this form to work"
+msgstr "JavaScript debe estar habilitado para esta forma de funcionamiento"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:1
+msgid "Existing Email Address"
+msgstr "Correo electrónico existente"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:2
+msgid "New Email Address"
+msgstr "Nuevo Correo electrónico"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:3
+msgid "Your new email address"
+msgstr "Tu nuevo correo electrónico"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:4
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Recibirás un email a tu nuevo correo electrónico con una solicitud de "
+"confirmación. Tras aceptarla el correo será cambiado definitivamente."
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:5
+#: views/subscription/web-manage-address.mjml.hbs:2
+msgid "Update Email Address"
+msgstr "Actualizar el correo electrónico"
+
+#: views/subscription/partials/subscription-manage-form.hbs:1
+#: views/subscription/web-manage.mjml.hbs:2
+msgid "Update Profile"
+msgstr "Actualizar perfil"
+
+#: views/subscription/partials/subscription-subscribe-form.hbs:1
+#: views/subscription/web-subscribe.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:1
+msgid "Subscribe to list"
+msgstr "Suscrito a la lista"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:1
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:1
+#: views/subscription/widget-subscribe.hbs:4
+msgid "Almost Finished"
+msgstr "Casi terminado"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:5
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Necesitamos confirmar tu dirección de correo electrónico. Para completar el "
+"proceso de suscripción, por favor haz clic en el enlace del correo "
+"electrónico que acabamos de enviarte."
+
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:2
+msgid ""
+"We need to confirm your email address. To complete the unsubscription "
+"process, please click the link in the email we just sent you."
+msgstr ""
+"Necesitamos confirmar tu dirección de correo electrónico. Para completar el "
+"proceso de darse de baja, por favor haga clic en el enlace del correo "
+"electrónico que acabamos de enviarte."
+
+#: views/subscription/web-manage-address.mjml.hbs:1
+msgid "Update Your Email Address"
+msgstr "Actualizar su correo electrónico"
+
+#: views/subscription/web-manage.mjml.hbs:1
+msgid "Update Your Preferences"
+msgstr "Actualizar sus preferencias"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:1
+msgid "Online Unsubscription Is Not Possible"
+msgstr "Darse de baja online no es posible"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:2
+msgid "Please contact us at"
+msgstr "Por favor, contácta con nosotros en"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:3
+msgid "to get removed from the list"
+msgstr "ser eliminado de la lista"
+
+#: views/subscription/web-subscribe.mjml.hbs:1
+msgid "Subscribe to List"
+msgstr "Suscribirse a la lista"
+
+#: views/subscription/web-subscribed-notice.mjml.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "¡Gracias por suscribirte!"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Dado de baja con éxito"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:2
+msgid "You have been removed from:"
+msgstr "Has sido eliminado de:"
+
+#: views/subscription/web-updated-notice.mjml.hbs:1
+msgid "Profile Updated"
+msgstr "Perfeil actualizado"
+
+#: views/subscription/web-updated-notice.mjml.hbs:2
+msgid "Your profile information has been updated."
+msgstr "La información de tu perfil ha sido actualizada"
+
+#: views/subscription/widget-subscribe.hbs:2
+msgid "Sending ..."
+msgstr "Enviando"
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Parece que tu ya estabas suscrito a esta lista"
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Nombre de plantilla"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr "Nombre de esta plantilla, por ejemplo Newsletter"
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "Editor HTML"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr "Comentario opcional sobre esta plantilla"
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr "Volver a plantillas"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr "Automatización Trigger "
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr "Seleccionar una lista para el Trigger"
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr "Nombre de Trigger"
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr "Nombre para este Trigger, por ejemplo: Suscritores inactivos"
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr "Comentarios opcionales sobre el Trigger"
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr "Regla Trigger"
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr "Trigger encendido"
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr "días después:"
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Evento"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Campaña"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr "Acción Trigger"
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr "Enviar campaña"
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr "Edit Trigger"
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr "Volver a Triggers"
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr "Trigger está activado"
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr "Eliminar Trigger"
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr "Encadenados (Triggered)"
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr "Suscriptores Encadenados (Triggered)"
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr "Suscriptores que han provocado que este Trigger se encienda"
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr "Hora de Trigger"
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr "Trigger"
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr "Camapaña Objetivo"
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr "Cuenta Trigger"
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr "Esta cuenta esta gestionada mediante LDAP."
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr "Dirección mail asociada"
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr "Tu dirección email"
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr ""
+"Este email es usado para recuperar una cuenta en caso de que no recuerdes la "
+"contraseña"
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr "Cambio de contraseña"
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+"Tu sólo necesitas completar este formulario si quieres cambiar la contraseña "
+"actual"
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr "Contraseña actual"
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr "Nueva contraseña"
+
+#: views/users/account.hbs:16 views/users/reset.hbs:8
+msgid "Confirm Password"
+msgstr "Confirmar contraseña"
+
+#: views/users/account.hbs:17 views/users/reset.hbs:9
+msgid "Confirm New Password"
+msgstr "Confirmar nueva contraseña"
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr ""
+"¿Estás seguro? El reinicio invalidará el token existente en este momento."
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr "¿Estás seguro?"
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr "Restablecer token de Acceso"
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr "Token de Acceso generado"
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr "Token de acceso personal:"
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr "Token de Acceso no generado aún"
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr "Notas sobre la API"
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+"Respuesta API es una estructura JSON con error y data"
+"code> propiedades. Si la respuesta error tiene un valor "
+"establecido la petición ha fallado."
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+"Necesitas definir correctamente Content-Type cuando se hace una "
+"petición. Tu puedes usar application/x-www-form-urlencoded para "
+"formulario de datos normal o application/json para carga JSON. "
+"El uso de multipart/form-data no es soportado."
+
+#: views/users/api.hbs:13
+msgid "Add subscription"
+msgstr "Añadir suscriptción"
+
+#: views/users/api.hbs:14
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+"Esta API llama a insertar un nuevo suscriptor o actualizar existente. Campos "
+"no incluidos no se modifican, pero si quieres actualizar solo el valor de "
+"LAST_NAME, FIRST_NAME no se modifica para suscripciones existentes."
+
+#: views/users/api.hbs:15 views/users/api.hbs:17 views/users/api.hbs:30
+#: views/users/api.hbs:32 views/users/api.hbs:38 views/users/api.hbs:40
+#: views/users/api.hbs:46 views/users/api.hbs:57 views/users/api.hbs:59
+#: views/users/api.hbs:65 views/users/api.hbs:67
+msgid "arguments"
+msgstr "razón/argumento"
+
+#: views/users/api.hbs:16 views/users/api.hbs:31 views/users/api.hbs:39
+#: views/users/api.hbs:47 views/users/api.hbs:58 views/users/api.hbs:66
+msgid "your personal access token"
+msgstr "tu token personal de acceso"
+
+#: views/users/api.hbs:18 views/users/api.hbs:33 views/users/api.hbs:41
+msgid "subscriber's email address"
+msgstr "Correo de Suscriptor"
+
+#: views/users/api.hbs:19 views/users/api.hbs:34 views/users/api.hbs:42
+#: views/users/api.hbs:61 views/users/api.hbs:69
+msgid "required"
+msgstr "Obligatorio"
+
+#: views/users/api.hbs:20
+msgid "subscriber's first name"
+msgstr "Nombre de suscriptor"
+
+#: views/users/api.hbs:21
+msgid "subscriber's last name"
+msgstr "Apellidos de suscriptor"
+
+#: views/users/api.hbs:22
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"la zona horaria del suscriptor (por ejemplo. \"Europa / Tallin\", \"PST\" o "
+"\"UTC\"). Si no se establece, por defecto es \"UTC\""
+
+#: views/users/api.hbs:23
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+"Valor de campo personalizado. Utilice sí / no para la opción de los valores "
+"del grupo (casillas de verificación, radios, menús desplegables)"
+
+#: views/users/api.hbs:24
+msgid "Additional POST arguments"
+msgstr "Los argumentos adicionales del POST"
+
+#: views/users/api.hbs:25
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+"Marca \"Sí\" si desea asegurarse de que el correo electrónico se marca como "
+"suscrito incluso si fue previamente marcado como baja. Si el correo "
+"electrónico ya fue dado de baja o bloqueado, el estado de suscripción no se "
+"cambia"
+
+#: views/users/api.hbs:26
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+"Marca \"Sí\" si desea enviar un correo electrónico de confirmación al "
+"suscriptor antes de que realmente se marque como suscrito"
+
+#: views/users/api.hbs:28
+msgid "Remove subscription"
+msgstr "Eliminar suscripción"
+
+#: views/users/api.hbs:29
+msgid "This API call marks a subscription as unsubscribed"
+msgstr "Esta llamada a la API marca una suscripción como dado de baja"
+
+#: views/users/api.hbs:36
+msgid "Delete subscription"
+msgstr "Eliminar suscripción"
+
+#: views/users/api.hbs:37
+msgid "This API call deletes a subscription"
+msgstr "Esta llamada a la API elimina una suscripción"
+
+#: views/users/api.hbs:44
+msgid "Get list of blacklisted emails"
+msgstr "Obtener la lista de correos electrónicos de la lista negra"
+
+#: views/users/api.hbs:45
+msgid "This API call get list of blacklisted emails."
+msgstr ""
+"Esta llamada a la API consigue la lista de correos electrónicos de la lista "
+"negra."
+
+#: views/users/api.hbs:48
+msgid "Start position"
+msgstr "Posición de salida"
+
+#: views/users/api.hbs:49
+msgid "optional, default 0"
+msgstr "opcional, por defecto 0"
+
+#: views/users/api.hbs:50
+msgid "limit emails count in response"
+msgstr "cantidad límite de emails en la respuesta"
+
+#: views/users/api.hbs:51
+msgid "optional, default 10000"
+msgstr "opcional, por defecto 10000"
+
+#: views/users/api.hbs:52
+msgid "filter by part of email"
+msgstr "filtrar por correo electrónico"
+
+#: views/users/api.hbs:53
+msgid "optional, default ''"
+msgstr "opcional, por defecto ''"
+
+#: views/users/api.hbs:56
+msgid "This API call either add emails to blacklist"
+msgstr "Esta llamada a la API añade correos electrónicos a la lista negra"
+
+#: views/users/api.hbs:60 views/users/api.hbs:68
+msgid "email address"
+msgstr "Correo electrónico"
+
+#: views/users/api.hbs:63
+msgid "Delete email from blacklist"
+msgstr "Eliminar correo electrónico de la lista negra"
+
+#: views/users/api.hbs:64
+msgid "This API call either delete emails from blacklist"
+msgstr ""
+"Esta llamada a la API ya sea borrado mensajes de correo electrónico de la "
+"lista negra"
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr "Restablecimiento de contraseña"
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr "¿Quieres restablecer tu contraseña?"
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr "Las cuentas se gestionan a través de LDAP."
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr "Restablecer la contraseña"
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+"Por favor proporcione el nombre de usuario o correo electrónico que utilizó "
+"cuando se inscribió en su cuenta Mailtrain."
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr ""
+"Te enviaremos un correo electrónico que te permitirá restablecer tu "
+"contraseña."
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr "Nombre de usuario o correo electrónico"
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr "Envía un correo electrónico de verificación"
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Recuérdame"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "¿Se te olvidó tu contraseña?"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr "Cambiar la contraseña nueva"
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr "Por favor, introduzca una contraseña nueva."
+
+#: lib/editor-helpers.js:17 routes/templates.js:95
+msgid "Could not find template with specified ID"
+msgstr "No se pudo encontrar la plantilla con el ID especificado"
+
+#: lib/editor-helpers.js:33 routes/archive.js:145 routes/campaigns.js:131
+#: routes/campaigns.js:284 routes/campaigns.js:379 routes/campaigns.js:427
+#: routes/campaigns.js:467 routes/campaigns.js:844 routes/campaigns.js:867
+#: routes/campaigns.js:886 routes/campaigns.js:908 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr "No se pudo encontrar campaña con el ID especificado"
+
+#: lib/editor-helpers.js:47 routes/editorapi.js:308
+msgid "Invalid resource type"
+msgstr "Tipo de recurso no válido"
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr "Mal código de estado %s"
+
+#: lib/helpers.js:33
+msgid "URL that points to the unsubscribe page"
+msgstr "URL que apunta a la página de darse de baja"
+
+#: lib/helpers.js:36
+msgid "URL that points to the preferences page of the subscriber"
+msgstr "URL que apunta a la página de preferencias del suscriptor"
+
+#: lib/helpers.js:39
+msgid "URL to preview the message in a browser"
+msgstr "URL para obtener una vista previa del mensaje en un navegador"
+
+#: lib/helpers.js:45 lib/models/segments.js:31
+msgid "First name"
+msgstr "Nombre"
+
+#: lib/helpers.js:48 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Apellidos"
+
+#: lib/helpers.js:51
+msgid "Full name (first and last name combined)"
+msgstr "Nombre completo (nombre y apellidos)"
+
+#: lib/helpers.js:54
+msgid "Unique ID that identifies the recipient"
+msgstr "ID único que identifica al destinatario"
+
+#: lib/helpers.js:57
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr "ID único que identifica la lista prevista para esta campaña"
+
+#: lib/helpers.js:60
+msgid "Unique ID that identifies current campaign"
+msgstr "ID único que identifica la campaña actual"
+
+#: lib/helpers.js:68 lib/helpers.js:80
+msgid "content from an RSS entry"
+msgstr "Contenido de una entrada RSS"
+
+#: lib/helpers.js:71
+msgid "RSS entry title"
+msgstr "Título de la entrada RSS"
+
+#: lib/helpers.js:74
+msgid "RSS entry date"
+msgstr "Fecha de entrada RSS"
+
+#: lib/helpers.js:77
+msgid "RSS entry link"
+msgstr "Enlace de entrada RSS"
+
+#: lib/helpers.js:83
+msgid "RSS entry summary"
+msgstr "Resumen de entrada RSS"
+
+#: lib/helpers.js:86
+msgid "RSS entry image URL"
+msgstr "URL de la imagen de entrada RSS"
+
+#: lib/mailer.js:245
+msgid "Invalid mail transport"
+msgstr "Modo fe envío de correo no válido"
+
+#: lib/models/campaigns.js:105 lib/models/campaigns.js:132
+#: lib/models/campaigns.js:205 lib/models/campaigns.js:328
+#: lib/models/campaigns.js:590 lib/models/campaigns.js:723
+msgid "Missing Campaign ID"
+msgstr "Falta el ID de campaña"
+
+#: lib/models/campaigns.js:241
+msgid "Emtpy or too large attahcment"
+msgstr "Adjunto vacío o de tamaño superior al posible"
+
+#: lib/models/campaigns.js:408 lib/models/campaigns.js:600
+msgid "Campaign Name must be set"
+msgstr "El nombre de la campaña se debe ajustar"
+
+#: lib/models/campaigns.js:412
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr "La URL del RSS se debe establecer y debe ser una URL válida"
+
+#: lib/models/campaigns.js:568
+msgid "Selected template not found"
+msgstr "La plantilla seleccionada no se encuentra"
+
+#: lib/models/campaigns.js:924
+msgid "Invalid or missing message ID"
+msgstr "Falta ID del mensaje o es inválido"
+
+#: lib/models/campaigns.js:1065
+msgid "Unrecognized message status"
+msgstr "Estado del mensaje no reconocido"
+
+#: lib/models/confirmations.js:27
+msgid "Could not store confirmation data"
+msgstr "No se pudo almacenar datos de confirmación"
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr "Desplegable"
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Fecha (MM/DD/YYY)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr "valor para la representación personalizada JSON"
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr "Opción"
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/forms.js:46 lib/models/lists.js:83 lib/models/lists.js:118
+#: lib/models/lists.js:232 lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:79 lib/models/subscriptions.js:387
+#: lib/models/subscriptions.js:563 lib/models/subscriptions.js:654
+#: lib/models/subscriptions.js:707 lib/models/subscriptions.js:770
+#: lib/models/subscriptions.js:813
+msgid "Missing List ID"
+msgstr "Falta el ID de la lista"
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr "El campo Opción requiere que un grupo está seleccionado"
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr "Falta el campo ID"
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr "El campo Nombre debe establecerse"
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr "Campo personalizado no encontrado"
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr "Desconocido el tipo de columna %s"
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr "Falta el nombre de la columna"
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr "Falta el ID de la lista"
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr "ID proporcionado de la lista no es encontrado"
+
+#: lib/models/forms.js:70 lib/models/forms.js:113 lib/models/forms.js:201
+#: lib/models/forms.js:291
+msgid "Missing Form ID"
+msgstr "Falta ID del Formulario"
+
+#: lib/models/forms.js:121 lib/models/forms.js:205
+msgid "Form Name must be set"
+msgstr "El Nombre del Formulario se debe ajustar"
+
+#: lib/models/forms.js:307
+msgid "Custom form not found"
+msgstr "Formulario personalizado no encontrado"
+
+#: lib/models/links.js:337 routes/campaigns.js:533 routes/campaigns.js:581
+#: routes/campaigns.js:621 routes/campaigns.js:671 services/sender.js:305
+msgid "Campaign not found"
+msgstr "Campaña no encontrada"
+
+#: lib/models/links.js:345 routes/lists.js:181 services/sender.js:312
+msgid "List not found"
+msgstr "Lista no encontrada"
+
+#: lib/models/links.js:353
+msgid "Subscription not found"
+msgstr "Suscripción no encontrada"
+
+#: lib/models/lists.js:134 lib/models/lists.js:178
+msgid "List Name must be set"
+msgstr "El nombre de la lista debe ser ajustado"
+
+#: lib/models/lists.js:261
+msgid "Missing List CID"
+msgstr "Falta CID de la lista"
+
+#: lib/models/report-templates.js:26 lib/models/report-templates.js:70
+#: lib/models/report-templates.js:142
+msgid "Missing report template ID"
+msgstr "Falta ID de plantilla informe"
+
+#: lib/models/report-templates.js:77
+msgid "Report template name must be set"
+msgstr "El nombre de la plantilla informe se debe ajustar"
+
+#: lib/models/reports.js:40 lib/models/reports.js:110 lib/models/reports.js:188
+msgid "Missing report ID"
+msgstr "Falta ID de informe "
+
+#: lib/models/reports.js:116
+msgid "Report name must be set"
+msgstr "Nombre del informe se debe ajustar"
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr "País de registro"
+
+#: lib/models/segments.js:19 lib/models/triggers.js:12
+msgid "Sign up date"
+msgstr "Fecha de inscripción"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:16
+msgid "Latest open"
+msgstr "Última apertura"
+
+#: lib/models/segments.js:27 lib/models/triggers.js:20
+msgid "Latest click"
+msgstr "Último clic"
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr "Falta el ID de segmento"
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr "El segmento no se encuentra"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr "%s días después de hoy"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr "%s días antes de hoy"
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr "hoy"
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr "Tipo de regla de segmento no válido"
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr "El segmento seleccionado no se encuentra"
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr "Tipo de regla no válida"
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr "Falta el ID de la regla"
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr "La regla especificada no se encontra"
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr "El segmento especificado no se encontra"
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr "La regla seleccionada no se encontra"
+
+#: lib/models/subscriptions.js:254 lib/models/subscriptions.js:284 lib/models/subscriptions.js:391
+msgid "Missing Subscription ID"
+msgstr "Falta el ID de Suscripción"
+
+#: lib/models/subscriptions.js:312
+msgid "Missing Subscription email address"
+msgstr "Falta el correo electrónico de suscripción"
+
+#: lib/models/subscriptions.js:567 lib/models/subscriptions.js:817
+msgid "Missing subscription ID"
+msgstr "Falta el ID de suscripción"
+
+#: lib/models/subscriptions.js:658 lib/models/subscriptions.js:711
+#: lib/models/subscriptions.js:747
+msgid "Missing Import ID"
+msgstr "Falta el ID de importación"
+
+#: lib/models/subscriptions.js:839
+msgid "Unknown subscription ID"
+msgstr "No se conoce el ID de suscripción"
+
+#: lib/models/subscriptions.js:844 routes/subscription.js:638
+msgid "Nothing seems to be changed"
+msgstr "Nada parece haber sido cambiado"
+
+#: lib/models/subscriptions.js:910 routes/subscription.js:472
+#: routes/subscription.js:544 routes/subscription.js:580
+#: routes/subscription.js:696 routes/subscription.js:771
+msgid "Subscription not found in this list"
+msgstr "La suscripción no se encuentra en esta lista"
+
+#: lib/models/templates.js:26 lib/models/templates.js:100
+#: lib/models/templates.js:144
+msgid "Missing Template ID"
+msgstr "Falta el ID de plantilla"
+
+#: lib/models/templates.js:55 lib/models/templates.js:104
+msgid "Template Name must be set"
+msgstr "El nombre de la plantilla se debe ajustar"
+
+#: lib/models/triggers.js:29
+msgid "Has Opened"
+msgstr "Ha abierto"
+
+#: lib/models/triggers.js:32
+msgid "Has Clicked"
+msgstr "Ha hecho clic"
+
+#: lib/models/triggers.js:35
+msgid "Not Opened"
+msgstr "No ha abierto"
+
+#: lib/models/triggers.js:38
+msgid "Not Clicked"
+msgstr "No ha hecho clic"
+
+#: lib/models/triggers.js:175 lib/models/triggers.js:212
+msgid "Missing or invalid list ID"
+msgstr "Falta ID de lista o es inválido"
+
+#: lib/models/triggers.js:179 lib/models/triggers.js:264
+msgid "Days in the past are not allowed"
+msgstr "No se permiten días pasados"
+
+#: lib/models/triggers.js:183 lib/models/triggers.js:204
+#: lib/models/triggers.js:268 lib/models/triggers.js:289
+msgid "Missing or invalid trigger rule"
+msgstr "Falta Regla encadenante o es inválida"
+
+#: lib/models/triggers.js:190 lib/models/triggers.js:275
+msgid "Invalid subscription configuration"
+msgstr "La configuración de suscripción no es válida"
+
+#: lib/models/triggers.js:197 lib/models/triggers.js:282
+msgid "Invalid campaign configuration"
+msgstr "Configuración de la campaña no es válida"
+
+#: lib/models/triggers.js:200 lib/models/triggers.js:285
+msgid "A campaing can not be a target for itself"
+msgstr "Una campaña no puede ser un objetivo por sí mismo"
+
+#: lib/models/triggers.js:233
+msgid "Could not store trigger row"
+msgstr "No se pudo almacenar el trigger"
+
+#: lib/models/triggers.js:250
+msgid "Missing or invalid Trigger ID"
+msgstr "Falta ID de Trigger o es inválido"
+
+#: lib/models/triggers.js:317
+msgid "Missing Trigger ID"
+msgstr "Falta ID de Trigger"
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr "No se pudo almacenar fila de usuario"
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr "El correo electrónico debe estar configurado"
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr "No se ha podido comprobar los datos de usuario"
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+"No se puede cambiar el correo electrónico como otro usuario con la misma "
+"dirección de correo electrónico que ya existe"
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr "Contraseña actual incorrecta"
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr "La nueva contraseña no se ha establecido"
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr "Las contraseñas no coinciden"
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr "El ID de usuario no se ha establecido"
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr "El nombre de usuario debe configurarse"
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr "Solicitud de cambio de contraseña de correo electrónico"
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr "Falta el nombre de usuario o restablecer Token"
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Nueva contraseña inválida"
+
+#: lib/passport.js:40
+msgid "%s logged out"
+msgstr "%s desconectado"
+
+#: lib/passport.js:53
+msgid "Failed to authenticate user"
+msgstr "Error de autenticación de usuario"
+
+#: lib/passport.js:69
+msgid "Logged in as %s"
+msgstr "Conectado como %s"
+
+#: lib/passport.js:128
+msgid "Incorrect username or password"
+msgstr "Nombre de usuario o contraseña incorrecta"
+
+#: lib/subscription-mail-helpers.js:28
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Suscripción Confirmada"
+
+#: lib/subscription-mail-helpers.js:39
+msgid "%s: Email Address Already Registered"
+msgstr "%s: Correo electrónico registrado"
+
+#: lib/subscription-mail-helpers.js:49
+msgid "%s: Please Confirm Email Change in Subscription"
+msgstr "%s: Por favor confirma el cambio de correo electrónico de suscripción"
+
+#: lib/subscription-mail-helpers.js:59
+msgid "%s: Please Confirm Subscription"
+msgstr "%s: Por favor confirma la Suscripción"
+
+#: lib/subscription-mail-helpers.js:69
+msgid "%s: Please Confirm Unsubscription"
+msgstr "%s: Por favor confirma la Baja"
+
+#: lib/subscription-mail-helpers.js:76
+msgid "%s: Unsubscription Confirmed"
+msgstr "%s: Baja confirmada :("
+
+#: lib/tools.js:154
+msgid "Blocked email address \"%s\""
+msgstr "Correo electrónico bloqueado \"%s\""
+
+#: lib/tools.js:163
+msgid "Invalid email address \"%s\"."
+msgstr "Correo electrónico inválido \"%s\"."
+
+#: lib/tools.js:166
+msgid "MX record not found for domain"
+msgstr "Registro MX para el dominio no encontrado"
+
+#: lib/tools.js:169
+msgid "Address domain not found"
+msgstr "No se ha encontrado dominio de la dirección"
+
+#: lib/tools.js:172
+msgid "Address domain name is required"
+msgstr "Se requiere el nombre de dominio"
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:230
+msgid "Not Found"
+msgstr "No encontrado"
+
+#: routes/archive.js:121 services/sender.js:451
+msgid "Received status code %s from %s"
+msgstr "Código de estado recibido %s de %s"
+
+#: routes/archive.js:153 routes/campaigns.js:894
+msgid "Attachment not found"
+msgstr "Adjunto no encontrado"
+
+#: routes/blacklist.js:13 routes/campaigns.js:26 routes/editorapi.js:35
+#: routes/fields.js:13 routes/forms.js:16 routes/grapejs.js:14
+#: routes/lists.js:50 routes/mosaico.js:14 routes/report-templates.js:20
+#: routes/reports.js:22 routes/segments.js:13 routes/settings.js:23
+#: routes/templates.js:18 routes/triggers.js:18 routes/users.js:75
+#: routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Tienes que estar registrado para acceder a contenido restringido"
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr "No se pudo crear la campaña"
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr "Campaña “%s” creada"
+
+#: routes/campaigns.js:209
+msgid "Campaign settings updated"
+msgstr "Configuración de la campaña actualizada"
+
+#: routes/campaigns.js:211
+msgid "Campaign settings not updated"
+msgstr "La configuración de la campaña no se ha actualizado"
+
+#: routes/campaigns.js:227 routes/campaigns.js:744
+msgid "Campaign deleted"
+msgstr "Campaña eliminada"
+
+#: routes/campaigns.js:229 routes/campaigns.js:746
+msgid "Could not delete specified campaign"
+msgstr "No se pudo eliminar la campaña especificada"
+
+#: routes/campaigns.js:248
+msgid "Idling"
+msgstr "Inactivo/No usado"
+
+#: routes/campaigns.js:251
+msgid "Scheduled"
+msgstr "Programado"
+
+#: routes/campaigns.js:257
+msgid "Paused"
+msgstr "Pausado"
+
+#: routes/campaigns.js:259
+msgid "Inactive"
+msgstr "Inactivo"
+
+#: routes/campaigns.js:261
+msgid "Active"
+msgstr "Activo"
+
+#: routes/campaigns.js:263
+msgid "Other"
+msgstr "Otros"
+
+#: routes/campaigns.js:421
+msgid "Unknown status selector"
+msgstr "Estado seleccionado no conocido"
+
+#: routes/campaigns.js:762
+msgid "Scheduled sending"
+msgstr "Envío programado"
+
+#: routes/campaigns.js:764
+msgid "Could not schedule sending"
+msgstr "No se puede programar el envío"
+
+#: routes/campaigns.js:776
+msgid "Sending resumed"
+msgstr "Envío reanudado"
+
+#: routes/campaigns.js:778
+msgid "Could not resume sending"
+msgstr "No se pudo reanudar el envío"
+
+#: routes/campaigns.js:790
+msgid "Sending reset"
+msgstr "Envío reiniciado"
+
+#: routes/campaigns.js:792
+msgid "Could not reset sending"
+msgstr "No se ha podido reiniciar el envío"
+
+#: routes/campaigns.js:804 routes/campaigns.js:832
+msgid "Sending paused"
+msgstr "Envío pausado"
+
+#: routes/campaigns.js:806 routes/campaigns.js:834
+msgid "Could not pause sending"
+msgstr "No se ha podido pausar el envío"
+
+#: routes/campaigns.js:818
+msgid "Sending activated"
+msgstr "Envío activado"
+
+#: routes/campaigns.js:820
+msgid "Could not activate sending"
+msgstr "No se ha podido activar el envío"
+
+#: routes/campaigns.js:855
+msgid "Attachment uploaded"
+msgstr "Adjunto subido"
+
+#: routes/campaigns.js:857
+msgid "Could not store attachment"
+msgstr "No se ha podido almacenar el adjunto"
+
+#: routes/campaigns.js:874
+msgid "Attachment deleted"
+msgstr "Adjunto eliminado"
+
+#: routes/campaigns.js:876
+msgid "Could not delete attachment"
+msgstr "No se ha podido eliminar el adjunto"
+
+#: routes/editorapi.js:41
+msgid "Invalid editor name"
+msgstr "Nombre de Editor inválido"
+
+#: routes/editorapi.js:237 routes/editorapi.js:275
+msgid "Method not supported"
+msgstr "Método no soportado"
+
+#: routes/editorapi.js:352
+msgid "Invalid resource type or ID"
+msgstr "Tipo de recurso o ID no válido"
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/forms.js:31 routes/forms.js:63 routes/forms.js:94
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr "ID de lista seleccionado no encontado"
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr "No se ha podido crear campo personalizado"
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr "Campo seleccionado no encontrado"
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr "Configuración del campo actualizado"
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr "Configuración del campo no actualizado"
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr "Campo personalizado eliminado"
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr "No se pudo eliminar el campo especificado"
+
+#: routes/forms.js:78
+msgid "Could not create custom form"
+msgstr "No se pudo crear el formulario personalizado"
+
+#: routes/forms.js:105
+msgid "Selected form not found"
+msgstr "El formulario seleccionado no se encuentra"
+
+#: routes/forms.js:136
+msgid "The plaintext version for this email"
+msgstr "Versión en formato texto para este correo electrónico"
+
+#: routes/forms.js:137
+msgid "Custom forms use MJML for formatting"
+msgstr "Formularios personalizados utilizan MJML para dar formato"
+
+#: routes/forms.js:138
+msgid "See the MJML documentation here"
+msgstr ""
+"Consulte la documentación de MJML aquí "
+
+#: routes/forms.js:146
+msgid "Layout"
+msgstr "Diseño"
+
+#: routes/forms.js:152
+msgid "Form Input Style"
+msgstr "Estilo de entrada de Formulario"
+
+#: routes/forms.js:154
+msgid ""
+"This CSS stylesheet defines the appearance of form input elements and alerts"
+msgstr ""
+"Esta hoja de estilo CSS define el aspecto de los elementos de entrada de "
+"formulario y alertas"
+
+#: routes/forms.js:160
+msgid "Web - Subscribe"
+msgstr "Web - Suscribirse"
+
+#: routes/forms.js:165
+msgid "Web - Confirm Subscription Notice"
+msgstr "Web - Aviso Confirmar suscripción"
+
+#: routes/forms.js:170
+msgid "Mail - Confirm Subscription (MJML)"
+msgstr "Mail - Confirmar suscripción (MJML)"
+
+#: routes/forms.js:175
+msgid "Mail - Confirm Subscription (Text)"
+msgstr "Mail - Confirmar suscripción (texto)"
+
+#: routes/forms.js:180
+msgid "Mail - Already Subscribed (MJML)"
+msgstr "Mail - Ya suscrito (MJML)"
+
+#: routes/forms.js:185
+msgid "Mail - Already Subscribed (Text)"
+msgstr "Mail - Ya Suscrito (texto)"
+
+#: routes/forms.js:190
+msgid "Web - Subscribed Notice"
+msgstr "Web - Aviso Suscripción"
+
+#: routes/forms.js:195
+msgid "Mail - Subscription Confirmed (MJML)"
+msgstr "Mail - Suscripción confirmada (MJML)"
+
+#: routes/forms.js:200
+msgid "Mail - Subscription Confirmed (Text)"
+msgstr "Mail - Suscripción confirmada (texto)"
+
+#: routes/forms.js:208
+msgid "Web - Manage Preferences"
+msgstr "Web - Gestión de Preferencias"
+
+#: routes/forms.js:213
+msgid "Web - Manage Address"
+msgstr "Web - Gestión de Dirección"
+
+#: routes/forms.js:218
+msgid "Web - Updated Notice"
+msgstr "Web - Aviso actualizado"
+
+#: routes/forms.js:226
+msgid "Web - Unsubscribe"
+msgstr "Web - Darse de baja"
+
+#: routes/forms.js:231
+msgid "Web - Confirm Unsubscription Notice"
+msgstr "Web - Confirmar Aviso de baja"
+
+#: routes/forms.js:236
+msgid "Mail - Confirm Unsubscription (MJML)"
+msgstr "Mail - Confirmar baja (MJML)"
+
+#: routes/forms.js:241
+msgid "Mail - Confirm Unsubscription (Text)"
+msgstr "Mail - Confirmar baja (MJML)"
+
+#: routes/forms.js:246
+msgid "Mail - Confirm Address Change (MJML)"
+msgstr "Mail - Confirmar Cambio de dirección (MJML)"
+
+#: routes/forms.js:251
+msgid "Mail - Confirm Address Change (Text)"
+msgstr "Mail - Confirmar Cambio de dirección (texto)"
+
+#: routes/forms.js:256
+msgid "Web - Unsubscribed Notice"
+msgstr "Web - Aviso Baja realizada"
+
+#: routes/forms.js:261
+msgid "Mail - Unsubscription Confirmed (MJML)"
+msgstr "Mail - Baja Confirmada (MJML)"
+
+#: routes/forms.js:266
+msgid "Mail - Unsubscription Confirmed (Text)"
+msgstr "Mail - Baja Confirmada (texto)"
+
+#: routes/forms.js:271
+msgid "Web - Manual Unsubscribe Notice"
+msgstr "Web - Aviso de Manual de Baja"
+
+#: routes/forms.js:309
+msgid "Form settings updated"
+msgstr "Configuración de formulario Actualizada"
+
+#: routes/forms.js:311
+msgid "Form settings not updated"
+msgstr "Configuración de formulario No Actualizada"
+
+#: routes/forms.js:327
+msgid "Custom form deleted"
+msgstr "Formulario Personalizado eliminado"
+
+#: routes/forms.js:329
+msgid "Could not delete specified form"
+msgstr "No se ha podido eliminar Formulario especificado"
+
+#: routes/index.js:11
+msgid "Self Hosted Newsletter App"
+msgstr "Auto alojamiento de Aplicación de Boletín "
+
+#: routes/links.js:39
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr ""
+"Vaya, no hemos podido encontrar un vínculo para la URL que ha hecho clic"
+
+#: routes/lists.js:82
+msgid "Could not create list"
+msgstr "No se ha podido crear la lista"
+
+#: routes/lists.js:85
+msgid "List created"
+msgstr "Lista creada"
+
+#: routes/lists.js:93 routes/lists.js:271 routes/lists.js:336
+#: routes/lists.js:375 routes/lists.js:444 routes/lists.js:469
+#: routes/lists.js:514 routes/lists.js:536 routes/lists.js:565
+#: routes/lists.js:644 routes/lists.js:701 routes/lists.js:728
+msgid "Could not find list with specified ID"
+msgstr "No se ha podido encontrar la lista con el ID especificado"
+
+#: routes/lists.js:122
+msgid "List settings updated"
+msgstr "Configuración de la lista actualizado"
+
+#: routes/lists.js:124
+msgid "List settings not updated"
+msgstr "Configuración de la lista no actualizado"
+
+#: routes/lists.js:142
+msgid "List deleted"
+msgstr "Lista eliminada"
+
+#: routes/lists.js:144
+msgid "Could not delete specified list"
+msgstr "No se ha eliminado la lista especificada"
+
+#: routes/lists.js:206
+msgid "Unknown"
+msgstr "desconocido"
+
+#: routes/lists.js:206
+msgid "Complained"
+msgstr "Queja"
+
+#: routes/lists.js:237
+msgid "Invalid key"
+msgstr "Clave inválida"
+
+#: routes/lists.js:239
+msgid "Expired key"
+msgstr "Clave caducada"
+
+#: routes/lists.js:241
+msgid "Revoked key"
+msgstr "Clave anulada"
+
+#: routes/lists.js:291
+msgid "Initializing"
+msgstr "Iniciando"
+
+#: routes/lists.js:294
+msgid "Initialized"
+msgstr "Iniciado"
+
+#: routes/lists.js:297
+msgid "Importing"
+msgstr "Importando"
+
+#: routes/lists.js:303
+msgid "Errored"
+msgstr "Erróneo"
+
+#: routes/lists.js:381 routes/lists.js:450 routes/lists.js:475
+msgid "Could not find subscriber with specified ID"
+msgstr "No se pudo encontrar el Suscriptor con el especificado ID"
+
+#: routes/lists.js:427
+msgid "Could not add subscription"
+msgstr "No se pudo añadir la suscripción"
+
+#: routes/lists.js:432
+msgid "%s was successfully added to your list"
+msgstr "%s ha sido añadido a su lista con éxito"
+
+#: routes/lists.js:434
+msgid "%s was not added to your list"
+msgstr "%s no ha sido añadido a su lista"
+
+#: routes/lists.js:456
+msgid "Could not unsubscribe user"
+msgstr "No se ha dado de baja al usuario"
+
+#: routes/lists.js:459
+msgid "%s was successfully unsubscribed from your list"
+msgstr "%s ha sido dado de baja de su lista con éxito"
+
+#: routes/lists.js:479
+msgid "%s was successfully removed from your list"
+msgstr "%s ha sido eliminado de su lista con éxito"
+
+#: routes/lists.js:491
+msgid "Another subscriber with email address %s already exists"
+msgstr "Otro suscriptor con correo electrónico %s ya existe"
+
+#: routes/lists.js:498
+msgid "Subscription settings updated"
+msgstr "Configuración de suscripción actualizada"
+
+#: routes/lists.js:500
+msgid "Subscription settings not updated"
+msgstr "Configuración de suscripción no actualizada"
+
+#: routes/lists.js:542 routes/lists.js:650 routes/lists.js:686
+#: routes/lists.js:714 routes/lists.js:734
+msgid "Could not find import data with specified ID"
+msgstr "No se pudo encontrar datos de importación con especificado ID"
+
+#: routes/lists.js:573
+msgid "Could not process CSV"
+msgstr "No se pudo procesar CSV"
+
+#: routes/lists.js:582
+msgid "Could not create importer"
+msgstr "No se pudo crear importación"
+
+#: routes/lists.js:633
+msgid "Empty file"
+msgstr "Archivo vacío"
+
+#: routes/lists.js:690
+msgid "Import started"
+msgstr "Importación empezada"
+
+#: routes/lists.js:718
+msgid "Import restarted"
+msgstr "Importación reiniciada"
+
+#: routes/lists.js:784
+msgid "One-step (i.e. no email with confirmation link)"
+msgstr "Un paso (es decir, no email de confirmación)"
+
+#: routes/lists.js:790
+msgid ""
+"One-step with unsubscription form (i.e. no email with confirmation link)"
+msgstr "Un paso con formulario de baja (es decir, no email de confirmación)"
+
+#: routes/lists.js:796
+msgid "Two-step (i.e. an email with confirmation link will be sent)"
+msgstr "Dos pasos (es decir, se envía email de confirmación)"
+
+#: routes/lists.js:802
+msgid ""
+"Two-step with unsubscription form (i.e. an email with confirmation link will "
+"be sent)"
+msgstr ""
+"Dos pasos con formulario de baja (es decir, se envía email de confirmación)"
+
+#: routes/lists.js:808
+msgid ""
+"Manual (i.e. unsubscription has to be performed by the list administrator)"
+msgstr "Manual (es decir, baja realizada por administrador)"
+
+#: routes/report-templates.js:246
+msgid "Could not create report template"
+msgstr "No se pudo crear informe de plantillas"
+
+#: routes/report-templates.js:249
+msgid "Report template “%s” created"
+msgstr "Informe de plantilla “%s” creado"
+
+#: routes/report-templates.js:257
+msgid "Could not find report template with specified ID"
+msgstr "No se encuentra informe de plantilla con ID especificado"
+
+#: routes/report-templates.js:280
+msgid "Report template updated"
+msgstr "Informe de plantilla actualizada"
+
+#: routes/report-templates.js:282
+msgid "Report template not updated"
+msgstr "Informe de plantilla no actualizada"
+
+#: routes/report-templates.js:298
+msgid "Report template deleted"
+msgstr "Informe de plantilla eliminada"
+
+#: routes/report-templates.js:300
+msgid "Could not delete specified report template"
+msgstr "No se pudo eliminar Informe de plantilla especificado"
+
+#: routes/reports.js:124 routes/reports.js:130
+msgid "Could not create report"
+msgstr "No se pudo crear informe"
+
+#: routes/reports.js:135
+msgid "Report “%s” created"
+msgstr "Informe \"%s\" creado"
+
+#: routes/reports.js:146 routes/reports.js:224 routes/reports.js:239
+#: routes/reports.js:265 routes/reports.js:275
+msgid "Could not find report with specified ID"
+msgstr "No se pudo encontrar el informe con el ID especificado"
+
+#: routes/reports.js:188 routes/reports.js:194
+msgid "Could not update report"
+msgstr "No se pudo actualizar el informe"
+
+#: routes/reports.js:197
+msgid "Report updated"
+msgstr "Informe actualizado"
+
+#: routes/reports.js:199
+msgid "Report not updated"
+msgstr "Informe no actualizado"
+
+#: routes/reports.js:212
+msgid "Report deleted"
+msgstr "Informe eliminado"
+
+#: routes/reports.js:214
+msgid "Could not delete specified report"
+msgstr "No se pudo eliminar informe especificado"
+
+#: routes/reports.js:230
+msgid "Could not find report template"
+msgstr "No se pudo encontrar informe especificado"
+
+#: routes/reports.js:260
+msgid "Unknown type of template"
+msgstr "Tipo desconocido de la plantilla"
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr "No se pudo crear el segmento"
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr "Segmento creado"
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr "ID de segmento seleccionado no encontrado"
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr "Ajustes de segmento actualizados"
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr "Ajustes de segmento no actualizados"
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr "Segmento eliminado"
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr "No se pudo eliminar segmento especificado"
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr "No se pudo crear la regla"
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr "Regla creada"
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr "Ajustes de regla actualizados"
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr "Ajustes de regla no actualizados"
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr "Regla eliminada"
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr "No se pudo eliminar regla especificada"
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "Usar TLS"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "Normalmente seleccionado para el puerto 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "Usar STARTTLS"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "Generalmente seleccionado por el puerto 587 y 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "No utilice el cifrado"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Ajustes actualizados"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Tipo de Correo Transporte no válido"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Clave de acceso inválido"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "Credenciales AWS inválidas"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Conexión rechazada, verificar nombre de host y puerto "
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"No se recibió el mensaje de saludo de servidor. Esto puede ocurrir cuando se "
+"conecta a un puerto TLS sin utilizar TLS."
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "No se recibió el mensaje de saludo de servidor."
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Tiempo de conexión agotado. Comprobar la configuración del firewall, puerto "
+"de destino probablemente está bloqueado."
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr "Autenticación no aceptada, servidor STARTTLS espera a ser utilizados."
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr "Error de autenticación, compruebe nombre de usuario y contraseña."
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "Verificación Remitente fallido."
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Servidor respondió con: \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr "Ajustes de remitente verificados, listo para enviar algún correo!"
+
+#: routes/subscription.js:33
+msgid "Not allowed by CORS"
+msgstr "No es permitido por CORS"
+
+#: routes/subscription.js:61 routes/subscription.js:175
+#: routes/subscription.js:285 routes/subscription.js:381
+#: routes/subscription.js:458 routes/subscription.js:534
+#: routes/subscription.js:565 routes/subscription.js:625
+#: routes/subscription.js:681 routes/subscription.js:759
+#: routes/subscription.js:896
+msgid "Selected list not found"
+msgstr "La lista seleccionada no se encuentra"
+
+#: routes/subscription.js:92
+msgid "Could not save subscription"
+msgstr "No se pudo guardar la suscripción"
+
+#: routes/subscription.js:117
+msgid "Subscriber info corrupted or missing"
+msgstr "Datos de Suscripción dañados o perdidos"
+
+#: routes/subscription.js:135
+msgid "Email address changed"
+msgstr "Correo electrónico ha cambiado"
+
+#: routes/subscription.js:178 routes/subscription.js:384
+msgid "The list does not allow public subscriptions."
+msgstr "La lista no permite suscripciones públicas."
+
+#: routes/subscription.js:354 routes/subscription.js:356
+msgid "Email address not set"
+msgstr "Correo electrónico no establecido"
+
+#: routes/subscription.js:652
+msgid ""
+"An email with further instructions has been sent to the provided address"
+msgstr ""
+"Un correo electrónico con más instrucciones ha sido enviado a la dirección "
+"proporcionada"
+
+#: routes/subscription.js:860 routes/subscription.js:876
+msgid "Public key is not set"
+msgstr "La clave pública no se ha establecido"
+
+#: routes/templates.js:84
+msgid "Could not create template"
+msgstr "No se pudo crear la plantilla"
+
+#: routes/templates.js:87
+msgid "Template created"
+msgstr "Planilla creada"
+
+#: routes/templates.js:126
+msgid "Template settings updated"
+msgstr "Configuración de plantilla actualizada"
+
+#: routes/templates.js:128
+msgid "Template settings not updated"
+msgstr "Configuración de plantilla no actualizada"
+
+#: routes/templates.js:144
+msgid "Template deleted"
+msgstr "Plantilla eliminada"
+
+#: routes/templates.js:146
+msgid "Could not delete specified template"
+msgstr "No se pudo eliminar la plantilla especificada"
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr "No se pudo encontrar lista seleccionada"
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr "No se pudo crear el Trigger"
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr "Trigger “%s” creado"
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr "Ajustes de Trigger actualizados"
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr "Ajustes de Trigger no actualizados"
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr "Trigger eliminado"
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr "No se pudo eliminar el Trigger especificado"
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr "No se pudo encontrar el Trigger con el ID especificado"
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr "Trigger no encontrado"
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+"Un correo electrónico con instrucciones para restablecer la contraseña ha "
+"sido enviada a su dirección de correo electrónico, si existe en nuestro "
+"sistema."
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr "Reinicio de Token desconocido o caducado"
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "Tu contraseña ha sido cambiada exitosamente"
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr "Datos de usuario no encontrados"
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr "Token de acceso actualizado"
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr "Token de acceso no actualizado"
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr "Información de cuenta actualizada"
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr "Información de cuenta no actualizada"
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr "Error de Feed: %s"
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr "Encontrado %s nueva campaña de mensajes desde Feed"
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr "No se ha encontrado nada nuevo en el Feed"
+
+#: services/feedcheck.js:146
+msgid "RSS entry %s"
+msgstr "Entrada RSS %s"
+
+#: services/importer.js:249
+msgid "Could not access import file"
+msgstr "No se pudo acceder al archivo de importación"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr "Desconocido tipo de Trigger %s"
diff --git a/languages/et.mo b/languages/et.mo
new file mode 100644
index 00000000..18e5f344
Binary files /dev/null and b/languages/et.mo differ
diff --git a/languages/et.po b/languages/et.po
new file mode 100644
index 00000000..88ad5bdb
--- /dev/null
+++ b/languages/et.po
@@ -0,0 +1,3551 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-03-07 21:44+0200\n"
+"PO-Revision-Date: 2017-03-08 20:25+0200\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: et\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.12\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+#: views/subscription/layout.hbs:1 routes/index.js:11
+msgid "Self hosted email newsletter app"
+msgstr "Enda majutatud e-posti uudiskirjade rakendus"
+
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/lists.hbs:1
+#: views/lists/segments/create.hbs:1 views/lists/segments/edit.hbs:1
+#: views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/settings.hbs:1 views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Esileht"
+
+#: views/campaigns/bounced.hbs:2 views/campaigns/campaigns.hbs:2
+#: views/campaigns/campaigns.hbs:7 views/campaigns/clicked.hbs:2
+#: views/campaigns/complained.hbs:2 views/campaigns/create-rss.hbs:2
+#: views/campaigns/create-triggered.hbs:2 views/campaigns/create.hbs:2
+#: views/campaigns/delivered.hbs:2 views/campaigns/edit-rss.hbs:2
+#: views/campaigns/edit-triggered.hbs:2 views/campaigns/edit.hbs:2
+#: views/campaigns/opened.hbs:2 views/campaigns/unsubscribed.hbs:2
+#: views/campaigns/upload-attachment.hbs:2 views/campaigns/view.hbs:2
+#: lib/tools.js:119 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Kampaaniad"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Tagasipõrgete info"
+
+#: views/campaigns/bounced.hbs:5 views/campaigns/clicked.hbs:5
+#: views/campaigns/complained.hbs:5 views/campaigns/delivered.hbs:5
+#: views/campaigns/edit-rss.hbs:5 views/campaigns/edit-triggered.hbs:5
+#: views/campaigns/edit.hbs:5 views/campaigns/opened.hbs:5
+#: views/campaigns/unsubscribed.hbs:5 views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Vaata kampaaniat"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Liikmed, kes põrkusid tagasi:"
+
+#: views/campaigns/bounced.hbs:7 views/campaigns/clicked.hbs:13
+#: views/campaigns/complained.hbs:7 views/campaigns/delivered.hbs:7
+#: views/campaigns/opened.hbs:7 views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:9 views/lists/view.hbs:18
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Aadress"
+
+#: views/campaigns/bounced.hbs:8 views/campaigns/clicked.hbs:14
+#: views/campaigns/complained.hbs:8 views/campaigns/delivered.hbs:8
+#: views/campaigns/opened.hbs:8 views/campaigns/unsubscribed.hbs:8
+#: views/lists/subscription/add.hbs:6 views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:19
+#: views/subscription/manage.hbs:4 views/subscription/subscribe.hbs:4
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Eesnimi"
+
+#: views/campaigns/bounced.hbs:9 views/campaigns/clicked.hbs:15
+#: views/campaigns/complained.hbs:9 views/campaigns/delivered.hbs:9
+#: views/campaigns/opened.hbs:9 views/campaigns/unsubscribed.hbs:9
+#: views/lists/subscription/add.hbs:7 views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:20
+#: views/subscription/manage.hbs:5 views/subscription/subscribe.hbs:5
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Perekonnanimi"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "SMTP vastus"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Tagasipõrke aeg"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:27
+msgid "Create Campaign"
+msgstr "Loo kampaania"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Tavaline kampaania"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "RSS kampaania"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr "Automaatkampaania"
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:71
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/lists.hbs:5
+#: views/lists/segments/segments.hbs:6 views/templates/templates.hbs:5
+#: views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Nimi"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:72
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10 views/lists/lists.hbs:8
+#: views/partials/merge-tag-reference.hbs:4 views/templates/create.hbs:9
+#: views/templates/edit.hbs:8 views/templates/templates.hbs:6
+#: views/triggers/create.hbs:7 views/triggers/edit.hbs:8
+#: views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Kirjeldus"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/view.hbs:21 views/lists/view.hbs:29
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Staatus"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:74
+#: views/lists/view.hbs:22 views/lists/view.hbs:23
+msgid "Created"
+msgstr "Loodud"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Lingi info"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:61
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:62
+msgid "Clicks"
+msgstr "Klikke"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:63
+msgid "% of clicks"
+msgstr "% klikkidest"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:64
+msgid "% of messages"
+msgstr "% kirjadest"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:67
+msgid "Aggregated clicks"
+msgstr "Agregeeritud klikid"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Liikmes, kes klikkisid lingile"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Liikmed, kes klikkisid sellele lingile"
+
+#: views/campaigns/clicked.hbs:16
+msgid "First click time"
+msgstr "Esimese kliki aeg"
+
+#: views/campaigns/clicked.hbs:17
+msgid "Click count"
+msgstr "Klikkide arv"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Kaebuste info"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Liikmed, kes kaebasid ja kes eemaldati listist:"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Kaebuse aeg"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:20
+msgid "Create RSS Campaign"
+msgstr "Loo RSS kampaania"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+"RSS kampaania seab üles träkkeri RSS aadressi pihta. Kui sellest leitakse "
+"uus postitus, siis see saadetakse valitud listile uue kirjana"
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Kampaania nimi"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/templates/create.hbs:11 views/templates/edit.hbs:10
+#: views/triggers/create.hbs:9 views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "HTML kasutamine on lubatud"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "List"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/subscription/manage.hbs:10 views/subscription/subscribe.hbs:10
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Vali"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "liiget"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "RSS voo aadress"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+"Uued postitused sellest RSS voost saadetakse listi liikmete uue kirjana"
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:17
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "E-posti “saatja nimi”"
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit.hbs:18 views/settings.hbs:23
+msgid "This is the name your emails will come from"
+msgstr "Seda nime näidatakse kirja saatja nimena"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "E-posti “saatja” aadress"
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:25
+msgid "This is the address people will send replies to"
+msgstr "Sellele aadressile saadavad inimesed vastuseid"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:23
+#: views/campaigns/create.hbs:26 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:25
+msgid "Disable clicked/opened tracking"
+msgstr "Lülita välja klikkide ja avamiste träkkimine"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr "Loo automaatkampaania"
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/templates/create.hbs:13
+msgid "Template"
+msgstr "Templiit"
+
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr "Templiidi valimine tekitab sellest kampaania jaoks eraldi koopia"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr "Või alternatiivselt kasuta veebiaadressi kirja sisu jaoks"
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+"Kirja saatmiselt tehakse selle aadressi pihta POST päring koos "
+"täiteväljadega. Kasuta seda võimalust, kui soovid HTML sisu genereerida "
+"omaenda skriptiga"
+
+#: views/campaigns/create-triggered.hbs:21 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr ""
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:27
+msgid "Keep it relevant and non-spammy"
+msgstr ""
+
+#: views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr ""
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr ""
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:23 views/campaigns/edit-triggered.hbs:26
+#: views/campaigns/edit.hbs:34
+msgid "Delete Campaign"
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:35 views/lists/edit.hbs:13
+#: views/lists/fields/edit.hbs:39 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:17
+#: views/settings.hbs:99 views/templates/edit.hbs:12 views/triggers/edit.hbs:30
+#: views/users/account.hbs:18
+msgid "Update"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+msgid "General"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:17
+msgid "his is the name your emails will come from"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26
+msgid "Template Settings"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27
+msgid "Template URL"
+msgstr ""
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr ""
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:29
+msgid "Attachments"
+msgstr ""
+
+#: views/campaigns/edit.hbs:30
+msgid "File"
+msgstr ""
+
+#: views/campaigns/edit.hbs:31
+msgid "Size"
+msgstr ""
+
+#: views/campaigns/edit.hbs:32 views/campaigns/view.hbs:66
+#: views/lists/fields/fields.hbs:12 views/lists/view.hbs:32
+msgid "No data available in table"
+msgstr ""
+
+#: views/campaigns/edit.hbs:33 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr ""
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr ""
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr ""
+
+#: views/campaigns/opened.hbs:10
+msgid "First open"
+msgstr ""
+
+#: views/campaigns/opened.hbs:11
+msgid "Opened count"
+msgstr ""
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr ""
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr ""
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:26
+#: views/lists/subscription/import.hbs:10 routes/lists.js:171
+msgid "Unsubscribed"
+msgstr ""
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr ""
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr ""
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr ""
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr ""
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr ""
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr ""
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr ""
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr ""
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr ""
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr ""
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr ""
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr ""
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:25
+msgid "Delivered"
+msgstr ""
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:22 routes/lists.js:171
+msgid "Bounced"
+msgstr ""
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who bounced"
+msgstr ""
+
+#: views/campaigns/view.hbs:24
+msgid "Complaints"
+msgstr ""
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who complained for this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who unsubscribed after this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:28
+msgid "Opened"
+msgstr ""
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who opened this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:30
+msgid "Clicked"
+msgstr ""
+
+#: views/campaigns/view.hbs:31 views/campaigns/view.hbs:68
+msgid "List subscribers who clicked on a link"
+msgstr ""
+
+#: views/campaigns/view.hbs:32
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:33
+msgid "Delay sending"
+msgstr ""
+
+#: views/campaigns/view.hbs:34
+msgid "hours"
+msgstr ""
+
+#: views/campaigns/view.hbs:35
+msgid "minutes"
+msgstr ""
+
+#: views/campaigns/view.hbs:36
+msgid "Send to subscribers:"
+msgstr ""
+
+#: views/campaigns/view.hbs:37
+msgid "Are you sure? This action would reset scheduling"
+msgstr ""
+
+#: views/campaigns/view.hbs:38
+msgid "Cancel"
+msgstr ""
+
+#: views/campaigns/view.hbs:39
+msgid "Sending scheduled"
+msgstr ""
+
+#: views/campaigns/view.hbs:40 views/campaigns/view.hbs:52
+msgid "Pause"
+msgstr ""
+
+#: views/campaigns/view.hbs:41 routes/campaigns.js:264
+msgid "Sending"
+msgstr ""
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:46
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:43 views/campaigns/view.hbs:47
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+
+#: views/campaigns/view.hbs:44
+msgid "Resume"
+msgstr ""
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Reset"
+msgstr ""
+
+#: views/campaigns/view.hbs:48
+msgid "Continue"
+msgstr ""
+
+#: views/campaigns/view.hbs:50
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+
+#: views/campaigns/view.hbs:51
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:53 views/campaigns/view.hbs:57
+msgid "Campaign status:"
+msgstr ""
+
+#: views/campaigns/view.hbs:54
+msgid "ACTIVE"
+msgstr ""
+
+#: views/campaigns/view.hbs:55
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:56
+msgid "Activate"
+msgstr ""
+
+#: views/campaigns/view.hbs:58
+msgid "INACTIVE"
+msgstr ""
+
+#: views/campaigns/view.hbs:59
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+
+#: views/campaigns/view.hbs:60
+msgid "see more"
+msgstr ""
+
+#: views/campaigns/view.hbs:65
+msgid "List subscribers who clicked this link"
+msgstr ""
+
+#: views/campaigns/view.hbs:69
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+
+#: views/campaigns/view.hbs:70
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+
+#: views/emails/confirm-html.hbs:1 views/emails/confirm-html.hbs:2
+#: views/emails/confirm-text.hbs:1
+msgid "Please Confirm Subscription"
+msgstr "Palun kinnita oma liitumissoov"
+
+#: views/emails/confirm-html.hbs:3 views/emails/confirm-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Jah, soovin liituda selle listiga"
+
+#: views/emails/confirm-html.hbs:4
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Kui said selle kirja kogemata, siis lihtsalt kustuta see. Sind ei lisata "
+"listi, kui sa ei kliki allolevale kinnituslingile"
+
+#: views/emails/confirm-html.hbs:5 views/emails/confirm-text.hbs:4
+#: views/emails/subscription-confirmed-html.hbs:7
+#: views/emails/subscription-confirmed-text.hbs:7
+#: views/emails/unsubscribe-confirmed-html.hbs:5
+#: views/emails/unsubscribe-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "Küsimustega seoses selle listiga võta ühendust järgmisel aadressil:"
+
+#: views/emails/confirm-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:5
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr ""
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/subscription/edit.hbs:15
+#: views/subscription/manage.hbs:12 views/subscription/unsubscribe.hbs:1
+#: views/subscription/unsubscribe.hbs:4 routes/lists.js:253
+msgid "Unsubscribe"
+msgstr ""
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr ""
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr ""
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:1
+#: views/emails/subscription-confirmed-text.hbs:1
+#: views/subscription/subscribed.hbs:1
+msgid "Subscription Confirmed"
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:2
+#: views/emails/subscription-confirmed-text.hbs:2
+#: views/subscription/subscribed.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:3
+#: views/emails/subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:4
+#: views/emails/subscription-confirmed-text.hbs:4
+#: views/subscription/subscribed.hbs:6
+msgid "manage your preferences"
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:5
+#: views/emails/subscription-confirmed-text.hbs:5
+#: views/subscription/subscribed.hbs:5 views/users/login.hbs:10
+msgid "or"
+msgstr ""
+
+#: views/emails/subscription-confirmed-html.hbs:6
+#: views/emails/subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr ""
+
+#: views/emails/unsubscribe-confirmed-html.hbs:1
+#: views/emails/unsubscribe-confirmed-text.hbs:1
+msgid "You are now unsubscribed"
+msgstr ""
+
+#: views/emails/unsubscribe-confirmed-html.hbs:2
+#: views/emails/unsubscribe-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr ""
+
+#: views/emails/unsubscribe-confirmed-html.hbs:3
+#: views/emails/unsubscribe-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr ""
+
+#: views/emails/unsubscribe-confirmed-html.hbs:4
+#: views/emails/unsubscribe-confirmed-text.hbs:4
+#: views/lists/subscription/add.hbs:16 routes/lists.js:253
+msgid "Subscribe"
+msgstr ""
+
+#: views/index.hbs:1
+msgid "Official Mailtrain Partners"
+msgstr "Ametlikud Mailtraini partnerid"
+
+#: views/index.hbs:2
+msgid "Free, open source mail server solution"
+msgstr ""
+
+#: views/index.hbs:3
+msgid ""
+"A reliable SMTP server, easy integration, and 12,000 messages a month free"
+msgstr ""
+
+#: views/index.hbs:4
+msgid "List management"
+msgstr ""
+
+#: views/index.hbs:5
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+
+#: views/index.hbs:6
+msgid "Custom fields"
+msgstr ""
+
+#: views/index.hbs:7
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+
+#: views/index.hbs:8
+msgid "List segmentation"
+msgstr ""
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+
+#: views/index.hbs:10
+msgid "Donate to author"
+msgstr ""
+
+#: views/index.hbs:11
+msgid ""
+"If you really like Mailtrain or your business benefits from it financially "
+"then I would really appreciate a small donation to keep the Mailtrain "
+"development engines running. You can either use Bitcoin or PayPal for "
+"donations. My Bitcoin wallet is 15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM"
+"code>"
+msgstr ""
+
+#: views/index.hbs:12
+msgid "or donate using PayPal"
+msgstr ""
+
+#: views/index.hbs:13
+msgid "RSS Campaigns"
+msgstr ""
+
+#: views/index.hbs:14
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+
+#: views/index.hbs:15
+msgid "GPG Encryption"
+msgstr ""
+
+#: views/index.hbs:16
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+
+#: views/index.hbs:17
+msgid "Click stats"
+msgstr ""
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+
+#: views/index.hbs:19
+msgid "Open source"
+msgstr ""
+
+#: views/index.hbs:20
+msgid "Mailtrain is available under GPLv3 license and completely open source."
+msgstr ""
+
+#: views/index.hbs:21
+msgid "Send via any provider"
+msgstr ""
+
+#: views/index.hbs:22
+msgid ""
+"Mailtrain recommends SendPulse even though you "
+"can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+
+#: views/index.hbs:23
+msgid "Trigger based automation"
+msgstr ""
+
+#: views/index.hbs:24
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr ""
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr ""
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr ""
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr ""
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr ""
+
+#: views/layout.hbs:7 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr ""
+
+#: views/layout.hbs:8
+msgid "Log out"
+msgstr ""
+
+#: views/layout.hbs:9 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr ""
+
+#: views/layout.hbs:10
+msgid "Self hosted newsletter app built on top of Nodemailer"
+msgstr ""
+
+#: views/layout.hbs:11 views/layout.hbs:13
+msgid "Source on GitHub"
+msgstr ""
+
+#: views/layout.hbs:12
+msgid "Subscribe to our newsletter"
+msgstr ""
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/lists.hbs:2
+#: views/lists/lists.hbs:4 views/lists/segments/create.hbs:2
+#: views/lists/segments/edit.hbs:2 views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:111
+msgid "Lists"
+msgstr ""
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:9
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr ""
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr ""
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:7
+msgid "Edit List"
+msgstr ""
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr ""
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr ""
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr ""
+
+#: views/lists/edit.hbs:12
+msgid "Delete List"
+msgstr ""
+
+#: views/lists/fields/create.hbs:3 views/lists/fields/edit.hbs:3
+#: views/lists/fields/fields.hbs:3 views/lists/fields/fields.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Fields"
+msgstr ""
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr ""
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr ""
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr ""
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr ""
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr ""
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr ""
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr ""
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr ""
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr ""
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr ""
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr ""
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr ""
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr ""
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr ""
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr ""
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr ""
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr ""
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr ""
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr ""
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr ""
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr ""
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr ""
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr ""
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr ""
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr ""
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr ""
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:25
+msgid "Type"
+msgstr ""
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/lists.hbs:9 views/lists/segments/segments.hbs:8
+#: views/lists/segments/view.hbs:12 views/templates/templates.hbs:7
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:287
+#: routes/campaigns.js:576 routes/campaigns.js:626 routes/lists.js:222
+#: routes/triggers.js:297
+msgid "Edit"
+msgstr ""
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr ""
+
+#: views/lists/lists.hbs:7
+msgid "Subscribers"
+msgstr ""
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:6
+#: views/lists/view.hbs:13
+msgid "Segments"
+msgstr ""
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr ""
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr ""
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:11
+msgid "Edit Segment"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr ""
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:12 views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr ""
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr ""
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr ""
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:12
+msgid "Segment"
+msgstr ""
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr ""
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr ""
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:5 views/subscription/manage.hbs:2
+#: views/subscription/subscribe.hbs:3 views/users/account.hbs:7
+msgid "Email Address"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:82 views/settings.hbs:97 views/subscription/manage.hbs:7
+#: views/subscription/subscribe.hbs:7
+msgid "Begins with"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr ""
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr ""
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/unsubscribe.hbs:3 lib/helpers.js:26
+#: lib/models/segments.js:11
+msgid "Email address"
+msgstr ""
+
+#: views/lists/subscription/edit.hbs:16
+msgid "Delete Subscription"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid "see here"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:10
+msgid "Fail reason"
+msgstr ""
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr ""
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:27
+#: views/users/api.hbs:35 views/users/api.hbs:43 views/users/api.hbs:55
+msgid "Example"
+msgstr ""
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:6
+msgid "CSV delimiter"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:7
+msgid "Categorize the imported subscribers as"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:8 routes/lists.js:171
+msgid "Subscribed"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:9
+msgid "Regular subscriber addresses"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:11
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr ""
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr ""
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr ""
+
+#: views/lists/view.hbs:8 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr ""
+
+#: views/lists/view.hbs:9
+msgid "Add Subscriber"
+msgstr ""
+
+#: views/lists/view.hbs:10
+msgid "Import Subscribers"
+msgstr ""
+
+#: views/lists/view.hbs:14
+msgid "Create New Segment"
+msgstr ""
+
+#: views/lists/view.hbs:15
+msgid "Filter"
+msgstr ""
+
+#: views/lists/view.hbs:16
+msgid "Subscriptions"
+msgstr ""
+
+#: views/lists/view.hbs:17
+msgid "Imports"
+msgstr ""
+
+#: views/lists/view.hbs:24 routes/campaigns.js:266 routes/lists.js:265
+msgid "Finished"
+msgstr ""
+
+#: views/lists/view.hbs:26
+msgid "Added"
+msgstr ""
+
+#: views/lists/view.hbs:27
+msgid "Updated"
+msgstr ""
+
+#: views/lists/view.hbs:28
+msgid "Failed"
+msgstr ""
+
+#: views/lists/view.hbs:30
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+
+#: views/lists/view.hbs:31
+msgid "Restart"
+msgstr ""
+
+#: views/partials/codeeditor.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr ""
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr ""
+
+#: views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr ""
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr ""
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr ""
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr ""
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr ""
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr ""
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr ""
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr ""
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr ""
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr ""
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr ""
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr ""
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr ""
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr ""
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr ""
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr ""
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr ""
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr ""
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr ""
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr ""
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr ""
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr ""
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr ""
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr ""
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr ""
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr ""
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr ""
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr ""
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr ""
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr ""
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr ""
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr ""
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr ""
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr ""
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr ""
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr ""
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr ""
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr ""
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr ""
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr ""
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr ""
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr ""
+
+#: views/settings.hbs:52
+msgid "Don't have an SMTP account yet? Create a free SendPulse account"
+msgstr ""
+
+#: views/settings.hbs:53
+msgid "here"
+msgstr ""
+
+#: views/settings.hbs:54
+msgid "Advanced Mailer settings"
+msgstr ""
+
+#: views/settings.hbs:55
+msgid "Log SMTP transactions"
+msgstr ""
+
+#: views/settings.hbs:56
+msgid "Allow self-signed certificates"
+msgstr ""
+
+#: views/settings.hbs:57
+msgid "Max connections"
+msgstr ""
+
+#: views/settings.hbs:58
+msgid "The count of max connections, eg. 10"
+msgstr ""
+
+#: views/settings.hbs:59
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+
+#: views/settings.hbs:60
+msgid "Max messages"
+msgstr ""
+
+#: views/settings.hbs:61
+msgid "The count of max messages, eg. 100"
+msgstr ""
+
+#: views/settings.hbs:62
+msgid ""
+"he number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+
+#: views/settings.hbs:63
+msgid "Throttling"
+msgstr ""
+
+#: views/settings.hbs:64
+msgid "Messages per hour eg. 1000"
+msgstr ""
+
+#: views/settings.hbs:65
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+
+#: views/settings.hbs:66
+msgid "VERP bounce handling"
+msgstr ""
+
+#: views/settings.hbs:67
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+
+#: views/settings.hbs:68
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+
+#: views/settings.hbs:69
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+
+#: views/settings.hbs:70
+msgid "Use VERP to catch bounces"
+msgstr ""
+
+#: views/settings.hbs:71
+msgid "Server hostname"
+msgstr ""
+
+#: views/settings.hbs:72
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr ""
+
+#: views/settings.hbs:73
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+
+#: views/settings.hbs:74
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+
+#: views/settings.hbs:75
+msgid "GPG Signing"
+msgstr ""
+
+#: views/settings.hbs:76
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+
+#: views/settings.hbs:77
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+
+#: views/settings.hbs:78
+msgid "Private Key Passphrase"
+msgstr ""
+
+#: views/settings.hbs:79
+msgid "Passphrase for the key if set"
+msgstr ""
+
+#: views/settings.hbs:80
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+
+#: views/settings.hbs:81
+msgid "GPG Private Key"
+msgstr ""
+
+#: views/settings.hbs:83
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+
+#: views/settings.hbs:84
+msgid "DKIM Signing by ZoneMTA"
+msgstr ""
+
+#: views/settings.hbs:85
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+
+#: views/settings.hbs:86
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+
+#: views/settings.hbs:87
+msgid "ZoneMTA DKIM API Key"
+msgstr ""
+
+#: views/settings.hbs:88
+msgid "Some secret value"
+msgstr ""
+
+#: views/settings.hbs:89
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+
+#: views/settings.hbs:90
+msgid "DKIM domain"
+msgstr ""
+
+#: views/settings.hbs:91
+msgid "Domain name for the DKIM key"
+msgstr ""
+
+#: views/settings.hbs:92
+msgid "Leave blank to use the sender email address domain"
+msgstr ""
+
+#: views/settings.hbs:93 views/settings.hbs:94
+msgid "DKIM key selector"
+msgstr ""
+
+#: views/settings.hbs:95
+msgid "Signing is disabled without a valid selector value"
+msgstr ""
+
+#: views/settings.hbs:96
+msgid "DKIM Private Key"
+msgstr ""
+
+#: views/settings.hbs:98
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+
+#: views/subscription/confirm-notice.hbs:1 views/subscription/subscribe.hbs:1
+msgid "Warning!"
+msgstr ""
+
+#: views/subscription/confirm-notice.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+
+#: views/subscription/confirm-notice.hbs:3
+msgid "Almost finished."
+msgstr ""
+
+#: views/subscription/confirm-notice.hbs:4
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+
+#: views/subscription/confirm-notice.hbs:5
+#: views/subscription/unsubscribe-notice.hbs:3
+#: views/subscription/updated-notice.hbs:3
+msgid "return to our website"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:1
+msgid "Update your Email Address"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:2
+msgid "Existing Email Address"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:3
+msgid "New Email Address"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:4
+msgid "Your new email address"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:5
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+
+#: views/subscription/manage-address.hbs:6
+msgid "Update Email Address"
+msgstr ""
+
+#: views/subscription/manage.hbs:1
+msgid "Update your preferences"
+msgstr ""
+
+#: views/subscription/manage.hbs:3
+msgid "want to change it?"
+msgstr ""
+
+#: views/subscription/manage.hbs:6 views/subscription/subscribe.hbs:6
+msgid "Download signature verification key"
+msgstr ""
+
+#: views/subscription/manage.hbs:8 views/subscription/subscribe.hbs:8
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+
+#: views/subscription/manage.hbs:9 views/subscription/subscribe.hbs:9
+msgid "optional"
+msgstr ""
+
+#: views/subscription/manage.hbs:11
+msgid "Update Profile"
+msgstr ""
+
+#: views/subscription/subscribe.hbs:2
+msgid "JavaScript must be enabled in order for the subscription form to work"
+msgstr ""
+
+#: views/subscription/subscribe.hbs:11
+msgid "Subscribe to list"
+msgstr ""
+
+#: views/subscription/subscribed.hbs:3
+msgid "Thank you for subscribing!"
+msgstr ""
+
+#: views/subscription/subscribed.hbs:4
+msgid "continue to our website"
+msgstr ""
+
+#: views/subscription/unsubscribe-notice.hbs:1
+msgid "Unsubscribe Successful"
+msgstr ""
+
+#: views/subscription/unsubscribe-notice.hbs:2
+msgid "You have been removed from:"
+msgstr ""
+
+#: views/subscription/unsubscribe.hbs:2
+msgid "Enter your email address to unsubscribe from:"
+msgstr ""
+
+#: views/subscription/updated-notice.hbs:1
+msgid "Profile Updated"
+msgstr ""
+
+#: views/subscription/updated-notice.hbs:2
+msgid "Your profile information has been updated."
+msgstr ""
+
+#: views/templates/create.hbs:2 views/templates/edit.hbs:2
+#: views/templates/templates.hbs:2 views/templates/templates.hbs:4
+#: lib/tools.js:115
+msgid "Templates"
+msgstr ""
+
+#: views/templates/create.hbs:3 views/templates/create.hbs:4
+#: views/templates/create.hbs:12 views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr ""
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr ""
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr ""
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr ""
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr ""
+
+#: views/templates/edit.hbs:3 views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr ""
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr ""
+
+#: views/templates/edit.hbs:11
+msgid "Delete Template"
+msgstr ""
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr ""
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr ""
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr ""
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr ""
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr ""
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr ""
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr ""
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr ""
+
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr ""
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr ""
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr ""
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr ""
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr ""
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr ""
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr ""
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr ""
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr ""
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr ""
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr ""
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr ""
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr ""
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr ""
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr ""
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr ""
+
+#: views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr ""
+
+#: views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr ""
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr ""
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr ""
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr ""
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr ""
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr ""
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr ""
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr ""
+
+#: views/users/account.hbs:16
+msgid "Confirm Password"
+msgstr ""
+
+#: views/users/account.hbs:17 views/users/reset.hbs:8
+msgid "Confirm New Password"
+msgstr ""
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr ""
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr ""
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr ""
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr ""
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr ""
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr ""
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr ""
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+
+#: views/users/api.hbs:13
+msgid "Add subscription"
+msgstr ""
+
+#: views/users/api.hbs:14
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+
+#: views/users/api.hbs:15 views/users/api.hbs:17 views/users/api.hbs:30
+#: views/users/api.hbs:32 views/users/api.hbs:38 views/users/api.hbs:40
+#: views/users/api.hbs:46 views/users/api.hbs:48
+msgid "arguments"
+msgstr ""
+
+#: views/users/api.hbs:16 views/users/api.hbs:31 views/users/api.hbs:39
+#: views/users/api.hbs:47
+msgid "your personal access token"
+msgstr ""
+
+#: views/users/api.hbs:18 views/users/api.hbs:33 views/users/api.hbs:41
+msgid "subscriber's email address"
+msgstr ""
+
+#: views/users/api.hbs:19 views/users/api.hbs:34 views/users/api.hbs:42
+#: views/users/api.hbs:50
+msgid "required"
+msgstr ""
+
+#: views/users/api.hbs:20
+msgid "subscriber's first name"
+msgstr ""
+
+#: views/users/api.hbs:21
+msgid "subscriber's last name"
+msgstr ""
+
+#: views/users/api.hbs:22
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+
+#: views/users/api.hbs:23
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+
+#: views/users/api.hbs:24
+msgid "Additional POST arguments"
+msgstr ""
+
+#: views/users/api.hbs:25
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+
+#: views/users/api.hbs:26
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+
+#: views/users/api.hbs:28
+msgid "Remove subscription"
+msgstr ""
+
+#: views/users/api.hbs:29
+msgid "This API call marks a subscription as unsubscribed"
+msgstr ""
+
+#: views/users/api.hbs:36
+msgid "Delete subscription"
+msgstr ""
+
+#: views/users/api.hbs:37
+msgid "This API call deletes a subscription"
+msgstr ""
+
+#: views/users/api.hbs:44
+msgid "Add new custom field"
+msgstr ""
+
+#: views/users/api.hbs:45
+msgid "This API call creates a new custom field for a list."
+msgstr ""
+
+#: views/users/api.hbs:49
+msgid "field name"
+msgstr ""
+
+#: views/users/api.hbs:51
+msgid "one of the following types:"
+msgstr ""
+
+#: views/users/api.hbs:52
+msgid ""
+"If the type is 'option' then you also need to specify the parent element ID"
+msgstr ""
+
+#: views/users/api.hbs:53
+msgid ""
+"Template for the group element. If not set, then values of the elements are "
+"joined with commas"
+msgstr ""
+
+#: views/users/api.hbs:54
+msgid ""
+"if not visible then the subscriber can not view or modify this value at the "
+"profile page"
+msgstr ""
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr ""
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr ""
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr ""
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr ""
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr ""
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr ""
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr ""
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr ""
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr ""
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr ""
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr ""
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr ""
+
+#: lib/helpers.js:17
+msgid "URL that points to the unsubscribe page"
+msgstr ""
+
+#: lib/helpers.js:20
+msgid "URL that points to the preferences page of the subscriber"
+msgstr ""
+
+#: lib/helpers.js:23
+msgid "URL to preview the message in a browser"
+msgstr ""
+
+#: lib/helpers.js:29 lib/models/segments.js:31
+msgid "First name"
+msgstr ""
+
+#: lib/helpers.js:32 lib/models/segments.js:35
+msgid "Last name"
+msgstr ""
+
+#: lib/helpers.js:35
+msgid "Full name (first and last name combined)"
+msgstr ""
+
+#: lib/helpers.js:38
+msgid "Unique ID that identifies the recipient"
+msgstr ""
+
+#: lib/helpers.js:41
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr ""
+
+#: lib/helpers.js:44
+msgid "Unique ID that identifies current campaign"
+msgstr ""
+
+#: lib/mailer.js:215
+msgid "Invalid mail transport"
+msgstr "Vigane maili transport"
+
+#: lib/models/campaigns.js:271 lib/models/campaigns.js:298
+#: lib/models/campaigns.js:371 lib/models/campaigns.js:494
+#: lib/models/campaigns.js:752 lib/models/campaigns.js:881
+msgid "Missing Campaign ID"
+msgstr ""
+
+#: lib/models/campaigns.js:407
+msgid "Emtpy or too large attahcment"
+msgstr ""
+
+#: lib/models/campaigns.js:573 lib/models/campaigns.js:761
+msgid "Campaign Name must be set"
+msgstr ""
+
+#: lib/models/campaigns.js:577
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr ""
+
+#: lib/models/campaigns.js:730
+msgid "Selected template not found"
+msgstr ""
+
+#: lib/models/campaigns.js:1082
+msgid "Invalid or missing message ID"
+msgstr ""
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr ""
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr ""
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr ""
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr ""
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/lists.js:81 lib/models/lists.js:175 lib/models/lists.js:212
+#: lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:88 lib/models/subscriptions.js:640
+#: lib/models/subscriptions.js:703 lib/models/subscriptions.js:889
+#: lib/models/subscriptions.js:992 lib/models/subscriptions.js:1046
+#: lib/models/subscriptions.js:1109 lib/models/subscriptions.js:1152
+msgid "Missing List ID"
+msgstr ""
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr ""
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr ""
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr ""
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr ""
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr ""
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr ""
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr ""
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr ""
+
+#: lib/models/links.js:328 routes/campaigns.js:541 routes/campaigns.js:590
+#: services/sender.js:304
+msgid "Campaign not found"
+msgstr ""
+
+#: lib/models/links.js:336 routes/lists.js:146 services/sender.js:311
+msgid "List not found"
+msgstr ""
+
+#: lib/models/links.js:344
+msgid "Subscription not found"
+msgstr ""
+
+#: lib/models/lists.js:117 lib/models/lists.js:179
+msgid "List Name must be set"
+msgstr ""
+
+#: lib/models/lists.js:241
+msgid "Missing List CID"
+msgstr ""
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr ""
+
+#: lib/models/segments.js:19 lib/models/triggers.js:11
+msgid "Sign up date"
+msgstr ""
+
+#: lib/models/segments.js:23 lib/models/triggers.js:15
+msgid "Latest open"
+msgstr ""
+
+#: lib/models/segments.js:27 lib/models/triggers.js:19
+msgid "Latest click"
+msgstr ""
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr ""
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr ""
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr ""
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr ""
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr ""
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr ""
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr ""
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr ""
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr ""
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr ""
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr ""
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr ""
+
+#: lib/models/subscriptions.js:233
+msgid "%s: Please Confirm Subscription"
+msgstr ""
+
+#: lib/models/subscriptions.js:324
+msgid "Could not save subscription"
+msgstr ""
+
+#: lib/models/subscriptions.js:507 lib/models/subscriptions.js:537
+msgid "Missing Subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:565
+msgid "Missing Subscription email address"
+msgstr ""
+
+#: lib/models/subscriptions.js:644 lib/models/subscriptions.js:893
+#: lib/models/subscriptions.js:1156
+msgid "Missing subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:707
+msgid "Missing email address"
+msgstr ""
+
+#: lib/models/subscriptions.js:996 lib/models/subscriptions.js:1050
+#: lib/models/subscriptions.js:1086
+msgid "Missing Import ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:1178
+msgid "Unknown subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:1183
+msgid "Nothing seems to be changed"
+msgstr ""
+
+#: lib/models/subscriptions.js:1197
+msgid "This address is already registered by someone else"
+msgstr ""
+
+#: lib/models/templates.js:51 lib/models/templates.js:122
+#: lib/models/templates.js:163
+msgid "Missing Template ID"
+msgstr ""
+
+#: lib/models/templates.js:80 lib/models/templates.js:126
+msgid "Template Name must be set"
+msgstr ""
+
+#: lib/models/triggers.js:28
+msgid "Has Opened"
+msgstr ""
+
+#: lib/models/triggers.js:31
+msgid "Has Clicked"
+msgstr ""
+
+#: lib/models/triggers.js:34
+msgid "Not Opened"
+msgstr ""
+
+#: lib/models/triggers.js:37
+msgid "Not Clicked"
+msgstr ""
+
+#: lib/models/triggers.js:174 lib/models/triggers.js:211
+msgid "Missing or invalid list ID"
+msgstr ""
+
+#: lib/models/triggers.js:178 lib/models/triggers.js:263
+msgid "Days in the past are not allowed"
+msgstr ""
+
+#: lib/models/triggers.js:182 lib/models/triggers.js:203
+#: lib/models/triggers.js:267 lib/models/triggers.js:288
+msgid "Missing or invalid trigger rule"
+msgstr ""
+
+#: lib/models/triggers.js:189 lib/models/triggers.js:274
+msgid "Invalid subscription configuration"
+msgstr ""
+
+#: lib/models/triggers.js:196 lib/models/triggers.js:281
+msgid "Invalid campaign configuration"
+msgstr ""
+
+#: lib/models/triggers.js:199 lib/models/triggers.js:284
+msgid "A campaing can not be a target for itself"
+msgstr ""
+
+#: lib/models/triggers.js:232
+msgid "Could not store trigger row"
+msgstr ""
+
+#: lib/models/triggers.js:249
+msgid "Missing or invalid Trigger ID"
+msgstr ""
+
+#: lib/models/triggers.js:316
+msgid "Missing Trigger ID"
+msgstr ""
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr ""
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr ""
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr ""
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr ""
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr ""
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr ""
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr ""
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr ""
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr ""
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr ""
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr ""
+
+#: lib/passport.js:38
+msgid "%s logged out"
+msgstr ""
+
+#: lib/passport.js:51
+msgid "Failed to authenticate user"
+msgstr ""
+
+#: lib/passport.js:67
+msgid "Logged in as %s"
+msgstr ""
+
+#: lib/passport.js:125
+msgid "Incorrect username or password"
+msgstr ""
+
+#: lib/tools.js:123
+msgid "Automation"
+msgstr ""
+
+#: lib/tools.js:133
+msgid "Blocked email address \"%s\""
+msgstr ""
+
+#: lib/tools.js:142
+msgid "Invalid email address \"%s\"."
+msgstr ""
+
+#: lib/tools.js:145
+msgid "MX record not found for domain"
+msgstr ""
+
+#: lib/tools.js:148
+msgid "Address domain not found"
+msgstr ""
+
+#: lib/tools.js:151
+msgid "Address domain name is required"
+msgstr ""
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:211
+msgid "Not Found"
+msgstr "Lehekülge ei leitud :("
+
+#: routes/archive.js:110 services/sender.js:447
+msgid "Received status code %s from %s"
+msgstr ""
+
+#: routes/archive.js:134 routes/campaigns.js:131 routes/campaigns.js:295
+#: routes/campaigns.js:390 routes/campaigns.js:435 routes/campaigns.js:475
+#: routes/campaigns.js:739 routes/campaigns.js:762 routes/campaigns.js:781
+#: routes/campaigns.js:803 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr ""
+
+#: routes/archive.js:142 routes/campaigns.js:789
+msgid "Attachment not found"
+msgstr ""
+
+#: routes/campaigns.js:26 routes/fields.js:13 routes/lists.js:49
+#: routes/segments.js:13 routes/settings.js:23 routes/templates.js:17
+#: routes/triggers.js:18 routes/users.js:75 routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Pead olema sisse logitud, et näha peidetud sisu"
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr ""
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr ""
+
+#: routes/campaigns.js:204
+msgid "content from an RSS entry"
+msgstr ""
+
+#: routes/campaigns.js:220
+msgid "Campaign settings updated"
+msgstr ""
+
+#: routes/campaigns.js:222
+msgid "Campaign settings not updated"
+msgstr ""
+
+#: routes/campaigns.js:238 routes/campaigns.js:639
+msgid "Campaign deleted"
+msgstr ""
+
+#: routes/campaigns.js:240 routes/campaigns.js:641
+msgid "Could not delete specified campaign"
+msgstr ""
+
+#: routes/campaigns.js:259
+msgid "Idling"
+msgstr ""
+
+#: routes/campaigns.js:262
+msgid "Scheduled"
+msgstr ""
+
+#: routes/campaigns.js:268
+msgid "Paused"
+msgstr ""
+
+#: routes/campaigns.js:270
+msgid "Inactive"
+msgstr ""
+
+#: routes/campaigns.js:272
+msgid "Active"
+msgstr ""
+
+#: routes/campaigns.js:274
+msgid "Other"
+msgstr ""
+
+#: routes/campaigns.js:429
+msgid "Unknown status selector"
+msgstr ""
+
+#: routes/campaigns.js:657
+msgid "Scheduled sending"
+msgstr ""
+
+#: routes/campaigns.js:659
+msgid "Could not schedule sending"
+msgstr ""
+
+#: routes/campaigns.js:671
+msgid "Sending resumed"
+msgstr ""
+
+#: routes/campaigns.js:673
+msgid "Could not resume sending"
+msgstr ""
+
+#: routes/campaigns.js:685
+msgid "Sending reset"
+msgstr ""
+
+#: routes/campaigns.js:687
+msgid "Could not reset sending"
+msgstr ""
+
+#: routes/campaigns.js:699 routes/campaigns.js:727
+msgid "Sending paused"
+msgstr ""
+
+#: routes/campaigns.js:701 routes/campaigns.js:729
+msgid "Could not pause sending"
+msgstr ""
+
+#: routes/campaigns.js:713
+msgid "Sending activated"
+msgstr ""
+
+#: routes/campaigns.js:715
+msgid "Could not activate sending"
+msgstr ""
+
+#: routes/campaigns.js:750
+msgid "Attachment uploaded"
+msgstr ""
+
+#: routes/campaigns.js:752
+msgid "Could not store attachment"
+msgstr ""
+
+#: routes/campaigns.js:769
+msgid "Attachment deleted"
+msgstr ""
+
+#: routes/campaigns.js:771
+msgid "Could not delete attachment"
+msgstr ""
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr ""
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr ""
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr ""
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr ""
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr ""
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr ""
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr ""
+
+#: routes/links.js:40
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr ""
+
+#: routes/lists.js:90
+msgid "Could not create list"
+msgstr ""
+
+#: routes/lists.js:93
+msgid "List created"
+msgstr ""
+
+#: routes/lists.js:101 routes/lists.js:236 routes/lists.js:301
+#: routes/lists.js:340 routes/lists.js:409 routes/lists.js:434
+#: routes/lists.js:479 routes/lists.js:501 routes/lists.js:530
+#: routes/lists.js:609 routes/lists.js:666 routes/lists.js:693
+msgid "Could not find list with specified ID"
+msgstr ""
+
+#: routes/lists.js:115
+msgid "List settings updated"
+msgstr ""
+
+#: routes/lists.js:117
+msgid "List settings not updated"
+msgstr ""
+
+#: routes/lists.js:133
+msgid "List deleted"
+msgstr ""
+
+#: routes/lists.js:135
+msgid "Could not delete specified list"
+msgstr ""
+
+#: routes/lists.js:171
+msgid "Unknown"
+msgstr ""
+
+#: routes/lists.js:171
+msgid "Complained"
+msgstr ""
+
+#: routes/lists.js:202
+msgid "Invalid key"
+msgstr ""
+
+#: routes/lists.js:204
+msgid "Expired key"
+msgstr ""
+
+#: routes/lists.js:206
+msgid "Revoked key"
+msgstr ""
+
+#: routes/lists.js:256
+msgid "Initializing"
+msgstr ""
+
+#: routes/lists.js:259
+msgid "Initialized"
+msgstr ""
+
+#: routes/lists.js:262
+msgid "Importing"
+msgstr ""
+
+#: routes/lists.js:268
+msgid "Errored"
+msgstr ""
+
+#: routes/lists.js:346 routes/lists.js:415 routes/lists.js:440
+msgid "Could not find subscriber with specified ID"
+msgstr ""
+
+#: routes/lists.js:392
+msgid "Could not add subscription"
+msgstr ""
+
+#: routes/lists.js:397
+msgid "%s was successfully added to your list"
+msgstr ""
+
+#: routes/lists.js:399
+msgid "%s was not added to your list"
+msgstr ""
+
+#: routes/lists.js:421
+msgid "Could not unsubscribe user"
+msgstr ""
+
+#: routes/lists.js:424
+msgid "%s was successfully unsubscribed from your list"
+msgstr ""
+
+#: routes/lists.js:444
+msgid "%s was successfully removed from your list"
+msgstr ""
+
+#: routes/lists.js:456
+msgid "Another subscriber with email address %s already exists"
+msgstr ""
+
+#: routes/lists.js:463
+msgid "Subscription settings updated"
+msgstr ""
+
+#: routes/lists.js:465
+msgid "Subscription settings not updated"
+msgstr ""
+
+#: routes/lists.js:507 routes/lists.js:615 routes/lists.js:651
+#: routes/lists.js:679 routes/lists.js:699
+msgid "Could not find import data with specified ID"
+msgstr ""
+
+#: routes/lists.js:538
+msgid "Could not process CSV"
+msgstr ""
+
+#: routes/lists.js:547
+msgid "Could not create importer"
+msgstr ""
+
+#: routes/lists.js:598
+msgid "Empty file"
+msgstr ""
+
+#: routes/lists.js:655
+msgid "Import started"
+msgstr ""
+
+#: routes/lists.js:683
+msgid "Import restarted"
+msgstr ""
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr ""
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr ""
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr ""
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr ""
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr ""
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr ""
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr ""
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr ""
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr ""
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr ""
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr ""
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr ""
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr ""
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "Kasuta TLSi"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "tavaliselt valitakse, kui port on 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "Kasuta STARTTLSi"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "tavaliselt valitakse, kui port on 587 või 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "Ära kasuta ühenduse krüpteerimist"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Seaded uuendatud"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Viga maili transpordi tüüp"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Vigae ligipääsuvõti"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "VIgased AWS võtmed"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Ühendusest keelduti, kontrolli domeeninime ja porti"
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"Ei saanud serverilt vastust, see juhtub tavaliselt kui ühendus TLS "
+"serverisse ilma TLS kasutamata"
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "Ei saanud serverilt vastust"
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Ühendus aegus. Kontrolli oma tulemüüri seadeid, tõenäoliselt on serveir port "
+"blokeeritud"
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr "Autentimist ei lubatud, server nõuab STARTTLS kasutamist"
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr "Autentimine ebaõnnestus, kontrolli kasutajanime ja parooli"
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "E-posti seadistuse kontroll ebaõnnestus"
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Server vastas \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr "E-posti seaded on kontrollitud, võid hakata kirju saatma"
+
+#: routes/subscription.js:22
+msgid "Selected subscription not found"
+msgstr ""
+
+#: routes/subscription.js:32 routes/subscription.js:103
+#: routes/subscription.js:141 routes/subscription.js:166
+#: routes/subscription.js:191 routes/subscription.js:232
+#: routes/subscription.js:270 routes/subscription.js:317
+#: routes/subscription.js:339 routes/subscription.js:368
+#: routes/subscription.js:392 routes/subscription.js:424
+msgid "Selected list not found"
+msgstr ""
+
+#: routes/subscription.js:78 routes/subscription.js:472
+msgid "%s: Subscription Confirmed"
+msgstr ""
+
+#: routes/subscription.js:217
+msgid "Email address not set"
+msgstr ""
+
+#: routes/subscription.js:255
+msgid "Could not store confirmation data"
+msgstr ""
+
+#: routes/subscription.js:284 routes/subscription.js:349
+#: routes/subscription.js:402
+msgid "Subscription not found from this list"
+msgstr ""
+
+#: routes/subscription.js:383
+msgid "Email address updated, check your mailbox for verification instructions"
+msgstr ""
+
+#: routes/subscription.js:499 routes/subscription.js:515
+msgid "Public key is not set"
+msgstr ""
+
+#: routes/templates.js:98
+msgid "Could not create template"
+msgstr ""
+
+#: routes/templates.js:101
+msgid "Template created"
+msgstr ""
+
+#: routes/templates.js:109
+msgid "Could not find template with specified ID"
+msgstr ""
+
+#: routes/templates.js:140
+msgid "Template settings updated"
+msgstr ""
+
+#: routes/templates.js:142
+msgid "Template settings not updated"
+msgstr ""
+
+#: routes/templates.js:158
+msgid "Template deleted"
+msgstr ""
+
+#: routes/templates.js:160
+msgid "Could not delete specified template"
+msgstr ""
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr ""
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr ""
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr ""
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr ""
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr ""
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr ""
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr ""
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr ""
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr ""
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr ""
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr ""
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr ""
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr ""
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr ""
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr ""
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr ""
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr ""
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr ""
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr ""
+
+#: services/feedcheck.js:143
+msgid "RSS entry %s"
+msgstr ""
+
+#: services/importer.js:243
+msgid "Could not access import file"
+msgstr ""
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr ""
diff --git a/languages/fr_FR.mo b/languages/fr_FR.mo
new file mode 100644
index 00000000..8ffb0982
Binary files /dev/null and b/languages/fr_FR.mo differ
diff --git a/languages/fr_FR.po b/languages/fr_FR.po
new file mode 100644
index 00000000..0b493f3b
--- /dev/null
+++ b/languages/fr_FR.po
@@ -0,0 +1,4796 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Language-Team: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2018-08-11 13:55+0200\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: 2018-08-09 16:59+0200\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Last-Translator: \n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Language: fr_FR\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+msgid "Self hosted email newsletter app"
+msgstr "Solution de Newsletter auto-hébergée"
+
+#: views/blacklist.hbs:1 views/campaigns/blacklisted.hbs:1
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/forms/create.hbs:1
+#: views/lists/forms/edit.hbs:1 views/lists/forms/forms.hbs:1
+#: views/lists/lists.hbs:1 views/lists/segments/create.hbs:1
+#: views/lists/segments/edit.hbs:1 views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/report-templates/create.hbs:1 views/report-templates/edit.hbs:1
+#: views/report-templates/report-templates.hbs:1
+#: views/reports/create-select-template.hbs:1 views/reports/create.hbs:1
+#: views/reports/edit.hbs:1 views/reports/output.hbs:1
+#: views/reports/reports.hbs:1 views/reports/view.hbs:1 views/settings.hbs:1
+#: views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Accueil"
+
+#: views/blacklist.hbs:2 views/blacklist.hbs:3 views/layout.hbs:7
+#: views/lists/subscription/edit.hbs:15
+msgid "Blacklist"
+msgstr "Liste noire"
+
+#: views/blacklist.hbs:4 views/users/api.hbs:76
+msgid "Add email to blacklist"
+msgstr "Ajouter à la liste noire"
+
+#: views/blacklist.hbs:5
+msgid "Add"
+msgstr "Ajouter"
+
+#: views/blacklist.hbs:6
+msgid "Email"
+msgstr "Email"
+
+#: views/campaigns/blacklisted.hbs:2 views/campaigns/bounced.hbs:2
+#: views/campaigns/campaigns.hbs:2 views/campaigns/campaigns.hbs:7
+#: views/campaigns/clicked.hbs:2 views/campaigns/complained.hbs:2
+#: views/campaigns/create-rss.hbs:2 views/campaigns/create-triggered.hbs:2
+#: views/campaigns/create.hbs:2 views/campaigns/delivered.hbs:2
+#: views/campaigns/edit-rss.hbs:2 views/campaigns/edit-triggered.hbs:2
+#: views/campaigns/edit.hbs:2 views/campaigns/opened.hbs:2
+#: views/campaigns/unsubscribed.hbs:2 views/campaigns/upload-attachment.hbs:2
+#: views/campaigns/view.hbs:2 lib/tools.js:133 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Campagnes"
+
+#: views/campaigns/blacklisted.hbs:3 views/campaigns/blacklisted.hbs:4
+msgid "Blacklisted info"
+msgstr "Information de liste noire"
+
+#: views/campaigns/blacklisted.hbs:5 views/campaigns/bounced.hbs:5
+#: views/campaigns/clicked.hbs:5 views/campaigns/complained.hbs:5
+#: views/campaigns/delivered.hbs:5 views/campaigns/edit-rss.hbs:5
+#: views/campaigns/edit-triggered.hbs:5 views/campaigns/edit.hbs:5
+#: views/campaigns/opened.hbs:5 views/campaigns/unsubscribed.hbs:5
+#: views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Voir la campagne"
+
+#: views/campaigns/blacklisted.hbs:6
+msgid "Subscribers who blacklisted by global blacklist:"
+msgstr "Listes des abonnés faisant partie de la liste noire globale :"
+
+#: views/campaigns/blacklisted.hbs:7 views/campaigns/bounced.hbs:7
+#: views/campaigns/clicked.hbs:15 views/campaigns/complained.hbs:7
+#: views/campaigns/delivered.hbs:7 views/campaigns/opened.hbs:9
+#: views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:8 views/lists/view.hbs:19
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Adresse"
+
+#: views/campaigns/blacklisted.hbs:8 views/campaigns/bounced.hbs:8
+#: views/campaigns/clicked.hbs:16 views/campaigns/complained.hbs:8
+#: views/campaigns/delivered.hbs:8 views/campaigns/opened.hbs:10
+#: views/campaigns/unsubscribed.hbs:8 views/lists/subscription/add.hbs:6
+#: views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:20
+#: views/subscription/partials/subscription-custom-fields.hbs:3
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Prénom"
+
+#: views/campaigns/blacklisted.hbs:9 views/campaigns/bounced.hbs:9
+#: views/campaigns/clicked.hbs:17 views/campaigns/complained.hbs:9
+#: views/campaigns/delivered.hbs:9 views/campaigns/opened.hbs:11
+#: views/campaigns/unsubscribed.hbs:9 views/lists/subscription/add.hbs:7
+#: views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:21
+#: views/subscription/partials/subscription-custom-fields.hbs:4
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Nom"
+
+#: views/campaigns/blacklisted.hbs:10
+msgid "Reason"
+msgstr "Raison"
+
+#: views/campaigns/blacklisted.hbs:11
+msgid "Time"
+msgstr "Heure"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Informations sur les rejets"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Abonnés en erreur qui ont été désinscrits :"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "Réponse SMTP"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Heure du rejet"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:26
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:30
+msgid "Create Campaign"
+msgstr "Créer une campagne"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Campagne ordinaire"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "Campagne RSS"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr "Campagne pilotée par déclencheurs"
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/forms/forms.hbs:6
+#: views/lists/lists.hbs:5 views/lists/segments/segments.hbs:6
+#: views/report-templates/partials/report-template-fields.hbs:1
+#: views/report-templates/report-templates.hbs:10
+#: views/reports/partials/report-fields.hbs:1
+#: views/reports/partials/report-fields.hbs:5
+#: views/reports/partials/report-fields.hbs:9 views/reports/reports.hbs:6
+#: views/templates/templates.hbs:5 views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Nom"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:74
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10
+#: views/lists/forms/edit.hbs:9 views/lists/forms/forms.hbs:7
+#: views/lists/lists.hbs:8 views/mosaico/editor.hbs:3
+#: views/partials/merge-tag-reference.hbs:4
+#: views/report-templates/partials/report-template-fields.hbs:3
+#: views/report-templates/report-templates.hbs:11
+#: views/reports/partials/report-fields.hbs:3
+#: views/reports/partials/report-fields.hbs:6 views/reports/reports.hbs:8
+#: views/templates/create.hbs:9 views/templates/edit.hbs:8
+#: views/templates/templates.hbs:6 views/triggers/create.hbs:7
+#: views/triggers/edit.hbs:8 views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Description"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:75
+#: views/lists/view.hbs:22 views/lists/view.hbs:30
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Statut"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:76
+#: views/lists/view.hbs:23 views/lists/view.hbs:24
+#: views/report-templates/report-templates.hbs:12
+#: views/reports/partials/report-fields.hbs:7 views/reports/reports.hbs:9
+msgid "Created"
+msgstr "Créé"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Information sur les liens"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:63
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:64
+msgid "Clicks"
+msgstr "Clics"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:65
+msgid "% of clicks"
+msgstr "% de clics"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:66
+msgid "% of messages"
+msgstr "% de messages"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:69
+msgid "Aggregated clicks"
+msgstr "Clics agrégés"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Abonnés ayant cliqué sur un lien :"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Abonnés ayant cliqué sur ce lien :"
+
+#: views/campaigns/clicked.hbs:13 views/campaigns/opened.hbs:7
+msgid "Stats by country"
+msgstr "Statistiques par pays"
+
+#: views/campaigns/clicked.hbs:14 views/campaigns/opened.hbs:8
+msgid "Stats by device type"
+msgstr "Statistiques par type d'équipement"
+
+#: views/campaigns/clicked.hbs:18
+msgid "First click time"
+msgstr "Heure du premier clic"
+
+#: views/campaigns/clicked.hbs:19
+msgid "Click count"
+msgstr "Nombre de clics"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Information de plainte"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Abonnés s'étant plaint et ayant été désinscrits :"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Heure de la plainte"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:21
+msgid "Create RSS Campaign"
+msgstr "Créer une campagne RSS"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+"Une campagne RSS met en place un traqueur de flux RSS. Dès qu'une nouvelle "
+"entrée est trouvée dans le flux, elle est envoyée à la liste sous forme mail."
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Nom de la campagne"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/report-templates/partials/report-template-fields.hbs:4
+#: views/reports/partials/report-fields.hbs:4 views/templates/create.hbs:11
+#: views/templates/edit.hbs:10 views/triggers/create.hbs:9
+#: views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "Le HTML est autorisé"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "Liste"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/reports/partials/report-select-template.hbs:2
+#: views/subscription/partials/subscription-custom-fields.hbs:9
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Sélectionner"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "abonnés"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "URL du flux RSS"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+"Les nouvelles entrées de ce flux RSS seront envoyées aux abonnés sous forme "
+"de messages mail"
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "Nom de l'émetteur du message"
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit-triggered.hbs:17 views/campaigns/edit.hbs:18
+#: views/settings.hbs:25
+msgid "This is the name your emails will come from"
+msgstr "Il s'agit du nom d'émetteur utilisé pour les messages de la liste"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "Adresse de l'émetteur du message"
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:21
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:27
+msgid "This is the address people will send replies to"
+msgstr "L'adresse à laquelle les utilisateurs enverront leurs réponses"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:28 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:27
+msgid "Disable opened tracking"
+msgstr "Désactiver le suivi des ouvertures"
+
+#: views/campaigns/create-rss.hbs:20 views/campaigns/create-triggered.hbs:25
+#: views/campaigns/create.hbs:29 views/campaigns/edit-rss.hbs:23
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:28
+msgid "Disable clicked tracking"
+msgstr "Désactiver le suivi des clics"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr "Créer une campagne programmée"
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/reports/reports.hbs:7 views/templates/create.hbs:13
+msgid "Template"
+msgstr "Modèle"
+
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr "Sélectionnez un modèle :"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr "Modèle de base pour la création de la campagne"
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr ""
+"Ou bien utiliser à la place une URL pour récupérer le contenu du message :"
+
+#: views/campaigns/create-triggered.hbs:17 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:26 views/campaigns/edit.hbs:31
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+"Lorsqu'un message est envoyé, cette URL sera POSTée avec les champs de "
+"publipostage dans le corps de la requête. Utilisez cette fonctionnalité si "
+"vous voulez générer le message HTML par vous-même"
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr "Objet du message"
+
+#: views/campaigns/create-triggered.hbs:23 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:29
+msgid "Keep it relevant and non-spammy"
+msgstr "Adéquat et non raccoleur"
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+"L'adresse à laquelle les utilisateurs enverront leurs réponses, sauf si une "
+"autre adresse Reply-to a été précisée"
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr "Adresse de réponse Reply-to du message"
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr ""
+"Si renseignée, les utilisateurs enverront leurs réponses à cette adresse"
+
+#: views/campaigns/create.hbs:26 views/campaigns/edit.hbs:25
+msgid "Custom unsubscribe (URL)"
+msgstr "Désabonnement personnalisé (URL)"
+
+#: views/campaigns/create.hbs:27 views/campaigns/edit.hbs:26
+msgid "Set a custom unsubscribe url"
+msgstr "Renseignez une URL de désabonnement personnalisée"
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr "Information de remise"
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+"Abonnés ayant reçu le message sans erreur, et ne s'étant pas désinscrit :"
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr "Heure de remise"
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr "Modifier la campagne RSS"
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr "Paramètres généraux"
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+"Utiliser le champ de publipostage spécial [RSS_ENTRY] pour désigner "
+"l'emplacement où sera inséré le contenu venant du RSS. Vous pouvez utiliser "
+"par ailleurs tout autre champ disponible."
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:37
+msgid "Delete Campaign"
+msgstr "Supprimer la campagne"
+
+#: views/campaigns/edit-rss.hbs:25 views/campaigns/edit-triggered.hbs:28
+#: views/campaigns/edit.hbs:38 views/lists/edit.hbs:22
+#: views/lists/fields/edit.hbs:39 views/lists/forms/edit.hbs:33
+#: views/lists/forms/forms.hbs:12 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:41 views/lists/subscription/edit.hbs:18
+#: views/reports/edit.hbs:6 views/settings.hbs:102 views/templates/edit.hbs:13
+#: views/triggers/edit.hbs:30 views/users/account.hbs:18
+msgid "Update"
+msgstr "Enregistrer"
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr "Modifier la campagne programmée"
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+#: routes/forms.js:143
+msgid "General"
+msgstr "Général"
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:29
+msgid "Template Settings"
+msgstr "Paramètres du modèle"
+
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:30
+msgid "Template URL"
+msgstr "URL du modèle"
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr "Modifier la campagne"
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:32
+msgid "Attachments"
+msgstr "Pièces jointes"
+
+#: views/campaigns/edit.hbs:33
+msgid "File"
+msgstr "Fichier"
+
+#: views/campaigns/edit.hbs:34
+msgid "Size"
+msgstr "Taille"
+
+#: views/campaigns/edit.hbs:35 views/campaigns/view.hbs:68
+#: views/lists/fields/fields.hbs:12 views/lists/forms/forms.hbs:9
+#: views/lists/view.hbs:33
+msgid "No data available in table"
+msgstr "Aucune donnée dans cette table"
+
+#: views/campaigns/edit.hbs:36 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr "Ajouter une pièce jointe"
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr "Informations d'ouverture"
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr "Abonnés ayant ouvert ce message :"
+
+#: views/campaigns/opened.hbs:12
+msgid "First open"
+msgstr "Première ouverture"
+
+#: views/campaigns/opened.hbs:13
+msgid "Opened count"
+msgstr "Nombre d'ouverture"
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr "Informations de désabonnement"
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr "Abonnés s'étant désinscrits"
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:28
+#: views/lists/subscription/import.hbs:13 routes/lists.js:206
+msgid "Unsubscribed"
+msgstr "Désabonnés"
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr "Télécharger"
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr "Aperçu"
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr "Liens"
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr "URL du flux"
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr "Dernière vérification"
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr "Pas encore vérifié"
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr ""
+"Activer la campagne pour commencer à surveiller l'arrivée de nouveaux "
+"messages dans le flux"
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr "Statut RSS"
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr "Prévisualiser la campagne comme"
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr "Ajouter un nouvel utilisateur de test"
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr "Aucun utilisateur de test, créez-en un ici"
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr "Lancer"
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:28
+msgid "Delivered"
+msgstr "Remis"
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr "Abonnés ayant reçu ce message"
+
+#: views/campaigns/view.hbs:22
+msgid "Blacklisted"
+msgstr "Mis en liste noire"
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who blacklisted by global blacklist"
+msgstr "Listes des abonnés faisant partie de la liste noire globale"
+
+#: views/campaigns/view.hbs:24 routes/lists.js:206
+msgid "Bounced"
+msgstr "Erreurs de distribution"
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who bounced"
+msgstr "Abonnés en erreur"
+
+#: views/campaigns/view.hbs:26
+msgid "Complaints"
+msgstr "Plaintes"
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who complained for this message"
+msgstr "Abonnés s'étant plaint après ce message"
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who unsubscribed after this message"
+msgstr "Abonnés s'étant désinscrits après ce message"
+
+#: views/campaigns/view.hbs:30
+msgid "Opened"
+msgstr "Ouvert"
+
+#: views/campaigns/view.hbs:31
+msgid "List subscribers who opened this message"
+msgstr "Abonnés ayant ouvert ce message"
+
+#: views/campaigns/view.hbs:32
+msgid "Clicked"
+msgstr "Cliqué"
+
+#: views/campaigns/view.hbs:33 views/campaigns/view.hbs:70
+msgid "List subscribers who clicked on a link"
+msgstr "Abonnés ayant cliqué sur un lien"
+
+#: views/campaigns/view.hbs:34
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+"Êtes-vous sûr ? Cette action va débuter l'envoi de messages à la liste "
+"sélectionnée"
+
+#: views/campaigns/view.hbs:35
+msgid "Delay sending"
+msgstr "Envoi programmé"
+
+#: views/campaigns/view.hbs:36
+msgid "hours"
+msgstr "heures"
+
+#: views/campaigns/view.hbs:37
+msgid "minutes"
+msgstr "minutes"
+
+#: views/campaigns/view.hbs:38
+msgid "Send to subscribers:"
+msgstr "Envoyer aux abonnés"
+
+#: views/campaigns/view.hbs:39
+msgid "Are you sure? This action would reset scheduling"
+msgstr "Êtes-vous sûr ? Cette action va réinitialiser les tâches programmées"
+
+#: views/campaigns/view.hbs:40
+msgid "Cancel"
+msgstr "Annuler"
+
+#: views/campaigns/view.hbs:41
+msgid "Sending scheduled"
+msgstr "Envoi programmé"
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:54
+msgid "Pause"
+msgstr "Pause"
+
+#: views/campaigns/view.hbs:43 routes/campaigns.js:254
+msgid "Sending"
+msgstr "Envoi"
+
+#: views/campaigns/view.hbs:44 views/campaigns/view.hbs:48
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+"Êtes-vous sûr ? Cette action va suspendre l'envoi de messages à la liste "
+"sélectionnée"
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+"Êtes-vous sûr ? Cette action va supprimer toutes les statistiques sur les "
+"tâches en cours"
+
+#: views/campaigns/view.hbs:46
+msgid "Resume"
+msgstr "Reprendre"
+
+#: views/campaigns/view.hbs:47 views/campaigns/view.hbs:51
+msgid "Reset"
+msgstr "Réinitialiser"
+
+#: views/campaigns/view.hbs:50
+msgid "Continue"
+msgstr "Continuer"
+
+#: views/campaigns/view.hbs:52
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+"Tous les messages ont été envoyés ! Choisissez \"Continuer\" si vous voulez "
+"envoyer cette campagne aux nouveaux abonnés"
+
+#: views/campaigns/view.hbs:53
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Êtes-vous sûr ? Cette action va suspendre l'envoi de mail depuis un flux RSS "
+"pour cette liste"
+
+#: views/campaigns/view.hbs:55 views/campaigns/view.hbs:59
+msgid "Campaign status:"
+msgstr "État de la campagne :"
+
+#: views/campaigns/view.hbs:56
+msgid "ACTIVE"
+msgstr "ACTIF"
+
+#: views/campaigns/view.hbs:57
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Êtes-vous sûr ? Cette action va débuter l'envoi de messages depuis les "
+"nouvelles entrées du flux RSS à la liste sélectionnée"
+
+#: views/campaigns/view.hbs:58
+msgid "Activate"
+msgstr "Activer"
+
+#: views/campaigns/view.hbs:60
+msgid "INACTIVE"
+msgstr "INACTIVE"
+
+#: views/campaigns/view.hbs:61
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+"Il s'agit d'une campagne programmée. Les messages ne sont envoyés qu'aux "
+"abonnés dont un événement active un déclencheur."
+
+#: views/campaigns/view.hbs:62
+msgid "see more"
+msgstr "voir plus"
+
+#: views/campaigns/view.hbs:67
+msgid "List subscribers who clicked this link"
+msgstr "Abonnés ayant cliqué ce lien"
+
+#: views/campaigns/view.hbs:71
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+"Les clics représentent le nombre d'abonnés uniques qui ont cliqué sur un "
+"lien spécifique, ou sur n'importe quel lien en vue aggrégée."
+
+#: views/campaigns/view.hbs:72
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+"Lorsqu'une nouvelle entrée est trouvée dans un flux RSS, une nouvelle "
+"campagne est créée à partir de cette entrée et sera listée ici"
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr "Changez votre mot de passe"
+
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr ""
+"Nous avons reçu une demande de changement de mot de passe pour votre compte "
+"Mailtrain :"
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr "Réinitialiser le mot de passe"
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+"Si vous n'avez pas demandé le changement de votre mot de passe, vous pouvez "
+"ignorer ce message et votre mot de passe restera inchangé."
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr "Préférences"
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/forms/edit.hbs:20
+#: views/lists/subscription/edit.hbs:16
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:2
+#: views/subscription/web-manage.mjml.hbs:3
+#: views/subscription/web-unsubscribe.mjml.hbs:1
+#: views/subscription/web-unsubscribe.mjml.hbs:2 routes/forms.js:223
+#: routes/lists.js:288
+msgid "Unsubscribe"
+msgstr "Se désabonner"
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr "Consulter dans votre navigateur"
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr "Bonjour [FIRST_NAME/Customer],"
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr "Cordialement,"
+
+#: views/index.hbs:1
+msgid "List Management"
+msgstr "Gestion de listes"
+
+#: views/index.hbs:2
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+"Mailtrain vous permet de gérer facilement vos listes, même très grandes. Des "
+"millions d'abonnés ? Aucun problème. Vous pouvez ajouter des abonnés "
+"manuellement, via l'API ou en les important depuis un fichier CSV. Toutes "
+"les listes disposent de champs de publipostage personnalisables."
+
+#: views/index.hbs:3 views/index.hbs:7 views/index.hbs:10 views/index.hbs:13
+#: views/index.hbs:16 views/index.hbs:19 views/index.hbs:22 views/index.hbs:25
+#: views/index.hbs:28
+msgid "Show more"
+msgstr "Voir plus"
+
+#: views/index.hbs:4 views/lists/fields/create.hbs:3
+#: views/lists/fields/edit.hbs:3 views/lists/fields/fields.hbs:3
+#: views/lists/fields/fields.hbs:5 views/lists/view.hbs:6
+msgid "Custom Fields"
+msgstr "Champs personnalisés"
+
+#: views/index.hbs:5
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+"Champs texte, nombres, menus déroulants ou cases à cocher, Mailtrain dispose "
+"de tout. N'importe quel champ personnalisé peut être inclus dans la "
+"newsletter grâce à des étiquettes de fusionnement."
+
+#: views/index.hbs:6
+msgid "Mailtrain also supports custom forms."
+msgstr "Mailtrain permet également de personnaliser les formulaires."
+
+#: views/index.hbs:8
+msgid "List Segmentation"
+msgstr "Segmentation de liste"
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+"Envoyer des messages aux abonnés correspondant à des règles de segmentation "
+"prédéfinies. Nul besoin de créer plusieurs listes présentant peu de "
+"différences."
+
+#: views/index.hbs:11
+msgid "RSS Campaigns"
+msgstr "Campagnes RSS"
+
+#: views/index.hbs:12
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+"Configurer Mailtrain pour surveiller des flux RSS, et, dès qu'une nouvelle "
+"entrée est détectée dans un flux, auto-générer une nouvelle campagne en "
+"utilisant les donnée de la nouvelle entrée comme contenu du message, et "
+"l'envoyer aux abonnés sélectionnés"
+
+#: views/index.hbs:14
+msgid "GPG Encryption"
+msgstr "Chiffrement GPG"
+
+#: views/index.hbs:15
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+"Si une liste est paramétrée avec un champ personnalisé pour les clés "
+"publiques GPG, alors les utilisateurs pourront télécharger la leur pour "
+"recevoir les messages sous forme chiffrée."
+
+#: views/index.hbs:17
+msgid "Click Stats"
+msgstr "Statistiques de clics"
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+"Après l'envoi d'une campagne, consultez les statistiques individuelles de "
+"clics pour chaque lien inclus dans le message."
+
+#: views/index.hbs:20
+msgid "Template Editors"
+msgstr "Éditeur de modèle"
+
+#: views/index.hbs:21
+msgid ""
+"Mailtrain ships with GrapeJS and Mosaico built in, two advanced template "
+"editors. Mailtrain also offers a code editor if you prefer to handcraft the "
+"HTML yourself."
+msgstr ""
+"Mailtrain inclut GrapeJS et Mosaico, deux éditeurs de templates avancés. "
+"Mailtrain offre également un éditeur de code si vous préférez créer le HTML "
+"par vous-même."
+
+#: views/index.hbs:23
+msgid "Send via Any Provider"
+msgstr "Envoyer via Any Provider"
+
+#: views/index.hbs:24
+msgid ""
+"You can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+"Vous pouvez utiliser n'importe quel fournisseur supportant le protocole SMTP "
+"pour envoyer votre newletter. Le traitement des rejets et retours via appels "
+"web est supporté avec SES, SparkPost, SendGrid et Mailgun, ainsi qu'avec "
+"Postfix et ZoneMTA."
+
+#: views/index.hbs:26 lib/tools.js:137
+msgid "Automation"
+msgstr "Automatisation"
+
+#: views/index.hbs:27
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+"Définissez des triggers pour envoyer des messages spécifiques lorsqu'une "
+"action utilisateur active le déclencheur."
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr "Basculer la navigation"
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr "Wiki"
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr "Blog"
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr "Compte"
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr "Configuration"
+
+#: views/layout.hbs:8 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr "API"
+
+#: views/layout.hbs:9
+msgid "Log out"
+msgstr "Déconnexion"
+
+#: views/layout.hbs:10 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr "Se connecter"
+
+#: views/layout.hbs:11
+msgid "Self Hosted Newsletter App Built on Top of Nodemailer"
+msgstr "Solution de Newsletter auto-hébergée construite autour de Nodemailer"
+
+#: views/layout.hbs:12 views/layout.hbs:14
+msgid "Source on GitHub"
+msgstr "Source sur GitHub"
+
+#: views/layout.hbs:13
+msgid "Subscribe to Our Newsletter"
+msgstr "S'abonner à notre lettre d'information"
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/forms/create.hbs:2
+#: views/lists/forms/edit.hbs:2 views/lists/forms/forms.hbs:2
+#: views/lists/lists.hbs:2 views/lists/lists.hbs:4
+#: views/lists/segments/create.hbs:2 views/lists/segments/edit.hbs:2
+#: views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:125 routes/lists.js:59
+msgid "Lists"
+msgstr "Listes"
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:13
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr "Créer une liste"
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr "Nom de la liste"
+
+#: views/lists/create.hbs:9 views/lists/edit.hbs:15
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Abonnement"
+
+#: views/lists/create.hbs:10 views/lists/edit.hbs:16
+msgid "Allow public users to subscribe themselves"
+msgstr "Permettre à tous les utilisateurs de s'abonner par eux-mêmes"
+
+#: views/lists/create.hbs:11 views/lists/edit.hbs:17
+msgid "Unsubscription"
+msgstr "Désabonnement"
+
+#: views/lists/create.hbs:12 views/lists/edit.hbs:18
+msgid "Select how an unsuscription request by subscriber is handled."
+msgstr ""
+"Choisissez comment une demande de désabonnement doit être prise en compte."
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:8
+msgid "Edit List"
+msgstr "Éditer la liste"
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr "Voir la liste"
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr "Identifiant de liste"
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr "Il s'agit de l'identifiant de liste présenté aux utilisateurs"
+
+#: views/lists/edit.hbs:12
+msgid "Custom Form"
+msgstr "Formulaire personnalisé"
+
+#: views/lists/edit.hbs:13 views/lists/forms/forms.hbs:11
+msgid "Default Mailtrain Form"
+msgstr "Formulaire de Mailtrain par défaut"
+
+#: views/lists/edit.hbs:14
+msgid ""
+"The custom form used for this list. You can create a form here."
+msgstr ""
+"Le formulaire personnalisé utilisé pour cette liste. Vous pouvez créer un "
+"formulaire ici."
+
+#: views/lists/edit.hbs:19
+msgid "Unsubscribe Header"
+msgstr "Entête de désabonnement"
+
+#: views/lists/edit.hbs:20
+msgid "Do not send List-Unsubscribe headers"
+msgstr "Ne pas envoyer les entêtes List-Unsubscribe"
+
+#: views/lists/edit.hbs:21
+msgid "Delete List"
+msgstr "Supprimer la liste"
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr "Créer un champ"
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr "Créer un champ personnalisé"
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr "Nom du champ"
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr "Type de champ"
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr "Texte"
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr "Nombre"
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr "Site web"
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr "Clé publique GPG"
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr "Texte multi-lignes"
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr "JSON"
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr "Date"
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr "Date (MM/JJ/AAAA)"
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr "Date (JJ/MM/AAAA)"
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr "Date de naissance"
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr "Date de naissance (MM/JJ)"
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr "Date de naissance (JJ/MM)"
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr "Groupé"
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr "Menus déroulants"
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr "Boutons radio"
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr "Cases à cocher"
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr "Option pour un groupe de valeurs"
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr "Groupe"
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr "Options de groupe requis"
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr "Valeur par défaut pour ce champ de publipostage"
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+"Pour les éléments groupés comme les cases à cocher, vous pouvez contrôler "
+"l'apparence du champ de publipostage avec une template optionnelle. La "
+"template utilise la syntaxe Handlebars et vous trouvez les valeurs dans le "
+"tableau {{values}}, par exemple {{#each values}} {{this}} "
+"{{/each}}. Si aucune template n'est définie, alors les valeurs sont "
+"concaténnées avec des virgules. Vous pouvez également utiliser la template "
+"pour présenter des valeurs JSON (si le JSON est un tableau, alors le tableau "
+"est accessible dans values, sinon vous accédez aux clés JSON "
+"directement)."
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Visible"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Ajouter un champ"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Modifier le champ"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr "Modifier le champ personnalisé"
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr "Retour aux champs"
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/mosaico/editor.hbs:2 views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr "Champ de publipostage"
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr "Champ de publipostage"
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr "Utilisez ce mot-clé dans votre contenu :"
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Supprimer le champ"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:26
+#: views/report-templates/partials/report-template-fields.hbs:5
+msgid "Type"
+msgstr "Type"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/forms/edit.hbs:26 views/lists/forms/forms.hbs:8
+#: views/lists/segments/segments.hbs:8 views/lists/segments/view.hbs:12
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:277
+#: routes/campaigns.js:569 routes/campaigns.js:658 routes/campaigns.js:707
+#: routes/lists.js:170 routes/lists.js:257 routes/report-templates.js:51
+#: routes/templates.js:183 routes/triggers.js:345
+msgid "Edit"
+msgstr "Modifier"
+
+#: views/lists/forms/create.hbs:3 views/lists/forms/edit.hbs:3
+#: views/lists/forms/forms.hbs:3 views/lists/forms/forms.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Forms"
+msgstr "Formulaires personnalisés"
+
+#: views/lists/forms/create.hbs:4
+msgid "Create Form"
+msgstr "Créer un formulaire"
+
+#: views/lists/forms/create.hbs:5 views/lists/forms/forms.hbs:4
+msgid "Create Custom Form"
+msgstr "Créer un formulaire personnalisé"
+
+#: views/lists/forms/create.hbs:6 views/lists/forms/create.hbs:7
+#: views/lists/forms/edit.hbs:7 views/lists/forms/edit.hbs:8
+msgid "Form Name"
+msgstr "Nom du formulaire"
+
+#: views/lists/forms/create.hbs:8
+msgid "Add Form"
+msgstr "Ajouter un formulaire"
+
+#: views/lists/forms/edit.hbs:4
+msgid "Edit Form"
+msgstr "Modifier le formulaire"
+
+#: views/lists/forms/edit.hbs:5
+msgid "Edit Custom Form"
+msgstr "Modifier le formulaire personnalisé"
+
+#: views/lists/forms/edit.hbs:6
+msgid "Back to forms"
+msgstr "Retour aux formulaires"
+
+#: views/lists/forms/edit.hbs:10
+msgid "Optional comments about this form"
+msgstr "Commentaire optionnel sur ce formulaire"
+
+#: views/lists/forms/edit.hbs:11
+msgid "Form Preview"
+msgstr "Prévisualisation du formulaire"
+
+#: views/lists/forms/edit.hbs:12
+msgid ""
+"Note: These links are solely for a quick preview. If you submit a preview "
+"form you'll get redirected to the list's default form."
+msgstr ""
+"NB : Ces liens sont fournis uniquement pour un avoir aperçu rapide. Si vous "
+"utilisez ces formulaires vous serez redirigés vers les formulaires par "
+"défaut."
+
+#: views/lists/forms/edit.hbs:13 views/lists/subscription/add.hbs:16
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:4
+#: routes/forms.js:157 routes/lists.js:288
+msgid "Subscribe"
+msgstr "Abonnement"
+
+#: views/lists/forms/edit.hbs:14
+msgid "Confirm Subscription Notice"
+msgstr "Confirmation d'abonnement"
+
+#: views/lists/forms/edit.hbs:15
+msgid "Confirm Unsubscription Notice"
+msgstr "Confirmation de désabonnement"
+
+#: views/lists/forms/edit.hbs:16
+msgid "Subscribed Notice"
+msgstr "Confirmation d'abonnement"
+
+#: views/lists/forms/edit.hbs:17
+msgid "Updated Notice"
+msgstr "Notification enregistrée"
+
+#: views/lists/forms/edit.hbs:18
+msgid "Unsubscribed Notice"
+msgstr "Notification de désabonnement"
+
+#: views/lists/forms/edit.hbs:19
+msgid "Manual Unsubscribe Notice"
+msgstr "Notification de désabonnement manuel"
+
+#: views/lists/forms/edit.hbs:21 routes/forms.js:205
+msgid "Manage"
+msgstr "Gérer"
+
+#: views/lists/forms/edit.hbs:22
+msgid "Manage Address"
+msgstr "Gestion des adresses"
+
+#: views/lists/forms/edit.hbs:23
+msgid "Create a test user for additional options"
+msgstr "Créer un utilisateur test pour les options additionnelles"
+
+#: views/lists/forms/edit.hbs:24 views/report-templates/create.hbs:3
+#: views/report-templates/edit.hbs:3
+#: views/report-templates/report-templates.hbs:3 views/templates/create.hbs:2
+#: views/templates/edit.hbs:2 views/templates/templates.hbs:2
+#: views/templates/templates.hbs:4 lib/tools.js:129 routes/templates.js:27
+msgid "Templates"
+msgstr "Modèles"
+
+#: views/lists/forms/edit.hbs:25
+msgid "Fields"
+msgstr "Champs"
+
+#: views/lists/forms/edit.hbs:27
+msgid "Form Fields"
+msgstr "Champs de formulaire"
+
+#: views/lists/forms/edit.hbs:28
+msgid "Fields hidden on subscription page:"
+msgstr "Champs masqués sur la page d'abonnement :"
+
+#: views/lists/forms/edit.hbs:29
+msgid "Fields shown on subscription page:"
+msgstr "Champs affichés sur la page d'abonnement :"
+
+#: views/lists/forms/edit.hbs:30
+msgid "Fields hidden on preferences page:"
+msgstr "Champs masqués sur la page de préférences :"
+
+#: views/lists/forms/edit.hbs:31
+msgid "Fields shown on preferences page:"
+msgstr "Champs affichés sur la page de préférences :"
+
+#: views/lists/forms/edit.hbs:32
+msgid "Delete Form"
+msgstr "Supprimer le formulaire"
+
+#: views/lists/forms/forms.hbs:10
+msgid "The default form for this list is:"
+msgstr "Le formulaire par défaut pour cette liste est :"
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7 views/reports/partials/report-fields.hbs:10
+msgid "Subscribers"
+msgstr "Abonnés"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:7
+#: views/lists/view.hbs:14
+msgid "Segments"
+msgstr "Segments"
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr "Créer un segment"
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr "Nom du segment"
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr "Correspondance des règles"
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr "Toutes les règles doivent correspondre"
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr "Au moins une des règles doit correspondre"
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr "Ajouter un segment"
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:12
+msgid "Edit Segment"
+msgstr "Modifier le segment"
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr "Retour aux segments"
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr "Supprimer le segment"
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Créer une règle"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Règle"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-edit.hbs:7
+msgid "Condition"
+msgstr "Condition"
+
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-edit.hbs:8
+msgid "Equals"
+msgstr "vaut"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid "Not equals"
+msgstr "Différent"
+
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-configure.hbs:33
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:11
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:32 views/lists/segments/rule-edit.hbs:37
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Valeur"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-edit.hbs:12
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+"Utiliser % comme caractère joker, par ex. \"%test\" correspond à toutes les "
+"valeurs qui finissent par \"test\""
+
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:33
+msgid "Use exact match"
+msgstr "Correspondance exacte"
+
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:15 views/lists/segments/rule-edit.hbs:20
+#: views/lists/segments/rule-edit.hbs:34
+msgid "Use range match"
+msgstr "Correspondance par plage"
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-edit.hbs:23
+msgid "Use relative range match"
+msgstr "Correspondance par plages relatives"
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:16 views/lists/segments/rule-edit.hbs:21
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:35
+msgid "From"
+msgstr "De"
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:29
+msgid "days"
+msgstr "jours"
+
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:26 views/lists/segments/rule-edit.hbs:30
+msgid "before today"
+msgstr "avant aujourd'hui"
+
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:27 views/lists/segments/rule-edit.hbs:31
+msgid "after today"
+msgstr "après aujourd'hui"
+
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:17 views/lists/segments/rule-edit.hbs:22
+#: views/lists/segments/rule-edit.hbs:28 views/lists/segments/rule-edit.hbs:36
+msgid "to"
+msgstr "à"
+
+#: views/lists/segments/rule-configure.hbs:34
+#: views/lists/segments/rule-edit.hbs:38 lib/models/segments.js:156
+#: lib/models/segments.js:419
+msgid "Selected"
+msgstr "Sélectionné"
+
+#: views/lists/segments/rule-configure.hbs:35
+#: views/lists/segments/rule-edit.hbs:39 lib/models/segments.js:156
+#: lib/models/segments.js:419
+msgid "Not selected"
+msgstr "Non sélectionné"
+
+#: views/lists/segments/rule-configure.hbs:36
+msgid "Add Rule"
+msgstr "Ajouter une règle"
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:18
+#: views/reports/create-select-template.hbs:5
+#: views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Suivant"
+
+#: views/lists/segments/rule-edit.hbs:40
+msgid "Delete Rule"
+msgstr "Supprimer la règle"
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr "Correspondance"
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:13
+msgid "Segment"
+msgstr "Segment"
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr "Règles de correspondance"
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr "Abonnés en correspondance"
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr "voir"
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Ajouter un abonné"
+
+#: views/lists/subscription/add.hbs:5
+#: views/subscription/partials/subscription-custom-fields.hbs:1
+#: views/users/account.hbs:7
+msgid "Email Address"
+msgstr "Adresse mail"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:85 views/settings.hbs:100
+#: views/subscription/partials/subscription-custom-fields.hbs:6
+msgid "Begins with"
+msgstr "qui commence par"
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Insérez une clé publique GPG pour chiffrer les messages envoyés à cet abonné"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Fuseau horaire"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "Utilisateur pour tests ?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+"Si activé, cet abonnement peut être utilisé pour prévisualiser les message "
+"des campagnes"
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+"Cette personne ne recevra pas de mail de confirmation, aussi assurez-vous "
+"que vous avez le droit de lui envoyer des messages."
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Modifier l'abonné"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Retour à la liste"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:1
+#: lib/helpers.js:42 lib/models/segments.js:11
+msgid "Email address"
+msgstr "Adresse mail"
+
+#: views/lists/subscription/edit.hbs:17
+msgid "Delete Subscription"
+msgstr "Supprimer l'abonnement"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Statut de l'import"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Adresses en erreur"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid ""
+"Role-based addresses like postmaster@example.com are blocked when importing. "
+"Subscribers with role-based email addresses can join your list using the "
+"subscription form"
+msgstr ""
+"Les adresse administratives comme postmaster@example.com sont supprimées "
+"lors des imports. Les utilisateurs disposant d'adresses administrativves "
+"doivent utiliser le formulaire d'abonnement"
+
+#: views/lists/subscription/import-failed.hbs:7
+msgid "see here"
+msgstr "voir ici"
+
+#: views/lists/subscription/import-failed.hbs:9
+msgid "Fail reason"
+msgstr "Raison de l'échec"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Importer des abonnés"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:21
+#: views/users/api.hbs:36 views/users/api.hbs:44 views/users/api.hbs:52
+#: views/users/api.hbs:64 views/users/api.hbs:75 views/users/api.hbs:83
+#: views/users/api.hbs:91 views/users/api.hbs:96 views/users/api.hbs:101
+#: views/users/api.hbs:106
+msgid "Example"
+msgstr "Exemple"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Lancer l'importation"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "Fichier CSV"
+
+#: views/lists/subscription/import.hbs:6
+msgid "The first line must contain column headings"
+msgstr "La première ligne doit contenir les entêtes de colonnes"
+
+#: views/lists/subscription/import.hbs:7
+msgid "CSV delimiter"
+msgstr "Délimiteur CSV"
+
+#: views/lists/subscription/import.hbs:8
+msgid "Categorize the imported subscribers as"
+msgstr "Catégoriser les abonnés importés comme"
+
+#: views/lists/subscription/import.hbs:9 routes/lists.js:206
+msgid "Subscribed"
+msgstr "Abonné"
+
+#: views/lists/subscription/import.hbs:10
+msgid "Regular subscriber addresses"
+msgstr "Abonnés ordinaires"
+
+#: views/lists/subscription/import.hbs:11
+msgid "Subscribed (Force)"
+msgstr "Abonné (forcé)"
+
+#: views/lists/subscription/import.hbs:12
+msgid "Regular subscriber addresses, resubscribe users that have unsubscribed"
+msgstr ""
+"Abonnés ordinaires, et réabonner les utilisateurs qui s'étaient désabonnés"
+
+#: views/lists/subscription/import.hbs:14
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr "Désabonnements. Les adresses seront désabonnées de la liste"
+
+#: views/lists/subscription/import.hbs:15
+msgid "Check imported emails"
+msgstr "Vérifier les adresses mail importées"
+
+#: views/lists/subscription/import.hbs:16 views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr "Activé"
+
+#: views/lists/subscription/import.hbs:17 views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr "Désactivé"
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Formulaire d'abonnement"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Actions sur la liste"
+
+#: views/lists/view.hbs:9 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr "Créer un déclencheur"
+
+#: views/lists/view.hbs:10
+msgid "Add Subscriber"
+msgstr "Ajouter un abonné"
+
+#: views/lists/view.hbs:11
+msgid "Import Subscribers"
+msgstr "Importer des abonnés"
+
+#: views/lists/view.hbs:15
+msgid "Create New Segment"
+msgstr "Créer un nouveau segment"
+
+#: views/lists/view.hbs:16
+msgid "Filter"
+msgstr "Filtre"
+
+#: views/lists/view.hbs:17
+msgid "Subscriptions"
+msgstr "Abonnements"
+
+#: views/lists/view.hbs:18
+msgid "Imports"
+msgstr "Imports"
+
+#: views/lists/view.hbs:25 routes/campaigns.js:256 routes/lists.js:300
+msgid "Finished"
+msgstr "Terminé"
+
+#: views/lists/view.hbs:27
+msgid "Added"
+msgstr "Ajouté"
+
+#: views/lists/view.hbs:28
+msgid "Updated"
+msgstr "Mis à jour"
+
+#: views/lists/view.hbs:29
+msgid "Failed"
+msgstr "Echec"
+
+#: views/lists/view.hbs:31
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+"Êtes-vous sûr ? Cette action ne doit être appelée que pour interrompre les "
+"imports bloqués"
+
+#: views/lists/view.hbs:32
+msgid "Restart"
+msgstr "Redémarrer"
+
+#: views/mosaico/editor.hbs:1 views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr "Lexique des champs de publipostage"
+
+#: views/mosaico/editor.hbs:4
+msgid "MOSAICO Responsive Email Designer"
+msgstr "Editeur de mail responsive MOSAICO"
+
+#: views/mosaico/editor.hbs:5
+msgid "Sucessfully saved"
+msgstr "Enregistré"
+
+#: views/mosaico/editor.hbs:6
+msgid "An error occured while saving the document"
+msgstr "Une erreur est survenue lors de l\\'enregistrement du document"
+
+#: views/mosaico/editor.hbs:7
+msgid "Unsaved changes will be lost. Close now?"
+msgstr ""
+"Les éventuelles modifications non sauvegardées seront perdues. Fermer "
+"maintenant ?"
+
+#: views/mosaico/editor.hbs:8 views/mosaico/editor.hbs:9
+msgid "Tags"
+msgstr "Champs de publipostage"
+
+#: views/partials/codeeditor.hbs:1 views/partials/grapejs.hbs:1
+#: views/partials/mosaico.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Contenu du modèle (HTML)"
+
+#: views/partials/editor-navbar.hbs:1
+msgid "SAVE"
+msgstr "ENREGISTRER"
+
+#: views/partials/editor-navbar.hbs:2
+msgid "SAVING"
+msgstr "ENREGISTRE"
+
+#: views/partials/editor-navbar.hbs:3
+msgid "CLOSE"
+msgstr "FERMER"
+
+#: views/partials/grapejs.hbs:2
+msgid "Open GrapeJS"
+msgstr "Ouvrir GrapeJS"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "Basculer la prévisualisation HTML"
+
+#: views/partials/html-to-text.hbs:1
+msgid ""
+"To extract the text from HTML click here."
+msgstr ""
+"Pour extraire le texte du HTML, cliquez ici."
+
+#: views/partials/html-to-text.hbs:2
+msgid ""
+"Please note that your existing plaintext in the field above will be "
+"overwritten. This feature uses the Premailer API, a third party "
+"service. Their Terms of Service and Privacy Policy apply."
+msgstr ""
+"Notez bien que le texte présent dans le champ ci-dessus sera remplacé. Cette "
+"fonctionnalité utilisePremailer API, un service tiers. Merci de "
+"vérifier leurs Conditions générales d'utilisation et de vie privée, qui "
+"s'appliquent en ce cas."
+
+#: views/partials/html-to-text.hbs:3
+msgid "An error occurred while talking to the server"
+msgstr "Une erreur est intervenue lors du dialogue avec le serveur"
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+"Les champs de publipostage sont des champs qui sont remplacés avant l'envoi "
+"du message. Le format du champ de publipostage est le suivant : "
+"[ETIQUETTE] ou [ETIQUETTE/defaut] où defaut"
+"code> est une valeur textuelle optionnelle utilisée lorsque ETIQUETTE"
+"code> est vide."
+
+#: views/partials/modal-carousel.hbs:1
+msgid "{{title}}"
+msgstr "{{title}}"
+
+#: views/partials/mosaico.hbs:2
+msgid "Open Mosaico"
+msgstr "Ouvrir Mosaico"
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Contenu du modèle (Texte)"
+
+#: views/report-templates/create.hbs:2 views/report-templates/edit.hbs:2
+#: views/report-templates/report-templates.hbs:2
+#: views/reports/create-select-template.hbs:2 views/reports/create.hbs:2
+#: views/reports/edit.hbs:2 views/reports/output.hbs:2
+#: views/reports/reports.hbs:2 views/reports/reports.hbs:5
+#: views/reports/view.hbs:2 lib/tools.js:144 routes/reports.js:31
+msgid "Reports"
+msgstr "Rapports"
+
+#: views/report-templates/create.hbs:4 views/report-templates/create.hbs:6
+#: views/report-templates/report-templates.hbs:4 views/templates/create.hbs:3
+#: views/templates/create.hbs:4 views/templates/create.hbs:12
+#: views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Créer un modèle"
+
+#: views/report-templates/create.hbs:5 routes/report-templates.js:231
+msgid "Create Report Template"
+msgstr "Créer un modèle de rapport"
+
+#: views/report-templates/edit.hbs:4 views/templates/edit.hbs:3
+#: views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Modifier le modèle"
+
+#: views/report-templates/edit.hbs:5 routes/report-templates.js:262
+msgid "Edit Report Template"
+msgstr "Modifier le modèle de rapport"
+
+#: views/report-templates/edit.hbs:6 views/templates/edit.hbs:12
+msgid "Delete Template"
+msgstr "Supprimer le modèle"
+
+#: views/report-templates/edit.hbs:7
+msgid "Update and Stay"
+msgstr "Mettre à jour et poursuivre"
+
+#: views/report-templates/edit.hbs:8
+msgid "Update and Leave"
+msgstr "Mettre à jour et quitter"
+
+#: views/report-templates/partials/report-template-fields.hbs:2
+msgid "Template Name"
+msgstr "Nom du modèle"
+
+#: views/report-templates/partials/report-template-fields.hbs:6
+msgid "User selectable fields"
+msgstr "Champs utilisateur utilisables"
+
+#: views/report-templates/partials/report-template-fields.hbs:7
+msgid "Data processing code"
+msgstr "Code de traitement des données"
+
+#: views/report-templates/partials/report-template-fields.hbs:8
+msgid "Rendering template"
+msgstr "Modèle de rendu"
+
+#: views/report-templates/report-templates.hbs:5
+msgid "Blank"
+msgstr "Vide"
+
+#: views/report-templates/report-templates.hbs:6
+msgid "All Subscribers"
+msgstr "Tous les abonnés"
+
+#: views/report-templates/report-templates.hbs:7
+msgid "Grouped Subscribers"
+msgstr "Abonnements groupés"
+
+#: views/report-templates/report-templates.hbs:8
+msgid "Export List as CSV"
+msgstr "Exporter la liste au format CSV"
+
+#: views/report-templates/report-templates.hbs:9 views/reports/reports.hbs:4
+#: routes/report-templates.js:29
+msgid "Report Templates"
+msgstr "Modèles de rapport"
+
+#: views/reports/create-select-template.hbs:3
+#: views/reports/create-select-template.hbs:4 views/reports/create.hbs:3
+#: views/reports/create.hbs:4 views/reports/create.hbs:5
+#: views/reports/reports.hbs:3 routes/reports.js:81
+msgid "Create Report"
+msgstr "Créer un rapport"
+
+#: views/reports/edit.hbs:3 views/reports/edit.hbs:4 routes/reports.js:151
+msgid "Edit Report"
+msgstr "Modifier le rapport"
+
+#: views/reports/edit.hbs:5
+msgid "Delete Report"
+msgstr "Supprimer le rapport"
+
+#: views/reports/partials/report-fields.hbs:2
+msgid "Report Name"
+msgstr "Nom du rapport"
+
+#: views/reports/partials/report-fields.hbs:8
+#: views/reports/partials/report-fields.hbs:11
+msgid ""
+"Select a campaign in the table above by clicking on the respective row "
+"number."
+msgstr ""
+"Sélectionnez une campagne dans la table ci-dessus en cliquant sur son numéro "
+"de ligne."
+
+#: views/reports/partials/report-select-template.hbs:1
+msgid "Report Template"
+msgstr "Modèle de rapport"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Adresse du service (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Entrez l'URL à laquelle ce service peut être joint"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "Email de l'administrateur"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr "Entrez l'adresse mail d'émission des messages système"
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr "Désactiver l'éditeur WYSIWYG"
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr ""
+"Si activé, l'editeur HTML affiche le code HTML sans la prévisualisation"
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr "Désactiver les messages de confirmation d'abonnement"
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+"Si activé, aucun message de confirmation suivant lequel un utilisateur a été "
+"abonné ou désabonné ne sera envoyé. Cela ne désactive pas les messages de "
+"confirmation d'abonnement."
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "Identifiant de suivi"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Entrez le code de suivi Google Analytics"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr "Annonce de la page d'accueil"
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr "Code HTML présent sur l'entête de la page d'accueil"
+
+#: views/settings.hbs:17
+msgid "X-Mailer header"
+msgstr "Entête X-Mailer"
+
+#: views/settings.hbs:18
+msgid "Set a custom X-Mailer header value or leave empty to disable it"
+msgstr ""
+"Renseignez un entête X-Mailer personnalisé, et laissez vide pour désactiver"
+
+#: views/settings.hbs:19
+msgid "Campaign defaults"
+msgstr "Paramètres par défaut de la campagne"
+
+#: views/settings.hbs:20
+msgid "Sender name"
+msgstr "Nom de l'émetteur"
+
+#: views/settings.hbs:21
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Nom de l'émetteur, par ex. My Awesome Company Ltd."
+
+#: views/settings.hbs:22
+msgid "Default address"
+msgstr "Adresse mail par défaut"
+
+#: views/settings.hbs:23
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+"Adresse de contact à fournir, par ex. 1234 Main Street, Anywhere, MA 01234, "
+"USA"
+
+#: views/settings.hbs:24
+msgid "Default \"from name\""
+msgstr "Nom d'émetteur par défaut"
+
+#: views/settings.hbs:26
+msgid "Default \"from\" email"
+msgstr "Adresse mail d'émetteur par défaut"
+
+#: views/settings.hbs:28
+msgid "Default \"subject line\""
+msgstr "Objet du mail par défaut"
+
+#: views/settings.hbs:30
+msgid "Default homepage (URL)"
+msgstr "Page d'accueil par défaut (URL)"
+
+#: views/settings.hbs:31
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr "URL où rediriger les utilisateurs abonnés, par ex. http://example.com/"
+
+#: views/settings.hbs:32
+msgid "Default custom unsubscribe (URL))"
+msgstr "URL de désabonnement personnalisable par défaut"
+
+#: views/settings.hbs:33
+msgid "Custom unsubscribe URL, eg. http://example.com/unsubscribe/[EMAIL]"
+msgstr ""
+"URL personnalisée de désabonnement, par ex. http://example.com/unsubscribe/"
+"[EMAIL]"
+
+#: views/settings.hbs:34
+msgid "Set a custom unsubscribe url."
+msgstr "Renseignez une URL de désabonnement personnalisée."
+
+#: views/settings.hbs:35
+msgid "Mailer Settings"
+msgstr "Paramètres mailer"
+
+#: views/settings.hbs:36
+msgid "These settings are required to send out e-mail messages"
+msgstr "Ces paramètres sont obligatoires pour envoyer des messages"
+
+#: views/settings.hbs:37
+msgid "SMTP"
+msgstr "SMTP"
+
+#: views/settings.hbs:38
+msgid "AWS SES"
+msgstr "AWS SES"
+
+#: views/settings.hbs:39
+msgid "Use SMTP for sending mail"
+msgstr "Utiliser SMTP pour envoyer les mails"
+
+#: views/settings.hbs:40
+msgid "Hostname"
+msgstr "Nom de machine"
+
+#: views/settings.hbs:41
+msgid "Port"
+msgstr "Port"
+
+#: views/settings.hbs:42
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr "Port, par ex. 465. Autodétecté si vide"
+
+#: views/settings.hbs:43
+msgid "Encryption"
+msgstr "Chiffrement"
+
+#: views/settings.hbs:44
+msgid "Disable SMTP authentication"
+msgstr "Désactiver l'authentification SMTP"
+
+#: views/settings.hbs:45 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Utilisateur"
+
+#: views/settings.hbs:46
+msgid "Username, eg. myaccount@example.com"
+msgstr "Nom d'utilisateur, par ex. myaccount@example.com"
+
+#: views/settings.hbs:47 views/settings.hbs:48 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr "Mot de passe"
+
+#: views/settings.hbs:49
+msgid "Use SES API for sending mail"
+msgstr "Utiliser l'API SES pour envoyer les mails"
+
+#: views/settings.hbs:50
+msgid "Access Key"
+msgstr "Clé d'accès"
+
+#: views/settings.hbs:51
+msgid "AWS Access Key Id"
+msgstr "ID de la clé d'accès AWS"
+
+#: views/settings.hbs:52
+msgid "Secret Key"
+msgstr "Clé secrète"
+
+#: views/settings.hbs:53
+msgid "AWS Secret Access Key"
+msgstr "Secret de la clé d'accès AWS"
+
+#: views/settings.hbs:54
+msgid "Region"
+msgstr "Région"
+
+#: views/settings.hbs:55
+msgid "Checking"
+msgstr "Vérification"
+
+#: views/settings.hbs:56
+msgid "Check Mailer config"
+msgstr "Vérifier la configuration du serveur mail"
+
+#: views/settings.hbs:57
+msgid "Advanced Mailer settings"
+msgstr "Paramètres avancés du serveur mail"
+
+#: views/settings.hbs:58
+msgid "Log SMTP transactions"
+msgstr "Log des transactions SMTP"
+
+#: views/settings.hbs:59
+msgid "Allow self-signed certificates"
+msgstr "Autoriser les certificats autosignés"
+
+#: views/settings.hbs:60
+msgid "Max connections"
+msgstr "Nombre maximum de connections"
+
+#: views/settings.hbs:61
+msgid "The count of max connections, eg. 10"
+msgstr "Le nombre maximum de connexions, par ex. 10"
+
+#: views/settings.hbs:62
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+"Le nombre maximum de connexions simultannées vers le serveur SMTP (par "
+"défaut 5). Cette limite s'entend par process d'envoi"
+
+#: views/settings.hbs:63
+msgid "Max messages"
+msgstr "Nombre maximum de messages"
+
+#: views/settings.hbs:64
+msgid "The count of max messages, eg. 100"
+msgstr "Le nombre maximum de messages, par ex. 100"
+
+#: views/settings.hbs:65
+msgid ""
+"The number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+"Le nombre de messages à envoyer au travers d'une connexion unique avant "
+"qu'elle ne soit fermée puis réouverte (par défaut 100)"
+
+#: views/settings.hbs:66
+msgid "Throttling"
+msgstr "Restrictions"
+
+#: views/settings.hbs:67
+msgid "Messages per hour eg. 1000"
+msgstr "Messages par heure ex: 1000"
+
+#: views/settings.hbs:68
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+"Nombre maximum de messages envoyés par heure. Laissez vide pour ne pas "
+"restreindre. Si votre fournisseur utilise une unité différente (messages/"
+"minute ou messages/seconde) convertissez cette limite en messages/heure (1 m/"
+"s => 3600 m/h). Cette limite se comprend par process d'émission."
+
+#: views/settings.hbs:69
+msgid "VERP bounce handling"
+msgstr "Traitement VERP des rejets"
+
+#: views/settings.hbs:70
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+"Mailtrain peut utiliser un routage VERP de façon à détecter les adresses en "
+"erreur. Pour cela le message est envoyé avec un adresse de retour VERP "
+"spécifique. Si le message est rejeté, un message de rejet est renvoyé à "
+"cette adresse VERP, permettant de détecter l'adresse en erreur."
+
+#: views/settings.hbs:71
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+"Pour que le VERP fonctionne, vous devez renseigner un enregistrement DNS MX "
+"qui pointe vers le nom de domaine de votre Mailtrain. Vérifiez également que "
+"l'interface VERP est disponible sur le port 25 de votre serveur (le port 25 "
+"nécessite habituellement les privilèges root). Si quelqu'un envoie un mail à "
+"someuser@verp-hostname, le mail doit atteindre ce serveur."
+
+#: views/settings.hbs:72
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+"Le VERP ne fonctionne habituellement que si vous utilisez votre propre "
+"serveur SMTP. Les services de relai ordinaires (SES, SparkPost, Gmail, etc.) "
+"tendent à supprimer les adresses VERP des messages."
+
+#: views/settings.hbs:73
+msgid "Use VERP to catch bounces"
+msgstr "Utiliser le VERP pour récupérer les rejets"
+
+#: views/settings.hbs:74
+msgid "Server hostname"
+msgstr "Nom de machine du serveur"
+
+#: views/settings.hbs:75
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr "Le nom du serveur VERP, par ex. bouces.example.com"
+
+#: views/settings.hbs:76
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+"Nom du serveur de traitement VERP. Ce nom d'hôte est habituellement utilisée "
+"dans l'entête SMTP FROM d'enveloppe, et est pointé par l'enregistrement DNS "
+"MX."
+
+#: views/settings.hbs:77
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+"Le serveur de traitement VERP n'est pas activé. Modifier le fichier de "
+"configuration et redémarrer le serveur pour l'activer"
+
+#: views/settings.hbs:78
+msgid "GPG Signing"
+msgstr "Signature GPG"
+
+#: views/settings.hbs:79
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+"Seuls les messages chiffrés peuvent être signés. Les abonnés qui n'ont pas "
+"fourni dans leur profil de clé publique GPG reçoivent normalement les mails. "
+"Les utilisateurs qui ont fourni leur clé GPG recevront les mails sous forme "
+"chiffrée, et si vous avez fourni une clé de signature, les messages seront "
+"en plus signés avec cette clé."
+
+#: views/settings.hbs:80
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+"Ne pas utiliser de clé sensible ici. La clé privée et la phrase de "
+"déchiffrement ne sont pas chiffrées dans la base de données."
+
+#: views/settings.hbs:81
+msgid "Private Key Passphrase"
+msgstr "Phrase de déchiffrement de la clé privée"
+
+#: views/settings.hbs:82
+msgid "Passphrase for the key if set"
+msgstr "Phrase de déchiffrement de la clé si fournie"
+
+#: views/settings.hbs:83
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+"Renseignez uniquement si votre clé privée est protégée par un mot de passe"
+
+#: views/settings.hbs:84
+msgid "GPG Private Key"
+msgstr "Clé privée GPG"
+
+#: views/settings.hbs:86
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+"Cette valeur est optionnelle. Si vous ne fournissez pas de clé privé GPG, "
+"les messages chiffrés sont envoyés sans signature."
+
+#: views/settings.hbs:87
+msgid "DKIM Signing by ZoneMTA"
+msgstr "Signature DKIM par ZoneMTA"
+
+#: views/settings.hbs:88
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+"Si vous utilisez ZoneMTA, Mailtrain peut fournir une clé DKIM pour signer "
+"les messages sortants. Les autres services fournissent habituellement leurs "
+"propres moyens pour signer vos messages avec DKIM"
+
+#: views/settings.hbs:89
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+"Ne pas utiliser de clé sensible ici. La clé privée n'est pas chiffrée dans "
+"la base de données."
+
+#: views/settings.hbs:90
+msgid "ZoneMTA DKIM API Key"
+msgstr "Clé de l'API DKIM ZoneMTA"
+
+#: views/settings.hbs:91
+msgid "Some secret value"
+msgstr "Valeur secrète"
+
+#: views/settings.hbs:92
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+"Valeur secrète connue de ZoneMTA pour les requêtes d'informations de clés "
+"DKIM. Si cette valeur a été générée lors de l'installation Mailtrain, elle "
+"peut être conservée."
+
+#: views/settings.hbs:93
+msgid "DKIM domain"
+msgstr "Domaine DKIM"
+
+#: views/settings.hbs:94
+msgid "Domain name for the DKIM key"
+msgstr "Nom de domaine pour la clé DKIM"
+
+#: views/settings.hbs:95
+msgid "Leave blank to use the sender email address domain"
+msgstr "Laissez vide pour utiliser le domaine de l'adresse mail de l'émetteur"
+
+#: views/settings.hbs:96 views/settings.hbs:97
+msgid "DKIM key selector"
+msgstr "Sélecteur de clé DKIM"
+
+#: views/settings.hbs:98
+msgid "Signing is disabled without a valid selector value"
+msgstr "L'abonnement est désactivé en l'absence de valeur de sélection valide"
+
+#: views/settings.hbs:99
+msgid "DKIM Private Key"
+msgstr "Clé privée DKIM"
+
+#: views/settings.hbs:101
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+"Cette valeur est optionnelle. Si vous ne fournissez pas de clé privée, les "
+"messages ne seront pas signés."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:1
+#: views/subscription/mail-already-subscribed-text.hbs:1
+#: lib/models/subscriptions.js:174 lib/models/subscriptions.js:895
+msgid "Email address already registered"
+msgstr "Adresse mail déjà enregistrée"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:2
+#: views/subscription/mail-already-subscribed-text.hbs:2
+msgid ""
+"We have received a subscription request. Your email address is however "
+"already registered."
+msgstr ""
+"Nous avons reçu une demande d'abonnement. Cependant votre adresse mail est "
+"déjà enregistrée."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:3
+#: views/subscription/mail-already-subscribed-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. Your existing "
+"subscription won't be affected."
+msgstr ""
+"Si vous avez reçu ce message par erreur, vous pouvez simplement le "
+"supprimer. Votre abonnement ne sera pas modifié."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:3
+msgid "If you want to modify your subscription then you can "
+msgstr "Si vous voulez modifier votre abonnement vous pouvez"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:5
+#: views/subscription/mail-already-subscribed-text.hbs:5
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:4
+msgid "manage your preferences"
+msgstr "gestion de vos préférences"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:6
+#: views/subscription/mail-already-subscribed-text.hbs:6
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-subscription-confirmed-text.hbs:5
+#: views/users/login.hbs:10
+msgid "or"
+msgstr "ou"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:7
+#: views/subscription/mail-already-subscribed-text.hbs:7
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:6
+#: views/subscription/mail-subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "désabonnement ici"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:7
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:3
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:3
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:4
+#: views/subscription/web-subscribed-notice.mjml.hbs:4
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:3
+#: views/subscription/web-updated-notice.mjml.hbs:3
+msgid "Return to our website"
+msgstr "Retour à notre site web"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:9
+#: views/subscription/mail-already-subscribed-text.hbs:8
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:4
+#: views/subscription/mail-confirm-address-change-text.hbs:4
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-subscription-text.hbs:4
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-unsubscription-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-text.hbs:7
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "Pour les questions à ce sujet, contactez :"
+
+#: views/subscription/mail-already-subscribed-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Si vous voulez modifier votre abonnement vous pouvez :"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:1
+#: views/subscription/mail-confirm-address-change-text.hbs:1
+msgid "Please Confirm Subscription Address Change"
+msgstr "Merci de confirmer votre changement d'adresse mail"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:2
+#: views/subscription/mail-confirm-address-change-text.hbs:2
+msgid "Yes, subscribe this email address to the list"
+msgstr "Oui, abonner cette adresse mail à cette liste"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:3
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Si vous avez reçu ce message par erreur, vous pouvez simplement le "
+"supprimer. Vous ne serez pas abonné tant que vous ne cliquez pas le lien ci-"
+"dessus."
+
+#: views/subscription/mail-confirm-address-change-text.hbs:3
+#: views/subscription/mail-confirm-subscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Si vous avez reçu ce message par erreur, vous pouvez simplement le "
+"supprimer. Vous ne serez pas abonné tant que vous ne cliquez pas le lien ci-"
+"dessus."
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:1
+#: views/subscription/mail-confirm-subscription-text.hbs:1
+#: views/subscription/mail-confirm-unsubscription-text.hbs:1
+#: routes/subscription.js:432
+msgid "Please Confirm Subscription"
+msgstr "Merci de confirmer votre abonnement"
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-subscription-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Oui, je m'abonne à cette liste"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:1
+msgid "Please Confirm Unsubscription"
+msgstr "Merci de confirmer votre désabonnement"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-unsubscription-text.hbs:2
+msgid "Yes, unsubscribe me from this list"
+msgstr "Oui, je me désabonne de cette liste"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed if you don't click the confirmation link above."
+msgstr ""
+"Si vous avez reçu ce message par erreur, vous pouvez simplement le "
+"supprimer. Vous ne serez pas désabonné tant que vous ne cliquez pas le lien "
+"ci-dessus."
+
+#: views/subscription/mail-confirm-unsubscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed unless you click the confirmation link above."
+msgstr ""
+"Si vous avez reçu ce message par erreur, vous pouvez simplement le "
+"supprimer. Vous ne serez pas abonné tant que vous ne cliquez pas le lien ci-"
+"dessus."
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-subscription-confirmed-text.hbs:1
+#: views/subscription/web-subscribed-notice.mjml.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Abonnement confirmé"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed"
+msgstr "Votre abonnement à la liste a été confirmé"
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:2
+#: views/subscription/web-subscribed-notice.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "Votre abonnement à la liste a été confirmé."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:1
+msgid "You Are Now Unsubscribed"
+msgstr "Vous êtes désormais désabonné"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:2
+msgid "We have removed your email address from our list"
+msgstr "Nous avons retiré votre adresse mail de notre liste"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:3
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr ""
+"Si vous vous êtes désabonné par erreur, vous pouvez à nouveau vous abonner "
+"ici :"
+
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Nous avons retiré votre adresse mail de notre liste."
+
+#: views/subscription/partials/subscription-custom-fields.hbs:2
+msgid "want to change it?"
+msgstr "Voulez-vous le changer ?"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:5
+msgid "Download signature verification key"
+msgstr "Télécharger la clé de vérification de signature"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:7
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+"Insérez ici votre clé publique GPG pour chiffrer les messages envoyés à "
+"votre adresse"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:8
+msgid "optional"
+msgstr "optionnel"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:1
+#: views/subscription/partials/subscription-flash-messages.hbs:3
+msgid "Warning!"
+msgstr "Attention !"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+"Si javascript n'était pas activé, aucun message de confirmation n'a été "
+"envoyé"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:4
+msgid "JavaScript must be enabled in order for this form to work"
+msgstr "JavaScript doit être activé pour utiliser ce formulaire"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:1
+msgid "Existing Email Address"
+msgstr "Adresse mail existante"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:2
+msgid "New Email Address"
+msgstr "Nouvelle adresse mail"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:3
+msgid "Your new email address"
+msgstr "Votre nouvelle adresse mail"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:4
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Vous allez recevoir une demande de confirmation à votre nouvelle adresse "
+"mail, que vous devrez acceptez pour que votre nouvelle adresse soit prise en "
+"compte"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:5
+#: views/subscription/web-manage-address.mjml.hbs:2
+msgid "Update Email Address"
+msgstr "Mettre à jour l'adresse mail"
+
+#: views/subscription/partials/subscription-manage-form.hbs:1
+#: views/subscription/web-manage.mjml.hbs:2
+msgid "Update Profile"
+msgstr "Mettre à jour le profil"
+
+#: views/subscription/partials/subscription-subscribe-form.hbs:1
+#: views/subscription/web-subscribe.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:1
+msgid "Subscribe to list"
+msgstr "S'abonner à la liste"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:1
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:1
+#: views/subscription/widget-subscribe.hbs:4
+msgid "Almost Finished"
+msgstr "Presque terminé"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:5
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Nous devons confirmer votre adresse mail. Pour terminer la procédure "
+"d'abonnement, merci de cliquer sur le lien présent dans le mail que nous "
+"venons de vous envoyer."
+
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:2
+msgid ""
+"We need to confirm your email address. To complete the unsubscription "
+"process, please click the link in the email we just sent you."
+msgstr ""
+"Nous devons confirmer votre adresse mail. Pour terminer la procédure de "
+"désabonnement, merci de cliquer sur le lien présent dans le mail que nous "
+"venons de vous envoyer."
+
+#: views/subscription/web-manage-address.mjml.hbs:1
+msgid "Update Your Email Address"
+msgstr "Mettre à jour votre adresse mail"
+
+#: views/subscription/web-manage.mjml.hbs:1
+msgid "Update Your Preferences"
+msgstr "Mettre à jour vos préférences"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:1
+msgid "Online Unsubscription Is Not Possible"
+msgstr "Le désabonnement en ligne n'est pas autorisé"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:2
+msgid "Please contact us at"
+msgstr "Merci de nous contacter à"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:3
+msgid "to get removed from the list"
+msgstr "pour être retiré de la liste"
+
+#: views/subscription/web-subscribe.mjml.hbs:1
+msgid "Subscribe to List"
+msgstr "S'abonner à la liste"
+
+#: views/subscription/web-subscribed-notice.mjml.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "Merci de votre abonnement !"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Désabonnement pris en compte"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:2
+msgid "You have been removed from:"
+msgstr "Vous avez été retiré de :"
+
+#: views/subscription/web-updated-notice.mjml.hbs:1
+msgid "Profile Updated"
+msgstr "Profil mis à jour"
+
+#: views/subscription/web-updated-notice.mjml.hbs:2
+msgid "Your profile information has been updated."
+msgstr "Vos informations de profil ont été enregistrées"
+
+#: views/subscription/widget-subscribe.hbs:2
+msgid "Sending ..."
+msgstr "Envoi ..."
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Il semble que vous soyez déjà abonné à cette liste."
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Nom du modèle"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr "Nom de ce modèle, par ex. Newsletter"
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "Éditeur HTML"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr "Commentaire optionnel sur ce modèle"
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr "Retour aux modèles"
+
+#: views/templates/edit.hbs:11
+msgid "Duplicate"
+msgstr "Dupliquer"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr "Déclencheurs des automatismes"
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr "Sélectionnez une liste pour le déclencheur"
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr "Nom du déclencheur"
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr "Nom de ce déclencheur, par ex. Abonnés inactifs"
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr "Commentaire optionnel sur ce déclencheur"
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr "Règle du déclencheur"
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr "Déclencheur lancé"
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr "jours suivants :"
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Évènement"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Campagne"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr "Action du déclencheur"
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr "Envoyer la campagne"
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr "Modifier le déclencheur"
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr "Retour aux déclencheurs"
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr "Le déclencheur est activé"
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr "Supprimer le déclencheur"
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr "Déclenché"
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr "Abonnés déclenchés"
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr "Abonnés ayant activé ce déclencheur"
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr "Heure du déclenchement"
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr "Déclencheur"
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr "Campagne cible"
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr "Nombre de déclencheurs"
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr "Ce compte est géré par le LDAP."
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr "Adresse mail associée"
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr "Votre adresse mail"
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr "Cette adresse vous permet de réinitialiser un mot de passe perdu"
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr "Changement du mot de passe"
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+"Vous avez uniquement ce formulaire à remplir pour changer votre mot de passe"
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr "Mot de passe actuel"
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr "Nouveau mot de passe"
+
+#: views/users/account.hbs:16 views/users/reset.hbs:8
+msgid "Confirm Password"
+msgstr "Confirmation du mot de passe"
+
+#: views/users/account.hbs:17 views/users/reset.hbs:9
+msgid "Confirm New Password"
+msgstr "Confirmez le nouveau mot de passe"
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr "Êtes-vous sûr ? La réinitialisation invaliderait les jetons existants."
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr "Êtes-vous sûr ?"
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr "Réinitialiser le jeton d'accès"
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr "Générer un jeton d'accès"
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr "Jeton d'accès privé :"
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr "Le jeton d'accès n'est pas encore généré"
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr "Notes à propos de l'API"
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+"La réponse de l'API est un document JSON avec les propriétés error"
+"code> et data. Si la propriété error est "
+"renseignée, alors la requête a échoué."
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+"Vous devez définir le bon Content-Type lors de vos requêtes. "
+"Vous pouvez utiliser soit application/x-www-form-urlencoded "
+"pour des données de formulaire, ou application/json pour une "
+"requête JSON. Vous ne pouvez pas utiliser multipart/form-data."
+
+#: views/users/api.hbs:13
+msgid "Get list of subscriptions"
+msgstr "Obtenir la liste des abonnés"
+
+#: views/users/api.hbs:14
+msgid ""
+"Retrieve a list of subscriptions to the list referenced by :listId. All "
+"fields of the subscribers will be returned. Note that custom fields will "
+"have generated names."
+msgstr ""
+"Récupérer l'ensemble des abonnements à la liste référencée :listId. Tous les "
+"champs des abonnés seront renvoyés. Notez que les champs personnalisés "
+"auront des noms générés automatiquement."
+
+#: views/users/api.hbs:15 views/users/api.hbs:24 views/users/api.hbs:26
+#: views/users/api.hbs:39 views/users/api.hbs:41 views/users/api.hbs:47
+#: views/users/api.hbs:49 views/users/api.hbs:55 views/users/api.hbs:57
+#: views/users/api.hbs:67 views/users/api.hbs:78 views/users/api.hbs:80
+#: views/users/api.hbs:86 views/users/api.hbs:88 views/users/api.hbs:94
+#: views/users/api.hbs:99 views/users/api.hbs:104
+msgid "arguments"
+msgstr "arguments"
+
+#: views/users/api.hbs:16 views/users/api.hbs:25 views/users/api.hbs:40
+#: views/users/api.hbs:48 views/users/api.hbs:56 views/users/api.hbs:68
+#: views/users/api.hbs:79 views/users/api.hbs:87 views/users/api.hbs:95
+#: views/users/api.hbs:100 views/users/api.hbs:105
+msgid "your personal access token"
+msgstr "votre token d'accès personnel"
+
+#: views/users/api.hbs:17 views/users/api.hbs:69
+msgid "Start position"
+msgstr "Position de démarrage"
+
+#: views/users/api.hbs:18 views/users/api.hbs:70
+msgid "optional, default 0"
+msgstr "optionnel, par défaut 0"
+
+#: views/users/api.hbs:19
+msgid "limit subscription count in response"
+msgstr "nombre maximal d'abonnements retournés"
+
+#: views/users/api.hbs:20 views/users/api.hbs:72
+msgid "optional, default 10000"
+msgstr "optionnel, par défaut 10000"
+
+#: views/users/api.hbs:22
+msgid "Add subscription"
+msgstr "Ajouter un abonnement"
+
+#: views/users/api.hbs:23
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+"Ce service de l'API insère ou met à jour un abonnement. Les champs non "
+"fournis sont laissés tels quels. Ainsi, pour un abonnement existant, si vous "
+"ne mettez à jour que la valeur de LAST_NAME, FIRST_NAME ne sera pas modifié."
+
+#: views/users/api.hbs:27 views/users/api.hbs:42 views/users/api.hbs:50
+msgid "subscriber's email address"
+msgstr "adresse mail de l'abonné"
+
+#: views/users/api.hbs:28 views/users/api.hbs:43 views/users/api.hbs:51
+#: views/users/api.hbs:59 views/users/api.hbs:82 views/users/api.hbs:90
+msgid "required"
+msgstr "obligatoire"
+
+#: views/users/api.hbs:29
+msgid "subscriber's first name"
+msgstr "prénom de l'abonné"
+
+#: views/users/api.hbs:30
+msgid "subscriber's last name"
+msgstr "nom de l'abonné"
+
+#: views/users/api.hbs:31
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"Fuseau horaire de l'abonné (par ex. \"Europe/Paris\", \"CEST\" ou \"UTC\"). "
+"Par défaut \"UTC\""
+
+#: views/users/api.hbs:32
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+"valeur du champ personnalisé. Utiliser yes/no pour des valeurs d'options "
+"groupées (cases à cocher, choix sur listes, menus déroulants)"
+
+#: views/users/api.hbs:33
+msgid "Additional POST arguments"
+msgstr "Arguments POST additionnels"
+
+#: views/users/api.hbs:34
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+"choisir \"oui\" si vous voulez être sur que l'adresse mail soit marquée "
+"comme abonnée, même si elle était précédemment marquée désabonnée. Si "
+"l'adresse mail était déjà désabonnée/bloquée, alors le statut d'abonnement "
+"n'est pas changé"
+
+#: views/users/api.hbs:35
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+"choisir \"oui\" si vous voulez envoyer un mail de confirmation aux nouveaux "
+"abonnés avant de marquer leur abonnement comme actif"
+
+#: views/users/api.hbs:37
+msgid "Remove subscription"
+msgstr "Retirer l'abonnement"
+
+#: views/users/api.hbs:38
+msgid "This API call marks a subscription as unsubscribed"
+msgstr "Ce service de l'API marque un abonnement comme désabonné"
+
+#: views/users/api.hbs:45
+msgid "Delete subscription"
+msgstr "Supprimer l'abonnement"
+
+#: views/users/api.hbs:46
+msgid "This API call deletes a subscription"
+msgstr "Ce service de l'API supprime un abonnement"
+
+#: views/users/api.hbs:53
+msgid "Add new custom field"
+msgstr "Ajouter un champ personnalisé"
+
+#: views/users/api.hbs:54
+msgid "This API call creates a new custom field for a list."
+msgstr "Ce service de l'API crée un nouveau champ personnalisé pour une liste."
+
+#: views/users/api.hbs:58
+msgid "field name"
+msgstr "nom du champ"
+
+#: views/users/api.hbs:60
+msgid "one of the following types:"
+msgstr "Un des types suivants :"
+
+#: views/users/api.hbs:61
+msgid ""
+"If the type is 'option' then you also need to specify the parent element ID"
+msgstr ""
+"Si le type est 'option', vous devez également spécifier l'ID de l'élément "
+"parent"
+
+#: views/users/api.hbs:62
+msgid ""
+"Template for the group element. If not set, then values of the elements are "
+"joined with commas"
+msgstr ""
+"Modèle pour le groupe d'éléments. Si vide, les valeurs seront concatennées "
+"avec des virgules"
+
+#: views/users/api.hbs:63
+msgid ""
+"if not visible then the subscriber can not view or modify this value at the "
+"profile page"
+msgstr ""
+"Si masqué, l'abonné ne peut pas voir ni modifier la valeur depuis sa page de "
+"profil"
+
+#: views/users/api.hbs:65
+msgid "Get list of blacklisted emails"
+msgstr "Obtenir les adresses mail en liste noire"
+
+#: views/users/api.hbs:66
+msgid "This API call get list of blacklisted emails."
+msgstr "Ce service de l'API renvoie la liste des mails dans la liste noire."
+
+#: views/users/api.hbs:71
+msgid "limit emails count in response"
+msgstr "nombre maximal d'adresses mail retournées"
+
+#: views/users/api.hbs:73
+msgid "filter by part of email"
+msgstr "Filtre sur partie d'adresse mail"
+
+#: views/users/api.hbs:74
+msgid "optional, default ''"
+msgstr "optionnel, par défaut ''"
+
+#: views/users/api.hbs:77
+msgid "This API call either add emails to blacklist"
+msgstr "Ce service de l'API ajoute des mails à la liste noire"
+
+#: views/users/api.hbs:81 views/users/api.hbs:89
+msgid "email address"
+msgstr "adresse mail"
+
+#: views/users/api.hbs:84
+msgid "Delete email from blacklist"
+msgstr "Supprimer le mail de la liste noire"
+
+#: views/users/api.hbs:85
+msgid "This API call either delete emails from blacklist"
+msgstr "Ce service de l'API supprime des mails de la liste noire"
+
+#: views/users/api.hbs:92
+msgid "Get the lists a user has subscribed to"
+msgstr "Obtenir la liste des listes auxquelles un utilisateur est abonné"
+
+#: views/users/api.hbs:93
+msgid "Retrieve the lists that the user with :email has subscribed to. "
+msgstr "Récupérer les listes auxquelles l'utilisateur :email est abonné. "
+
+#: views/users/api.hbs:97
+msgid "Get all lists"
+msgstr "Obtenir toutes les listes"
+
+#: views/users/api.hbs:98
+msgid "Retrieve every list. "
+msgstr "Récupérer toutes les listes. "
+
+#: views/users/api.hbs:102
+msgid "Get list by id"
+msgstr "Obtenir une liste via son id"
+
+#: views/users/api.hbs:103
+msgid "Retrieve the list with :id "
+msgstr "Récupérer la liste avec :id "
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr "Réinitialisation du mot de passe"
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr "Réinitialiser votre mot de passe ?"
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr "Les comptes sont gérés par le LDAP."
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr "Réinitialiser le mot de passe"
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+"Merci d'entrer le nom d'utilisateur et l'adresse mail que vous avez "
+"fournis lors de votre inscription au service."
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr ""
+"Nous allons vous envoyer un mail qui vous permettra de réinitialiser votre "
+"mot de passe."
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr "Nom d'utilisateur ou adresse mail"
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr "Envoyer un mail de vérification"
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Se souvenir de moi"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "Mot de passe oublié ?"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr "Choisissez votre nouveau mot de passe"
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr "Merci de saisir un nouveau mot de passe."
+
+#: lib/editor-helpers.js:17 routes/templates.js:95
+msgid "Could not find template with specified ID"
+msgstr "Ne peut trouver de modèle avec cet identifiant"
+
+#: lib/editor-helpers.js:33 routes/archive.js:145 routes/campaigns.js:132
+#: routes/campaigns.js:285 routes/campaigns.js:380 routes/campaigns.js:428
+#: routes/campaigns.js:468 routes/campaigns.js:845 routes/campaigns.js:868
+#: routes/campaigns.js:887 routes/campaigns.js:909 routes/triggers.js:172
+msgid "Could not find campaign with specified ID"
+msgstr "Aucune campagne ne correspond à cet identifiant"
+
+#: lib/editor-helpers.js:47 routes/editorapi.js:320
+msgid "Invalid resource type"
+msgstr "Type de ressource invalide"
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr "Code de statut d'erreur %s"
+
+#: lib/helpers.js:33
+msgid "URL that points to the unsubscribe page"
+msgstr "URL vers la page de désabonnement"
+
+#: lib/helpers.js:36
+msgid "URL that points to the preferences page of the subscriber"
+msgstr "URL vers la page de préférences de l'abonné"
+
+#: lib/helpers.js:39
+msgid "URL to preview the message in a browser"
+msgstr "URL de visualisation du message dans le navigateur"
+
+#: lib/helpers.js:45 lib/models/segments.js:31
+msgid "First name"
+msgstr "Prénom"
+
+#: lib/helpers.js:48 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Nom"
+
+#: lib/helpers.js:51
+msgid "Full name (first and last name combined)"
+msgstr "Nom complet (Prénom et nom combinés)"
+
+#: lib/helpers.js:54
+msgid "Unique ID that identifies the recipient"
+msgstr "Identifiant unique du destinataire"
+
+#: lib/helpers.js:57
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr "Identifiant unique de la liste utilisée pour cette campagne"
+
+#: lib/helpers.js:60
+msgid "Unique ID that identifies current campaign"
+msgstr "Identifiant unique de cette campagne"
+
+#: lib/helpers.js:68 lib/helpers.js:80
+msgid "content from an RSS entry"
+msgstr "Contenu d'une entrée RSS"
+
+#: lib/helpers.js:71
+msgid "RSS entry title"
+msgstr "Titre de l'entrée RSS"
+
+#: lib/helpers.js:74
+msgid "RSS entry date"
+msgstr "Date de l'entrée RSS"
+
+#: lib/helpers.js:77
+msgid "RSS entry link"
+msgstr "Lien de l'entrée RSS"
+
+#: lib/helpers.js:83
+msgid "RSS entry summary"
+msgstr "Résumé de l'entrée RSS"
+
+#: lib/helpers.js:86
+msgid "RSS entry image URL"
+msgstr "URL de l'image de l'entrée RSS"
+
+#: lib/mailer.js:245
+msgid "Invalid mail transport"
+msgstr "Transport mail invalide"
+
+#: lib/models/campaigns.js:105 lib/models/campaigns.js:132
+#: lib/models/campaigns.js:205 lib/models/campaigns.js:328
+#: lib/models/campaigns.js:590 lib/models/campaigns.js:723
+msgid "Missing Campaign ID"
+msgstr "Identifiant de campagne manquant"
+
+#: lib/models/campaigns.js:241
+msgid "Emtpy or too large attahcment"
+msgstr "Pièce jointe vide ou trop grande"
+
+#: lib/models/campaigns.js:408 lib/models/campaigns.js:600
+msgid "Campaign Name must be set"
+msgstr "Le nom de la campagne est obligatoire"
+
+#: lib/models/campaigns.js:412
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr "L'URL du flux RSS doit être renseignée et valide"
+
+#: lib/models/campaigns.js:568
+msgid "Selected template not found"
+msgstr "Modèle inconnu"
+
+#: lib/models/campaigns.js:924
+msgid "Invalid or missing message ID"
+msgstr "Message ID invalide ou manquant"
+
+#: lib/models/campaigns.js:1065
+msgid "Unrecognized message status"
+msgstr "Message de statut non reconnu"
+
+#: lib/models/confirmations.js:27
+msgid "Could not store confirmation data"
+msgstr "Les confirmation n'a pas pu être enregistrée"
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr "Menu déroulant"
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Date (MM/JJ/YYY)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr "Valeur JSON pour un affichage personnalisé"
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr "Option"
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/forms.js:46 lib/models/lists.js:115 lib/models/lists.js:150
+#: lib/models/lists.js:265 lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:79 lib/models/subscriptions.js:390
+#: lib/models/subscriptions.js:566 lib/models/subscriptions.js:657
+#: lib/models/subscriptions.js:710 lib/models/subscriptions.js:773
+#: lib/models/subscriptions.js:816
+msgid "Missing List ID"
+msgstr "Identifiant de liste manquant"
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr "Les champs Option nécessitent le choix d'un groupe"
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr "Identifiant de champ manquant"
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr "Le nom du champ est obligatoire"
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr "Champ personnalisé introuvable"
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr "Type de colonne \"%s\" inconnu"
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr "Nom de colonne manquant"
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr "Identifiant de liste manquant"
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr "Identifiant de la liste inconnu"
+
+#: lib/models/forms.js:70 lib/models/forms.js:113 lib/models/forms.js:201
+#: lib/models/forms.js:291
+msgid "Missing Form ID"
+msgstr "Identifiant de fomulaire manquant"
+
+#: lib/models/forms.js:121 lib/models/forms.js:205
+msgid "Form Name must be set"
+msgstr "Le nom du formulaire est obligatoire"
+
+#: lib/models/forms.js:307
+msgid "Custom form not found"
+msgstr "Formulaire personnalisé introuvable"
+
+#: lib/models/links.js:337 routes/campaigns.js:534 routes/campaigns.js:582
+#: routes/campaigns.js:622 routes/campaigns.js:672 services/sender.js:305
+msgid "Campaign not found"
+msgstr "Campagne introuvable"
+
+#: lib/models/links.js:345 routes/lists.js:181 services/sender.js:312
+msgid "List not found"
+msgstr "Liste non trouvée"
+
+#: lib/models/links.js:353
+msgid "Subscription not found"
+msgstr "Abonnement non trouvé"
+
+#: lib/models/lists.js:167 lib/models/lists.js:211
+msgid "List Name must be set"
+msgstr "Le nom de la liste est obligatoire"
+
+#: lib/models/lists.js:294
+msgid "Missing List CID"
+msgstr "Identifiant CID de liste manquant"
+
+#: lib/models/report-templates.js:26 lib/models/report-templates.js:70
+#: lib/models/report-templates.js:142
+msgid "Missing report template ID"
+msgstr "Identifiant de modèle de rapport manquant"
+
+#: lib/models/report-templates.js:77
+msgid "Report template name must be set"
+msgstr "Le nom du modèle de rapport est obligatoire"
+
+#: lib/models/reports.js:40 lib/models/reports.js:110 lib/models/reports.js:188
+msgid "Missing report ID"
+msgstr "Identifiant de rapport manquant"
+
+#: lib/models/reports.js:116
+msgid "Report name must be set"
+msgstr "Nom de rapport obligatoire"
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr "Pays d'inscription"
+
+#: lib/models/segments.js:19 lib/models/triggers.js:14
+msgid "Sign up date"
+msgstr "Date d'inscription"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:18
+msgid "Latest open"
+msgstr "Dernière ouverture"
+
+#: lib/models/segments.js:27 lib/models/triggers.js:22
+msgid "Latest click"
+msgstr "Dernier clic"
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr "Identifiant de segment manquant"
+
+#: lib/models/segments.js:85 lib/models/segments.js:551
+#: lib/models/segments.js:661
+msgid "Segment not found"
+msgstr "Segment introuvable"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:409 lib/models/segments.js:410
+msgid "%s days after today"
+msgstr "%s jours à partir d'aujourd'hui"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:409 lib/models/segments.js:410
+msgid "%s days before today"
+msgstr "%s days avant aujourd'hui"
+
+#: lib/models/segments.js:148 lib/models/segments.js:411
+msgid "today"
+msgstr "aujourd'hui"
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr "Règle de segmentation invalide"
+
+#: lib/models/segments.js:289 lib/models/segments.js:455 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr "Segment inconnu"
+
+#: lib/models/segments.js:294 lib/models/segments.js:460 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr "Type de règle invalide"
+
+#: lib/models/segments.js:359 lib/models/segments.js:435
+#: lib/models/segments.js:526
+msgid "Missing Rule ID"
+msgstr "Identifiant de règle manquant"
+
+#: lib/models/segments.js:375
+msgid "Specified rule not found"
+msgstr "La ègle demandée est introuvable"
+
+#: lib/models/segments.js:386
+msgid "Specified segment not found"
+msgstr "Le segment spécifié est introuvable"
+
+#: lib/models/segments.js:446
+msgid "Selected rule not found"
+msgstr "Règle inconnue"
+
+#: lib/models/subscriptions.js:257 lib/models/subscriptions.js:287
+#: lib/models/subscriptions.js:394
+msgid "Missing Subscription ID"
+msgstr "Identifiant d'abonnement manquant"
+
+#: lib/models/subscriptions.js:315
+msgid "Missing Subscription email address"
+msgstr "Adresse mail d'abonnement manquante"
+
+#: lib/models/subscriptions.js:570 lib/models/subscriptions.js:820
+msgid "Missing subscription ID"
+msgstr "Identifiant d'abonnement manquant"
+
+#: lib/models/subscriptions.js:661 lib/models/subscriptions.js:714
+#: lib/models/subscriptions.js:750
+msgid "Missing Import ID"
+msgstr "Identifiant d'import manquant"
+
+#: lib/models/subscriptions.js:842
+msgid "Unknown subscription ID"
+msgstr "ID d'abonnement inconnu"
+
+#: lib/models/subscriptions.js:847 routes/subscription.js:639
+msgid "Nothing seems to be changed"
+msgstr "Rien ne semble avoir été modifié"
+
+#: lib/models/subscriptions.js:913 routes/subscription.js:473
+#: routes/subscription.js:545 routes/subscription.js:581
+#: routes/subscription.js:697 routes/subscription.js:772
+msgid "Subscription not found in this list"
+msgstr "Abonnement introuvable dans cette liste"
+
+#: lib/models/templates.js:26 lib/models/templates.js:102
+#: lib/models/templates.js:157
+msgid "Missing Template ID"
+msgstr "Identifiant de modèle manquant"
+
+#: lib/models/templates.js:55 lib/models/templates.js:106
+msgid "Template Name must be set"
+msgstr "Le nom du modèle est obligatoire"
+
+#: lib/models/templates.js:147
+msgid "Template does not exist"
+msgstr "Le modèle n'existe pas"
+
+#: lib/models/triggers.js:31
+msgid "Has Opened"
+msgstr "A ouvert"
+
+#: lib/models/triggers.js:34
+msgid "Has Clicked"
+msgstr "A cliqué"
+
+#: lib/models/triggers.js:37
+msgid "Not Opened"
+msgstr "Non ouvert"
+
+#: lib/models/triggers.js:40
+msgid "Not Clicked"
+msgstr "Non cliqué"
+
+#: lib/models/triggers.js:221 lib/models/triggers.js:258
+msgid "Missing or invalid list ID"
+msgstr "Identifiant de liste manquant ou invalide"
+
+#: lib/models/triggers.js:225 lib/models/triggers.js:310
+msgid "Days in the past are not allowed"
+msgstr "Jours dans le passé interdits"
+
+#: lib/models/triggers.js:229 lib/models/triggers.js:250
+#: lib/models/triggers.js:314 lib/models/triggers.js:335
+msgid "Missing or invalid trigger rule"
+msgstr "Règle de déclenchement manquante ou invalide"
+
+#: lib/models/triggers.js:236 lib/models/triggers.js:321
+msgid "Invalid subscription configuration"
+msgstr "Configuration d'abonnement invalide"
+
+#: lib/models/triggers.js:243 lib/models/triggers.js:328
+msgid "Invalid campaign configuration"
+msgstr "Configuration incorrecte de la campagne"
+
+#: lib/models/triggers.js:246 lib/models/triggers.js:331
+msgid "A campaing can not be a target for itself"
+msgstr "Une campagne ne peut pas être envoyée à elle-même"
+
+#: lib/models/triggers.js:279
+msgid "Could not store trigger row"
+msgstr "Le déclencheur n'a pas pu être enregistré"
+
+#: lib/models/triggers.js:296
+msgid "Missing or invalid Trigger ID"
+msgstr "Identifiant de déclencheur manquant ou invalide"
+
+#: lib/models/triggers.js:363
+msgid "Missing Trigger ID"
+msgstr "Identifiant de déclencheur manquant"
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr "L'utilisateur n'a pas pu être enregistré"
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr "L'adresse mail est obligatoire"
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr "Échec à la vérification des données utilisateur"
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+"Ne peut changer l'adresse mail, car un autre utilisateur avec la même "
+"adresse existe déjà"
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr "Mot de passe actuel incorrect"
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr "Nouveau mot de passe non enregistré"
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr "Les mots de passe ne correspondent pas"
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr "Identifiant utilisateur non fourni"
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr "Nom d'utilisateur obligatoire"
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr "Demande de changement de mot de passe"
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr "Token de réinitialisation ou nom d'utilisateur manquant"
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Nouveau mot de passe invalide"
+
+#: lib/passport.js:50
+msgid "%s logged out"
+msgstr "%s déconnecté"
+
+#: lib/passport.js:65
+msgid "Failed to authenticate user"
+msgstr "Échec à l'authentification de l'utilisateur"
+
+#: lib/passport.js:81
+msgid "Logged in as %s"
+msgstr "Connecté comme %s"
+
+#: lib/passport.js:191
+msgid "Incorrect username or password"
+msgstr "Nom d'utilisateur ou mot de passe incorrect"
+
+#: lib/subscription-mail-helpers.js:28
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Abonnement confirmé"
+
+#: lib/subscription-mail-helpers.js:39
+msgid "%s: Email Address Already Registered"
+msgstr "%s: Adresse mail déjà enregistrée"
+
+#: lib/subscription-mail-helpers.js:49
+msgid "%s: Please Confirm Email Change in Subscription"
+msgstr "%s: Merci de confirmer le changement de mail de l'abonnement"
+
+#: lib/subscription-mail-helpers.js:59
+msgid "%s: Please Confirm Subscription"
+msgstr "%: Merci de confirmer l'abonnement"
+
+#: lib/subscription-mail-helpers.js:69
+msgid "%s: Please Confirm Unsubscription"
+msgstr "%: Merci de confirmer le désabonnement"
+
+#: lib/subscription-mail-helpers.js:76
+msgid "%s: Unsubscription Confirmed"
+msgstr "%s: Désabonnement confirmé"
+
+#: lib/tools.js:154
+msgid "Blocked email address \"%s\""
+msgstr "Adresse mail bloquée \"%s\""
+
+#: lib/tools.js:163
+msgid "Invalid email address \"%s\"."
+msgstr "Adresse mail \"%s\" invalide."
+
+#: lib/tools.js:166
+msgid "MX record not found for domain"
+msgstr "Enregistrement MX introuvable pour le domaine"
+
+#: lib/tools.js:169
+msgid "Address domain not found"
+msgstr "Le nom de domaine de l'adresse est inconnu"
+
+#: lib/tools.js:172
+msgid "Address domain name is required"
+msgstr "Le nom de domaine de l'adresse est requis"
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:230
+msgid "Not Found"
+msgstr "Non trouvé"
+
+#: routes/archive.js:121 services/sender.js:454
+msgid "Received status code %s from %s"
+msgstr "Le code de statut %s a été reçu de %s"
+
+#: routes/archive.js:153 routes/campaigns.js:895
+msgid "Attachment not found"
+msgstr "Pièce jointe introuvable"
+
+#: routes/blacklist.js:13 routes/campaigns.js:26 routes/editorapi.js:32
+#: routes/fields.js:13 routes/forms.js:16 routes/grapejs.js:15
+#: routes/lists.js:50 routes/mosaico.js:14 routes/report-templates.js:20
+#: routes/reports.js:22 routes/segments.js:13 routes/settings.js:23
+#: routes/templates.js:18 routes/triggers.js:19 routes/users.js:75
+#: routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Vous devez être connecté pour accéder à cet espace"
+
+#: routes/campaigns.js:118
+msgid "Could not create campaign"
+msgstr "La campagne n'a pas pu être créée"
+
+#: routes/campaigns.js:121
+msgid "Campaign “%s” created"
+msgstr "Campagne \"%s\" créée"
+
+#: routes/campaigns.js:210
+msgid "Campaign settings updated"
+msgstr "Les paramètres de la campagne ont été mis à jour"
+
+#: routes/campaigns.js:212
+msgid "Campaign settings not updated"
+msgstr "Les paramètres de la campagne n'ont pas pu être mis à jour"
+
+#: routes/campaigns.js:228 routes/campaigns.js:745
+msgid "Campaign deleted"
+msgstr "Campagne supprimée"
+
+#: routes/campaigns.js:230 routes/campaigns.js:747
+msgid "Could not delete specified campaign"
+msgstr "La campagne n'a pas pu être supprimée"
+
+#: routes/campaigns.js:249
+msgid "Idling"
+msgstr "Inactif"
+
+#: routes/campaigns.js:252
+msgid "Scheduled"
+msgstr "Programmé"
+
+#: routes/campaigns.js:258
+msgid "Paused"
+msgstr "En pause"
+
+#: routes/campaigns.js:260
+msgid "Inactive"
+msgstr "Inactif"
+
+#: routes/campaigns.js:262
+msgid "Active"
+msgstr "Actif"
+
+#: routes/campaigns.js:264
+msgid "Other"
+msgstr "Autre"
+
+#: routes/campaigns.js:422
+msgid "Unknown status selector"
+msgstr "Sélecteur de statut inconnu"
+
+#: routes/campaigns.js:763
+msgid "Scheduled sending"
+msgstr "Envoi programmé"
+
+#: routes/campaigns.js:765
+msgid "Could not schedule sending"
+msgstr "L'envoi n'a pas pu être programmé"
+
+#: routes/campaigns.js:777
+msgid "Sending resumed"
+msgstr "Envoi relancé"
+
+#: routes/campaigns.js:779
+msgid "Could not resume sending"
+msgstr "L'envoi n'a pas pu être relancé"
+
+#: routes/campaigns.js:791
+msgid "Sending reset"
+msgstr "Envoi réinitialisé"
+
+#: routes/campaigns.js:793
+msgid "Could not reset sending"
+msgstr "L'envoi n'a pas pu être réinitialisé"
+
+#: routes/campaigns.js:805 routes/campaigns.js:833
+msgid "Sending paused"
+msgstr "Envoi mis en pause"
+
+#: routes/campaigns.js:807 routes/campaigns.js:835
+msgid "Could not pause sending"
+msgstr "L'envoi n'a pas pu être interrompu"
+
+#: routes/campaigns.js:819
+msgid "Sending activated"
+msgstr "Envoi activé"
+
+#: routes/campaigns.js:821
+msgid "Could not activate sending"
+msgstr "Impossible d'activer l'envoi"
+
+#: routes/campaigns.js:856
+msgid "Attachment uploaded"
+msgstr "Pièce jointe téléchargée"
+
+#: routes/campaigns.js:858
+msgid "Could not store attachment"
+msgstr "La pièce jointe n'a pas pu être enregistrée"
+
+#: routes/campaigns.js:875
+msgid "Attachment deleted"
+msgstr "Pièce jointe supprimée"
+
+#: routes/campaigns.js:877
+msgid "Could not delete attachment"
+msgstr "La pièce jointe n'a pas pu être supprimée"
+
+#: routes/editorapi.js:38
+msgid "Invalid editor name"
+msgstr "Nom d'éditeur invalide"
+
+#: routes/editorapi.js:146
+msgid "Method not supported"
+msgstr "Méthode non supportée"
+
+#: routes/editorapi.js:381
+msgid "Invalid resource type or ID"
+msgstr "Type ou ID de ressource invalide"
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/forms.js:31 routes/forms.js:63 routes/forms.js:94
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr "Identifiant de liste inconnu"
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr "Le champ personnalisé n'a pas pu être créé"
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr "Champ inconnu"
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr "Les paramètres du champ ont été enregistrés"
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr "Les paramètres du champ n'ont pas pu être mis à jour"
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr "Champ personnalisé supprimé"
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr "Le champ n'a pas pu être supprimé"
+
+#: routes/forms.js:78
+msgid "Could not create custom form"
+msgstr "Le formulaire n'a pas pu être créé"
+
+#: routes/forms.js:105
+msgid "Selected form not found"
+msgstr "Formulaire inconnu"
+
+#: routes/forms.js:136
+msgid "The plaintext version for this email"
+msgstr "Version texte de ce mail"
+
+#: routes/forms.js:137
+msgid "Custom forms use MJML for formatting"
+msgstr "Les formulaires personnalisés utilisent le formatage MJML"
+
+#: routes/forms.js:138
+msgid "See the MJML documentation here"
+msgstr "Voir ici la documentation MJML"
+
+#: routes/forms.js:146
+msgid "Layout"
+msgstr "Format"
+
+#: routes/forms.js:152
+msgid "Form Input Style"
+msgstr "Style des zones Input de formulaire"
+
+#: routes/forms.js:154
+msgid ""
+"This CSS stylesheet defines the appearance of form input elements and alerts"
+msgstr ""
+"Cette feuille de style CSS définit l'apparence des zones de saisie et des "
+"alertes du formulaire"
+
+#: routes/forms.js:160
+msgid "Web - Subscribe"
+msgstr "Web - Abonnement"
+
+#: routes/forms.js:165
+msgid "Web - Confirm Subscription Notice"
+msgstr "Web - Information de confirmation d'abonnement"
+
+#: routes/forms.js:170
+msgid "Mail - Confirm Subscription (MJML)"
+msgstr "Mail - Confirmation d'abonnement (MJML)"
+
+#: routes/forms.js:175
+msgid "Mail - Confirm Subscription (Text)"
+msgstr "Mail - Confirmation d'abonnement (Texte)"
+
+#: routes/forms.js:180
+msgid "Mail - Already Subscribed (MJML)"
+msgstr "Mail - Déjà abonné (MJML)"
+
+#: routes/forms.js:185
+msgid "Mail - Already Subscribed (Text)"
+msgstr "Mail - Déjà abonné (Texte)"
+
+#: routes/forms.js:190
+msgid "Web - Subscribed Notice"
+msgstr "Web - Information d'abonné"
+
+#: routes/forms.js:195
+msgid "Mail - Subscription Confirmed (MJML)"
+msgstr "Mail - Abonnement confirmé (MJML)"
+
+#: routes/forms.js:200
+msgid "Mail - Subscription Confirmed (Text)"
+msgstr "Mail - Abonnement confirmé (Texte)"
+
+#: routes/forms.js:208
+msgid "Web - Manage Preferences"
+msgstr "Web - Gestion des préférences"
+
+#: routes/forms.js:213
+msgid "Web - Manage Address"
+msgstr "Web - Gestion de l'adresse"
+
+#: routes/forms.js:218
+msgid "Web - Updated Notice"
+msgstr "Web - Information enregistrée"
+
+#: routes/forms.js:226
+msgid "Web - Unsubscribe"
+msgstr "Web - Désabonnement"
+
+#: routes/forms.js:231
+msgid "Web - Confirm Unsubscription Notice"
+msgstr "Web - Information de confirmation de désabonnement"
+
+#: routes/forms.js:236
+msgid "Mail - Confirm Unsubscription (MJML)"
+msgstr "Mail - Confirmation de désabonnement (MJML)"
+
+#: routes/forms.js:241
+msgid "Mail - Confirm Unsubscription (Text)"
+msgstr "Mail - Confirmation de désabonnement (Texte)"
+
+#: routes/forms.js:246
+msgid "Mail - Confirm Address Change (MJML)"
+msgstr "Mail - Confirmation de changement d'adresse (MJML)"
+
+#: routes/forms.js:251
+msgid "Mail - Confirm Address Change (Text)"
+msgstr "Mail - Confirmation de changement d'adresse (Texte)"
+
+#: routes/forms.js:256
+msgid "Web - Unsubscribed Notice"
+msgstr "Web - Information de confirmation de désabonnement"
+
+#: routes/forms.js:261
+msgid "Mail - Unsubscription Confirmed (MJML)"
+msgstr "Mail - Désbonnement confirmé (MJML)"
+
+#: routes/forms.js:266
+msgid "Mail - Unsubscription Confirmed (Text)"
+msgstr "Mail - Désbonnement confirmé (Texte)"
+
+#: routes/forms.js:271
+msgid "Web - Manual Unsubscribe Notice"
+msgstr "Web - Information de désabonnement manuel"
+
+#: routes/forms.js:309
+msgid "Form settings updated"
+msgstr "Les paramètres du formulaire ont été enregistrés"
+
+#: routes/forms.js:311
+msgid "Form settings not updated"
+msgstr "Les paramètres du formulaire n'ont pas pu être modifiés"
+
+#: routes/forms.js:327
+msgid "Custom form deleted"
+msgstr "Formulaire personnalisé supprimé"
+
+#: routes/forms.js:329
+msgid "Could not delete specified form"
+msgstr "Le formulaire n'a pas pu être supprimé"
+
+#: routes/index.js:11
+msgid "Self Hosted Newsletter App"
+msgstr "Solution de Newsletter auto-hébergée"
+
+#: routes/links.js:39
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr "Oups, nous n'avons pas trouvé le lien sur lequel vous avez cliqué"
+
+#: routes/lists.js:82
+msgid "Could not create list"
+msgstr "La liste n'a pas pu être créée"
+
+#: routes/lists.js:85
+msgid "List created"
+msgstr "Liste créée"
+
+#: routes/lists.js:93 routes/lists.js:271 routes/lists.js:336
+#: routes/lists.js:375 routes/lists.js:444 routes/lists.js:469
+#: routes/lists.js:514 routes/lists.js:536 routes/lists.js:565
+#: routes/lists.js:657 routes/lists.js:714 routes/lists.js:741
+msgid "Could not find list with specified ID"
+msgstr "Ne peut trouver la liste avec cet identifiant"
+
+#: routes/lists.js:122
+msgid "List settings updated"
+msgstr "Les paramètres de la liste ont été mis à jour"
+
+#: routes/lists.js:124
+msgid "List settings not updated"
+msgstr "Les paramètres de la liste n'ont pu être enregistrés"
+
+#: routes/lists.js:142
+msgid "List deleted"
+msgstr "Liste supprimée"
+
+#: routes/lists.js:144
+msgid "Could not delete specified list"
+msgstr "La liste n'a pas pu être supprimée"
+
+#: routes/lists.js:206
+msgid "Unknown"
+msgstr "Inconnu"
+
+#: routes/lists.js:206
+msgid "Complained"
+msgstr "Plainte"
+
+#: routes/lists.js:237
+msgid "Invalid key"
+msgstr "Clé invalide"
+
+#: routes/lists.js:239
+msgid "Expired key"
+msgstr "Clé expirée"
+
+#: routes/lists.js:241
+msgid "Revoked key"
+msgstr "Clé révoquée"
+
+#: routes/lists.js:288
+msgid "Force Subscribe"
+msgstr "Forcer l'abonnement"
+
+#: routes/lists.js:291
+msgid "Initializing"
+msgstr "Initialisation"
+
+#: routes/lists.js:294
+msgid "Initialized"
+msgstr "Initialisé"
+
+#: routes/lists.js:297
+msgid "Importing"
+msgstr "Import en cours"
+
+#: routes/lists.js:303
+msgid "Errored"
+msgstr "En erreur"
+
+#: routes/lists.js:381 routes/lists.js:450 routes/lists.js:475
+msgid "Could not find subscriber with specified ID"
+msgstr "Ne peut trouver d'abonné avec cet identifiant"
+
+#: routes/lists.js:427
+msgid "Could not add subscription"
+msgstr "L'abonnement n'a pas pu être ajouté"
+
+#: routes/lists.js:432
+msgid "%s was successfully added to your list"
+msgstr "%s a été ajouté à votre liste"
+
+#: routes/lists.js:434
+msgid "%s was not added to your list"
+msgstr "%s n'a pas été ajouté à votre liste"
+
+#: routes/lists.js:456
+msgid "Could not unsubscribe user"
+msgstr "L'utilisateur n'a pas pu être désabonné"
+
+#: routes/lists.js:459
+msgid "%s was successfully unsubscribed from your list"
+msgstr "%s a été désabonné de votre liste"
+
+#: routes/lists.js:479
+msgid "%s was successfully removed from your list"
+msgstr "%s a été retiré de votre liste"
+
+#: routes/lists.js:491
+msgid "Another subscriber with email address %s already exists"
+msgstr "Un autre abonné avec l'adresse mail %s existe déjà"
+
+#: routes/lists.js:498
+msgid "Subscription settings updated"
+msgstr "Les paramètres de l'abonnement ont été enregitrés"
+
+#: routes/lists.js:500
+msgid "Subscription settings not updated"
+msgstr "Les paramètres de l'abonnement n'ont pas pu être mis à jour"
+
+#: routes/lists.js:542 routes/lists.js:663 routes/lists.js:699
+#: routes/lists.js:727 routes/lists.js:747
+msgid "Could not find import data with specified ID"
+msgstr "Ne peut trouver l'import de données avec cet identifiant"
+
+#: routes/lists.js:573
+msgid "Could not process CSV"
+msgstr "Le CSV n'a pas pu être traité"
+
+#: routes/lists.js:589
+msgid "Could not create importer"
+msgstr "L'import n'a pas pu être créé"
+
+#: routes/lists.js:643
+msgid "Empty file"
+msgstr "Fichier vide"
+
+#: routes/lists.js:646
+msgid "Too few rows"
+msgstr "Trop peu de lignes"
+
+#: routes/lists.js:703
+msgid "Import started"
+msgstr "Import démarré"
+
+#: routes/lists.js:731
+msgid "Import restarted"
+msgstr "Import relancé"
+
+#: routes/lists.js:797
+msgid "One-step (i.e. no email with confirmation link)"
+msgstr "En une étape (pas d'envoi de mail avec lien de confirmation)"
+
+#: routes/lists.js:803
+msgid ""
+"One-step with unsubscription form (i.e. no email with confirmation link)"
+msgstr ""
+"En une étape avec formulaire de désabonnement (pas d'envoi de mail avec lien "
+"de confirmation)"
+
+#: routes/lists.js:809
+msgid "Two-step (i.e. an email with confirmation link will be sent)"
+msgstr "En deux étapes (envoi d'un mail avec avec lien de confirmation)"
+
+#: routes/lists.js:815
+msgid ""
+"Two-step with unsubscription form (i.e. an email with confirmation link will "
+"be sent)"
+msgstr ""
+"En deux étapes avec formulaire de désabonnement (envoi d'un mail avec avec "
+"lien de confirmation)"
+
+#: routes/lists.js:821
+msgid ""
+"Manual (i.e. unsubscription has to be performed by the list administrator)"
+msgstr ""
+"Manuel (le désabonnement doit être fait par l'administrateur de la liste)"
+
+#: routes/report-templates.js:246
+msgid "Could not create report template"
+msgstr "Le modèle de rapport n'a pas pu être créé"
+
+#: routes/report-templates.js:249
+msgid "Report template “%s” created"
+msgstr "Modèle de rapport \"%s\" créé"
+
+#: routes/report-templates.js:257
+msgid "Could not find report template with specified ID"
+msgstr "Ne peut trouver le modèle de rapport avec cet identifiant"
+
+#: routes/report-templates.js:280
+msgid "Report template updated"
+msgstr "Modèle de rapport enregistré"
+
+#: routes/report-templates.js:282
+msgid "Report template not updated"
+msgstr "Le modèle de rapport n'a pas pu être enregistré"
+
+#: routes/report-templates.js:298
+msgid "Report template deleted"
+msgstr "Modèle de rapport supprimé"
+
+#: routes/report-templates.js:300
+msgid "Could not delete specified report template"
+msgstr "Le modèle de rapport n'a pas pu être supprimé"
+
+#: routes/reports.js:124 routes/reports.js:130
+msgid "Could not create report"
+msgstr "Le rapport n'a pas pu être créé"
+
+#: routes/reports.js:135
+msgid "Report “%s” created"
+msgstr "Rapport \"%s\" créé"
+
+#: routes/reports.js:146 routes/reports.js:224 routes/reports.js:239
+#: routes/reports.js:265 routes/reports.js:275
+msgid "Could not find report with specified ID"
+msgstr "Ne peut trouver le rapport avec cet identifiant"
+
+#: routes/reports.js:188 routes/reports.js:194
+msgid "Could not update report"
+msgstr "Le rapport n'a pas pu être mis à jour"
+
+#: routes/reports.js:197
+msgid "Report updated"
+msgstr "Rapport enregistré"
+
+#: routes/reports.js:199
+msgid "Report not updated"
+msgstr "Le rapport n'a pas pu être enregistré"
+
+#: routes/reports.js:212
+msgid "Report deleted"
+msgstr "Rapport supprimé"
+
+#: routes/reports.js:214
+msgid "Could not delete specified report"
+msgstr "Le rapport n'a pas pu être supprimé"
+
+#: routes/reports.js:230
+msgid "Could not find report template"
+msgstr "Le modèle de rapport associé n'a pas pu être trouvé"
+
+#: routes/reports.js:260
+msgid "Unknown type of template"
+msgstr "Type de modèle inconnu"
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr "Le segment n'a pas pu être créé"
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr "Segment créé"
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr "Identifiant de segment inconnu"
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr "Configuration du segment enregistrée"
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr "Configuration du segment non enregistrée"
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr "Segment supprimé"
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr "Le segment n'a pas pu être supprimé"
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr "La règle n'a pas pu être créée"
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr "Règle créée"
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr "Paramètres de la règle enregistrés"
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr "Paramètres de la règle non mis à jour"
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr "Règle supprimée"
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr "La règle n'a pas pu être supprimée"
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "Utiliser TLS"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "Utilisé habituellement pour le port 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "Utiliser STARTTLS"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "Utilisé habituellement pour les ports 587 et 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "Ne pas utiliser le chiffrement"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Configuration mise à jour"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Type de transport mail invalide"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Clé d'accès invalide"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "Credentials AWS invalides"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Connexion refusée, vérifiez l'adresse du serveur et le port."
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"N'a pas reçu le message de présentation du serveur. Cela peut survenir lors "
+"d'une connexion à port TLS sans utiliser TLS"
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "N'a pas reçu le message de présentation du serveur."
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Connexion expirée. Vérifiez vos règles de firewall, le port de destination "
+"est certainement bloqué."
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr ""
+"La tentative d'authentification est rejetée. Le serveur impose l'utilisation "
+"de STARTTLS."
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr ""
+"Échec de l'authentification, vérifiez le nom d'utilisateur et le mot de "
+"passe."
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "Echec à la vérification du serveur mail."
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Le serveur a répondu : \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr "Paramètres mailer vérifiés, prêt à envoyer du mail !"
+
+#: routes/subscription.js:33
+msgid "Not allowed by CORS"
+msgstr "Interdit par CORS"
+
+#: routes/subscription.js:61 routes/subscription.js:176
+#: routes/subscription.js:286 routes/subscription.js:382
+#: routes/subscription.js:459 routes/subscription.js:535
+#: routes/subscription.js:566 routes/subscription.js:626
+#: routes/subscription.js:682 routes/subscription.js:760
+#: routes/subscription.js:897
+msgid "Selected list not found"
+msgstr "Liste inconnue"
+
+#: routes/subscription.js:93
+msgid "Could not save subscription"
+msgstr "L'abonnement n'a pas pu être enregistré"
+
+#: routes/subscription.js:118
+msgid "Subscriber info corrupted or missing"
+msgstr "Information sur l'abonné manquante ou corrompue"
+
+#: routes/subscription.js:136
+msgid "Email address changed"
+msgstr "Adresse mail changée"
+
+#: routes/subscription.js:179 routes/subscription.js:385
+msgid "The list does not allow public subscriptions."
+msgstr "La liste ne permet pas les abonnements libres."
+
+#: routes/subscription.js:355 routes/subscription.js:357
+msgid "Email address not set"
+msgstr "L'adresse mail n'est pas précisée"
+
+#: routes/subscription.js:653
+msgid ""
+"An email with further instructions has been sent to the provided address"
+msgstr "Un mail avec des instructions a été envoyé à l'adresse fournie"
+
+#: routes/subscription.js:861 routes/subscription.js:877
+msgid "Public key is not set"
+msgstr "La clé publique n'est pas renseignée"
+
+#: routes/templates.js:84
+msgid "Could not create template"
+msgstr "Le modèle n'a pas pu être créé"
+
+#: routes/templates.js:87
+msgid "Template created"
+msgstr "Modèle créé"
+
+#: routes/templates.js:126
+msgid "Template settings updated"
+msgstr "Paramètres du modèle enregistrés"
+
+#: routes/templates.js:128
+msgid "Template settings not updated"
+msgstr "Les paramètres du modèle n'ont pas pu être mis à jour"
+
+#: routes/templates.js:144
+msgid "Template duplicated"
+msgstr "Modèle dupliqué"
+
+#: routes/templates.js:146
+msgid "Could not duplicate specified template"
+msgstr "Le modèle n'a pas pu être dupliqué"
+
+#: routes/templates.js:157
+msgid "Template deleted"
+msgstr "Modèle supprimé"
+
+#: routes/templates.js:159
+msgid "Could not delete specified template"
+msgstr "Le modèle n'a pas pu être supprimé"
+
+#: routes/triggers.js:64 routes/triggers.js:88 routes/triggers.js:180
+msgid "Could not find selected list"
+msgstr "La liste sélectionnée n'a pas pu être trouvée"
+
+#: routes/triggers.js:94 routes/triggers.js:100 routes/triggers.js:186
+msgid "Error while finding selected segment"
+msgstr "Erreur à la recherche du segment sélectionné"
+
+#: routes/triggers.js:157
+msgid "Could not create trigger"
+msgstr "Le déclencheur n'a pas pu être créé"
+
+#: routes/triggers.js:164
+msgid "Trigger “%s” created"
+msgstr "Déclencheur \"%s\" créé"
+
+#: routes/triggers.js:197
+msgid "Error while finding selected segment subscribers"
+msgstr "Erreur lors de la recherche des abonnés du segment"
+
+#: routes/triggers.js:262
+msgid "Trigger settings updated"
+msgstr "Paramètres du déclencheur enregistrés"
+
+#: routes/triggers.js:264
+msgid "Trigger settings not updated"
+msgstr "Les paramètres du déclencheur n'ont pas pu être enregistrés"
+
+#: routes/triggers.js:276
+msgid "Trigger deleted"
+msgstr "Déclencheur supprimé"
+
+#: routes/triggers.js:278
+msgid "Could not delete specified trigger"
+msgstr "Le déclencheur n'a pas pu être supprimé"
+
+#: routes/triggers.js:290
+msgid "Could not find trigger with specified ID"
+msgstr "Ne peut trouver de déclencheur avec cet identifiant"
+
+#: routes/triggers.js:303
+msgid "Trigger not found"
+msgstr "Déclencheur inconnu"
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+"Un mail avec les instructions de réinitialisation du mot de passe à été "
+"envoyée à votre adresse, si elle est enregistrée dans notre système."
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr "Token de réinitialisation inconnu ou expiré"
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "Votre mot de passe a bien été changé"
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr "Données utilisateurs non trouvées"
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr "Le jeton d'accès a été mis à jour"
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr "Le jeton d'accès n'a pas été mis à jour"
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr "Les informations sur le compte ont été mises à jour"
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr "Les informations sur le compte n'ont pas été mises à jour"
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr "Erreur du flux : %s"
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr "%s nouveau(x) message(s) ont été trouvés dans le flux RSS"
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr "Aucun nouvel élément dans le flux RSS"
+
+#: services/feedcheck.js:146
+msgid "RSS entry %s"
+msgstr "Entrée RSS %s"
+
+#: services/importer.js:249
+msgid "Could not access import file"
+msgstr "Ne peut ouvrir le fichier d'import"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr "Type de déclencheur %s inconnu"
diff --git a/languages/hu_HU.mo b/languages/hu_HU.mo
new file mode 100644
index 00000000..524af8aa
Binary files /dev/null and b/languages/hu_HU.mo differ
diff --git a/languages/hu_HU.po b/languages/hu_HU.po
new file mode 100644
index 00000000..8d42cfe9
--- /dev/null
+++ b/languages/hu_HU.po
@@ -0,0 +1,4521 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Language-Team: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2018-09-10 16:02+0200\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: 2018-07-29 01:47+0200\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Last-Translator: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Language: hu_HU\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+msgid "Self hosted email newsletter app"
+msgstr "Saját üzemeltetésű hírlevél-program"
+
+#: views/blacklist.hbs:1 views/campaigns/blacklisted.hbs:1
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/forms/create.hbs:1
+#: views/lists/forms/edit.hbs:1 views/lists/forms/forms.hbs:1
+#: views/lists/lists.hbs:1 views/lists/segments/create.hbs:1
+#: views/lists/segments/edit.hbs:1 views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/report-templates/create.hbs:1 views/report-templates/edit.hbs:1
+#: views/report-templates/report-templates.hbs:1
+#: views/reports/create-select-template.hbs:1 views/reports/create.hbs:1
+#: views/reports/edit.hbs:1 views/reports/output.hbs:1
+#: views/reports/reports.hbs:1 views/reports/view.hbs:1 views/settings.hbs:1
+#: views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Nyitólap"
+
+#: views/blacklist.hbs:2 views/blacklist.hbs:3 views/layout.hbs:7
+#: views/lists/subscription/edit.hbs:15
+msgid "Blacklist"
+msgstr "Feketelista"
+
+#: views/blacklist.hbs:4 views/users/api.hbs:76
+msgid "Add email to blacklist"
+msgstr "Email feketelistázása"
+
+#: views/blacklist.hbs:5
+msgid "Add"
+msgstr "Hozzáadás"
+
+#: views/blacklist.hbs:6
+msgid "Email"
+msgstr "Email"
+
+#: views/campaigns/blacklisted.hbs:2 views/campaigns/bounced.hbs:2
+#: views/campaigns/campaigns.hbs:2 views/campaigns/campaigns.hbs:7
+#: views/campaigns/clicked.hbs:2 views/campaigns/complained.hbs:2
+#: views/campaigns/create-rss.hbs:2 views/campaigns/create-triggered.hbs:2
+#: views/campaigns/create.hbs:2 views/campaigns/delivered.hbs:2
+#: views/campaigns/edit-rss.hbs:2 views/campaigns/edit-triggered.hbs:2
+#: views/campaigns/edit.hbs:2 views/campaigns/opened.hbs:2
+#: views/campaigns/unsubscribed.hbs:2 views/campaigns/upload-attachment.hbs:2
+#: views/campaigns/view.hbs:2 lib/tools.js:133 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Kampányok"
+
+#: views/campaigns/blacklisted.hbs:3 views/campaigns/blacklisted.hbs:4
+msgid "Blacklisted info"
+msgstr "Feketelista info"
+
+#: views/campaigns/blacklisted.hbs:5 views/campaigns/bounced.hbs:5
+#: views/campaigns/clicked.hbs:5 views/campaigns/complained.hbs:5
+#: views/campaigns/delivered.hbs:5 views/campaigns/edit-rss.hbs:5
+#: views/campaigns/edit-triggered.hbs:5 views/campaigns/edit.hbs:5
+#: views/campaigns/opened.hbs:5 views/campaigns/unsubscribed.hbs:5
+#: views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Kampány megtekintése"
+
+#: views/campaigns/blacklisted.hbs:6
+msgid "Subscribers who blacklisted by global blacklist:"
+msgstr "Feliratkozók, akik szerepelnek a globális feketelistán"
+
+#: views/campaigns/blacklisted.hbs:7 views/campaigns/bounced.hbs:7
+#: views/campaigns/clicked.hbs:15 views/campaigns/complained.hbs:7
+#: views/campaigns/delivered.hbs:7 views/campaigns/opened.hbs:9
+#: views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:8 views/lists/view.hbs:19
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Cím"
+
+#: views/campaigns/blacklisted.hbs:8 views/campaigns/bounced.hbs:8
+#: views/campaigns/clicked.hbs:16 views/campaigns/complained.hbs:8
+#: views/campaigns/delivered.hbs:8 views/campaigns/opened.hbs:10
+#: views/campaigns/unsubscribed.hbs:8 views/lists/subscription/add.hbs:6
+#: views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:20
+#: views/subscription/partials/subscription-custom-fields.hbs:3
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Keresztnév"
+
+#: views/campaigns/blacklisted.hbs:9 views/campaigns/bounced.hbs:9
+#: views/campaigns/clicked.hbs:17 views/campaigns/complained.hbs:9
+#: views/campaigns/delivered.hbs:9 views/campaigns/opened.hbs:11
+#: views/campaigns/unsubscribed.hbs:9 views/lists/subscription/add.hbs:7
+#: views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:21
+#: views/subscription/partials/subscription-custom-fields.hbs:4
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Vezetéknév"
+
+#: views/campaigns/blacklisted.hbs:10
+msgid "Reason"
+msgstr "Ok"
+
+#: views/campaigns/blacklisted.hbs:11
+msgid "Time"
+msgstr "Időpont"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Visszapattanás info"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Feliratkozók, akik visszapattanás miatt le lettek íratva:"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "SMTP válasz"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Visszapattanás ideje"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:26
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:28
+msgid "Create Campaign"
+msgstr "Kampány létrehozása"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Sima kampány"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "RSS kampány"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr ""
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/forms/forms.hbs:6
+#: views/lists/lists.hbs:5 views/lists/segments/segments.hbs:6
+#: views/report-templates/partials/report-template-fields.hbs:1
+#: views/report-templates/report-templates.hbs:10
+#: views/reports/partials/report-fields.hbs:1
+#: views/reports/partials/report-fields.hbs:5
+#: views/reports/partials/report-fields.hbs:9 views/reports/reports.hbs:6
+#: views/templates/templates.hbs:5 views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Név"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:74
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10
+#: views/lists/forms/edit.hbs:9 views/lists/forms/forms.hbs:7
+#: views/lists/lists.hbs:8 views/mosaico/editor.hbs:3
+#: views/partials/merge-tag-reference.hbs:4
+#: views/report-templates/partials/report-template-fields.hbs:3
+#: views/report-templates/report-templates.hbs:11
+#: views/reports/partials/report-fields.hbs:3
+#: views/reports/partials/report-fields.hbs:6 views/reports/reports.hbs:8
+#: views/templates/create.hbs:9 views/templates/edit.hbs:8
+#: views/templates/templates.hbs:6 views/triggers/create.hbs:7
+#: views/triggers/edit.hbs:8 views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Leírás"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:75
+#: views/lists/view.hbs:22 views/lists/view.hbs:30
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Státusz"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:76
+#: views/lists/view.hbs:23 views/lists/view.hbs:24
+#: views/report-templates/report-templates.hbs:12
+#: views/reports/partials/report-fields.hbs:7 views/reports/reports.hbs:9
+msgid "Created"
+msgstr "Létrehozva"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Link információ"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:63
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:64
+msgid "Clicks"
+msgstr "Kattintások"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:65
+msgid "% of clicks"
+msgstr "%-a a kattintásoknak"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:66
+msgid "% of messages"
+msgstr "%-a az üzeneteknek"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:69
+msgid "Aggregated clicks"
+msgstr "Összesített kattintások"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Feliratkozók, akik rákattintottak egy linkre:"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Feliratkozók, akik rákattintottak erre a linkre:"
+
+#: views/campaigns/clicked.hbs:13 views/campaigns/opened.hbs:7
+msgid "Stats by country"
+msgstr "Országok szerinti statisztika"
+
+#: views/campaigns/clicked.hbs:14 views/campaigns/opened.hbs:8
+msgid "Stats by device type"
+msgstr "Eszköz szerinti statisztika"
+
+#: views/campaigns/clicked.hbs:18
+msgid "First click time"
+msgstr ""
+
+#: views/campaigns/clicked.hbs:19
+msgid "Click count"
+msgstr "Kattintások száma"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Reklamálások info"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Felhasználók, akik reklamáltak, ezért le lettek íratva"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Reklamálás ideje"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:21
+msgid "Create RSS Campaign"
+msgstr "RSS kampány létrehozása"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Kampány neve"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/report-templates/partials/report-template-fields.hbs:4
+#: views/reports/partials/report-fields.hbs:4 views/templates/create.hbs:11
+#: views/templates/edit.hbs:10 views/triggers/create.hbs:9
+#: views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "HTML megengedett"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "Lista"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/reports/partials/report-select-template.hbs:2
+#: views/subscription/partials/subscription-custom-fields.hbs:9
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Kiválasztás"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "feliratkozók"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "RSS URL-je"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "Email feladó neve"
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit-triggered.hbs:17 views/campaigns/edit.hbs:18
+#: views/settings.hbs:23
+msgid "This is the name your emails will come from"
+msgstr "Ez az a név, ami alatt az emailek meg fognak jelenni"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "Email feladó címe"
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:21
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:25
+msgid "This is the address people will send replies to"
+msgstr "Ez a cím, amiről érkezni látják majd a leveleket"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:26 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:25
+msgid "Disable opened tracking"
+msgstr "Megnyitások követésének letiltása"
+
+#: views/campaigns/create-rss.hbs:20 views/campaigns/create-triggered.hbs:25
+#: views/campaigns/create.hbs:27 views/campaigns/edit-rss.hbs:23
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26
+msgid "Disable clicked tracking"
+msgstr "Kattintások követésének letiltása"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr ""
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/reports/reports.hbs:7 views/templates/create.hbs:13
+msgid "Template"
+msgstr "Sablon"
+
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr "Sablon kiválasztása:"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr ""
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr ""
+
+#: views/campaigns/create-triggered.hbs:17 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:26 views/campaigns/edit.hbs:29
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr "Email tárgya"
+
+#: views/campaigns/create-triggered.hbs:23 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:27
+msgid "Keep it relevant and non-spammy"
+msgstr ""
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr ""
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr "RSS kampány szerkesztése"
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr "Általános beállítások"
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:35
+msgid "Delete Campaign"
+msgstr "Kampány törlése"
+
+#: views/campaigns/edit-rss.hbs:25 views/campaigns/edit-triggered.hbs:28
+#: views/campaigns/edit.hbs:36 views/lists/edit.hbs:22
+#: views/lists/fields/edit.hbs:39 views/lists/forms/edit.hbs:33
+#: views/lists/forms/forms.hbs:12 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:18
+#: views/reports/edit.hbs:6 views/settings.hbs:97 views/templates/edit.hbs:13
+#: views/triggers/edit.hbs:30 views/users/account.hbs:18
+msgid "Update"
+msgstr "Frissítés"
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+#: routes/forms.js:143
+msgid "General"
+msgstr ""
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27
+msgid "Template Settings"
+msgstr "Sablon beállítások"
+
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28
+msgid "Template URL"
+msgstr "Sablon URL"
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr "Kampány szerkesztése"
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:30
+msgid "Attachments"
+msgstr "Csatolmányok"
+
+#: views/campaigns/edit.hbs:31
+msgid "File"
+msgstr "File"
+
+#: views/campaigns/edit.hbs:32
+msgid "Size"
+msgstr "Méret"
+
+#: views/campaigns/edit.hbs:33 views/campaigns/view.hbs:68
+#: views/lists/fields/fields.hbs:12 views/lists/forms/forms.hbs:9
+#: views/lists/view.hbs:33
+msgid "No data available in table"
+msgstr "Nincs adat a táblázatban."
+
+#: views/campaigns/edit.hbs:34 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr "Csatolmány hozzáadása"
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr "Megnyitásokról információ"
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr "Feliratkozók, akik megnyitották ezt az üzenetet:"
+
+#: views/campaigns/opened.hbs:12
+msgid "First open"
+msgstr "Első megnyitás"
+
+#: views/campaigns/opened.hbs:13
+msgid "Opened count"
+msgstr "Megnyitások száma"
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr "Leiratkozásokról információ:"
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr "Feliratkozók, akik leiratkoztak:"
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:28
+#: views/lists/subscription/import.hbs:13 routes/lists.js:206
+msgid "Unsubscribed"
+msgstr ""
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr "Feltöltés"
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr "Áttekintés"
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr "Linkek"
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr ""
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr ""
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr ""
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr ""
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr "RSS státusz"
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr "Kampány előnezete, mint"
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr "Teszt felhasználó hozzáadása"
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr "Nincs még teszt felhasználó, hozzon létre egyet itt"
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr ""
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:26
+msgid "Delivered"
+msgstr "Készbesítve"
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr "Azon felhasználók listázása, akik megkapták ezt az üzenetet"
+
+#: views/campaigns/view.hbs:22
+msgid "Blacklisted"
+msgstr "Feketelistán szereplők"
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who blacklisted by global blacklist"
+msgstr ""
+"Azon felhasználók listázása, akik feketelistára kerültek, mert a globális "
+"feketelistán szerepeltek"
+
+#: views/campaigns/view.hbs:24 routes/lists.js:206
+msgid "Bounced"
+msgstr "Visszapattant"
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who bounced"
+msgstr ""
+
+#: views/campaigns/view.hbs:26
+msgid "Complaints"
+msgstr ""
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who complained for this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who unsubscribed after this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:30
+msgid "Opened"
+msgstr ""
+
+#: views/campaigns/view.hbs:31
+msgid "List subscribers who opened this message"
+msgstr ""
+
+#: views/campaigns/view.hbs:32
+msgid "Clicked"
+msgstr ""
+
+#: views/campaigns/view.hbs:33 views/campaigns/view.hbs:70
+msgid "List subscribers who clicked on a link"
+msgstr ""
+
+#: views/campaigns/view.hbs:34
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:35
+msgid "Delay sending"
+msgstr ""
+
+#: views/campaigns/view.hbs:36
+msgid "hours"
+msgstr "óra"
+
+#: views/campaigns/view.hbs:37
+msgid "minutes"
+msgstr "perc"
+
+#: views/campaigns/view.hbs:38
+msgid "Send to subscribers:"
+msgstr ""
+
+#: views/campaigns/view.hbs:39
+msgid "Are you sure? This action would reset scheduling"
+msgstr ""
+
+#: views/campaigns/view.hbs:40
+msgid "Cancel"
+msgstr "Mégse"
+
+#: views/campaigns/view.hbs:41
+msgid "Sending scheduled"
+msgstr "Küldés időzítve"
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:54
+msgid "Pause"
+msgstr ""
+
+#: views/campaigns/view.hbs:43 routes/campaigns.js:253
+msgid "Sending"
+msgstr "Küldés folyamatban"
+
+#: views/campaigns/view.hbs:44 views/campaigns/view.hbs:48
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+
+#: views/campaigns/view.hbs:46
+msgid "Resume"
+msgstr "Folytatás"
+
+#: views/campaigns/view.hbs:47 views/campaigns/view.hbs:51
+msgid "Reset"
+msgstr ""
+
+#: views/campaigns/view.hbs:50
+msgid "Continue"
+msgstr "Tovább"
+
+#: views/campaigns/view.hbs:52
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+
+#: views/campaigns/view.hbs:53
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:55 views/campaigns/view.hbs:59
+msgid "Campaign status:"
+msgstr "Kampány státusza"
+
+#: views/campaigns/view.hbs:56
+msgid "ACTIVE"
+msgstr "AKTÍV"
+
+#: views/campaigns/view.hbs:57
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+
+#: views/campaigns/view.hbs:58
+msgid "Activate"
+msgstr "Aktív"
+
+#: views/campaigns/view.hbs:60
+msgid "INACTIVE"
+msgstr "INAKTÍV"
+
+#: views/campaigns/view.hbs:61
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+
+#: views/campaigns/view.hbs:62
+msgid "see more"
+msgstr ""
+
+#: views/campaigns/view.hbs:67
+msgid "List subscribers who clicked this link"
+msgstr ""
+
+#: views/campaigns/view.hbs:71
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+
+#: views/campaigns/view.hbs:72
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr "Jelszó megváltoztatása"
+
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr ""
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr "Beállítások"
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/forms/edit.hbs:20
+#: views/lists/subscription/edit.hbs:16
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:2
+#: views/subscription/web-manage.mjml.hbs:3
+#: views/subscription/web-unsubscribe.mjml.hbs:1
+#: views/subscription/web-unsubscribe.mjml.hbs:2 routes/forms.js:223
+#: routes/lists.js:288
+msgid "Unsubscribe"
+msgstr "Leiratkozás"
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr "Üzenet megtekintése böngészőben"
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr "Kedves [FIRST_NAME/Customer]!"
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr "Üdvözlettel,"
+
+#: views/index.hbs:1
+msgid "List Management"
+msgstr "A lista kezelői"
+
+#: views/index.hbs:2
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+
+#: views/index.hbs:3 views/index.hbs:7 views/index.hbs:10 views/index.hbs:13
+#: views/index.hbs:16 views/index.hbs:19 views/index.hbs:22 views/index.hbs:25
+#: views/index.hbs:28
+msgid "Show more"
+msgstr ""
+
+#: views/index.hbs:4 views/lists/fields/create.hbs:3
+#: views/lists/fields/edit.hbs:3 views/lists/fields/fields.hbs:3
+#: views/lists/fields/fields.hbs:5 views/lists/view.hbs:6
+msgid "Custom Fields"
+msgstr "Egyedi mezők"
+
+#: views/index.hbs:5
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+
+#: views/index.hbs:6
+msgid "Mailtrain also supports custom forms."
+msgstr ""
+
+#: views/index.hbs:8
+msgid "List Segmentation"
+msgstr ""
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+
+#: views/index.hbs:11
+msgid "RSS Campaigns"
+msgstr "RSS kampányok"
+
+#: views/index.hbs:12
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+
+#: views/index.hbs:14
+msgid "GPG Encryption"
+msgstr "GPG titkosítás"
+
+#: views/index.hbs:15
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+
+#: views/index.hbs:17
+msgid "Click Stats"
+msgstr ""
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+
+#: views/index.hbs:20
+msgid "Template Editors"
+msgstr ""
+
+#: views/index.hbs:21
+msgid ""
+"Mailtrain ships with GrapeJS and Mosaico built in, two advanced template "
+"editors. Mailtrain also offers a code editor if you prefer to handcraft the "
+"HTML yourself."
+msgstr ""
+
+#: views/index.hbs:23
+msgid "Send via Any Provider"
+msgstr ""
+
+#: views/index.hbs:24
+msgid ""
+"You can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+
+#: views/index.hbs:26 lib/tools.js:137
+msgid "Automation"
+msgstr ""
+
+#: views/index.hbs:27
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr ""
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr "Wiki"
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr "Blog"
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr "Fiók"
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr "Beállítások"
+
+#: views/layout.hbs:8 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr "API"
+
+#: views/layout.hbs:9
+msgid "Log out"
+msgstr "Kijelentkezés"
+
+#: views/layout.hbs:10 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr "Bejelentkezés"
+
+#: views/layout.hbs:11
+msgid "Self Hosted Newsletter App Built on Top of Nodemailer"
+msgstr ""
+
+#: views/layout.hbs:12 views/layout.hbs:14
+msgid "Source on GitHub"
+msgstr "Forráskód a GitHub-on"
+
+#: views/layout.hbs:13
+msgid "Subscribe to Our Newsletter"
+msgstr "Feliratkozás hírlevelünkre"
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/forms/create.hbs:2
+#: views/lists/forms/edit.hbs:2 views/lists/forms/forms.hbs:2
+#: views/lists/lists.hbs:2 views/lists/lists.hbs:4
+#: views/lists/segments/create.hbs:2 views/lists/segments/edit.hbs:2
+#: views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:125 routes/lists.js:59
+msgid "Lists"
+msgstr "Listák"
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:13
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr "Lista létrehozása"
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr "Lista neve"
+
+#: views/lists/create.hbs:9 views/lists/edit.hbs:15
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Feliratkozás"
+
+#: views/lists/create.hbs:10 views/lists/edit.hbs:16
+msgid "Allow public users to subscribe themselves"
+msgstr "Nyilvános űrlapról való feliratkozás engedélyezése"
+
+#: views/lists/create.hbs:11 views/lists/edit.hbs:17
+msgid "Unsubscription"
+msgstr "Leiratkozás"
+
+#: views/lists/create.hbs:12 views/lists/edit.hbs:18
+msgid "Select how an unsuscription request by subscriber is handled."
+msgstr ""
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:8
+msgid "Edit List"
+msgstr "Lista szerkesztése"
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr "Lista megtekintése"
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr "Lista ID"
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr ""
+
+#: views/lists/edit.hbs:12
+msgid "Custom Form"
+msgstr "Egyedi űrlap"
+
+#: views/lists/edit.hbs:13 views/lists/forms/forms.hbs:11
+msgid "Default Mailtrain Form"
+msgstr "Alapértelmezett Mailtrain űrlap"
+
+#: views/lists/edit.hbs:14
+msgid ""
+"The custom form used for this list. You can create a form here."
+msgstr ""
+"Egyedi űrlap ehhez a listához. Itt "
+"hozhat létre új űrlapot."
+
+#: views/lists/edit.hbs:19
+msgid "Unsubscribe Header"
+msgstr "Leiratkozás fejléc"
+
+#: views/lists/edit.hbs:20
+msgid "Do not send List-Unsubscribe headers"
+msgstr "Leiratkozás fejléc küldésének letiltása"
+
+#: views/lists/edit.hbs:21
+msgid "Delete List"
+msgstr "Lista törlése"
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr "Mező létrehozása"
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr "Egyedi mező létrehozása"
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr "Mező neve"
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr "Mező típusa"
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr "Szöveg"
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr "Szám"
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr "Weboldal"
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr "GPG publikus kulcs"
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr "Többsoros szöveg"
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr "JSON"
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr "Dátum"
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr "Dátum (HH/NN/ÉÉÉÉ)"
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr "Dátum (NN/HH/ÉÉÉÉ)"
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr "Születésnap"
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr "Születésnap (HH/NN)"
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr "Születésnap (NN/HH)"
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr "Csoportosított"
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr "Lenyíló menük"
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr "Rádió gombok"
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr "Jelölőmezők"
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr ""
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr "Csoport"
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr ""
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr ""
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Látható"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Mező hozzáadása"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Mező szerkesztése"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/mosaico/editor.hbs:2 views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr ""
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Mező törlése"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:26
+#: views/report-templates/partials/report-template-fields.hbs:5
+msgid "Type"
+msgstr "Típus"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/forms/edit.hbs:26 views/lists/forms/forms.hbs:8
+#: views/lists/segments/segments.hbs:8 views/lists/segments/view.hbs:12
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:276
+#: routes/campaigns.js:568 routes/campaigns.js:657 routes/campaigns.js:706
+#: routes/lists.js:170 routes/lists.js:257 routes/report-templates.js:51
+#: routes/templates.js:183 routes/triggers.js:297
+msgid "Edit"
+msgstr "Szerkesztés"
+
+#: views/lists/forms/create.hbs:3 views/lists/forms/edit.hbs:3
+#: views/lists/forms/forms.hbs:3 views/lists/forms/forms.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Forms"
+msgstr ""
+
+#: views/lists/forms/create.hbs:4
+msgid "Create Form"
+msgstr ""
+
+#: views/lists/forms/create.hbs:5 views/lists/forms/forms.hbs:4
+msgid "Create Custom Form"
+msgstr ""
+
+#: views/lists/forms/create.hbs:6 views/lists/forms/create.hbs:7
+#: views/lists/forms/edit.hbs:7 views/lists/forms/edit.hbs:8
+msgid "Form Name"
+msgstr ""
+
+#: views/lists/forms/create.hbs:8
+msgid "Add Form"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:4
+msgid "Edit Form"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:5
+msgid "Edit Custom Form"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:6
+msgid "Back to forms"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:10
+msgid "Optional comments about this form"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:11
+msgid "Form Preview"
+msgstr "Űrlap előnézete"
+
+#: views/lists/forms/edit.hbs:12
+msgid ""
+"Note: These links are solely for a quick preview. If you submit a preview "
+"form you'll get redirected to the list's default form."
+msgstr ""
+
+#: views/lists/forms/edit.hbs:13 views/lists/subscription/add.hbs:16
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:4
+#: routes/forms.js:157 routes/lists.js:288
+msgid "Subscribe"
+msgstr "Feliratkozás"
+
+#: views/lists/forms/edit.hbs:14
+msgid "Confirm Subscription Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:15
+msgid "Confirm Unsubscription Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:16
+msgid "Subscribed Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:17
+msgid "Updated Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:18
+msgid "Unsubscribed Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:19
+msgid "Manual Unsubscribe Notice"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:21 routes/forms.js:205
+msgid "Manage"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:22
+msgid "Manage Address"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:23
+msgid "Create a test user for additional options"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:24 views/report-templates/create.hbs:3
+#: views/report-templates/edit.hbs:3
+#: views/report-templates/report-templates.hbs:3 views/templates/create.hbs:2
+#: views/templates/edit.hbs:2 views/templates/templates.hbs:2
+#: views/templates/templates.hbs:4 lib/tools.js:129 routes/templates.js:27
+msgid "Templates"
+msgstr "Sablonok"
+
+#: views/lists/forms/edit.hbs:25
+msgid "Fields"
+msgstr "Mezők"
+
+#: views/lists/forms/edit.hbs:27
+msgid "Form Fields"
+msgstr "Űrlap mezők"
+
+#: views/lists/forms/edit.hbs:28
+msgid "Fields hidden on subscription page:"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:29
+msgid "Fields shown on subscription page:"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:30
+msgid "Fields hidden on preferences page:"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:31
+msgid "Fields shown on preferences page:"
+msgstr ""
+
+#: views/lists/forms/edit.hbs:32
+msgid "Delete Form"
+msgstr "Űrlap törlése"
+
+#: views/lists/forms/forms.hbs:10
+msgid "The default form for this list is:"
+msgstr ""
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7 views/reports/partials/report-fields.hbs:10
+msgid "Subscribers"
+msgstr "Feliratkozók"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:7
+#: views/lists/view.hbs:14
+msgid "Segments"
+msgstr ""
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr ""
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr ""
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr ""
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:12
+msgid "Edit Segment"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr ""
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Szabály létrehozása"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Szabály"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Érték"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr "Pontos találat használata"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr "Tartomány találat használata"
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr "Relatív tartomány találat használata"
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr ""
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr ""
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:18
+#: views/reports/create-select-template.hbs:5
+#: views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Következő"
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr ""
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr ""
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:13
+msgid "Segment"
+msgstr ""
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr ""
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr ""
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Feliratkozó hozzáadása"
+
+#: views/lists/subscription/add.hbs:5
+#: views/subscription/partials/subscription-custom-fields.hbs:1
+#: views/users/account.hbs:7
+msgid "Email Address"
+msgstr "Email cím"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:80 views/settings.hbs:95
+#: views/subscription/partials/subscription-custom-fields.hbs:6
+msgid "Begins with"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Adjon meg egy GPG publikus kulcsot, amivel az üzenetek titkosítva lesznek "
+"küldéskor"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Időzóna"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "Teszt felhasználó?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Feliratkozó szerkesztése"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Vissza a listához"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:1
+#: lib/helpers.js:42 lib/models/segments.js:11
+msgid "Email address"
+msgstr "Email cím"
+
+#: views/lists/subscription/edit.hbs:17
+msgid "Delete Subscription"
+msgstr "Feliratkozás törlése"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Importálás státusza"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Hibás címek"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid ""
+"Role-based addresses like postmaster@example.com are blocked when importing. "
+"Subscribers with role-based email addresses can join your list using the "
+"subscription form"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:7
+msgid "see here"
+msgstr ""
+
+#: views/lists/subscription/import-failed.hbs:9
+msgid "Fail reason"
+msgstr "Hiba oka"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Feliratkozók imprtálása"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:21
+#: views/users/api.hbs:36 views/users/api.hbs:44 views/users/api.hbs:52
+#: views/users/api.hbs:64 views/users/api.hbs:75 views/users/api.hbs:83
+#: views/users/api.hbs:91 views/users/api.hbs:96 views/users/api.hbs:101
+#: views/users/api.hbs:106
+msgid "Example"
+msgstr "Példa"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Importálás megkezdése"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "CSV file"
+
+#: views/lists/subscription/import.hbs:6
+msgid "The first line must contain column headings"
+msgstr "Az első sor fejlécet kell, hogy tartalmazzon"
+
+#: views/lists/subscription/import.hbs:7
+msgid "CSV delimiter"
+msgstr "CSV elválasztó"
+
+#: views/lists/subscription/import.hbs:8
+msgid "Categorize the imported subscribers as"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:9 routes/lists.js:206
+msgid "Subscribed"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:10
+msgid "Regular subscriber addresses"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:11
+msgid "Subscribed (Force)"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:12
+msgid "Regular subscriber addresses, resubscribe users that have unsubscribed"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:14
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:15
+msgid "Check imported emails"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:16 views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr ""
+
+#: views/lists/subscription/import.hbs:17 views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr ""
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Feliratkozós űrlap"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Lista műveletek"
+
+#: views/lists/view.hbs:9 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr ""
+
+#: views/lists/view.hbs:10
+msgid "Add Subscriber"
+msgstr "Feliratkozó hozzáadása"
+
+#: views/lists/view.hbs:11
+msgid "Import Subscribers"
+msgstr "Feliratkozók importálása"
+
+#: views/lists/view.hbs:15
+msgid "Create New Segment"
+msgstr ""
+
+#: views/lists/view.hbs:16
+msgid "Filter"
+msgstr "Szűrés"
+
+#: views/lists/view.hbs:17
+msgid "Subscriptions"
+msgstr ""
+
+#: views/lists/view.hbs:18
+msgid "Imports"
+msgstr ""
+
+#: views/lists/view.hbs:25 routes/campaigns.js:255 routes/lists.js:300
+msgid "Finished"
+msgstr "Befejezve"
+
+#: views/lists/view.hbs:27
+msgid "Added"
+msgstr "Hozzáadva"
+
+#: views/lists/view.hbs:28
+msgid "Updated"
+msgstr "Frissítve"
+
+#: views/lists/view.hbs:29
+msgid "Failed"
+msgstr ""
+
+#: views/lists/view.hbs:31
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+
+#: views/lists/view.hbs:32
+msgid "Restart"
+msgstr "Újrakezdés"
+
+#: views/mosaico/editor.hbs:1 views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr ""
+
+#: views/mosaico/editor.hbs:4
+msgid "MOSAICO Responsive Email Designer"
+msgstr ""
+
+#: views/mosaico/editor.hbs:5
+msgid "Sucessfully saved"
+msgstr "Sikeres mentés"
+
+#: views/mosaico/editor.hbs:6
+msgid "An error occured while saving the document"
+msgstr "A dokumentum mentése közben hiba lépett fel."
+
+#: views/mosaico/editor.hbs:7
+msgid "Unsaved changes will be lost. Close now?"
+msgstr "Az el nem mentett változtatások el fognak veszni. Bezárja?"
+
+#: views/mosaico/editor.hbs:8 views/mosaico/editor.hbs:9
+msgid "Tags"
+msgstr "Címkék"
+
+#: views/partials/codeeditor.hbs:1 views/partials/grapejs.hbs:1
+#: views/partials/mosaico.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Sablon tartalma (HTML)"
+
+#: views/partials/editor-navbar.hbs:1
+msgid "SAVE"
+msgstr "MENTÉS"
+
+#: views/partials/editor-navbar.hbs:2
+msgid "SAVING"
+msgstr "MENTÉS FOLYMATBAN"
+
+#: views/partials/editor-navbar.hbs:3
+msgid "CLOSE"
+msgstr "BEZÁRÁS"
+
+#: views/partials/grapejs.hbs:2
+msgid "Open GrapeJS"
+msgstr "GrapeJS megnyitása"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "HTML előnézet átváltása"
+
+#: views/partials/html-to-text.hbs:1
+msgid ""
+"To extract the text from HTML click here."
+msgstr ""
+
+#: views/partials/html-to-text.hbs:2
+msgid ""
+"Please note that your existing plaintext in the field above will be "
+"overwritten. This feature uses the Premailer API, a third party "
+"service. Their Terms of Service and Privacy Policy apply."
+msgstr ""
+
+#: views/partials/html-to-text.hbs:3
+msgid "An error occurred while talking to the server"
+msgstr ""
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+
+#: views/partials/modal-carousel.hbs:1
+msgid "{{title}}"
+msgstr ""
+
+#: views/partials/mosaico.hbs:2
+msgid "Open Mosaico"
+msgstr "Mosaico megnyitása"
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Sablon tartalma (sima szöveg)"
+
+#: views/report-templates/create.hbs:2 views/report-templates/edit.hbs:2
+#: views/report-templates/report-templates.hbs:2
+#: views/reports/create-select-template.hbs:2 views/reports/create.hbs:2
+#: views/reports/edit.hbs:2 views/reports/output.hbs:2
+#: views/reports/reports.hbs:2 views/reports/reports.hbs:5
+#: views/reports/view.hbs:2 lib/tools.js:144 routes/reports.js:31
+msgid "Reports"
+msgstr "Jelentések"
+
+#: views/report-templates/create.hbs:4 views/report-templates/create.hbs:6
+#: views/report-templates/report-templates.hbs:4 views/templates/create.hbs:3
+#: views/templates/create.hbs:4 views/templates/create.hbs:12
+#: views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Sablon létrehozása"
+
+#: views/report-templates/create.hbs:5 routes/report-templates.js:231
+msgid "Create Report Template"
+msgstr "Jelentés sablon létrehozása"
+
+#: views/report-templates/edit.hbs:4 views/templates/edit.hbs:3
+#: views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Sablon szerkesztése"
+
+#: views/report-templates/edit.hbs:5 routes/report-templates.js:262
+msgid "Edit Report Template"
+msgstr "Jelentés sablon szerkesztése"
+
+#: views/report-templates/edit.hbs:6 views/templates/edit.hbs:12
+msgid "Delete Template"
+msgstr "Sablon törlése"
+
+#: views/report-templates/edit.hbs:7
+msgid "Update and Stay"
+msgstr ""
+
+#: views/report-templates/edit.hbs:8
+msgid "Update and Leave"
+msgstr ""
+
+#: views/report-templates/partials/report-template-fields.hbs:2
+msgid "Template Name"
+msgstr "Sablon neve"
+
+#: views/report-templates/partials/report-template-fields.hbs:6
+msgid "User selectable fields"
+msgstr ""
+
+#: views/report-templates/partials/report-template-fields.hbs:7
+msgid "Data processing code"
+msgstr ""
+
+#: views/report-templates/partials/report-template-fields.hbs:8
+msgid "Rendering template"
+msgstr ""
+
+#: views/report-templates/report-templates.hbs:5
+msgid "Blank"
+msgstr ""
+
+#: views/report-templates/report-templates.hbs:6
+msgid "All Subscribers"
+msgstr "Összes feliratkozó"
+
+#: views/report-templates/report-templates.hbs:7
+msgid "Grouped Subscribers"
+msgstr ""
+
+#: views/report-templates/report-templates.hbs:8
+msgid "Export List as CSV"
+msgstr "Lista exportálása CSV-be"
+
+#: views/report-templates/report-templates.hbs:9 views/reports/reports.hbs:4
+#: routes/report-templates.js:29
+msgid "Report Templates"
+msgstr "Jelentés sablonok"
+
+#: views/reports/create-select-template.hbs:3
+#: views/reports/create-select-template.hbs:4 views/reports/create.hbs:3
+#: views/reports/create.hbs:4 views/reports/create.hbs:5
+#: views/reports/reports.hbs:3 routes/reports.js:81
+msgid "Create Report"
+msgstr "Jelentés létrehozása"
+
+#: views/reports/edit.hbs:3 views/reports/edit.hbs:4 routes/reports.js:151
+msgid "Edit Report"
+msgstr "Jelentés szerkesztése"
+
+#: views/reports/edit.hbs:5
+msgid "Delete Report"
+msgstr "Jelentés törlése"
+
+#: views/reports/partials/report-fields.hbs:2
+msgid "Report Name"
+msgstr "Jelentés neve"
+
+#: views/reports/partials/report-fields.hbs:8
+#: views/reports/partials/report-fields.hbs:11
+msgid ""
+"Select a campaign in the table above by clicking on the respective row "
+"number."
+msgstr ""
+
+#: views/reports/partials/report-select-template.hbs:1
+msgid "Report Template"
+msgstr "Jelentés sablon"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Szolgáltatás címe (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Adja meg az URL-t, amiről ez a szolgáltatás elérhető"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "Admin email"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr ""
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr ""
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr ""
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "Követő ID"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Google Analytics követőkód megadása"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr ""
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr ""
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr ""
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr "Küldő neve"
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Küldő neve, pl.: Éncégem Kft."
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr "Alapértelmezett postai cím"
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr ""
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr ""
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr ""
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr ""
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr ""
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr ""
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr ""
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr "SMTP"
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr "AWS SES"
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr "SMTP használata levélküldéshez"
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr ""
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr "Port"
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr ""
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr "Titkosítás"
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr "SMTP azonosítás letiltása"
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Felhasználónév"
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr "Felhasználónév, pl.: myaccount@example.com"
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr "Jelszó"
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr "SES API használata levélküldéshez"
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr ""
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr ""
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr ""
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr ""
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr "Régió"
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr ""
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr ""
+
+#: views/settings.hbs:52
+msgid "Advanced Mailer settings"
+msgstr ""
+
+#: views/settings.hbs:53
+msgid "Log SMTP transactions"
+msgstr "SMTP tranzakciók naplózása"
+
+#: views/settings.hbs:54
+msgid "Allow self-signed certificates"
+msgstr ""
+
+#: views/settings.hbs:55
+msgid "Max connections"
+msgstr ""
+
+#: views/settings.hbs:56
+msgid "The count of max connections, eg. 10"
+msgstr ""
+
+#: views/settings.hbs:57
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+
+#: views/settings.hbs:58
+msgid "Max messages"
+msgstr ""
+
+#: views/settings.hbs:59
+msgid "The count of max messages, eg. 100"
+msgstr ""
+
+#: views/settings.hbs:60
+msgid ""
+"The number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+
+#: views/settings.hbs:61
+msgid "Throttling"
+msgstr ""
+
+#: views/settings.hbs:62
+msgid "Messages per hour eg. 1000"
+msgstr ""
+
+#: views/settings.hbs:63
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+
+#: views/settings.hbs:64
+msgid "VERP bounce handling"
+msgstr ""
+
+#: views/settings.hbs:65
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+
+#: views/settings.hbs:66
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+
+#: views/settings.hbs:67
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+
+#: views/settings.hbs:68
+msgid "Use VERP to catch bounces"
+msgstr ""
+
+#: views/settings.hbs:69
+msgid "Server hostname"
+msgstr ""
+
+#: views/settings.hbs:70
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr ""
+
+#: views/settings.hbs:71
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+
+#: views/settings.hbs:72
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+
+#: views/settings.hbs:73
+msgid "GPG Signing"
+msgstr "GPG aláírás"
+
+#: views/settings.hbs:74
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+
+#: views/settings.hbs:75
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+
+#: views/settings.hbs:76
+msgid "Private Key Passphrase"
+msgstr ""
+
+#: views/settings.hbs:77
+msgid "Passphrase for the key if set"
+msgstr ""
+
+#: views/settings.hbs:78
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+
+#: views/settings.hbs:79
+msgid "GPG Private Key"
+msgstr "GPG privát kulcs"
+
+#: views/settings.hbs:81
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+
+#: views/settings.hbs:82
+msgid "DKIM Signing by ZoneMTA"
+msgstr ""
+
+#: views/settings.hbs:83
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+
+#: views/settings.hbs:84
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+
+#: views/settings.hbs:85
+msgid "ZoneMTA DKIM API Key"
+msgstr ""
+
+#: views/settings.hbs:86
+msgid "Some secret value"
+msgstr ""
+
+#: views/settings.hbs:87
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+
+#: views/settings.hbs:88
+msgid "DKIM domain"
+msgstr ""
+
+#: views/settings.hbs:89
+msgid "Domain name for the DKIM key"
+msgstr ""
+
+#: views/settings.hbs:90
+msgid "Leave blank to use the sender email address domain"
+msgstr ""
+
+#: views/settings.hbs:91 views/settings.hbs:92
+msgid "DKIM key selector"
+msgstr ""
+
+#: views/settings.hbs:93
+msgid "Signing is disabled without a valid selector value"
+msgstr ""
+
+#: views/settings.hbs:94
+msgid "DKIM Private Key"
+msgstr ""
+
+#: views/settings.hbs:96
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:1
+#: views/subscription/mail-already-subscribed-text.hbs:1
+#: lib/models/subscriptions.js:174 lib/models/subscriptions.js:895
+msgid "Email address already registered"
+msgstr "Ezt az email címet már regisztrálták."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:2
+#: views/subscription/mail-already-subscribed-text.hbs:2
+msgid ""
+"We have received a subscription request. Your email address is however "
+"already registered."
+msgstr ""
+"Megkaptuk a feliratkozási kérelmét, viszont címe már eddig is regisztrálva "
+"volt."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:3
+#: views/subscription/mail-already-subscribed-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. Your existing "
+"subscription won't be affected."
+msgstr ""
+"Ha véletlenül kapta ezt a levelet, egyszerűen törölje. A feliratkozás "
+"státusza nem fog változni."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:3
+msgid "If you want to modify your subscription then you can "
+msgstr "Ha szeretné megváltoztatni feliratkozását, akkor"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:5
+#: views/subscription/mail-already-subscribed-text.hbs:5
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:4
+msgid "manage your preferences"
+msgstr "módosíthatja beállításait"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:6
+#: views/subscription/mail-already-subscribed-text.hbs:6
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-subscription-confirmed-text.hbs:5
+#: views/users/login.hbs:10
+msgid "or"
+msgstr "vagy"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:7
+#: views/subscription/mail-already-subscribed-text.hbs:7
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:6
+#: views/subscription/mail-subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "leiratkozhat itt"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:7
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:3
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:3
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:4
+#: views/subscription/web-subscribed-notice.mjml.hbs:4
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:3
+#: views/subscription/web-updated-notice.mjml.hbs:3
+msgid "Return to our website"
+msgstr "Visszatérés az odalunkra"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:9
+#: views/subscription/mail-already-subscribed-text.hbs:8
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:4
+#: views/subscription/mail-confirm-address-change-text.hbs:4
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-subscription-text.hbs:4
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-unsubscription-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-text.hbs:7
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "A listával kapcsolatos kérdéseivel itt tud megkeresni minket:"
+
+#: views/subscription/mail-already-subscribed-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Ha szeretné megváltoztatni feliratkozását, akkor"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:1
+#: views/subscription/mail-confirm-address-change-text.hbs:1
+msgid "Please Confirm Subscription Address Change"
+msgstr "Kérjük erősítse meg a feliratkozáshoz használt emailcímének változását"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:2
+#: views/subscription/mail-confirm-address-change-text.hbs:2
+msgid "Yes, subscribe this email address to the list"
+msgstr "Igen, szeretnék feliratkozni a listára ezzel az email-lel."
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:3
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Ha nem ön kérte ezt a levelet, nyugodtan törölheti. Ha nem kattint a fenti "
+"linkre, továbbra is feliratkozva marad."
+
+#: views/subscription/mail-confirm-address-change-text.hbs:3
+#: views/subscription/mail-confirm-subscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Ha nem ön kérte ezt a levelet, nyugodtan törölheti. Ha nem kattint a fenti "
+"linkre, nem vesszük fel a listára."
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:1
+#: views/subscription/mail-confirm-subscription-text.hbs:1
+#: views/subscription/mail-confirm-unsubscription-text.hbs:1
+#: routes/subscription.js:432
+msgid "Please Confirm Subscription"
+msgstr "Erősítse meg a feliratkozást"
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-subscription-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Igen, szeretnék feliratkozni a listára."
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:1
+msgid "Please Confirm Unsubscription"
+msgstr "Erősítse meg a leiratkozást"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-unsubscription-text.hbs:2
+msgid "Yes, unsubscribe me from this list"
+msgstr "Igen, szeretnék leiratkozni a listáról."
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed if you don't click the confirmation link above."
+msgstr ""
+"Ha nem ön kérte ezt a levelet, nyugodtan törölheti. Ha nem kattint a fenti "
+"linkre, továbbra is feliratkozva marad."
+
+#: views/subscription/mail-confirm-unsubscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed unless you click the confirmation link above."
+msgstr ""
+"Ha nem ön kérte ezt a levelet, nyugodtan törölheti. Ha nem kattint a fenti "
+"linkre, továbbra is feliratkozva marad."
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-subscription-confirmed-text.hbs:1
+#: views/subscription/web-subscribed-notice.mjml.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Feliratkozás megerősítve"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed"
+msgstr "A listára való feliratkozása megerősítve."
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:2
+#: views/subscription/web-subscribed-notice.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "A listára való feliratkozása megerősítve."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:1
+msgid "You Are Now Unsubscribed"
+msgstr "Leiratkozott a listáról."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:2
+msgid "We have removed your email address from our list"
+msgstr "Email címét eltávolítottuk a listánkról."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:3
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr "Ha véletlenül iratkozott le, újra feliratkozhat itt:"
+
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Email címét eltávolítottuk a listánkról."
+
+#: views/subscription/partials/subscription-custom-fields.hbs:2
+msgid "want to change it?"
+msgstr "meg akarja változtatni?"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:5
+msgid "Download signature verification key"
+msgstr ""
+
+#: views/subscription/partials/subscription-custom-fields.hbs:7
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr "Adja meg publikus GPG kulcsát, hogy kódolt üzeneteket küldhessünk"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:8
+msgid "optional"
+msgstr "nem kötelező"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:1
+#: views/subscription/partials/subscription-flash-messages.hbs:3
+msgid "Warning!"
+msgstr "Figyelem!"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+"Ha a JavaScript nem volt engedélyezve, akkor nem küldünk megerősítő levelet."
+
+#: views/subscription/partials/subscription-flash-messages.hbs:4
+msgid "JavaScript must be enabled in order for this form to work"
+msgstr "Engedélyezni kell a JavaScriptet az űrlap használatához."
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:1
+msgid "Existing Email Address"
+msgstr "Eddigi email cím"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:2
+msgid "New Email Address"
+msgstr "Új email cím"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:3
+msgid "Your new email address"
+msgstr "Az ön új email címe"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:4
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Küldünk egy megerősítést kérő üzenetet az új email címére. Az új cím csak "
+"akkor lép érvénybe, ha az üzenetben rákattint a megerősítésre."
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:5
+#: views/subscription/web-manage-address.mjml.hbs:2
+msgid "Update Email Address"
+msgstr "Email cím cseréje"
+
+#: views/subscription/partials/subscription-manage-form.hbs:1
+#: views/subscription/web-manage.mjml.hbs:2
+msgid "Update Profile"
+msgstr "Profil frissítése"
+
+#: views/subscription/partials/subscription-subscribe-form.hbs:1
+#: views/subscription/web-subscribe.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:1
+msgid "Subscribe to list"
+msgstr "Feliratkozás"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:1
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:1
+#: views/subscription/widget-subscribe.hbs:4
+msgid "Almost Finished"
+msgstr "Majdnem kész"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:5
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Meg kell erősítenie email címét. A feliratkozás befejezéséhez kattintson a "
+"linkre, amit a megerősítést kérő üzenetben küldtünk."
+
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:2
+msgid ""
+"We need to confirm your email address. To complete the unsubscription "
+"process, please click the link in the email we just sent you."
+msgstr ""
+"Meg kell erősítenie email címét. A leiratkozás befejezéséhez kattintson a "
+"linkre, amit a megerősítést kérő üzenetben küldtünk."
+
+#: views/subscription/web-manage-address.mjml.hbs:1
+msgid "Update Your Email Address"
+msgstr "Email cím frissítése"
+
+#: views/subscription/web-manage.mjml.hbs:1
+msgid "Update Your Preferences"
+msgstr "Beállítások frissítése"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:1
+msgid "Online Unsubscription Is Not Possible"
+msgstr "Nem lehetséges az online feliratkozás."
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:2
+msgid "Please contact us at"
+msgstr "Vegye fel velünk a kapcsolatot itt:"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:3
+msgid "to get removed from the list"
+msgstr "hogy eltávolítsuk a listáról."
+
+#: views/subscription/web-subscribe.mjml.hbs:1
+msgid "Subscribe to List"
+msgstr "Feliratkozás a listára"
+
+#: views/subscription/web-subscribed-notice.mjml.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "Köszönjük, hogy feliratkozott!"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Sikeresen leiratkozott."
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:2
+msgid "You have been removed from:"
+msgstr "El lett távolítva innen:"
+
+#: views/subscription/web-updated-notice.mjml.hbs:1
+msgid "Profile Updated"
+msgstr "Profil frissítve."
+
+#: views/subscription/web-updated-notice.mjml.hbs:2
+msgid "Your profile information has been updated."
+msgstr "A profilja frissült."
+
+#: views/subscription/widget-subscribe.hbs:2
+msgid "Sending ..."
+msgstr "Küldés..."
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Úgy tűnik, korábban már feliratkozott a listára."
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Sablon neve"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr ""
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "HTML szerkesztő"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr ""
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr ""
+
+#: views/templates/edit.hbs:11
+msgid "Duplicate"
+msgstr "Duplikálás"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr ""
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr ""
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr ""
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr ""
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr ""
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr ""
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr ""
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr ""
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Esemény"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Kampány"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr ""
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr ""
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr ""
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr ""
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr ""
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr ""
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr ""
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr ""
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr ""
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr ""
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr ""
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr ""
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr ""
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr ""
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr ""
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr ""
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr ""
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr ""
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr ""
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr ""
+
+#: views/users/account.hbs:16 views/users/reset.hbs:8
+msgid "Confirm Password"
+msgstr ""
+
+#: views/users/account.hbs:17 views/users/reset.hbs:9
+msgid "Confirm New Password"
+msgstr ""
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr ""
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr ""
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr ""
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr ""
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr ""
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr ""
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr ""
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+
+#: views/users/api.hbs:13
+msgid "Get list of subscriptions"
+msgstr ""
+
+#: views/users/api.hbs:14
+msgid ""
+"Retrieve a list of subscriptions to the list referenced by :listId. All "
+"fields of the subscribers will be returned. Note that custom fields will "
+"have generated names."
+msgstr ""
+
+#: views/users/api.hbs:15 views/users/api.hbs:24 views/users/api.hbs:26
+#: views/users/api.hbs:39 views/users/api.hbs:41 views/users/api.hbs:47
+#: views/users/api.hbs:49 views/users/api.hbs:55 views/users/api.hbs:57
+#: views/users/api.hbs:67 views/users/api.hbs:78 views/users/api.hbs:80
+#: views/users/api.hbs:86 views/users/api.hbs:88 views/users/api.hbs:94
+#: views/users/api.hbs:99 views/users/api.hbs:104
+msgid "arguments"
+msgstr ""
+
+#: views/users/api.hbs:16 views/users/api.hbs:25 views/users/api.hbs:40
+#: views/users/api.hbs:48 views/users/api.hbs:56 views/users/api.hbs:68
+#: views/users/api.hbs:79 views/users/api.hbs:87 views/users/api.hbs:95
+#: views/users/api.hbs:100 views/users/api.hbs:105
+msgid "your personal access token"
+msgstr ""
+
+#: views/users/api.hbs:17 views/users/api.hbs:69
+msgid "Start position"
+msgstr ""
+
+#: views/users/api.hbs:18 views/users/api.hbs:70
+msgid "optional, default 0"
+msgstr ""
+
+#: views/users/api.hbs:19
+msgid "limit subscription count in response"
+msgstr ""
+
+#: views/users/api.hbs:20 views/users/api.hbs:72
+msgid "optional, default 10000"
+msgstr ""
+
+#: views/users/api.hbs:22
+msgid "Add subscription"
+msgstr ""
+
+#: views/users/api.hbs:23
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+
+#: views/users/api.hbs:27 views/users/api.hbs:42 views/users/api.hbs:50
+msgid "subscriber's email address"
+msgstr ""
+
+#: views/users/api.hbs:28 views/users/api.hbs:43 views/users/api.hbs:51
+#: views/users/api.hbs:59 views/users/api.hbs:82 views/users/api.hbs:90
+msgid "required"
+msgstr ""
+
+#: views/users/api.hbs:29
+msgid "subscriber's first name"
+msgstr "feliratkozó keresztneve"
+
+#: views/users/api.hbs:30
+msgid "subscriber's last name"
+msgstr "feliratkozó vezetékneve"
+
+#: views/users/api.hbs:31
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"Feliratkozó időzónája (pl.: \"Europe/Budapest\", \"CEST\", \"UTC\"). "
+"Alapértelmezés szerint \"UTC\"."
+
+#: views/users/api.hbs:32
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+
+#: views/users/api.hbs:33
+msgid "Additional POST arguments"
+msgstr ""
+
+#: views/users/api.hbs:34
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+
+#: views/users/api.hbs:35
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+
+#: views/users/api.hbs:37
+msgid "Remove subscription"
+msgstr ""
+
+#: views/users/api.hbs:38
+msgid "This API call marks a subscription as unsubscribed"
+msgstr ""
+
+#: views/users/api.hbs:45
+msgid "Delete subscription"
+msgstr ""
+
+#: views/users/api.hbs:46
+msgid "This API call deletes a subscription"
+msgstr ""
+
+#: views/users/api.hbs:53
+msgid "Add new custom field"
+msgstr ""
+
+#: views/users/api.hbs:54
+msgid "This API call creates a new custom field for a list."
+msgstr ""
+
+#: views/users/api.hbs:58
+msgid "field name"
+msgstr ""
+
+#: views/users/api.hbs:60
+msgid "one of the following types:"
+msgstr ""
+
+#: views/users/api.hbs:61
+msgid ""
+"If the type is 'option' then you also need to specify the parent element ID"
+msgstr ""
+
+#: views/users/api.hbs:62
+msgid ""
+"Template for the group element. If not set, then values of the elements are "
+"joined with commas"
+msgstr ""
+
+#: views/users/api.hbs:63
+msgid ""
+"if not visible then the subscriber can not view or modify this value at the "
+"profile page"
+msgstr ""
+
+#: views/users/api.hbs:65
+msgid "Get list of blacklisted emails"
+msgstr ""
+
+#: views/users/api.hbs:66
+msgid "This API call get list of blacklisted emails."
+msgstr ""
+
+#: views/users/api.hbs:71
+msgid "limit emails count in response"
+msgstr ""
+
+#: views/users/api.hbs:73
+msgid "filter by part of email"
+msgstr ""
+
+#: views/users/api.hbs:74
+msgid "optional, default ''"
+msgstr ""
+
+#: views/users/api.hbs:77
+msgid "This API call either add emails to blacklist"
+msgstr ""
+
+#: views/users/api.hbs:81 views/users/api.hbs:89
+msgid "email address"
+msgstr ""
+
+#: views/users/api.hbs:84
+msgid "Delete email from blacklist"
+msgstr ""
+
+#: views/users/api.hbs:85
+msgid "This API call either delete emails from blacklist"
+msgstr ""
+
+#: views/users/api.hbs:92
+msgid "Get the lists a user has subscribed to"
+msgstr ""
+
+#: views/users/api.hbs:93
+msgid "Retrieve the lists that the user with :email has subscribed to. "
+msgstr ""
+
+#: views/users/api.hbs:97
+msgid "Get all lists"
+msgstr ""
+
+#: views/users/api.hbs:98
+msgid "Retrieve every list. "
+msgstr ""
+
+#: views/users/api.hbs:102
+msgid "Get list by id"
+msgstr ""
+
+#: views/users/api.hbs:103
+msgid "Retrieve the list with :id "
+msgstr ""
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr ""
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr ""
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr ""
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr ""
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr ""
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr ""
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr ""
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Emlékezzen rám"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "Elfelejtett jelszó"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr ""
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr ""
+
+#: lib/editor-helpers.js:17 routes/templates.js:95
+msgid "Could not find template with specified ID"
+msgstr ""
+
+#: lib/editor-helpers.js:33 routes/archive.js:145 routes/campaigns.js:131
+#: routes/campaigns.js:284 routes/campaigns.js:379 routes/campaigns.js:427
+#: routes/campaigns.js:467 routes/campaigns.js:844 routes/campaigns.js:867
+#: routes/campaigns.js:886 routes/campaigns.js:908 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr ""
+
+#: lib/editor-helpers.js:47 routes/editorapi.js:320
+msgid "Invalid resource type"
+msgstr ""
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr ""
+
+#: lib/helpers.js:33
+msgid "URL that points to the unsubscribe page"
+msgstr ""
+
+#: lib/helpers.js:36
+msgid "URL that points to the preferences page of the subscriber"
+msgstr ""
+
+#: lib/helpers.js:39
+msgid "URL to preview the message in a browser"
+msgstr ""
+
+#: lib/helpers.js:45 lib/models/segments.js:31
+msgid "First name"
+msgstr "Keresztnév"
+
+#: lib/helpers.js:48 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Vezetéknév"
+
+#: lib/helpers.js:51
+msgid "Full name (first and last name combined)"
+msgstr "Teljes név (vezetéknév + keresztnév)"
+
+#: lib/helpers.js:54
+msgid "Unique ID that identifies the recipient"
+msgstr ""
+
+#: lib/helpers.js:57
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr ""
+
+#: lib/helpers.js:60
+msgid "Unique ID that identifies current campaign"
+msgstr ""
+
+#: lib/helpers.js:68 lib/helpers.js:80
+msgid "content from an RSS entry"
+msgstr ""
+
+#: lib/helpers.js:71
+msgid "RSS entry title"
+msgstr ""
+
+#: lib/helpers.js:74
+msgid "RSS entry date"
+msgstr ""
+
+#: lib/helpers.js:77
+msgid "RSS entry link"
+msgstr ""
+
+#: lib/helpers.js:83
+msgid "RSS entry summary"
+msgstr ""
+
+#: lib/helpers.js:86
+msgid "RSS entry image URL"
+msgstr ""
+
+#: lib/mailer.js:245
+msgid "Invalid mail transport"
+msgstr ""
+
+#: lib/models/campaigns.js:105 lib/models/campaigns.js:132
+#: lib/models/campaigns.js:205 lib/models/campaigns.js:328
+#: lib/models/campaigns.js:590 lib/models/campaigns.js:723
+msgid "Missing Campaign ID"
+msgstr ""
+
+#: lib/models/campaigns.js:241
+msgid "Emtpy or too large attahcment"
+msgstr ""
+
+#: lib/models/campaigns.js:408 lib/models/campaigns.js:600
+msgid "Campaign Name must be set"
+msgstr ""
+
+#: lib/models/campaigns.js:412
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr ""
+
+#: lib/models/campaigns.js:568
+msgid "Selected template not found"
+msgstr ""
+
+#: lib/models/campaigns.js:924
+msgid "Invalid or missing message ID"
+msgstr ""
+
+#: lib/models/campaigns.js:1065
+msgid "Unrecognized message status"
+msgstr ""
+
+#: lib/models/confirmations.js:27
+msgid "Could not store confirmation data"
+msgstr ""
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr ""
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Dátum (NN/HH/ÉÉÉÉ)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr ""
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr ""
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/forms.js:46 lib/models/lists.js:115 lib/models/lists.js:150
+#: lib/models/lists.js:265 lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:79 lib/models/subscriptions.js:390
+#: lib/models/subscriptions.js:566 lib/models/subscriptions.js:657
+#: lib/models/subscriptions.js:710 lib/models/subscriptions.js:773
+#: lib/models/subscriptions.js:816
+msgid "Missing List ID"
+msgstr ""
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr ""
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr ""
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr ""
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr ""
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr ""
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr ""
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr ""
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr ""
+
+#: lib/models/forms.js:70 lib/models/forms.js:113 lib/models/forms.js:201
+#: lib/models/forms.js:291
+msgid "Missing Form ID"
+msgstr ""
+
+#: lib/models/forms.js:121 lib/models/forms.js:205
+msgid "Form Name must be set"
+msgstr ""
+
+#: lib/models/forms.js:307
+msgid "Custom form not found"
+msgstr ""
+
+#: lib/models/links.js:337 routes/campaigns.js:533 routes/campaigns.js:581
+#: routes/campaigns.js:621 routes/campaigns.js:671 services/sender.js:305
+msgid "Campaign not found"
+msgstr ""
+
+#: lib/models/links.js:345 routes/lists.js:181 services/sender.js:312
+msgid "List not found"
+msgstr "Lista nem található."
+
+#: lib/models/links.js:353
+msgid "Subscription not found"
+msgstr ""
+
+#: lib/models/lists.js:167 lib/models/lists.js:211
+msgid "List Name must be set"
+msgstr ""
+
+#: lib/models/lists.js:294
+msgid "Missing List CID"
+msgstr ""
+
+#: lib/models/report-templates.js:26 lib/models/report-templates.js:70
+#: lib/models/report-templates.js:142
+msgid "Missing report template ID"
+msgstr ""
+
+#: lib/models/report-templates.js:77
+msgid "Report template name must be set"
+msgstr ""
+
+#: lib/models/reports.js:40 lib/models/reports.js:110 lib/models/reports.js:188
+msgid "Missing report ID"
+msgstr ""
+
+#: lib/models/reports.js:116
+msgid "Report name must be set"
+msgstr ""
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr ""
+
+#: lib/models/segments.js:19 lib/models/triggers.js:12
+msgid "Sign up date"
+msgstr "Feliratkozás ideje"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:16
+msgid "Latest open"
+msgstr ""
+
+#: lib/models/segments.js:27 lib/models/triggers.js:20
+msgid "Latest click"
+msgstr ""
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr ""
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr ""
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr ""
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr ""
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr ""
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr ""
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr ""
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr ""
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr ""
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr ""
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr ""
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr ""
+
+#: lib/models/subscriptions.js:257 lib/models/subscriptions.js:287
+#: lib/models/subscriptions.js:394
+msgid "Missing Subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:315
+msgid "Missing Subscription email address"
+msgstr ""
+
+#: lib/models/subscriptions.js:570 lib/models/subscriptions.js:820
+msgid "Missing subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:661 lib/models/subscriptions.js:714
+#: lib/models/subscriptions.js:750
+msgid "Missing Import ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:842
+msgid "Unknown subscription ID"
+msgstr ""
+
+#: lib/models/subscriptions.js:847 routes/subscription.js:639
+msgid "Nothing seems to be changed"
+msgstr ""
+
+#: lib/models/subscriptions.js:913 routes/subscription.js:473
+#: routes/subscription.js:545 routes/subscription.js:581
+#: routes/subscription.js:697 routes/subscription.js:772
+msgid "Subscription not found in this list"
+msgstr ""
+
+#: lib/models/templates.js:26 lib/models/templates.js:102
+#: lib/models/templates.js:157
+msgid "Missing Template ID"
+msgstr ""
+
+#: lib/models/templates.js:55 lib/models/templates.js:106
+msgid "Template Name must be set"
+msgstr ""
+
+#: lib/models/templates.js:147
+msgid "Template does not exist"
+msgstr ""
+
+#: lib/models/triggers.js:29
+msgid "Has Opened"
+msgstr ""
+
+#: lib/models/triggers.js:32
+msgid "Has Clicked"
+msgstr ""
+
+#: lib/models/triggers.js:35
+msgid "Not Opened"
+msgstr ""
+
+#: lib/models/triggers.js:38
+msgid "Not Clicked"
+msgstr ""
+
+#: lib/models/triggers.js:178 lib/models/triggers.js:215
+msgid "Missing or invalid list ID"
+msgstr ""
+
+#: lib/models/triggers.js:182 lib/models/triggers.js:267
+msgid "Days in the past are not allowed"
+msgstr ""
+
+#: lib/models/triggers.js:186 lib/models/triggers.js:207
+#: lib/models/triggers.js:271 lib/models/triggers.js:292
+msgid "Missing or invalid trigger rule"
+msgstr ""
+
+#: lib/models/triggers.js:193 lib/models/triggers.js:278
+msgid "Invalid subscription configuration"
+msgstr ""
+
+#: lib/models/triggers.js:200 lib/models/triggers.js:285
+msgid "Invalid campaign configuration"
+msgstr ""
+
+#: lib/models/triggers.js:203 lib/models/triggers.js:288
+msgid "A campaing can not be a target for itself"
+msgstr ""
+
+#: lib/models/triggers.js:236
+msgid "Could not store trigger row"
+msgstr ""
+
+#: lib/models/triggers.js:253
+msgid "Missing or invalid Trigger ID"
+msgstr ""
+
+#: lib/models/triggers.js:320
+msgid "Missing Trigger ID"
+msgstr ""
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr ""
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr ""
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr ""
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr ""
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr ""
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr ""
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr ""
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr ""
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr ""
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr ""
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Érvénytelen új jelszó"
+
+#: lib/passport.js:49
+msgid "%s logged out"
+msgstr "%s kijelentkezett"
+
+#: lib/passport.js:64
+msgid "Failed to authenticate user"
+msgstr "Felhasználó azonosítása nem sikerült"
+
+#: lib/passport.js:80
+msgid "Logged in as %s"
+msgstr "Bejelenetezve, mint %s"
+
+#: lib/passport.js:180
+msgid "Incorrect username or password"
+msgstr "Helytelen felhasználónév vagy jelszó"
+
+#: lib/subscription-mail-helpers.js:28
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Feliratkozás megerősítve"
+
+#: lib/subscription-mail-helpers.js:39
+msgid "%s: Email Address Already Registered"
+msgstr "%s: Emailcím már regisztrálva van"
+
+#: lib/subscription-mail-helpers.js:49
+msgid "%s: Please Confirm Email Change in Subscription"
+msgstr "%s: Kérjük erősítse meg email címének megváltoztatását"
+
+#: lib/subscription-mail-helpers.js:59
+msgid "%s: Please Confirm Subscription"
+msgstr "%s: Kérjük erősítse meg a feliratkozást"
+
+#: lib/subscription-mail-helpers.js:69
+msgid "%s: Please Confirm Unsubscription"
+msgstr "%s: Kérjük erősítse meg a leiratkozást"
+
+#: lib/subscription-mail-helpers.js:76
+msgid "%s: Unsubscription Confirmed"
+msgstr "%s: Leiratkozás megerősítve"
+
+#: lib/tools.js:154
+msgid "Blocked email address \"%s\""
+msgstr "Blokkolt email cím \"%s\""
+
+#: lib/tools.js:163
+msgid "Invalid email address \"%s\"."
+msgstr "Érvénytelen email cím \"%s\""
+
+#: lib/tools.js:166
+msgid "MX record not found for domain"
+msgstr "MX rekord nem található a domain-hez"
+
+#: lib/tools.js:169
+msgid "Address domain not found"
+msgstr ""
+
+#: lib/tools.js:172
+msgid "Address domain name is required"
+msgstr ""
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:230
+msgid "Not Found"
+msgstr "Nem található"
+
+#: routes/archive.js:121 services/sender.js:454
+msgid "Received status code %s from %s"
+msgstr ""
+
+#: routes/archive.js:153 routes/campaigns.js:894
+msgid "Attachment not found"
+msgstr "Csatolmány nem található"
+
+#: routes/blacklist.js:13 routes/campaigns.js:26 routes/editorapi.js:32
+#: routes/fields.js:13 routes/forms.js:16 routes/grapejs.js:15
+#: routes/lists.js:50 routes/mosaico.js:14 routes/report-templates.js:20
+#: routes/reports.js:22 routes/segments.js:13 routes/settings.js:23
+#: routes/templates.js:18 routes/triggers.js:18 routes/users.js:75
+#: routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr ""
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr ""
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr ""
+
+#: routes/campaigns.js:209
+msgid "Campaign settings updated"
+msgstr ""
+
+#: routes/campaigns.js:211
+msgid "Campaign settings not updated"
+msgstr ""
+
+#: routes/campaigns.js:227 routes/campaigns.js:744
+msgid "Campaign deleted"
+msgstr "Kampány törölve"
+
+#: routes/campaigns.js:229 routes/campaigns.js:746
+msgid "Could not delete specified campaign"
+msgstr "Kampány törlése nem sikerült"
+
+#: routes/campaigns.js:248
+msgid "Idling"
+msgstr ""
+
+#: routes/campaigns.js:251
+msgid "Scheduled"
+msgstr "Időzítve"
+
+#: routes/campaigns.js:257
+msgid "Paused"
+msgstr ""
+
+#: routes/campaigns.js:259
+msgid "Inactive"
+msgstr "Inaktív"
+
+#: routes/campaigns.js:261
+msgid "Active"
+msgstr "Aktív"
+
+#: routes/campaigns.js:263
+msgid "Other"
+msgstr ""
+
+#: routes/campaigns.js:421
+msgid "Unknown status selector"
+msgstr ""
+
+#: routes/campaigns.js:762
+msgid "Scheduled sending"
+msgstr ""
+
+#: routes/campaigns.js:764
+msgid "Could not schedule sending"
+msgstr ""
+
+#: routes/campaigns.js:776
+msgid "Sending resumed"
+msgstr ""
+
+#: routes/campaigns.js:778
+msgid "Could not resume sending"
+msgstr ""
+
+#: routes/campaigns.js:790
+msgid "Sending reset"
+msgstr ""
+
+#: routes/campaigns.js:792
+msgid "Could not reset sending"
+msgstr ""
+
+#: routes/campaigns.js:804 routes/campaigns.js:832
+msgid "Sending paused"
+msgstr ""
+
+#: routes/campaigns.js:806 routes/campaigns.js:834
+msgid "Could not pause sending"
+msgstr ""
+
+#: routes/campaigns.js:818
+msgid "Sending activated"
+msgstr ""
+
+#: routes/campaigns.js:820
+msgid "Could not activate sending"
+msgstr ""
+
+#: routes/campaigns.js:855
+msgid "Attachment uploaded"
+msgstr ""
+
+#: routes/campaigns.js:857
+msgid "Could not store attachment"
+msgstr ""
+
+#: routes/campaigns.js:874
+msgid "Attachment deleted"
+msgstr ""
+
+#: routes/campaigns.js:876
+msgid "Could not delete attachment"
+msgstr ""
+
+#: routes/editorapi.js:38
+msgid "Invalid editor name"
+msgstr ""
+
+#: routes/editorapi.js:146
+msgid "Method not supported"
+msgstr ""
+
+#: routes/editorapi.js:381
+msgid "Invalid resource type or ID"
+msgstr ""
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/forms.js:31 routes/forms.js:63 routes/forms.js:94
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr ""
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr ""
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr ""
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr ""
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr ""
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr ""
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr ""
+
+#: routes/forms.js:78
+msgid "Could not create custom form"
+msgstr ""
+
+#: routes/forms.js:105
+msgid "Selected form not found"
+msgstr ""
+
+#: routes/forms.js:136
+msgid "The plaintext version for this email"
+msgstr ""
+
+#: routes/forms.js:137
+msgid "Custom forms use MJML for formatting"
+msgstr ""
+
+#: routes/forms.js:138
+msgid "See the MJML documentation here"
+msgstr ""
+
+#: routes/forms.js:146
+msgid "Layout"
+msgstr ""
+
+#: routes/forms.js:152
+msgid "Form Input Style"
+msgstr ""
+
+#: routes/forms.js:154
+msgid ""
+"This CSS stylesheet defines the appearance of form input elements and alerts"
+msgstr ""
+
+#: routes/forms.js:160
+msgid "Web - Subscribe"
+msgstr ""
+
+#: routes/forms.js:165
+msgid "Web - Confirm Subscription Notice"
+msgstr ""
+
+#: routes/forms.js:170
+msgid "Mail - Confirm Subscription (MJML)"
+msgstr ""
+
+#: routes/forms.js:175
+msgid "Mail - Confirm Subscription (Text)"
+msgstr ""
+
+#: routes/forms.js:180
+msgid "Mail - Already Subscribed (MJML)"
+msgstr ""
+
+#: routes/forms.js:185
+msgid "Mail - Already Subscribed (Text)"
+msgstr ""
+
+#: routes/forms.js:190
+msgid "Web - Subscribed Notice"
+msgstr ""
+
+#: routes/forms.js:195
+msgid "Mail - Subscription Confirmed (MJML)"
+msgstr ""
+
+#: routes/forms.js:200
+msgid "Mail - Subscription Confirmed (Text)"
+msgstr ""
+
+#: routes/forms.js:208
+msgid "Web - Manage Preferences"
+msgstr ""
+
+#: routes/forms.js:213
+msgid "Web - Manage Address"
+msgstr ""
+
+#: routes/forms.js:218
+msgid "Web - Updated Notice"
+msgstr ""
+
+#: routes/forms.js:226
+msgid "Web - Unsubscribe"
+msgstr ""
+
+#: routes/forms.js:231
+msgid "Web - Confirm Unsubscription Notice"
+msgstr ""
+
+#: routes/forms.js:236
+msgid "Mail - Confirm Unsubscription (MJML)"
+msgstr ""
+
+#: routes/forms.js:241
+msgid "Mail - Confirm Unsubscription (Text)"
+msgstr ""
+
+#: routes/forms.js:246
+msgid "Mail - Confirm Address Change (MJML)"
+msgstr ""
+
+#: routes/forms.js:251
+msgid "Mail - Confirm Address Change (Text)"
+msgstr ""
+
+#: routes/forms.js:256
+msgid "Web - Unsubscribed Notice"
+msgstr ""
+
+#: routes/forms.js:261
+msgid "Mail - Unsubscription Confirmed (MJML)"
+msgstr ""
+
+#: routes/forms.js:266
+msgid "Mail - Unsubscription Confirmed (Text)"
+msgstr ""
+
+#: routes/forms.js:271
+msgid "Web - Manual Unsubscribe Notice"
+msgstr ""
+
+#: routes/forms.js:309
+msgid "Form settings updated"
+msgstr ""
+
+#: routes/forms.js:311
+msgid "Form settings not updated"
+msgstr ""
+
+#: routes/forms.js:327
+msgid "Custom form deleted"
+msgstr ""
+
+#: routes/forms.js:329
+msgid "Could not delete specified form"
+msgstr ""
+
+#: routes/index.js:11
+msgid "Self Hosted Newsletter App"
+msgstr ""
+
+#: routes/links.js:39
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr ""
+
+#: routes/lists.js:82
+msgid "Could not create list"
+msgstr ""
+
+#: routes/lists.js:85
+msgid "List created"
+msgstr "Lista létrehozva"
+
+#: routes/lists.js:93 routes/lists.js:271 routes/lists.js:336
+#: routes/lists.js:375 routes/lists.js:444 routes/lists.js:469
+#: routes/lists.js:514 routes/lists.js:536 routes/lists.js:565
+#: routes/lists.js:657 routes/lists.js:714 routes/lists.js:741
+msgid "Could not find list with specified ID"
+msgstr ""
+
+#: routes/lists.js:122
+msgid "List settings updated"
+msgstr ""
+
+#: routes/lists.js:124
+msgid "List settings not updated"
+msgstr ""
+
+#: routes/lists.js:142
+msgid "List deleted"
+msgstr "Lista törölve"
+
+#: routes/lists.js:144
+msgid "Could not delete specified list"
+msgstr ""
+
+#: routes/lists.js:206
+msgid "Unknown"
+msgstr ""
+
+#: routes/lists.js:206
+msgid "Complained"
+msgstr ""
+
+#: routes/lists.js:237
+msgid "Invalid key"
+msgstr ""
+
+#: routes/lists.js:239
+msgid "Expired key"
+msgstr ""
+
+#: routes/lists.js:241
+msgid "Revoked key"
+msgstr ""
+
+#: routes/lists.js:288
+msgid "Force Subscribe"
+msgstr ""
+
+#: routes/lists.js:291
+msgid "Initializing"
+msgstr ""
+
+#: routes/lists.js:294
+msgid "Initialized"
+msgstr ""
+
+#: routes/lists.js:297
+msgid "Importing"
+msgstr ""
+
+#: routes/lists.js:303
+msgid "Errored"
+msgstr ""
+
+#: routes/lists.js:381 routes/lists.js:450 routes/lists.js:475
+msgid "Could not find subscriber with specified ID"
+msgstr ""
+
+#: routes/lists.js:427
+msgid "Could not add subscription"
+msgstr ""
+
+#: routes/lists.js:432
+msgid "%s was successfully added to your list"
+msgstr ""
+
+#: routes/lists.js:434
+msgid "%s was not added to your list"
+msgstr ""
+
+#: routes/lists.js:456
+msgid "Could not unsubscribe user"
+msgstr ""
+
+#: routes/lists.js:459
+msgid "%s was successfully unsubscribed from your list"
+msgstr ""
+
+#: routes/lists.js:479
+msgid "%s was successfully removed from your list"
+msgstr ""
+
+#: routes/lists.js:491
+msgid "Another subscriber with email address %s already exists"
+msgstr ""
+
+#: routes/lists.js:498
+msgid "Subscription settings updated"
+msgstr ""
+
+#: routes/lists.js:500
+msgid "Subscription settings not updated"
+msgstr ""
+
+#: routes/lists.js:542 routes/lists.js:663 routes/lists.js:699
+#: routes/lists.js:727 routes/lists.js:747
+msgid "Could not find import data with specified ID"
+msgstr ""
+
+#: routes/lists.js:573
+msgid "Could not process CSV"
+msgstr ""
+
+#: routes/lists.js:589
+msgid "Could not create importer"
+msgstr ""
+
+#: routes/lists.js:643
+msgid "Empty file"
+msgstr ""
+
+#: routes/lists.js:646
+msgid "Too few rows"
+msgstr ""
+
+#: routes/lists.js:703
+msgid "Import started"
+msgstr ""
+
+#: routes/lists.js:731
+msgid "Import restarted"
+msgstr ""
+
+#: routes/lists.js:797
+msgid "One-step (i.e. no email with confirmation link)"
+msgstr ""
+
+#: routes/lists.js:803
+msgid ""
+"One-step with unsubscription form (i.e. no email with confirmation link)"
+msgstr ""
+
+#: routes/lists.js:809
+msgid "Two-step (i.e. an email with confirmation link will be sent)"
+msgstr ""
+
+#: routes/lists.js:815
+msgid ""
+"Two-step with unsubscription form (i.e. an email with confirmation link will "
+"be sent)"
+msgstr ""
+
+#: routes/lists.js:821
+msgid ""
+"Manual (i.e. unsubscription has to be performed by the list administrator)"
+msgstr ""
+
+#: routes/report-templates.js:246
+msgid "Could not create report template"
+msgstr ""
+
+#: routes/report-templates.js:249
+msgid "Report template “%s” created"
+msgstr ""
+
+#: routes/report-templates.js:257
+msgid "Could not find report template with specified ID"
+msgstr ""
+
+#: routes/report-templates.js:280
+msgid "Report template updated"
+msgstr ""
+
+#: routes/report-templates.js:282
+msgid "Report template not updated"
+msgstr ""
+
+#: routes/report-templates.js:298
+msgid "Report template deleted"
+msgstr ""
+
+#: routes/report-templates.js:300
+msgid "Could not delete specified report template"
+msgstr ""
+
+#: routes/reports.js:124 routes/reports.js:130
+msgid "Could not create report"
+msgstr ""
+
+#: routes/reports.js:135
+msgid "Report “%s” created"
+msgstr ""
+
+#: routes/reports.js:146 routes/reports.js:224 routes/reports.js:239
+#: routes/reports.js:265 routes/reports.js:275
+msgid "Could not find report with specified ID"
+msgstr ""
+
+#: routes/reports.js:188 routes/reports.js:194
+msgid "Could not update report"
+msgstr ""
+
+#: routes/reports.js:197
+msgid "Report updated"
+msgstr ""
+
+#: routes/reports.js:199
+msgid "Report not updated"
+msgstr ""
+
+#: routes/reports.js:212
+msgid "Report deleted"
+msgstr ""
+
+#: routes/reports.js:214
+msgid "Could not delete specified report"
+msgstr ""
+
+#: routes/reports.js:230
+msgid "Could not find report template"
+msgstr ""
+
+#: routes/reports.js:260
+msgid "Unknown type of template"
+msgstr ""
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr ""
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr ""
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr ""
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr ""
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr ""
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr ""
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr ""
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr ""
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr ""
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr ""
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr ""
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr ""
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr ""
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr ""
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr ""
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr ""
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr ""
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr ""
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr ""
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr ""
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr ""
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr ""
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr ""
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr ""
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr ""
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr ""
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr ""
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr ""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr ""
+
+#: routes/subscription.js:33
+msgid "Not allowed by CORS"
+msgstr ""
+
+#: routes/subscription.js:61 routes/subscription.js:176
+#: routes/subscription.js:286 routes/subscription.js:382
+#: routes/subscription.js:459 routes/subscription.js:535
+#: routes/subscription.js:566 routes/subscription.js:626
+#: routes/subscription.js:682 routes/subscription.js:760
+#: routes/subscription.js:897
+msgid "Selected list not found"
+msgstr "Lista nem található"
+
+#: routes/subscription.js:93
+msgid "Could not save subscription"
+msgstr "Feliratkozás mentése nem sikerült"
+
+#: routes/subscription.js:118
+msgid "Subscriber info corrupted or missing"
+msgstr ""
+
+#: routes/subscription.js:136
+msgid "Email address changed"
+msgstr "Email cím megváltoztatva."
+
+#: routes/subscription.js:179 routes/subscription.js:385
+msgid "The list does not allow public subscriptions."
+msgstr "A lista nem fogad nyilvános feliratkozásokat."
+
+#: routes/subscription.js:355 routes/subscription.js:357
+msgid "Email address not set"
+msgstr "Email cím nincs megadva."
+
+#: routes/subscription.js:653
+msgid ""
+"An email with further instructions has been sent to the provided address"
+msgstr "A további teendőket tartalmazó levelet kiküldtük a megadott címre. "
+
+#: routes/subscription.js:861 routes/subscription.js:877
+msgid "Public key is not set"
+msgstr "Publikus kulcs nincs megadva."
+
+#: routes/templates.js:84
+msgid "Could not create template"
+msgstr "Sablon létrehozása nem sikerült"
+
+#: routes/templates.js:87
+msgid "Template created"
+msgstr "Sablon létrehozva."
+
+#: routes/templates.js:126
+msgid "Template settings updated"
+msgstr "Sablon beállításai frissítve"
+
+#: routes/templates.js:128
+msgid "Template settings not updated"
+msgstr ""
+
+#: routes/templates.js:144
+msgid "Template duplicated"
+msgstr ""
+
+#: routes/templates.js:146
+msgid "Could not duplicate specified template"
+msgstr ""
+
+#: routes/templates.js:157
+msgid "Template deleted"
+msgstr "Sablon törölve."
+
+#: routes/templates.js:159
+msgid "Could not delete specified template"
+msgstr ""
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr ""
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr ""
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr ""
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr ""
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr ""
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr ""
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr ""
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr ""
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr ""
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr ""
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "A jelszava sikeresen megváltoztatva."
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr ""
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr ""
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr ""
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr ""
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr ""
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr ""
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr ""
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr ""
+
+#: services/feedcheck.js:146
+msgid "RSS entry %s"
+msgstr "RSS bejegyzés %s"
+
+#: services/importer.js:249
+msgid "Could not access import file"
+msgstr "Import file nem érhető el"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr ""
diff --git a/languages/it_IT.mo b/languages/it_IT.mo
new file mode 100644
index 00000000..7e5a8f97
Binary files /dev/null and b/languages/it_IT.mo differ
diff --git a/languages/it_IT.po b/languages/it_IT.po
new file mode 100644
index 00000000..b35ef79f
--- /dev/null
+++ b/languages/it_IT.po
@@ -0,0 +1,4661 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Language-Team: \n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2018-04-11 12:42+0200\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: 2018-04-05 15:43+0200\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Last-Translator: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Language: it\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+msgid "Self hosted email newsletter app"
+msgstr "Applicazione di newsletter self-hosted"
+
+#: views/blacklist.hbs:1 views/campaigns/blacklisted.hbs:1
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/forms/create.hbs:1
+#: views/lists/forms/edit.hbs:1 views/lists/forms/forms.hbs:1
+#: views/lists/lists.hbs:1 views/lists/segments/create.hbs:1
+#: views/lists/segments/edit.hbs:1 views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/report-templates/create.hbs:1 views/report-templates/edit.hbs:1
+#: views/report-templates/report-templates.hbs:1
+#: views/reports/create-select-template.hbs:1 views/reports/create.hbs:1
+#: views/reports/edit.hbs:1 views/reports/output.hbs:1
+#: views/reports/reports.hbs:1 views/reports/view.hbs:1 views/settings.hbs:1
+#: views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Home"
+
+#: views/blacklist.hbs:2 views/blacklist.hbs:3 views/layout.hbs:7
+#: views/lists/subscription/edit.hbs:15
+msgid "Blacklist"
+msgstr "Lista nera"
+
+#: views/blacklist.hbs:4 views/users/api.hbs:76
+msgid "Add email to blacklist"
+msgstr "Aggiungi email alla lista nera"
+
+#: views/blacklist.hbs:5
+msgid "Add"
+msgstr "Aggiungi"
+
+#: views/blacklist.hbs:6
+msgid "Email"
+msgstr "Email"
+
+#: views/campaigns/blacklisted.hbs:2 views/campaigns/bounced.hbs:2
+#: views/campaigns/campaigns.hbs:2 views/campaigns/campaigns.hbs:7
+#: views/campaigns/clicked.hbs:2 views/campaigns/complained.hbs:2
+#: views/campaigns/create-rss.hbs:2 views/campaigns/create-triggered.hbs:2
+#: views/campaigns/create.hbs:2 views/campaigns/delivered.hbs:2
+#: views/campaigns/edit-rss.hbs:2 views/campaigns/edit-triggered.hbs:2
+#: views/campaigns/edit.hbs:2 views/campaigns/opened.hbs:2
+#: views/campaigns/unsubscribed.hbs:2 views/campaigns/upload-attachment.hbs:2
+#: views/campaigns/view.hbs:2 lib/tools.js:133 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Campagne"
+
+#: views/campaigns/blacklisted.hbs:3 views/campaigns/blacklisted.hbs:4
+msgid "Blacklisted info"
+msgstr "Informazioni lista nera"
+
+#: views/campaigns/blacklisted.hbs:5 views/campaigns/bounced.hbs:5
+#: views/campaigns/clicked.hbs:5 views/campaigns/complained.hbs:5
+#: views/campaigns/delivered.hbs:5 views/campaigns/edit-rss.hbs:5
+#: views/campaigns/edit-triggered.hbs:5 views/campaigns/edit.hbs:5
+#: views/campaigns/opened.hbs:5 views/campaigns/unsubscribed.hbs:5
+#: views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Vedi campagna"
+
+#: views/campaigns/blacklisted.hbs:6
+msgid "Subscribers who blacklisted by global blacklist:"
+msgstr "Iscritti in lista nera derivati dalla lista nera globale:"
+
+#: views/campaigns/blacklisted.hbs:7 views/campaigns/bounced.hbs:7
+#: views/campaigns/clicked.hbs:15 views/campaigns/complained.hbs:7
+#: views/campaigns/delivered.hbs:7 views/campaigns/opened.hbs:9
+#: views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:8 views/lists/view.hbs:19
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Indirizzo"
+
+#: views/campaigns/blacklisted.hbs:8 views/campaigns/bounced.hbs:8
+#: views/campaigns/clicked.hbs:16 views/campaigns/complained.hbs:8
+#: views/campaigns/delivered.hbs:8 views/campaigns/opened.hbs:10
+#: views/campaigns/unsubscribed.hbs:8 views/lists/subscription/add.hbs:6
+#: views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:20
+#: views/subscription/partials/subscription-custom-fields.hbs:3
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Nome"
+
+#: views/campaigns/blacklisted.hbs:9 views/campaigns/bounced.hbs:9
+#: views/campaigns/clicked.hbs:17 views/campaigns/complained.hbs:9
+#: views/campaigns/delivered.hbs:9 views/campaigns/opened.hbs:11
+#: views/campaigns/unsubscribed.hbs:9 views/lists/subscription/add.hbs:7
+#: views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:21
+#: views/subscription/partials/subscription-custom-fields.hbs:4
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Cognome"
+
+#: views/campaigns/blacklisted.hbs:10
+msgid "Reason"
+msgstr "Ragione"
+
+#: views/campaigns/blacklisted.hbs:11
+msgid "Time"
+msgstr "Tempo"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Informazioni rimbalzo"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Iscritti che hanno rimbalzato e sono stati rimossi:"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "Risposta SMTP"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Tempo di rimbalzo"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:26
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:28
+msgid "Create Campaign"
+msgstr "Crea Campagna"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Campagna regolare"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "Campagna RSS"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr "Campagna attivabile"
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/forms/forms.hbs:6
+#: views/lists/lists.hbs:5 views/lists/segments/segments.hbs:6
+#: views/report-templates/partials/report-template-fields.hbs:1
+#: views/report-templates/report-templates.hbs:10
+#: views/reports/partials/report-fields.hbs:1
+#: views/reports/partials/report-fields.hbs:5
+#: views/reports/partials/report-fields.hbs:9 views/reports/reports.hbs:6
+#: views/templates/templates.hbs:5 views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Nome"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:74
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10
+#: views/lists/forms/edit.hbs:9 views/lists/forms/forms.hbs:7
+#: views/lists/lists.hbs:8 views/mosaico/editor.hbs:3
+#: views/partials/merge-tag-reference.hbs:4
+#: views/report-templates/partials/report-template-fields.hbs:3
+#: views/report-templates/report-templates.hbs:11
+#: views/reports/partials/report-fields.hbs:3
+#: views/reports/partials/report-fields.hbs:6 views/reports/reports.hbs:8
+#: views/templates/create.hbs:9 views/templates/edit.hbs:8
+#: views/templates/templates.hbs:6 views/triggers/create.hbs:7
+#: views/triggers/edit.hbs:8 views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Descrizione"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:75
+#: views/lists/view.hbs:22 views/lists/view.hbs:30
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Stato"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:76
+#: views/lists/view.hbs:23 views/lists/view.hbs:24
+#: views/report-templates/report-templates.hbs:12
+#: views/reports/partials/report-fields.hbs:7 views/reports/reports.hbs:9
+msgid "Created"
+msgstr "Creato"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Informazioni link"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:63
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:64
+msgid "Clicks"
+msgstr "Clicks"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:65
+msgid "% of clicks"
+msgstr "% di clicks"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:66
+msgid "% of messages"
+msgstr "% di messagi"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:69
+msgid "Aggregated clicks"
+msgstr "Clicks aggregati"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Iscritti che hanno cliccato un link:"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Iscritti che hanno cliccato questo link:"
+
+#: views/campaigns/clicked.hbs:13 views/campaigns/opened.hbs:7
+msgid "Stats by country"
+msgstr "Statistiche per nazione"
+
+#: views/campaigns/clicked.hbs:14 views/campaigns/opened.hbs:8
+msgid "Stats by device type"
+msgstr "Statistiche per tipo di dispositivo"
+
+#: views/campaigns/clicked.hbs:18
+msgid "First click time"
+msgstr "Tempo primo click"
+
+#: views/campaigns/clicked.hbs:19
+msgid "Click count"
+msgstr "Conteggio clicks"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Informazioni reclamo"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Iscritti che hanno reclamato e sono stati rimossi"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Tempo reclamo"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:21
+msgid "Create RSS Campaign"
+msgstr "Crea campagna RSS"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+"Le campagne RSS configurano un registratore per gli indirizzi dei feed RSS. "
+"Qualvolta un nuovo elemento venga trovato per il feed, viene inviato alle "
+"liste selezionate come una email."
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Nome campagna"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/report-templates/partials/report-template-fields.hbs:4
+#: views/reports/partials/report-fields.hbs:4 views/templates/create.hbs:11
+#: views/templates/edit.hbs:10 views/triggers/create.hbs:9
+#: views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "HTML è consentito"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "Lista"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/reports/partials/report-select-template.hbs:2
+#: views/subscription/partials/subscription-custom-fields.hbs:9
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Seleziona"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "Iscritti"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "URL del feed RSS"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+"I nuovi elementi per questo feed RSS sono inviati agli iscritti come "
+"messaggi email."
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "Email da \"Nome\""
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit-triggered.hbs:17 views/campaigns/edit.hbs:18
+#: views/settings.hbs:23
+msgid "This is the name your emails will come from"
+msgstr "Questo è il nome che verrà' visualizzato come mittente"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "Email dall'indirizzo"
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:21
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:25
+msgid "This is the address people will send replies to"
+msgstr "Questo è l'indirizzo a cui gli iscritti risponderanno"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:26 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:25
+msgid "Disable opened tracking"
+msgstr "Disabilita tracciamento aperture"
+
+#: views/campaigns/create-rss.hbs:20 views/campaigns/create-triggered.hbs:25
+#: views/campaigns/create.hbs:27 views/campaigns/edit-rss.hbs:23
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26
+msgid "Disable clicked tracking"
+msgstr "Disabilita tracciamento clicks"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr "Crea una campagna attivabile"
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/reports/reports.hbs:7 views/templates/create.hbs:13
+msgid "Template"
+msgstr "Template"
+
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr "Seleziona un template:"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr "Selezionando un template, si crea una copia su cui andare a lavorare"
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr "In alternativa utilizza un URL per il contenuto del messaggio:"
+
+#: views/campaigns/create-triggered.hbs:17 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:26 views/campaigns/edit.hbs:29
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+"Se un messaggio viene inviato questa URL verrà' richiamata assorbendo i "
+"merge tags come body del messaggio. Utilizza questa opzione se vuoi scrivere "
+"tu l'HTML del messaggio"
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr "Oggetto dell'email"
+
+#: views/campaigns/create-triggered.hbs:23 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:27
+msgid "Keep it relevant and non-spammy"
+msgstr "Ricordati di mantenerla rilevante e non creare spam"
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+"Questo è l'indirizzo a cui gli iscritti risponderanno se non specifichi un "
+"indirizzo email 'reply-to'"
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr "Indirizzo email 'reply-to'"
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr "Se impostato, questo sarà' l'indirizzo a cui le persone risponderanno"
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr "Informazioni della consegna"
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+"Iscritti che hanno ricevuto il messaggio e non hanno reclamato e non si sono "
+"rimossi"
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr "Ora di consegna"
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr "Modifica campagna RSS"
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr "Impostazioni generali"
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+"Utilizza tag di assorbimento speciali [RSS_ENTRY] per evidenziare il "
+"contenuto del messaggio all'interno del RSS. Puoi inoltre utilizzare "
+"qualsiasi tag di merge valido."
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:35
+msgid "Delete Campaign"
+msgstr "Cancella "
+
+#: views/campaigns/edit-rss.hbs:25 views/campaigns/edit-triggered.hbs:28
+#: views/campaigns/edit.hbs:36 views/lists/edit.hbs:20
+#: views/lists/fields/edit.hbs:39 views/lists/forms/edit.hbs:33
+#: views/lists/forms/forms.hbs:12 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:18
+#: views/reports/edit.hbs:6 views/settings.hbs:97 views/templates/edit.hbs:13
+#: views/triggers/edit.hbs:30 views/users/account.hbs:18
+msgid "Update"
+msgstr "Aggiorna"
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr "Modifica campagna azionabile"
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+#: routes/forms.js:143
+msgid "General"
+msgstr "Generale"
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27
+msgid "Template Settings"
+msgstr "Impostazioni Template"
+
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28
+msgid "Template URL"
+msgstr "URL Template"
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr "Modifica Campagna"
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:30
+msgid "Attachments"
+msgstr "Allegati"
+
+#: views/campaigns/edit.hbs:31
+msgid "File"
+msgstr "File"
+
+#: views/campaigns/edit.hbs:32
+msgid "Size"
+msgstr "Dimensione"
+
+#: views/campaigns/edit.hbs:33 views/campaigns/view.hbs:68
+#: views/lists/fields/fields.hbs:12 views/lists/forms/forms.hbs:9
+#: views/lists/view.hbs:33
+msgid "No data available in table"
+msgstr "Non ci sono dati disponibili nella tabella"
+
+#: views/campaigns/edit.hbs:34 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr "Aggiungi allegato"
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr "Informazioni apertura"
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr "Iscritti che hanno aperto il messaggio:"
+
+#: views/campaigns/opened.hbs:12
+msgid "First open"
+msgstr "Prima apertura"
+
+#: views/campaigns/opened.hbs:13
+msgid "Opened count"
+msgstr "Numero di aperture"
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr "Informazioni utenti rimossi"
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr "Iscritti che si sono rimossi:"
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:28
+#: views/lists/subscription/import.hbs:13 routes/lists.js:206
+msgid "Unsubscribed"
+msgstr "Rimossi"
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr "Carica"
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr "Panoramica"
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr "Links"
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr "Feed URL"
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr "Ultimo controllo"
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr "Non ancora controllati"
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr "attiva la campagna per controllare il feed per nuovi messaggi"
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr "Stato RSS"
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr "Guarda l'anteprima come"
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr "Aggiungi un utente di test"
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr "Non sono presenti utenti di test, creane uno qui"
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr "Vai"
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:26
+msgid "Delivered"
+msgstr "Consegnato"
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr "Elenca iscritti che hanno ricevuto il messaggio"
+
+#: views/campaigns/view.hbs:22
+msgid "Blacklisted"
+msgstr "In lista nera"
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who blacklisted by global blacklist"
+msgstr "Lista degli iscritti in lista nera per la lista nera globale"
+
+#: views/campaigns/view.hbs:24 routes/lists.js:206
+msgid "Bounced"
+msgstr "Rimbalzato"
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who bounced"
+msgstr "Lista utenti che hanno rimbalzato"
+
+#: views/campaigns/view.hbs:26
+msgid "Complaints"
+msgstr "Reclami"
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who complained for this message"
+msgstr "Lista degli iscritti che hanno fatto un reclamo per questo messaggio"
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who unsubscribed after this message"
+msgstr ""
+"Lista degli utenti che si sono cancellati in seguito a questo messaggio"
+
+#: views/campaigns/view.hbs:30
+msgid "Opened"
+msgstr "Aperta"
+
+#: views/campaigns/view.hbs:31
+msgid "List subscribers who opened this message"
+msgstr "Lista degli iscritti che hanno aperto questo messaggio"
+
+#: views/campaigns/view.hbs:32
+msgid "Clicked"
+msgstr "Cliccate"
+
+#: views/campaigns/view.hbs:33 views/campaigns/view.hbs:70
+msgid "List subscribers who clicked on a link"
+msgstr "Lista degli iscritti che hanno cliccato su di un link"
+
+#: views/campaigns/view.hbs:34
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+"Sei sicuro? Questa azione farà iniziare l'invio dei messaggi alla lista "
+"selezionata"
+
+#: views/campaigns/view.hbs:35
+msgid "Delay sending"
+msgstr "Ritarda invio"
+
+#: views/campaigns/view.hbs:36
+msgid "hours"
+msgstr "ore"
+
+#: views/campaigns/view.hbs:37
+msgid "minutes"
+msgstr "minuti"
+
+#: views/campaigns/view.hbs:38
+msgid "Send to subscribers:"
+msgstr "Invia agli iscritti:"
+
+#: views/campaigns/view.hbs:39
+msgid "Are you sure? This action would reset scheduling"
+msgstr "Sei sicuro? Questa azione resetterà la programmazione"
+
+#: views/campaigns/view.hbs:40
+msgid "Cancel"
+msgstr "Annulla"
+
+#: views/campaigns/view.hbs:41
+msgid "Sending scheduled"
+msgstr "Invio programmato"
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:54
+msgid "Pause"
+msgstr "Pausa"
+
+#: views/campaigns/view.hbs:43 routes/campaigns.js:253
+msgid "Sending"
+msgstr "Invio in corso"
+
+#: views/campaigns/view.hbs:44 views/campaigns/view.hbs:48
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+"Sei sicuro? Questa azione riprenderà l'invio dei messaggi alla lista "
+"selzionata"
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+"Sei sicuro? Questa azione resetterà tutte le statistiche riguardanti il "
+"progresso attuale"
+
+#: views/campaigns/view.hbs:46
+msgid "Resume"
+msgstr "Riprendi"
+
+#: views/campaigns/view.hbs:47 views/campaigns/view.hbs:51
+msgid "Reset"
+msgstr "Resetta"
+
+#: views/campaigns/view.hbs:50
+msgid "Continue"
+msgstr "Continua"
+
+#: views/campaigns/view.hbs:52
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+"Tutti i messaggi inviati! Premi \"Continua\" se vuoi inviare questa campagna "
+"ai nuovi iscritti"
+
+#: views/campaigns/view.hbs:53
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Sei sicuro? Questa azione metterà in pausa l'invio dei nuovi ingressi dal "
+"feed RSS come email alla lista selezionata"
+
+#: views/campaigns/view.hbs:55 views/campaigns/view.hbs:59
+msgid "Campaign status:"
+msgstr "Stato campagna:"
+
+#: views/campaigns/view.hbs:56
+msgid "ACTIVE"
+msgstr "ATTIVA"
+
+#: views/campaigns/view.hbs:57
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Sei sicuro? Questa azione iniziera ad inviare i nuovi ingressi dal feed RSS "
+"come email alla lista selezionata"
+
+#: views/campaigns/view.hbs:58
+msgid "Activate"
+msgstr "Attiva"
+
+#: views/campaigns/view.hbs:60
+msgid "INACTIVE"
+msgstr "INATTIVA"
+
+#: views/campaigns/view.hbs:61
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+"Questa e' una campagna innescabile. I messaggi sono inviati solo agli "
+"iscritti che hanno innescato questa campagna"
+
+#: views/campaigns/view.hbs:62
+msgid "see more"
+msgstr "guarda di più"
+
+#: views/campaigns/view.hbs:67
+msgid "List subscribers who clicked this link"
+msgstr "Lista iscritti che hanno cliccato questo link"
+
+#: views/campaigns/view.hbs:71
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+"I clicks sono contati come iscritti unici che hanno cliccato un link "
+"specifico o (nella vista aggregata) su di un qualsiasi link"
+
+#: views/campaigns/view.hbs:72
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+"Se un nuovo ingresso è trovato nel feed della campagna, una nuova sotto-"
+"campagna verrà creata per quella entry e sarà visualizzata ui"
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr "Cambia la tua password"
+
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr ""
+"Abbiamo ricevuto una richiesta di cambio password per il tuo account "
+"Mailtrain"
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr "Cambia password"
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+"Se non hai chiesto tu di cambiare password, puoi ignorare questa email e la "
+"tua password resterà la stessa."
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr "Preferenze"
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/forms/edit.hbs:20
+#: views/lists/subscription/edit.hbs:16
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:2
+#: views/subscription/web-manage.mjml.hbs:3
+#: views/subscription/web-unsubscribe.mjml.hbs:1
+#: views/subscription/web-unsubscribe.mjml.hbs:2 routes/forms.js:223
+#: routes/lists.js:288
+msgid "Unsubscribe"
+msgstr "Cancella iscrizione"
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr "Guarda questa email nel tuo browser"
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr "Ciao [FIRST_NAME/Customer],"
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr "Ringraziandoti"
+
+#: views/index.hbs:1
+msgid "List Management"
+msgstr "Gestione lista"
+
+#: views/index.hbs:2
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+"Mailtrain ti permette di gestire facilmente grosse liste. Milioni di "
+"iscritti? Nessun problema. Puoi aggiungere iscritti manualmente, via API "
+"oppure importarli tramite CSV. Tutte le liste hanno la possibilità di "
+"aggiungere campi personalizzati e tag di merge."
+
+#: views/index.hbs:3 views/index.hbs:7 views/index.hbs:10 views/index.hbs:13
+#: views/index.hbs:16 views/index.hbs:19 views/index.hbs:22 views/index.hbs:25
+#: views/index.hbs:28
+msgid "Show more"
+msgstr "Guarda di più"
+
+#: views/index.hbs:4 views/lists/fields/create.hbs:3
+#: views/lists/fields/edit.hbs:3 views/lists/fields/fields.hbs:3
+#: views/lists/fields/fields.hbs:5 views/lists/view.hbs:6
+msgid "Custom Fields"
+msgstr "Campi personalizzati"
+
+#: views/index.hbs:5
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+"Campi di testo, numeri, drop downs o segni di spunta, Mailtrain li "
+"implementa tutti. Ogni campo personalizzato può essere incluso nella "
+"newsletter generata tramite i tag di merge."
+
+#: views/index.hbs:6
+msgid "Mailtrain also supports custom forms."
+msgstr "Mailtrain supporta form personalizzati"
+
+#: views/index.hbs:8
+msgid "List Segmentation"
+msgstr "Segmentazione della lista"
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+"Invia messaggi solo agli iscritti che rientrano in una regola di "
+"segmentazione predefinita. Non c'è bisogno di creare liste separate con "
+"piccole differenze."
+
+#: views/index.hbs:11
+msgid "RSS Campaigns"
+msgstr "Campagne RSS"
+
+#: views/index.hbs:12
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+"Configura Mailtrain per tracciare i feed RSS e se viene identificato un "
+"nuovo ingresso Mailtrain auto genera una nuova campagna utilizzando i dati "
+"del contenuto del messaggio del feed e lo invia agli iscritti selezionati."
+
+#: views/index.hbs:14
+msgid "GPG Encryption"
+msgstr "Crittografia GPG"
+
+#: views/index.hbs:15
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+"Se una lista ha un campo personalizzato per un set di chiave pubblica GPG "
+"allora gli iscritti possono caricare la loro chiave GPG pubblica per "
+"ricevere messaggi criptati dalla lista."
+
+#: views/index.hbs:17
+msgid "Click Stats"
+msgstr "Statistiche click"
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+"Dopo che una campagna è stata inviata, controlla le statistiche di ogni "
+"click per ogni link incluso nel messaggio."
+
+#: views/index.hbs:20
+msgid "Template Editors"
+msgstr "Editors dei templates"
+
+#: views/index.hbs:21
+msgid ""
+"Mailtrain ships with GrapeJS and Mosaico built in, two advanced template "
+"editors. Mailtrain also offers a code editor if you prefer to handcraft the "
+"HTML yourself."
+msgstr ""
+"Mailtrain include GrapeJS e Mosaico, due editors di template avanzati. "
+"Mailtrain offre inoltre un editor di codice se preferisci scrivere tu l'HTML."
+
+#: views/index.hbs:23
+msgid "Send via Any Provider"
+msgstr "Invia tramite qualsiasi provider"
+
+#: views/index.hbs:24
+msgid ""
+"You can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+"Puoi utilizzare qualsiasi provider che supporti SMTP per inviare la tua "
+"newsletter. La gestione di rimbalzi e reclami via webhooks è supportata per "
+"SES, SparkPost, SendGrid, Mailgun, Postfix e ZoneMTA."
+
+#: views/index.hbs:26 lib/tools.js:137
+msgid "Automation"
+msgstr "Automazione"
+
+#: views/index.hbs:27
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+"Definisci gli inneschi di automazione per l'invio di messaggi specifici "
+"quando un utente innesca una azione specifica."
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr "Attiva navigazione"
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr "Wiki"
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr "Blog"
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr "Account"
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr "Impostazioni"
+
+#: views/layout.hbs:8 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr "API"
+
+#: views/layout.hbs:9
+msgid "Log out"
+msgstr "Esci"
+
+#: views/layout.hbs:10 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr "Log in"
+
+#: views/layout.hbs:11
+msgid "Self Hosted Newsletter App Built on Top of Nodemailer"
+msgstr ""
+"Applicazione per newsletter self hosted costruita sulla base di Nodemailer"
+
+#: views/layout.hbs:12 views/layout.hbs:14
+msgid "Source on GitHub"
+msgstr "Sorgenti su GitHub"
+
+#: views/layout.hbs:13
+msgid "Subscribe to Our Newsletter"
+msgstr "Iscriviti alla nostra Newsletter"
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/forms/create.hbs:2
+#: views/lists/forms/edit.hbs:2 views/lists/forms/forms.hbs:2
+#: views/lists/lists.hbs:2 views/lists/lists.hbs:4
+#: views/lists/segments/create.hbs:2 views/lists/segments/edit.hbs:2
+#: views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:125 routes/lists.js:59
+msgid "Lists"
+msgstr "Liste"
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:13
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr "Crea Lista"
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr "Nome lista"
+
+#: views/lists/create.hbs:9 views/lists/edit.hbs:15
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Iscrizione"
+
+#: views/lists/create.hbs:10 views/lists/edit.hbs:16
+msgid "Allow public users to subscribe themselves"
+msgstr "Permetti utenti pubblici di iscriversi da soli"
+
+#: views/lists/create.hbs:11 views/lists/edit.hbs:17
+msgid "Unsubscription"
+msgstr "Cancellazione iscrizione"
+
+#: views/lists/create.hbs:12 views/lists/edit.hbs:18
+msgid "Select how an unsuscription request by subscriber is handled."
+msgstr ""
+"Seleziona come una richiesta di rimozione dell'iscrizione viene gestita."
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:8
+msgid "Edit List"
+msgstr "Modifica lista"
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr "Guarda Lista"
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr "ID lista"
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr "Questo è l'ID della lista mostrato agli iscritti"
+
+#: views/lists/edit.hbs:12
+msgid "Custom Form"
+msgstr "Form personalizzato"
+
+#: views/lists/edit.hbs:13 views/lists/forms/forms.hbs:11
+msgid "Default Mailtrain Form"
+msgstr "Form predefinito di Mailtrain"
+
+#: views/lists/edit.hbs:14
+msgid ""
+"The custom form used for this list. You can create a form here."
+msgstr ""
+"Il form personalizzato per questa lista. Puoi creare un form qui."
+
+#: views/lists/edit.hbs:19
+msgid "Delete List"
+msgstr "Cancella lista"
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr "Crea campo"
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr "Crea campo personalizzato"
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr "Nome campo"
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr "Tipo campo"
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr "Testo"
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr "Numero"
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr "Sito web"
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr "Chiave pubblica GPG"
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr "Testo multi linea"
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr "JSON"
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr "Data"
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr "Data (MM/GG/ANNO)"
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr "Data (GG/MM/ANNO)"
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr "Compleanno"
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr "Compleanno (MM/GG)"
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr "Compleanno (GG/MM)"
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr "Raggruppati"
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr "Drop Downs"
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr "Radio Buttons"
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr "Checkboxes"
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr "Option for group value"
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr "Group"
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr "Richiesto per le group options"
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr "Valore di merge tag di default"
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+"Per i gruppi di elementi come i checkboxes, puoi controllare l'aspetto "
+"visivo del merge tag con un template opzionale. Il template usa la sintassi "
+"di handlebars e puoi trovare tutti i valori dall'array {{values}}"
+"code>, per esempio {{#each values}} {{this}} {{/each}}. Se il "
+"template non è definito allora i valori multipli vengono uniti dalla "
+"virgola. Puoi anche utilizzare questo template per visualizzare valori JSON "
+"(se il valore JSON è un array allora l'array viene esposto come "
+"values, altrimenti puoi accedere direttamente alle keys del "
+"JSON)."
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Visibile"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Aggiungi campo"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Modifica campo"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr "Modifica campo personalizzato"
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr "Indietro ai campi"
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/mosaico/editor.hbs:2 views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr "Merge tag"
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr "Merge Tag"
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr "Metti questo tag nel tuo contenuto:"
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Elimina campo"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:26
+#: views/report-templates/partials/report-template-fields.hbs:5
+msgid "Type"
+msgstr "Tipo"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/forms/edit.hbs:26 views/lists/forms/forms.hbs:8
+#: views/lists/segments/segments.hbs:8 views/lists/segments/view.hbs:12
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:276
+#: routes/campaigns.js:568 routes/campaigns.js:657 routes/campaigns.js:706
+#: routes/lists.js:170 routes/lists.js:257 routes/report-templates.js:51
+#: routes/templates.js:183 routes/triggers.js:297
+msgid "Edit"
+msgstr "Modifica"
+
+#: views/lists/forms/create.hbs:3 views/lists/forms/edit.hbs:3
+#: views/lists/forms/forms.hbs:3 views/lists/forms/forms.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Forms"
+msgstr "Form personalizzati"
+
+#: views/lists/forms/create.hbs:4
+msgid "Create Form"
+msgstr "Crea form"
+
+#: views/lists/forms/create.hbs:5 views/lists/forms/forms.hbs:4
+msgid "Create Custom Form"
+msgstr "Crea form personalizzato"
+
+#: views/lists/forms/create.hbs:6 views/lists/forms/create.hbs:7
+#: views/lists/forms/edit.hbs:7 views/lists/forms/edit.hbs:8
+msgid "Form Name"
+msgstr "Nome form"
+
+#: views/lists/forms/create.hbs:8
+msgid "Add Form"
+msgstr "Aggiungi form"
+
+#: views/lists/forms/edit.hbs:4
+msgid "Edit Form"
+msgstr "Modifica Form"
+
+#: views/lists/forms/edit.hbs:5
+msgid "Edit Custom Form"
+msgstr "Modifica form personalizzato"
+
+#: views/lists/forms/edit.hbs:6
+msgid "Back to forms"
+msgstr "Indietro ai forms"
+
+#: views/lists/forms/edit.hbs:10
+msgid "Optional comments about this form"
+msgstr "Commenti opzionali per questo form"
+
+#: views/lists/forms/edit.hbs:11
+msgid "Form Preview"
+msgstr "Anteprima Form"
+
+#: views/lists/forms/edit.hbs:12
+msgid ""
+"Note: These links are solely for a quick preview. If you submit a preview "
+"form you'll get redirected to the list's default form."
+msgstr ""
+"Nota: Questi links sono solo per un'anteprima veloce. Se confermi l'invio di "
+"un form in anteprima verrai rediretto al form di default della lista."
+
+#: views/lists/forms/edit.hbs:13 views/lists/subscription/add.hbs:16
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:4
+#: routes/forms.js:157 routes/lists.js:288
+msgid "Subscribe"
+msgstr "Iscriviti"
+
+#: views/lists/forms/edit.hbs:14
+msgid "Confirm Subscription Notice"
+msgstr "Notifica iscrizione confermata"
+
+#: views/lists/forms/edit.hbs:15
+msgid "Confirm Unsubscription Notice"
+msgstr "Conferma notifica di cancellazione iscrizione"
+
+#: views/lists/forms/edit.hbs:16
+msgid "Subscribed Notice"
+msgstr "Notifica iscrizione"
+
+#: views/lists/forms/edit.hbs:17
+msgid "Updated Notice"
+msgstr "Notifica di aggiornamento"
+
+#: views/lists/forms/edit.hbs:18
+msgid "Unsubscribed Notice"
+msgstr "Notifica di cancellazione di iscrizione"
+
+#: views/lists/forms/edit.hbs:19
+msgid "Manual Unsubscribe Notice"
+msgstr "Notifica di cancellazione iscrizione manuale"
+
+#: views/lists/forms/edit.hbs:21 routes/forms.js:205
+msgid "Manage"
+msgstr "Gestisci"
+
+#: views/lists/forms/edit.hbs:22
+msgid "Manage Address"
+msgstr "Gestisci indirizzo"
+
+#: views/lists/forms/edit.hbs:23
+msgid "Create a test user for additional options"
+msgstr "Crea un utente di test per le opzioni aggiuntive"
+
+#: views/lists/forms/edit.hbs:24 views/report-templates/create.hbs:3
+#: views/report-templates/edit.hbs:3
+#: views/report-templates/report-templates.hbs:3 views/templates/create.hbs:2
+#: views/templates/edit.hbs:2 views/templates/templates.hbs:2
+#: views/templates/templates.hbs:4 lib/tools.js:129 routes/templates.js:27
+msgid "Templates"
+msgstr "Templates"
+
+#: views/lists/forms/edit.hbs:25
+msgid "Fields"
+msgstr "Campi"
+
+#: views/lists/forms/edit.hbs:27
+msgid "Form Fields"
+msgstr "Campi del form"
+
+#: views/lists/forms/edit.hbs:28
+msgid "Fields hidden on subscription page:"
+msgstr "Campi nascosti sulla pagina di iscrizione:"
+
+#: views/lists/forms/edit.hbs:29
+msgid "Fields shown on subscription page:"
+msgstr "Campi mostrati sulla pagina di iscrizione:"
+
+#: views/lists/forms/edit.hbs:30
+msgid "Fields hidden on preferences page:"
+msgstr "Campi nascosti sulla pagina delle preferenze:"
+
+#: views/lists/forms/edit.hbs:31
+msgid "Fields shown on preferences page:"
+msgstr "Campi mostrati sulla pagina delle preferenze:"
+
+#: views/lists/forms/edit.hbs:32
+msgid "Delete Form"
+msgstr "Cancella form"
+
+#: views/lists/forms/forms.hbs:10
+msgid "The default form for this list is:"
+msgstr "Il form di default per questa lista:"
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7 views/reports/partials/report-fields.hbs:10
+msgid "Subscribers"
+msgstr "Iscritti"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:7
+#: views/lists/view.hbs:14
+msgid "Segments"
+msgstr "Segmenti"
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr "Crea segmento"
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr "Nome segmento"
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr "Regola di corrispondenza"
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr "Tutte le regole devono corrispondere con"
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr "Qualsiasi regola può corrispondere con"
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr "Aggiungi segmento"
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:12
+msgid "Edit Segment"
+msgstr "Modifica segmento"
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr "Indietro ai segmenti"
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr "Elimina segmento"
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Crea regola"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Regola"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Valore"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+"Usa % come carattere jolly, per esempio \"%test\" fa passare tutti i valori "
+"che finiscono con \"test\""
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr "Usa corrispondenza esatta"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr "Usa range di corrispondenza"
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr "Usa range di corrispondenza relativo"
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr "Da"
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr "giorni"
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr "prima di oggi"
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr "dopo di oggi"
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr "a"
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr "Selezionati"
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr "Non selezionati"
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr "Aggiungi regola"
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:18
+#: views/reports/create-select-template.hbs:5
+#: views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Avanti"
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr "Cancella regola"
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr "Corrispondi"
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:13
+msgid "Segment"
+msgstr "Segmento"
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr "Corrisponde alla regola"
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr "Iscritti corrispondenti"
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr "mostra"
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Aggiungi iscritto"
+
+#: views/lists/subscription/add.hbs:5
+#: views/subscription/partials/subscription-custom-fields.hbs:1
+#: views/users/account.hbs:7
+msgid "Email Address"
+msgstr "Indirizzo Email"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:80 views/settings.hbs:95
+#: views/subscription/partials/subscription-custom-fields.hbs:6
+msgid "Begins with"
+msgstr "Inizia con"
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Inserisci chiave pubblica GPG che verrà usata per crittografare i messaggi "
+"per questo iscritto"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Fuso orario"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "Utente di test?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+"Se selezionato, questa iscrizione può essere usata per l'anteprima dei "
+"messaggi della campagna"
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+"Questa persona non riceverà una email di conferma, quindi assicurati di "
+"avere il permesso di inviargli emails."
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Modifica iscrizione"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Indietro alla lista"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/partials/subscription-unsubscribe-form.hbs:1
+#: lib/helpers.js:42 lib/models/segments.js:11
+msgid "Email address"
+msgstr "Indirizzo email"
+
+#: views/lists/subscription/edit.hbs:17
+msgid "Delete Subscription"
+msgstr "Elimina iscrizione"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Stato dell' Import"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Indiirizzi falliti"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid ""
+"Role-based addresses like postmaster@example.com are blocked when importing. "
+"Subscribers with role-based email addresses can join your list using the "
+"subscription form"
+msgstr ""
+"Gli indirizzi di ruolo come postmaster@example.com sono bloccati durante "
+"l'import. Questi indirizzi possono iscriversi alla tua lista con il form di "
+"iscrizione online."
+
+#: views/lists/subscription/import-failed.hbs:7
+msgid "see here"
+msgstr "guarda qui"
+
+#: views/lists/subscription/import-failed.hbs:9
+msgid "Fail reason"
+msgstr "Motivo di errore"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Importa iscritti"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:21
+#: views/users/api.hbs:36 views/users/api.hbs:44 views/users/api.hbs:52
+#: views/users/api.hbs:64 views/users/api.hbs:75 views/users/api.hbs:83
+#: views/users/api.hbs:91 views/users/api.hbs:96
+msgid "Example"
+msgstr "Esempio"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Inizia import"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "File CSV"
+
+#: views/lists/subscription/import.hbs:6
+msgid "The first line must contain column headings"
+msgstr "La prima linea deve contenere le intestazioni di colonna"
+
+#: views/lists/subscription/import.hbs:7
+msgid "CSV delimiter"
+msgstr "Delimitatore file CSV"
+
+#: views/lists/subscription/import.hbs:8
+msgid "Categorize the imported subscribers as"
+msgstr "Categorizza gli iscritti importati come"
+
+#: views/lists/subscription/import.hbs:9 routes/lists.js:206
+msgid "Subscribed"
+msgstr "Iscritto"
+
+#: views/lists/subscription/import.hbs:10
+msgid "Regular subscriber addresses"
+msgstr "Indirizzi regolari degli iscritti"
+
+#: views/lists/subscription/import.hbs:11
+msgid "Subscribed (Force)"
+msgstr "Iscrizione (Forzata)"
+
+#: views/lists/subscription/import.hbs:12
+msgid "Regular subscriber addresses, resubscribe users that have unsubscribed"
+msgstr ""
+"Indirizzi regolari degli utenti registrati, riscrizione utenti che hanno "
+"cancellato l'iscrizione"
+
+#: views/lists/subscription/import.hbs:14
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr "Email soppresse che saranno cancellate dalla tua lista"
+
+#: views/lists/subscription/import.hbs:15
+msgid "Check imported emails"
+msgstr "Controlla le emails importate"
+
+#: views/lists/subscription/import.hbs:16 views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr "Abilitato"
+
+#: views/lists/subscription/import.hbs:17 views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr "Disabilitato"
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Form di iscrizione"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Lista azioni"
+
+#: views/lists/view.hbs:9 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr "Crea innesco"
+
+#: views/lists/view.hbs:10
+msgid "Add Subscriber"
+msgstr "Aggiungi iscrizione"
+
+#: views/lists/view.hbs:11
+msgid "Import Subscribers"
+msgstr "Importa iscrizioni"
+
+#: views/lists/view.hbs:15
+msgid "Create New Segment"
+msgstr "Crea nuovo segmento"
+
+#: views/lists/view.hbs:16
+msgid "Filter"
+msgstr "Filtra"
+
+#: views/lists/view.hbs:17
+msgid "Subscriptions"
+msgstr "Iscrizioni"
+
+#: views/lists/view.hbs:18
+msgid "Imports"
+msgstr "Importazioni"
+
+#: views/lists/view.hbs:25 routes/campaigns.js:255 routes/lists.js:300
+msgid "Finished"
+msgstr "Finito"
+
+#: views/lists/view.hbs:27
+msgid "Added"
+msgstr "Aggiunto"
+
+#: views/lists/view.hbs:28
+msgid "Updated"
+msgstr "Aggiornato"
+
+#: views/lists/view.hbs:29
+msgid "Failed"
+msgstr "Errore"
+
+#: views/lists/view.hbs:31
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+"Sei sicuro? Questa azione deve essere chiamata solo per risolvere "
+"importazioni in stato di stallo"
+
+#: views/lists/view.hbs:32
+msgid "Restart"
+msgstr "Riavvia"
+
+#: views/mosaico/editor.hbs:1 views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr "Referenza dei tag di merge"
+
+#: views/mosaico/editor.hbs:4
+msgid "MOSAICO Responsive Email Designer"
+msgstr "MOSAICO REsponsive Email Designer"
+
+#: views/mosaico/editor.hbs:5
+msgid "Sucessfully saved"
+msgstr "Salvato con successo"
+
+#: views/mosaico/editor.hbs:6
+msgid "An error occured while saving the document"
+msgstr "Errore durante il salvataggio del documento"
+
+#: views/mosaico/editor.hbs:7
+msgid "Unsaved changes will be lost. Close now?"
+msgstr "Le modifiche non salvate andranno perdute, Chiudere ora?"
+
+#: views/mosaico/editor.hbs:8 views/mosaico/editor.hbs:9
+msgid "Tags"
+msgstr "Tags"
+
+#: views/partials/codeeditor.hbs:1 views/partials/grapejs.hbs:1
+#: views/partials/mosaico.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Contenuto template (HTML)"
+
+#: views/partials/editor-navbar.hbs:1
+msgid "SAVE"
+msgstr "SALVA"
+
+#: views/partials/editor-navbar.hbs:2
+msgid "SAVING"
+msgstr "STO SALVANDO"
+
+#: views/partials/editor-navbar.hbs:3
+msgid "CLOSE"
+msgstr "CHIUDI"
+
+#: views/partials/grapejs.hbs:2
+msgid "Open GrapeJS"
+msgstr "Apri GrapeJS"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "Attiva anteprima HTML"
+
+#: views/partials/html-to-text.hbs:1
+msgid ""
+"To extract the text from HTML click here."
+msgstr ""
+"Per estrarre il testo dal codice HTML clicca qui."
+
+#: views/partials/html-to-text.hbs:2
+msgid ""
+"Please note that your existing plaintext in the field above will be "
+"overwritten. This feature uses the Premailer API, a third party "
+"service. Their Terms of Service and Privacy Policy apply."
+msgstr ""
+"Per favore nota che il tuo testo nel campo qui sopra verrà sovrascritto. "
+"Questa caratteristica usa le Premailer API, un servizio di "
+"terzi. I loro Termini per il servizio e la loro Privacy Policy è applicato."
+
+#: views/partials/html-to-text.hbs:3
+msgid "An error occurred while talking to the server"
+msgstr "C'è stato un errore nel comunicare con il server"
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+"Merge tags sono tags che sono sostituiti prima dell'invio del messaggio. Il "
+"formato del merge tag è il seguente [TAG_NAME] oppure "
+"[TAG_NAME/fallback] dove fallback è un valore "
+"opzionale di testo utilizzato quando TAG_NAME è vuoto."
+
+#: views/partials/modal-carousel.hbs:1
+msgid "{{title}}"
+msgstr "{{}}"
+
+#: views/partials/mosaico.hbs:2
+msgid "Open Mosaico"
+msgstr "Apri Mosaico"
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Contenuto del template (test semplice)"
+
+#: views/report-templates/create.hbs:2 views/report-templates/edit.hbs:2
+#: views/report-templates/report-templates.hbs:2
+#: views/reports/create-select-template.hbs:2 views/reports/create.hbs:2
+#: views/reports/edit.hbs:2 views/reports/output.hbs:2
+#: views/reports/reports.hbs:2 views/reports/reports.hbs:5
+#: views/reports/view.hbs:2 lib/tools.js:144 routes/reports.js:31
+msgid "Reports"
+msgstr "Reports"
+
+#: views/report-templates/create.hbs:4 views/report-templates/create.hbs:6
+#: views/report-templates/report-templates.hbs:4 views/templates/create.hbs:3
+#: views/templates/create.hbs:4 views/templates/create.hbs:12
+#: views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Crea template"
+
+#: views/report-templates/create.hbs:5 routes/report-templates.js:231
+msgid "Create Report Template"
+msgstr "Crea Template di report"
+
+#: views/report-templates/edit.hbs:4 views/templates/edit.hbs:3
+#: views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Modifica Template"
+
+#: views/report-templates/edit.hbs:5 routes/report-templates.js:262
+msgid "Edit Report Template"
+msgstr "Modifica template report"
+
+#: views/report-templates/edit.hbs:6 views/templates/edit.hbs:12
+msgid "Delete Template"
+msgstr "Elimina template"
+
+#: views/report-templates/edit.hbs:7
+msgid "Update and Stay"
+msgstr "Salva e continua"
+
+#: views/report-templates/edit.hbs:8
+msgid "Update and Leave"
+msgstr "Salva ed esci"
+
+#: views/report-templates/partials/report-template-fields.hbs:2
+msgid "Template Name"
+msgstr "Nome template"
+
+#: views/report-templates/partials/report-template-fields.hbs:6
+msgid "User selectable fields"
+msgstr "Campi selezionabili dagli utenti"
+
+#: views/report-templates/partials/report-template-fields.hbs:7
+msgid "Data processing code"
+msgstr "Codice che processa data"
+
+#: views/report-templates/partials/report-template-fields.hbs:8
+msgid "Rendering template"
+msgstr "Template di rendering"
+
+#: views/report-templates/report-templates.hbs:5
+msgid "Blank"
+msgstr "Vuoto"
+
+#: views/report-templates/report-templates.hbs:6
+msgid "All Subscribers"
+msgstr "Tutti gli iscritti"
+
+#: views/report-templates/report-templates.hbs:7
+msgid "Grouped Subscribers"
+msgstr "Iscritti raggruppati"
+
+#: views/report-templates/report-templates.hbs:8
+msgid "Export List as CSV"
+msgstr "Esporta lista come CSV"
+
+#: views/report-templates/report-templates.hbs:9 views/reports/reports.hbs:4
+#: routes/report-templates.js:29
+msgid "Report Templates"
+msgstr "Templates di report"
+
+#: views/reports/create-select-template.hbs:3
+#: views/reports/create-select-template.hbs:4 views/reports/create.hbs:3
+#: views/reports/create.hbs:4 views/reports/create.hbs:5
+#: views/reports/reports.hbs:3 routes/reports.js:81
+msgid "Create Report"
+msgstr "Crea report"
+
+#: views/reports/edit.hbs:3 views/reports/edit.hbs:4 routes/reports.js:151
+msgid "Edit Report"
+msgstr "Modifica Report"
+
+#: views/reports/edit.hbs:5
+msgid "Delete Report"
+msgstr "Elimina report"
+
+#: views/reports/partials/report-fields.hbs:2
+msgid "Report Name"
+msgstr "Nome report"
+
+#: views/reports/partials/report-fields.hbs:8
+#: views/reports/partials/report-fields.hbs:11
+msgid ""
+"Select a campaign in the table above by clicking on the respective row "
+"number."
+msgstr ""
+"Seleziona una campagna nella tabella qui sopra cliccando sul numero della "
+"riga."
+
+#: views/reports/partials/report-select-template.hbs:1
+msgid "Report Template"
+msgstr "Template del report"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Indirizzo del servizio (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Inserisci l'URL a cui puoi accedere a questo servizio"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "Email amministratore"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+"Inserisci l'indirizzo mail che verra' utilizzato nel campo \"Da\" per i "
+"messaggi di sistemi"
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr "Disabilita l'editor avanzato WYSIWYG"
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr ""
+"Se selezionato l'editor del messaggio visualizza il codice HTML senza "
+"anteprima"
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr "Disabilita i messaggi di conferma iscrizione"
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+"Se selezionato il software non invia messaggi di avvenuta iscrizione e "
+"cancellazione. Questo non disabilita l'invio di messaggi per i link di "
+"conferma delle azioni."
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "ID Tracciamento"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Inserisci il codice di tracciamento di Google Analytics"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr "Annuncio pagina iniziale"
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr "Codice HTML visualizzato nell'header dell'home page"
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr "Valori predefiniti campagna"
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr "Nome mittente"
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Nome mittente, per esempio : Super Compagnia S.r.l."
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr "Indirizzo predefinito"
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+"Indirizzo fisico di contatto, per esempio: via Duomo 71, Milano, 20100 (MI)"
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr "Valore predefinito nome mittente"
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr "Valore predefinito email mittente"
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr "Valore predefinito oggetto"
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr "Valore predefinito sito (URL)"
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr ""
+"URL a cui reindirizzare gli utenti iscritti alla newsletter, per esempio "
+"http://example.com"
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr "Impostazioni mailer"
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr "Queste impostazioni sono richieste per inviare messaggi email"
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr ""
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr ""
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr "Usa SMTP per spedire le email"
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr ""
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr ""
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr ""
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr "Crittografia"
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr "Disabilita autenticazione SMTP"
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Nome utente"
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr "Nome utente (per esempio account@example.com)"
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr ""
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr ""
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr ""
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr ""
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr ""
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr ""
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr "Regione"
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr "Controllo"
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr "Controlla la configurazione del mailer"
+
+#: views/settings.hbs:52
+msgid "Advanced Mailer settings"
+msgstr "Impostazioni Mailer avanzate"
+
+#: views/settings.hbs:53
+msgid "Log SMTP transactions"
+msgstr ""
+
+#: views/settings.hbs:54
+msgid "Allow self-signed certificates"
+msgstr ""
+
+#: views/settings.hbs:55
+msgid "Max connections"
+msgstr "Massime connessioni"
+
+#: views/settings.hbs:56
+msgid "The count of max connections, eg. 10"
+msgstr "Numero massimo di connessioni (per esempio 10)"
+
+#: views/settings.hbs:57
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+
+#: views/settings.hbs:58
+msgid "Max messages"
+msgstr "Massimo messaggi"
+
+#: views/settings.hbs:59
+msgid "The count of max messages, eg. 100"
+msgstr "Il numero dei messaggi massimi, per esempio 1000"
+
+#: views/settings.hbs:60
+msgid ""
+"The number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+
+#: views/settings.hbs:61
+msgid "Throttling"
+msgstr ""
+
+#: views/settings.hbs:62
+msgid "Messages per hour eg. 1000"
+msgstr "Messaggi all'ora"
+
+#: views/settings.hbs:63
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+"Numero di messaggi massimo da inviare all'ora. Lascia il campo vuoto o con 0 "
+"per non rallentare. Se il tuo provider usa diversi limiti di velocità di "
+"invio (messaggi al minuto o al secondo), converti il valore per adattarlo (1 "
+"mail / secondo => 3600 mail / ora ). Questo valore è per ogni singolo "
+"processo di invio."
+
+#: views/settings.hbs:64
+msgid "VERP bounce handling"
+msgstr ""
+
+#: views/settings.hbs:65
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+
+#: views/settings.hbs:66
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+
+#: views/settings.hbs:67
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+
+#: views/settings.hbs:68
+msgid "Use VERP to catch bounces"
+msgstr ""
+
+#: views/settings.hbs:69
+msgid "Server hostname"
+msgstr ""
+
+#: views/settings.hbs:70
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr ""
+
+#: views/settings.hbs:71
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+
+#: views/settings.hbs:72
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+
+#: views/settings.hbs:73
+msgid "GPG Signing"
+msgstr ""
+
+#: views/settings.hbs:74
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+
+#: views/settings.hbs:75
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+
+#: views/settings.hbs:76
+msgid "Private Key Passphrase"
+msgstr ""
+
+#: views/settings.hbs:77
+msgid "Passphrase for the key if set"
+msgstr ""
+
+#: views/settings.hbs:78
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr ""
+
+#: views/settings.hbs:79
+msgid "GPG Private Key"
+msgstr ""
+
+#: views/settings.hbs:81
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+
+#: views/settings.hbs:82
+msgid "DKIM Signing by ZoneMTA"
+msgstr ""
+
+#: views/settings.hbs:83
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+
+#: views/settings.hbs:84
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+
+#: views/settings.hbs:85
+msgid "ZoneMTA DKIM API Key"
+msgstr ""
+
+#: views/settings.hbs:86
+msgid "Some secret value"
+msgstr ""
+
+#: views/settings.hbs:87
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+
+#: views/settings.hbs:88
+msgid "DKIM domain"
+msgstr ""
+
+#: views/settings.hbs:89
+msgid "Domain name for the DKIM key"
+msgstr ""
+
+#: views/settings.hbs:90
+msgid "Leave blank to use the sender email address domain"
+msgstr ""
+
+#: views/settings.hbs:91 views/settings.hbs:92
+msgid "DKIM key selector"
+msgstr ""
+
+#: views/settings.hbs:93
+msgid "Signing is disabled without a valid selector value"
+msgstr ""
+
+#: views/settings.hbs:94
+msgid "DKIM Private Key"
+msgstr ""
+
+#: views/settings.hbs:96
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:1
+#: views/subscription/mail-already-subscribed-text.hbs:1
+#: lib/models/subscriptions.js:174 lib/models/subscriptions.js:895
+msgid "Email address already registered"
+msgstr "Indirizzo email già registrato"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:2
+#: views/subscription/mail-already-subscribed-text.hbs:2
+msgid ""
+"We have received a subscription request. Your email address is however "
+"already registered."
+msgstr ""
+"Abbiamo ricevuto una richiesta di iscrizione alla nostra newsletter. La tua "
+"email è già registrata."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:3
+#: views/subscription/mail-already-subscribed-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. Your existing "
+"subscription won't be affected."
+msgstr ""
+"Se tu ricevi questa email per errore, cancellala semplicemente. La tua "
+"registrazione non subirà alcuna modifica."
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:3
+msgid "If you want to modify your subscription then you can "
+msgstr "Se vuoi modificare la tua iscrizione allora puoi"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:5
+#: views/subscription/mail-already-subscribed-text.hbs:5
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:4
+msgid "manage your preferences"
+msgstr "gestire le tue preferenze"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:6
+#: views/subscription/mail-already-subscribed-text.hbs:6
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-subscription-confirmed-text.hbs:5
+#: views/users/login.hbs:10
+msgid "or"
+msgstr "oppure"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:7
+#: views/subscription/mail-already-subscribed-text.hbs:7
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:6
+#: views/subscription/mail-subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "cancellare l'iscrizione qui"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:7
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:3
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:3
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:4
+#: views/subscription/web-subscribed-notice.mjml.hbs:4
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:3
+#: views/subscription/web-updated-notice.mjml.hbs:3
+msgid "Return to our website"
+msgstr "Torna sul nostro sito"
+
+#: views/subscription/mail-already-subscribed-html.mjml.hbs:9
+#: views/subscription/mail-already-subscribed-text.hbs:8
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:4
+#: views/subscription/mail-confirm-address-change-text.hbs:4
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-subscription-text.hbs:4
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:4
+#: views/subscription/mail-confirm-unsubscription-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:8
+#: views/subscription/mail-subscription-confirmed-text.hbs:7
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:5
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "Per domande riguardanti questa newsletter, contatta:"
+
+#: views/subscription/mail-already-subscribed-text.hbs:4
+#: views/subscription/mail-subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Se vuoi modificare la tua iscrizione allora puoi:"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:1
+#: views/subscription/mail-confirm-address-change-text.hbs:1
+msgid "Please Confirm Subscription Address Change"
+msgstr "Per favore conferma il cambio dell'indirizzo dell'iscrizione"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:2
+#: views/subscription/mail-confirm-address-change-text.hbs:2
+msgid "Yes, subscribe this email address to the list"
+msgstr "Sì, iscrivimi alla lista"
+
+#: views/subscription/mail-confirm-address-change-html.mjml.hbs:3
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Se ricevi questa email per errore, semplicemente cancellala. Non verrai "
+"registrato se non clicchi sul link di conferma qui sopra."
+
+#: views/subscription/mail-confirm-address-change-text.hbs:3
+#: views/subscription/mail-confirm-subscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Se ricevi questa email per errore, semplicemente cancellala. Non verrai "
+"registrato se non clicchi sul link di conferma qui sopra."
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:1
+#: views/subscription/mail-confirm-subscription-text.hbs:1
+#: views/subscription/mail-confirm-unsubscription-text.hbs:1
+#: routes/subscription.js:432
+msgid "Please Confirm Subscription"
+msgstr "Per favore conferma la tua iscrizione"
+
+#: views/subscription/mail-confirm-subscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-subscription-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Sì, iscrivimi a questa lista"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:1
+msgid "Please Confirm Unsubscription"
+msgstr "Per favore conferma la cancellazione dell'iscrizione"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:2
+#: views/subscription/mail-confirm-unsubscription-text.hbs:2
+msgid "Yes, unsubscribe me from this list"
+msgstr "Sì, cancella la mia iscrizione alla lista"
+
+#: views/subscription/mail-confirm-unsubscription-html.mjml.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed if you don't click the confirmation link above."
+msgstr ""
+"Se ricevi questo messaggio per errore, cancellalo pure. Non sarai cancellato "
+"dalla tua iscrizione se non clicchi sul link di conferma."
+
+#: views/subscription/mail-confirm-unsubscription-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"unsubscribed unless you click the confirmation link above."
+msgstr ""
+"Se ricevi questo messaggio per errore, cancellalo pure. Non sarai cancellato "
+"dalla tua iscrizione se non clicchi sul link di conferma."
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-subscription-confirmed-text.hbs:1
+#: views/subscription/web-subscribed-notice.mjml.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Iscrizione confermata"
+
+#: views/subscription/mail-subscription-confirmed-html.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed"
+msgstr "La tua iscrizione alla nostra lista è stata confermata"
+
+#: views/subscription/mail-subscription-confirmed-text.hbs:2
+#: views/subscription/web-subscribed-notice.mjml.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "La tua iscrizione alla nostra lista è stata confermata."
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:1
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:1
+msgid "You Are Now Unsubscribed"
+msgstr "La tua iscrizione è stata cancellata"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:2
+msgid "We have removed your email address from our list"
+msgstr "Ti abbiamo rimosso dalla nostra lista"
+
+#: views/subscription/mail-unsubscription-confirmed-html.mjml.hbs:3
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr "Se ti sei cancellato per sbaglio, puoi iscriverti nuovamente qui:"
+
+#: views/subscription/mail-unsubscription-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Abbiamo rimosso la tua email dalla nostra lista."
+
+#: views/subscription/partials/subscription-custom-fields.hbs:2
+msgid "want to change it?"
+msgstr "vuoi cambiarlo?"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:5
+msgid "Download signature verification key"
+msgstr "Scarica la chiave di verifica"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:7
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+"Inserisci la tua chiave pubblica GPG qui per cifrare i messaggi inviati al "
+"tuo server"
+
+#: views/subscription/partials/subscription-custom-fields.hbs:8
+msgid "optional"
+msgstr "opzionale"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:1
+#: views/subscription/partials/subscription-flash-messages.hbs:3
+msgid "Warning!"
+msgstr "Attenzione!"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr ""
+"Se JavaScript non è abilitato, non verrà inviato alcun messaggio di conferma"
+
+#: views/subscription/partials/subscription-flash-messages.hbs:4
+msgid "JavaScript must be enabled in order for this form to work"
+msgstr ""
+"JavaScript deve essere abilitato per il funzionamento di questo modulo da "
+"compilare"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:1
+msgid "Existing Email Address"
+msgstr "Indirizzo email esistente"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:2
+msgid "New Email Address"
+msgstr "Nuovo indirizzo email"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:3
+msgid "Your new email address"
+msgstr "Il tuo nuovo indirizzo email"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:4
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Riceverai una richiesta di conferma al tuo nuovo indirizzo di posta e devi "
+"confermarlo per far sì che la modifica abbia effetto"
+
+#: views/subscription/partials/subscription-manage-address-form.hbs:5
+#: views/subscription/web-manage-address.mjml.hbs:2
+msgid "Update Email Address"
+msgstr "Aggiorna indirizzo email"
+
+#: views/subscription/partials/subscription-manage-form.hbs:1
+#: views/subscription/web-manage.mjml.hbs:2
+msgid "Update Profile"
+msgstr "Aggiorna profilo"
+
+#: views/subscription/partials/subscription-subscribe-form.hbs:1
+#: views/subscription/web-subscribe.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:1
+msgid "Subscribe to list"
+msgstr "Iscrivita alla lista"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:1
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:1
+#: views/subscription/widget-subscribe.hbs:4
+msgid "Almost Finished"
+msgstr "Quasi finito"
+
+#: views/subscription/web-confirm-subscription-notice.mjml.hbs:2
+#: views/subscription/widget-subscribe.hbs:5
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Dobbiamo confermare il tuo indirizzo email. Per completare l'iscrizione, "
+"clicca sul link che ti abbiamo inviato al tuo indirizzo email."
+
+#: views/subscription/web-confirm-unsubscription-notice.mjml.hbs:2
+msgid ""
+"We need to confirm your email address. To complete the unsubscription "
+"process, please click the link in the email we just sent you."
+msgstr ""
+"Abbiamo bisogno che confermi il tuo indirizzo email. Per completare il "
+"processo di rimossione, si prega di cliccare il link che ti abbiamo appena "
+"spedito."
+
+#: views/subscription/web-manage-address.mjml.hbs:1
+msgid "Update Your Email Address"
+msgstr "Aggiorna il tuo indirizzo email"
+
+#: views/subscription/web-manage.mjml.hbs:1
+msgid "Update Your Preferences"
+msgstr "Aggiorna le tue preferenze"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:1
+msgid "Online Unsubscription Is Not Possible"
+msgstr "La rimozione dell'iscrizione non è fattibile online"
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:2
+msgid "Please contact us at"
+msgstr "Puoi contattarci all'indirizzo "
+
+#: views/subscription/web-manual-unsubscribe-notice.mjml.hbs:3
+msgid "to get removed from the list"
+msgstr "per essere rimosso dalla lista"
+
+#: views/subscription/web-subscribe.mjml.hbs:1
+msgid "Subscribe to List"
+msgstr "Iscriviti alla lista"
+
+#: views/subscription/web-subscribed-notice.mjml.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "Grazie per la tua iscrizione!"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Rimozione eseguita con successo"
+
+#: views/subscription/web-unsubscribed-notice.mjml.hbs:2
+msgid "You have been removed from:"
+msgstr "Se stato rimosso da:"
+
+#: views/subscription/web-updated-notice.mjml.hbs:1
+msgid "Profile Updated"
+msgstr "Profilo Aggiornato"
+
+#: views/subscription/web-updated-notice.mjml.hbs:2
+msgid "Your profile information has been updated."
+msgstr "Le informazioni del tuo profilo sono stato aggiornate."
+
+#: views/subscription/widget-subscribe.hbs:2
+msgid "Sending ..."
+msgstr "Invio ..."
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Sembra che tu ti sia già iscritto a questa lista."
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Nome Template"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr "Nome di questo template eg. Newsletter promozioni"
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "Editor HTML"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr "Commenti opzionali per questo template"
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr "Indietro ai templates"
+
+#: views/templates/edit.hbs:11
+msgid "Duplicate"
+msgstr "Duplica"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr "Trigger di automazione"
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr "Seleziona una lista per questo trigger"
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr "Nome trigger"
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr "Nome per questo trigger, per esempio: iscritti inattivi"
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr "Commenti opzionali per questo trigger"
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr "Regola trigger"
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr "Attivazione trigger"
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr "dopo giorni:"
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Evento"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Campagna"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr "Azione trigger"
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr "Invia campagna"
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr "Modifica trigger"
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr "Indietro ai triggers"
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr "Il trigger è abilitato"
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr "Elimina trigger"
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr "Trigger azionato"
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr "Iscritti con trigger azionati"
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr "Iscritti che hanno azionato questo trigger"
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr "Ora azionamento Trigger"
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr ""
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr "Campagna targetizzata"
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr "Conteggio trigger azionati"
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr "Questo account è controllato tramite LDAP."
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr "Indirizzo email associato"
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr "Il tuo indirizzo email"
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr "Questo indirizzo è utilizzato per il recupero della password"
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr "Cambia password"
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr ""
+"Hai bisogno di completare questo form solo se vuoi cambiare la tua password "
+"attuale"
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr "Password attuale"
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr "Nuova password"
+
+#: views/users/account.hbs:16 views/users/reset.hbs:8
+msgid "Confirm Password"
+msgstr "Conferma password"
+
+#: views/users/account.hbs:17 views/users/reset.hbs:9
+msgid "Confirm New Password"
+msgstr "Conferma nuova password"
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr "Sei sicuro? Il reset invaliderà i tokens che esistono al momento"
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr "Sei sicuro?"
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr "Resetta token di accesso"
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr "Genera token di accesso"
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr "Token di accesso personale:"
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr "Token di accesso non generato"
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr "Note sull'API"
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+"La risposta API è una struttura JSON con proprietà error e "
+"data. Se la risposta ha il valore error impostato, "
+"la richiesta è fallita."
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+"Devi definire il giusto Content-Type quando esegui una "
+"richiesta. Puoi usare application/x-www-form-urlencoded per i "
+"dati dei form normali, oppure application/json per JSON "
+"payload. Non è supportato multipart/form-data."
+
+#: views/users/api.hbs:13
+msgid "Get list of subscriptions"
+msgstr "Ottieni lista delle iscrizioni"
+
+#: views/users/api.hbs:14
+msgid ""
+"Retrieve a list of subscriptions to the list referenced by :listId. All "
+"fields of the subscribers will be returned. Note that custom fields will "
+"have generated names."
+msgstr ""
+"Ottieni una lista delle iscrizioni alla lista :listId. Tutti i campi degli "
+"iscritti saranno restituiti. Nota che i campi personalizzati avranno dei "
+"nomi automaticamente generati."
+
+#: views/users/api.hbs:15 views/users/api.hbs:24 views/users/api.hbs:26
+#: views/users/api.hbs:39 views/users/api.hbs:41 views/users/api.hbs:47
+#: views/users/api.hbs:49 views/users/api.hbs:55 views/users/api.hbs:57
+#: views/users/api.hbs:67 views/users/api.hbs:78 views/users/api.hbs:80
+#: views/users/api.hbs:86 views/users/api.hbs:88 views/users/api.hbs:94
+msgid "arguments"
+msgstr "argomenti"
+
+#: views/users/api.hbs:16 views/users/api.hbs:25 views/users/api.hbs:40
+#: views/users/api.hbs:48 views/users/api.hbs:56 views/users/api.hbs:68
+#: views/users/api.hbs:79 views/users/api.hbs:87 views/users/api.hbs:95
+msgid "your personal access token"
+msgstr "il tuo token di accesso personale"
+
+#: views/users/api.hbs:17 views/users/api.hbs:69
+msgid "Start position"
+msgstr "Posizionale di inizio"
+
+#: views/users/api.hbs:18 views/users/api.hbs:70
+msgid "optional, default 0"
+msgstr "opzionale, 0 di default"
+
+#: views/users/api.hbs:19
+msgid "limit subscription count in response"
+msgstr "limita il numero di iscrizioni in risposta"
+
+#: views/users/api.hbs:20 views/users/api.hbs:72
+msgid "optional, default 10000"
+msgstr "opzionale, default 10000"
+
+#: views/users/api.hbs:22
+msgid "Add subscription"
+msgstr "Aggiungi iscrizione"
+
+#: views/users/api.hbs:23
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+"Questa chiamata API aggiunge o aggiorna una iscrizione. I campi non inclusi "
+"saranno lasciati come erano, quindi se si aggiorna LAST_NAME, FIRST_NAME "
+"rimarrà invariato per quella iscrizione."
+
+#: views/users/api.hbs:27 views/users/api.hbs:42 views/users/api.hbs:50
+msgid "subscriber's email address"
+msgstr "indirizzo email dell'iscritto"
+
+#: views/users/api.hbs:28 views/users/api.hbs:43 views/users/api.hbs:51
+#: views/users/api.hbs:59 views/users/api.hbs:82 views/users/api.hbs:90
+msgid "required"
+msgstr "richiesto"
+
+#: views/users/api.hbs:29
+msgid "subscriber's first name"
+msgstr "nome dell'iscritto"
+
+#: views/users/api.hbs:30
+msgid "subscriber's last name"
+msgstr "cognome dell'iscritto"
+
+#: views/users/api.hbs:31
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"timezone dell'iscritto (esempio: \"Europe/Tallinn\", \"PST\" or \"UTC\"). Se "
+"non impostato il valore di default è \"UTC\""
+
+#: views/users/api.hbs:32
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+"valore dei campi personalizzati. Usa si/no per i valori dei gruppi di "
+"opzioni (checkboxes, radios, drop downs) "
+
+#: views/users/api.hbs:33
+msgid "Additional POST arguments"
+msgstr ""
+
+#: views/users/api.hbs:34
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+"selezionare \"sì\" se vuoi essere sicuro che la mail venga salvata come "
+"iscritta anche se precedentemente cancellata. Se la mail si era già "
+"cancellata o bloccata, lo stato di iscrizione non cambierà."
+
+#: views/users/api.hbs:35
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+"selezionare \"sì\" se vuoi inviare la mail di conferma all'email "
+"delliscrizione prima di salvarlo come iscritto"
+
+#: views/users/api.hbs:37
+msgid "Remove subscription"
+msgstr "Rimuovi iscrizione"
+
+#: views/users/api.hbs:38
+msgid "This API call marks a subscription as unsubscribed"
+msgstr "Questa chiamata API segna una iscrizione come rimossa."
+
+#: views/users/api.hbs:45
+msgid "Delete subscription"
+msgstr "Cancella iscrizione"
+
+#: views/users/api.hbs:46
+msgid "This API call deletes a subscription"
+msgstr "Questa API cancella una iscrizione"
+
+#: views/users/api.hbs:53
+msgid "Add new custom field"
+msgstr "Aggiungi un campo personalizzato"
+
+#: views/users/api.hbs:54
+msgid "This API call creates a new custom field for a list."
+msgstr "Questa chiamata API crea un nuovo campo personalizzato per una lista."
+
+#: views/users/api.hbs:58
+msgid "field name"
+msgstr "nome campo"
+
+#: views/users/api.hbs:60
+msgid "one of the following types:"
+msgstr "uno dei seguenti tipi:"
+
+#: views/users/api.hbs:61
+msgid ""
+"If the type is 'option' then you also need to specify the parent element ID"
+msgstr ""
+"Se il tipo è 'option' devi anche specificare l'ID dell'elemento parente"
+
+#: views/users/api.hbs:62
+msgid ""
+"Template for the group element. If not set, then values of the elements are "
+"joined with commas"
+msgstr ""
+"Template per il gruppo di elementi. Se non impostato, allora i valori "
+"verranno separati da una virgola"
+
+#: views/users/api.hbs:63
+msgid ""
+"if not visible then the subscriber can not view or modify this value at the "
+"profile page"
+msgstr ""
+"se non visibile l'iscritto non potrà modificare questo valore nella pagina "
+"del profilo"
+
+#: views/users/api.hbs:65
+msgid "Get list of blacklisted emails"
+msgstr "Ottieni emails in lista nera"
+
+#: views/users/api.hbs:66
+msgid "This API call get list of blacklisted emails."
+msgstr "Questa chiamata API ottiene una lista delle email in lista nera."
+
+#: views/users/api.hbs:71
+msgid "limit emails count in response"
+msgstr "limita il numero di emails nella risposta"
+
+#: views/users/api.hbs:73
+msgid "filter by part of email"
+msgstr "filtra per parte della email"
+
+#: views/users/api.hbs:74
+msgid "optional, default ''"
+msgstr "opzionale, default ''"
+
+#: views/users/api.hbs:77
+msgid "This API call either add emails to blacklist"
+msgstr "Questa chiamata API aggiunge emails alla lista nera"
+
+#: views/users/api.hbs:81 views/users/api.hbs:89
+msgid "email address"
+msgstr "indirizzo email"
+
+#: views/users/api.hbs:84
+msgid "Delete email from blacklist"
+msgstr "Cancella email dalla lista nera."
+
+#: views/users/api.hbs:85
+msgid "This API call either delete emails from blacklist"
+msgstr "Questa chiamata API cancella emails dalla lista nera"
+
+#: views/users/api.hbs:92
+msgid "Get the lists a user has subscribed to"
+msgstr "Ottini le listi a cui un utente si è iscritto"
+
+#: views/users/api.hbs:93
+msgid "Retrieve the lists that the user with :email has subscribed to. "
+msgstr "Ottieni le liste a cui l'utente con :email si è iscritto"
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr "Resetta password"
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr "Resettare la password?"
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr "Gli accounts sono gestiti tramite LDAP."
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr "Resetta password"
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+"Si prega di inserire lo username o la email inserita al momento della "
+"registrazione."
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr "Ti invieremo una email che ti permetterà di cambiare password."
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr "Username o email"
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr "Invia email di verifica"
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Ricordati di me"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "Password dimenticata?"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr "Scegli la tua nuova password"
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr "Inserire una nuova password."
+
+#: lib/editor-helpers.js:17 routes/templates.js:95
+msgid "Could not find template with specified ID"
+msgstr "Template con l'ID specificato non trovato"
+
+#: lib/editor-helpers.js:33 routes/archive.js:145 routes/campaigns.js:131
+#: routes/campaigns.js:284 routes/campaigns.js:379 routes/campaigns.js:427
+#: routes/campaigns.js:467 routes/campaigns.js:844 routes/campaigns.js:867
+#: routes/campaigns.js:886 routes/campaigns.js:908 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr "Campagna con l'ID specificato non trovata"
+
+#: lib/editor-helpers.js:47 routes/editorapi.js:320
+msgid "Invalid resource type"
+msgstr "Tipo di risorsa invalida"
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr "Codice %s di stato sbagliato "
+
+#: lib/helpers.js:33
+msgid "URL that points to the unsubscribe page"
+msgstr "URL per la pagina di rimozione dall'iscrizione"
+
+#: lib/helpers.js:36
+msgid "URL that points to the preferences page of the subscriber"
+msgstr "URL per la pagina delle preferenze dell'iscritto"
+
+#: lib/helpers.js:39
+msgid "URL to preview the message in a browser"
+msgstr "URL per l'anteprima del messaggio nel browser"
+
+#: lib/helpers.js:45 lib/models/segments.js:31
+msgid "First name"
+msgstr "Nome"
+
+#: lib/helpers.js:48 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Cognome"
+
+#: lib/helpers.js:51
+msgid "Full name (first and last name combined)"
+msgstr "Nome e Cognome"
+
+#: lib/helpers.js:54
+msgid "Unique ID that identifies the recipient"
+msgstr "ID unico che identifica il destinatario"
+
+#: lib/helpers.js:57
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr "ID unico che identifica la lista usata per questa campagna"
+
+#: lib/helpers.js:60
+msgid "Unique ID that identifies current campaign"
+msgstr "ID unico che identifica la campagna corrente"
+
+#: lib/helpers.js:68 lib/helpers.js:80
+msgid "content from an RSS entry"
+msgstr "contenuto dal messaggio RSS"
+
+#: lib/helpers.js:71
+msgid "RSS entry title"
+msgstr "Titolo RSS entry"
+
+#: lib/helpers.js:74
+msgid "RSS entry date"
+msgstr ""
+
+#: lib/helpers.js:77
+msgid "RSS entry link"
+msgstr ""
+
+#: lib/helpers.js:83
+msgid "RSS entry summary"
+msgstr ""
+
+#: lib/helpers.js:86
+msgid "RSS entry image URL"
+msgstr ""
+
+#: lib/mailer.js:245
+msgid "Invalid mail transport"
+msgstr "Trasporto mail invalido"
+
+#: lib/models/campaigns.js:105 lib/models/campaigns.js:132
+#: lib/models/campaigns.js:205 lib/models/campaigns.js:328
+#: lib/models/campaigns.js:590 lib/models/campaigns.js:723
+msgid "Missing Campaign ID"
+msgstr "ID campagna mancante"
+
+#: lib/models/campaigns.js:241
+msgid "Emtpy or too large attahcment"
+msgstr "Allegato troppo grande o mancante"
+
+#: lib/models/campaigns.js:408 lib/models/campaigns.js:600
+msgid "Campaign Name must be set"
+msgstr "Il nome della campagna è obbligatorio"
+
+#: lib/models/campaigns.js:412
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr ""
+
+#: lib/models/campaigns.js:568
+msgid "Selected template not found"
+msgstr "Template selezionato non trovato"
+
+#: lib/models/campaigns.js:924
+msgid "Invalid or missing message ID"
+msgstr "ID messaggio mancante o invalido"
+
+#: lib/models/campaigns.js:1065
+msgid "Unrecognized message status"
+msgstr "Stato del messaggio non riconosciuto"
+
+#: lib/models/confirmations.js:27
+msgid "Could not store confirmation data"
+msgstr "Impossibile salvare i dati di conferma"
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr "Drop Down"
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Data (MM/GG/AAAA)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr "Valore JSON per visualizzazione personalizzata"
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr "Opzione"
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/forms.js:46 lib/models/lists.js:115 lib/models/lists.js:150
+#: lib/models/lists.js:264 lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:79 lib/models/subscriptions.js:390
+#: lib/models/subscriptions.js:566 lib/models/subscriptions.js:657
+#: lib/models/subscriptions.js:710 lib/models/subscriptions.js:773
+#: lib/models/subscriptions.js:816
+msgid "Missing List ID"
+msgstr "ID lista mancante"
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr "Il campo Option richiede la selezione di un gruppo"
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr "ID campo manvante"
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr "Il nome del campo deve essere impostato"
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr "Campo personalizzato non trovato"
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr "Tipo di colonna %s non riconosciuto"
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr "nome colonna mancante"
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr "ID lista mancante"
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr "ID lista non trovato"
+
+#: lib/models/forms.js:70 lib/models/forms.js:113 lib/models/forms.js:201
+#: lib/models/forms.js:291
+msgid "Missing Form ID"
+msgstr "ID Form mancante"
+
+#: lib/models/forms.js:121 lib/models/forms.js:205
+msgid "Form Name must be set"
+msgstr "Il nome del form è obbligatorio"
+
+#: lib/models/forms.js:307
+msgid "Custom form not found"
+msgstr "Form personalizzato non trovato"
+
+#: lib/models/links.js:337 routes/campaigns.js:533 routes/campaigns.js:581
+#: routes/campaigns.js:621 routes/campaigns.js:671 services/sender.js:305
+msgid "Campaign not found"
+msgstr "Campagna non trovata"
+
+#: lib/models/links.js:345 routes/lists.js:181 services/sender.js:312
+msgid "List not found"
+msgstr "Lista non trovat"
+
+#: lib/models/links.js:353
+msgid "Subscription not found"
+msgstr "Iscrizione non trovata"
+
+#: lib/models/lists.js:166 lib/models/lists.js:210
+msgid "List Name must be set"
+msgstr "Il nome della lista è obbligatorio"
+
+#: lib/models/lists.js:293
+msgid "Missing List CID"
+msgstr "CID lista mancante"
+
+#: lib/models/report-templates.js:26 lib/models/report-templates.js:70
+#: lib/models/report-templates.js:142
+msgid "Missing report template ID"
+msgstr "ID template di reportistica mancante"
+
+#: lib/models/report-templates.js:77
+msgid "Report template name must be set"
+msgstr "Il nome del template di report è obbligatorio"
+
+#: lib/models/reports.js:40 lib/models/reports.js:110 lib/models/reports.js:188
+msgid "Missing report ID"
+msgstr "ID report mancante"
+
+#: lib/models/reports.js:116
+msgid "Report name must be set"
+msgstr "Il nome del report è obblicatorio"
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr "Nazione di registrazione"
+
+#: lib/models/segments.js:19 lib/models/triggers.js:12
+msgid "Sign up date"
+msgstr "Data registrazione"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:16
+msgid "Latest open"
+msgstr "Ultima apertura"
+
+#: lib/models/segments.js:27 lib/models/triggers.js:20
+msgid "Latest click"
+msgstr "Ultimo click"
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr "ID segmento mancante"
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr "Segmento non trovato"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr "%s giorni a partire da oggi"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr "$s giorni fa"
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr "oggi"
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr "Tipo di regola del segmento non valido"
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr "Segmento selezionato non trovato"
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr "Tipo di regola non valida"
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr "ID regola mancante"
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr "Regola specificata non trovata"
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr "Segmento selezionato non trovato"
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr "Regola selezionata non trovata"
+
+#: lib/models/subscriptions.js:257 lib/models/subscriptions.js:287
+#: lib/models/subscriptions.js:394
+msgid "Missing Subscription ID"
+msgstr "ID iscrizione mancante"
+
+#: lib/models/subscriptions.js:315
+msgid "Missing Subscription email address"
+msgstr "Indirizzo email di iscrizione mancante"
+
+#: lib/models/subscriptions.js:570 lib/models/subscriptions.js:820
+msgid "Missing subscription ID"
+msgstr "ID di iscrizione mancante"
+
+#: lib/models/subscriptions.js:661 lib/models/subscriptions.js:714
+#: lib/models/subscriptions.js:750
+msgid "Missing Import ID"
+msgstr "ID di import mancante"
+
+#: lib/models/subscriptions.js:842
+msgid "Unknown subscription ID"
+msgstr "ID iscrizione sconosciuto"
+
+#: lib/models/subscriptions.js:847 routes/subscription.js:639
+msgid "Nothing seems to be changed"
+msgstr "Nulla sembra essere cambiato"
+
+#: lib/models/subscriptions.js:913 routes/subscription.js:473
+#: routes/subscription.js:545 routes/subscription.js:581
+#: routes/subscription.js:697 routes/subscription.js:772
+msgid "Subscription not found in this list"
+msgstr "Iscrizione non trovata nella lista"
+
+#: lib/models/templates.js:26 lib/models/templates.js:102
+#: lib/models/templates.js:157
+msgid "Missing Template ID"
+msgstr "ID template mancante"
+
+#: lib/models/templates.js:55 lib/models/templates.js:106
+msgid "Template Name must be set"
+msgstr "Nome template obbligatorio"
+
+#: lib/models/templates.js:147
+msgid "Template does not exist"
+msgstr "Il template non esiste"
+
+#: lib/models/triggers.js:29
+msgid "Has Opened"
+msgstr "Ha aperto"
+
+#: lib/models/triggers.js:32
+msgid "Has Clicked"
+msgstr "Ha cliccato"
+
+#: lib/models/triggers.js:35
+msgid "Not Opened"
+msgstr "Non aperto"
+
+#: lib/models/triggers.js:38
+msgid "Not Clicked"
+msgstr "Non cliccato"
+
+#: lib/models/triggers.js:178 lib/models/triggers.js:215
+msgid "Missing or invalid list ID"
+msgstr "ID Lista mancante on non valido"
+
+#: lib/models/triggers.js:182 lib/models/triggers.js:267
+msgid "Days in the past are not allowed"
+msgstr "Giorni nel passato non sono permessi"
+
+#: lib/models/triggers.js:186 lib/models/triggers.js:207
+#: lib/models/triggers.js:271 lib/models/triggers.js:292
+msgid "Missing or invalid trigger rule"
+msgstr "Regola di trigger mancante o non valido"
+
+#: lib/models/triggers.js:193 lib/models/triggers.js:278
+msgid "Invalid subscription configuration"
+msgstr "Configurazione di iscrizione non valida"
+
+#: lib/models/triggers.js:200 lib/models/triggers.js:285
+msgid "Invalid campaign configuration"
+msgstr "Configurazione della campagna non valid"
+
+#: lib/models/triggers.js:203 lib/models/triggers.js:288
+msgid "A campaing can not be a target for itself"
+msgstr "Una campagna non può' essere il target di sè stessa"
+
+#: lib/models/triggers.js:236
+msgid "Could not store trigger row"
+msgstr "Impossibile salvare la riga di trigger"
+
+#: lib/models/triggers.js:253
+msgid "Missing or invalid Trigger ID"
+msgstr "ID trigger mancante o non valido"
+
+#: lib/models/triggers.js:320
+msgid "Missing Trigger ID"
+msgstr "ID trigger mancante"
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr "Impossibile salvare riga utente"
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr "Indirizzo email obbligatorio"
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr "Controllo dati inseriti fallito"
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+"Impossibile cambiare indirizzo email poiché esiste un account già associato "
+"all'indirizzo"
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr "Password corrente errata"
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr "Nuova password non impostata"
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr "Le password non corrispondono"
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr "ID utente non impostato"
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr "Il nome utente è obbligatorio"
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr "Richiesta cambio password del Mailer"
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr "nome utente o tocken di accesso invalido"
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Nuova password non valida"
+
+#: lib/passport.js:49
+msgid "%s logged out"
+msgstr "%s è uscito"
+
+#: lib/passport.js:63
+msgid "Failed to authenticate user"
+msgstr "Impossibile verificare utente"
+
+#: lib/passport.js:79
+msgid "Logged in as %s"
+msgstr "Connesso come %s"
+
+#: lib/passport.js:179
+msgid "Incorrect username or password"
+msgstr "Nome utente o password errata"
+
+#: lib/subscription-mail-helpers.js:28
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Iscrizione confermata"
+
+#: lib/subscription-mail-helpers.js:39
+msgid "%s: Email Address Already Registered"
+msgstr "%s: Indirizzo email già iscritto"
+
+#: lib/subscription-mail-helpers.js:49
+msgid "%s: Please Confirm Email Change in Subscription"
+msgstr "%s: Per favore conferma il cambio di indirizzo email nell'iscrizione"
+
+#: lib/subscription-mail-helpers.js:59
+msgid "%s: Please Confirm Subscription"
+msgstr "%s: Per favore conferma la tua iscrizione"
+
+#: lib/subscription-mail-helpers.js:69
+msgid "%s: Please Confirm Unsubscription"
+msgstr "%s: Per favore conferma l'intenzione di rimuovere l'iscrizione"
+
+#: lib/subscription-mail-helpers.js:76
+msgid "%s: Unsubscription Confirmed"
+msgstr "%s: Rimozione dell'iscrizione confermata"
+
+#: lib/tools.js:154
+msgid "Blocked email address \"%s\""
+msgstr "Email \"%s\" bloccata"
+
+#: lib/tools.js:163
+msgid "Invalid email address \"%s\"."
+msgstr "Email \"%s\" invalida."
+
+#: lib/tools.js:166
+msgid "MX record not found for domain"
+msgstr "Non trovo gli MX records per il dominio"
+
+#: lib/tools.js:169
+msgid "Address domain not found"
+msgstr "Dominio dell'indirizzo non trovato"
+
+#: lib/tools.js:172
+msgid "Address domain name is required"
+msgstr "Il dominio dell'indirizzo è obbligatorio"
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:230
+msgid "Not Found"
+msgstr "Non trovato"
+
+#: routes/archive.js:121 services/sender.js:449
+msgid "Received status code %s from %s"
+msgstr "Ricevuto codice di stato %s da %s"
+
+#: routes/archive.js:153 routes/campaigns.js:894
+msgid "Attachment not found"
+msgstr "Allegato non trovato"
+
+#: routes/blacklist.js:13 routes/campaigns.js:26 routes/editorapi.js:32
+#: routes/fields.js:13 routes/forms.js:16 routes/grapejs.js:15
+#: routes/lists.js:50 routes/mosaico.js:14 routes/report-templates.js:20
+#: routes/reports.js:22 routes/segments.js:13 routes/settings.js:23
+#: routes/templates.js:18 routes/triggers.js:18 routes/users.js:75
+#: routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Devi aver effettuato l'accesso per accedere ai contenuti riservati"
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr "Impossibile creare la campagna"
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr "Campagna \"%s\" creata"
+
+#: routes/campaigns.js:209
+msgid "Campaign settings updated"
+msgstr "Impostazioni della campagna aggiornate"
+
+#: routes/campaigns.js:211
+msgid "Campaign settings not updated"
+msgstr "Impostazioni della campagna non aggiornata"
+
+#: routes/campaigns.js:227 routes/campaigns.js:744
+msgid "Campaign deleted"
+msgstr "Campagna eliminata"
+
+#: routes/campaigns.js:229 routes/campaigns.js:746
+msgid "Could not delete specified campaign"
+msgstr "Impossibile cancellare la campagna selezionata"
+
+#: routes/campaigns.js:248
+msgid "Idling"
+msgstr "Aspettando"
+
+#: routes/campaigns.js:251
+msgid "Scheduled"
+msgstr "In programma"
+
+#: routes/campaigns.js:257
+msgid "Paused"
+msgstr "In pausa"
+
+#: routes/campaigns.js:259
+msgid "Inactive"
+msgstr "Inattiva"
+
+#: routes/campaigns.js:261
+msgid "Active"
+msgstr "Attiva"
+
+#: routes/campaigns.js:263
+msgid "Other"
+msgstr "Altro"
+
+#: routes/campaigns.js:421
+msgid "Unknown status selector"
+msgstr "Selettore di stato non trovato"
+
+#: routes/campaigns.js:762
+msgid "Scheduled sending"
+msgstr "Invio programmato"
+
+#: routes/campaigns.js:764
+msgid "Could not schedule sending"
+msgstr "Impossibile programmare l'invio"
+
+#: routes/campaigns.js:776
+msgid "Sending resumed"
+msgstr "Invio ripreso"
+
+#: routes/campaigns.js:778
+msgid "Could not resume sending"
+msgstr "Impossibile riprendere invio"
+
+#: routes/campaigns.js:790
+msgid "Sending reset"
+msgstr "Reset invio"
+
+#: routes/campaigns.js:792
+msgid "Could not reset sending"
+msgstr "Impossibile resettare l'invio"
+
+#: routes/campaigns.js:804 routes/campaigns.js:832
+msgid "Sending paused"
+msgstr "Invio in pausa"
+
+#: routes/campaigns.js:806 routes/campaigns.js:834
+msgid "Could not pause sending"
+msgstr "Impossibile mettere in pausa l'invio"
+
+#: routes/campaigns.js:818
+msgid "Sending activated"
+msgstr "Invio attivato"
+
+#: routes/campaigns.js:820
+msgid "Could not activate sending"
+msgstr "Impossibile attivare l'invio"
+
+#: routes/campaigns.js:855
+msgid "Attachment uploaded"
+msgstr "Allegato caricato"
+
+#: routes/campaigns.js:857
+msgid "Could not store attachment"
+msgstr "Impossibile salvare allegato"
+
+#: routes/campaigns.js:874
+msgid "Attachment deleted"
+msgstr "Allegato eliminato"
+
+#: routes/campaigns.js:876
+msgid "Could not delete attachment"
+msgstr "Impossibile eliminare allegato"
+
+#: routes/editorapi.js:38
+msgid "Invalid editor name"
+msgstr "Nome editor invalido"
+
+#: routes/editorapi.js:146
+msgid "Method not supported"
+msgstr "Metodo non supportato"
+
+#: routes/editorapi.js:381
+msgid "Invalid resource type or ID"
+msgstr "ID o tipo di risorsa invalido"
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/forms.js:31 routes/forms.js:63 routes/forms.js:94
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr "ID lista selezionata non trovata"
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr "Impossibile creare campo personalizzato"
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr "Campo selezionato non trovato"
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr "Impostazioni campo aggiornate"
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr "Impostazioni campo non aggiornate"
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr "Campo personalizzato eliminato"
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr "Impossibile eliminare campo specificato"
+
+#: routes/forms.js:78
+msgid "Could not create custom form"
+msgstr "Impossibile creare campo personalizzato"
+
+#: routes/forms.js:105
+msgid "Selected form not found"
+msgstr "Form selezionato non trovato"
+
+#: routes/forms.js:136
+msgid "The plaintext version for this email"
+msgstr "La versione di solo testo della mail"
+
+#: routes/forms.js:137
+msgid "Custom forms use MJML for formatting"
+msgstr "I form personalizzati usano MJML per la formattazione"
+
+#: routes/forms.js:138
+msgid "See the MJML documentation here"
+msgstr ""
+"Guarda la documentazione di MJML qui"
+
+#: routes/forms.js:146
+msgid "Layout"
+msgstr "Layout"
+
+#: routes/forms.js:152
+msgid "Form Input Style"
+msgstr "Stile input del form"
+
+#: routes/forms.js:154
+msgid ""
+"This CSS stylesheet defines the appearance of form input elements and alerts"
+msgstr ""
+"Questo stylesheet CSS definisce lo stile degli elementi di input dei form e "
+"degli alert"
+
+#: routes/forms.js:160
+msgid "Web - Subscribe"
+msgstr "Web - Iscriviti"
+
+#: routes/forms.js:165
+msgid "Web - Confirm Subscription Notice"
+msgstr "Web - Notifica di conferma dell'iscrizione"
+
+#: routes/forms.js:170
+msgid "Mail - Confirm Subscription (MJML)"
+msgstr "Mail - Conferma di iscrizione (MJML)"
+
+#: routes/forms.js:175
+msgid "Mail - Confirm Subscription (Text)"
+msgstr "Mail - Conferma di iscrizione (Testo)"
+
+#: routes/forms.js:180
+msgid "Mail - Already Subscribed (MJML)"
+msgstr "Mail - Già iscritto (MJML)"
+
+#: routes/forms.js:185
+msgid "Mail - Already Subscribed (Text)"
+msgstr "Mail - Già iscritto (Testo)"
+
+#: routes/forms.js:190
+msgid "Web - Subscribed Notice"
+msgstr "Web - Notifica di iscrizione"
+
+#: routes/forms.js:195
+msgid "Mail - Subscription Confirmed (MJML)"
+msgstr "Mail - Conferma di iscrizione (MJML)"
+
+#: routes/forms.js:200
+msgid "Mail - Subscription Confirmed (Text)"
+msgstr "Mail - Conferma di iscrizione (Testo)"
+
+#: routes/forms.js:208
+msgid "Web - Manage Preferences"
+msgstr "Web - Gestisci l preferenze"
+
+#: routes/forms.js:213
+msgid "Web - Manage Address"
+msgstr "Web - Gestisci indirizzo"
+
+#: routes/forms.js:218
+msgid "Web - Updated Notice"
+msgstr "Web - Notifica di aggiornamento"
+
+#: routes/forms.js:226
+msgid "Web - Unsubscribe"
+msgstr "Web - Rimozione iscrizione"
+
+#: routes/forms.js:231
+msgid "Web - Confirm Unsubscription Notice"
+msgstr "Web - Conferma la notifica di rimozione dell'iscrizione"
+
+#: routes/forms.js:236
+msgid "Mail - Confirm Unsubscription (MJML)"
+msgstr "Mail - Conferma la rimozione dell'iscrizione (MJML)"
+
+#: routes/forms.js:241
+msgid "Mail - Confirm Unsubscription (Text)"
+msgstr "Mail - Conferma la rimozione dell'iscrizione (Text)"
+
+#: routes/forms.js:246
+msgid "Mail - Confirm Address Change (MJML)"
+msgstr "Mail - Conferma il cambio di indirizzo (MJML)"
+
+#: routes/forms.js:251
+msgid "Mail - Confirm Address Change (Text)"
+msgstr "Mail - Conferma il cambio di indirizzo (Testo)"
+
+#: routes/forms.js:256
+msgid "Web - Unsubscribed Notice"
+msgstr "Web - Notifica di rimozione"
+
+#: routes/forms.js:261
+msgid "Mail - Unsubscription Confirmed (MJML)"
+msgstr "Mail - Rimozione confermata (MJML)"
+
+#: routes/forms.js:266
+msgid "Mail - Unsubscription Confirmed (Text)"
+msgstr "Mail - Rimozione confermata (Text)"
+
+#: routes/forms.js:271
+msgid "Web - Manual Unsubscribe Notice"
+msgstr "Web - Notifica di rimozione manuale"
+
+#: routes/forms.js:309
+msgid "Form settings updated"
+msgstr "Impostazioni form aggiornate"
+
+#: routes/forms.js:311
+msgid "Form settings not updated"
+msgstr "Impostazioni form non aggiornate"
+
+#: routes/forms.js:327
+msgid "Custom form deleted"
+msgstr "Form personalizzato non cancellato"
+
+#: routes/forms.js:329
+msgid "Could not delete specified form"
+msgstr "Impossibile eliminare il form specificato"
+
+#: routes/index.js:11
+msgid "Self Hosted Newsletter App"
+msgstr "Applicazione di newsletter self-hosted"
+
+#: routes/links.js:39
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr "Oops, non riusciamo a trovare un link per l'URL che hai cliccato"
+
+#: routes/lists.js:82
+msgid "Could not create list"
+msgstr "Impossibile creare lista"
+
+#: routes/lists.js:85
+msgid "List created"
+msgstr "Lista creata"
+
+#: routes/lists.js:93 routes/lists.js:271 routes/lists.js:336
+#: routes/lists.js:375 routes/lists.js:444 routes/lists.js:469
+#: routes/lists.js:514 routes/lists.js:536 routes/lists.js:565
+#: routes/lists.js:657 routes/lists.js:714 routes/lists.js:741
+msgid "Could not find list with specified ID"
+msgstr "Impossibile trovare la lista dell'ID specificato"
+
+#: routes/lists.js:122
+msgid "List settings updated"
+msgstr "Impostazioni lista aggiornate"
+
+#: routes/lists.js:124
+msgid "List settings not updated"
+msgstr "Impostazioni lista non aggiornate"
+
+#: routes/lists.js:142
+msgid "List deleted"
+msgstr "Lista cancellata"
+
+#: routes/lists.js:144
+msgid "Could not delete specified list"
+msgstr "Impossibile cancellare la lista specificata"
+
+#: routes/lists.js:206
+msgid "Unknown"
+msgstr "Sconosciuto"
+
+#: routes/lists.js:206
+msgid "Complained"
+msgstr "Reclamato"
+
+#: routes/lists.js:237
+msgid "Invalid key"
+msgstr "Chiave invalida"
+
+#: routes/lists.js:239
+msgid "Expired key"
+msgstr "Chiave scaduta"
+
+#: routes/lists.js:241
+msgid "Revoked key"
+msgstr "Chiave revocate"
+
+#: routes/lists.js:288
+msgid "Force Subscribe"
+msgstr "Forza iscrizione"
+
+#: routes/lists.js:291
+msgid "Initializing"
+msgstr "Inizializzando"
+
+#: routes/lists.js:294
+msgid "Initialized"
+msgstr "Inizializzato"
+
+#: routes/lists.js:297
+msgid "Importing"
+msgstr "Importando"
+
+#: routes/lists.js:303
+msgid "Errored"
+msgstr "Errore"
+
+#: routes/lists.js:381 routes/lists.js:450 routes/lists.js:475
+msgid "Could not find subscriber with specified ID"
+msgstr "Iscritto con ID specificato non trovato"
+
+#: routes/lists.js:427
+msgid "Could not add subscription"
+msgstr "Impossibile aggiungere iscrizione"
+
+#: routes/lists.js:432
+msgid "%s was successfully added to your list"
+msgstr "%s aggiunto alla lista con successo"
+
+#: routes/lists.js:434
+msgid "%s was not added to your list"
+msgstr "%s non aggiunto alla lista"
+
+#: routes/lists.js:456
+msgid "Could not unsubscribe user"
+msgstr "Impossibile rimuovere iscrizione utente"
+
+#: routes/lists.js:459
+msgid "%s was successfully unsubscribed from your list"
+msgstr "Rimozione iscrizione % dalla lista avvenuta con successo"
+
+#: routes/lists.js:479
+msgid "%s was successfully removed from your list"
+msgstr "Iscrizione %s cancellata con successo"
+
+#: routes/lists.js:491
+msgid "Another subscriber with email address %s already exists"
+msgstr "Una iscrizione con l'email %s esiste già"
+
+#: routes/lists.js:498
+msgid "Subscription settings updated"
+msgstr "Impostazioni di iscrizione aggiornate"
+
+#: routes/lists.js:500
+msgid "Subscription settings not updated"
+msgstr "Impostazioni di iscrizione non aggiornate"
+
+#: routes/lists.js:542 routes/lists.js:663 routes/lists.js:699
+#: routes/lists.js:727 routes/lists.js:747
+msgid "Could not find import data with specified ID"
+msgstr "Impossibile trovare dati di importo per l'ID specificato"
+
+#: routes/lists.js:573
+msgid "Could not process CSV"
+msgstr "Impossibile elaborare CSV"
+
+#: routes/lists.js:589
+msgid "Could not create importer"
+msgstr "Impossibile creare una importazione"
+
+#: routes/lists.js:643
+msgid "Empty file"
+msgstr "File vuoto"
+
+#: routes/lists.js:646
+msgid "Too few rows"
+msgstr "Troppe poche righe"
+
+#: routes/lists.js:703
+msgid "Import started"
+msgstr "Importazione iniziato"
+
+#: routes/lists.js:731
+msgid "Import restarted"
+msgstr "Importazione riniziato"
+
+#: routes/lists.js:797
+msgid "One-step (i.e. no email with confirmation link)"
+msgstr "Uno step (no email con link di conferma)"
+
+#: routes/lists.js:803
+msgid ""
+"One-step with unsubscription form (i.e. no email with confirmation link)"
+msgstr "Uno step con form di cancellazione (no email con link di conferma)"
+
+#: routes/lists.js:809
+msgid "Two-step (i.e. an email with confirmation link will be sent)"
+msgstr "Due step (una email con link di conferma viene inviata)"
+
+#: routes/lists.js:815
+msgid ""
+"Two-step with unsubscription form (i.e. an email with confirmation link will "
+"be sent)"
+msgstr ""
+"Form di cancellazione a due step (una mail con link di conferma viene "
+"inviata)"
+
+#: routes/lists.js:821
+msgid ""
+"Manual (i.e. unsubscription has to be performed by the list administrator)"
+msgstr ""
+"Manuale (p.es. la cancellazione deve essere eseguita dall'amministratore "
+"della lista)"
+
+#: routes/report-templates.js:246
+msgid "Could not create report template"
+msgstr "Impossibile creare il template di report"
+
+#: routes/report-templates.js:249
+msgid "Report template “%s” created"
+msgstr "Template report \"%s\" creato"
+
+#: routes/report-templates.js:257
+msgid "Could not find report template with specified ID"
+msgstr "Impossibile trovare il template del report specificato"
+
+#: routes/report-templates.js:280
+msgid "Report template updated"
+msgstr "Template report aggiornato"
+
+#: routes/report-templates.js:282
+msgid "Report template not updated"
+msgstr "Template report non aggiornato"
+
+#: routes/report-templates.js:298
+msgid "Report template deleted"
+msgstr "Template report eliminato"
+
+#: routes/report-templates.js:300
+msgid "Could not delete specified report template"
+msgstr "Impossibile eliminare il template del report"
+
+#: routes/reports.js:124 routes/reports.js:130
+msgid "Could not create report"
+msgstr "Impossibile creare il report"
+
+#: routes/reports.js:135
+msgid "Report “%s” created"
+msgstr "Creato report \"%s\""
+
+#: routes/reports.js:146 routes/reports.js:224 routes/reports.js:239
+#: routes/reports.js:265 routes/reports.js:275
+msgid "Could not find report with specified ID"
+msgstr "Impossibile trovare il report con l'ID specificato"
+
+#: routes/reports.js:188 routes/reports.js:194
+msgid "Could not update report"
+msgstr "Impossibile aggiornare il report"
+
+#: routes/reports.js:197
+msgid "Report updated"
+msgstr "Report aggiornato"
+
+#: routes/reports.js:199
+msgid "Report not updated"
+msgstr "Report non aggiornato"
+
+#: routes/reports.js:212
+msgid "Report deleted"
+msgstr "Report eliminato"
+
+#: routes/reports.js:214
+msgid "Could not delete specified report"
+msgstr "Impossibile eliminare il report specificato"
+
+#: routes/reports.js:230
+msgid "Could not find report template"
+msgstr "Template di reportistica non trovato"
+
+#: routes/reports.js:260
+msgid "Unknown type of template"
+msgstr "Tipo di template sconosciuto"
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr "Impossibile creare segmento"
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr "Segmento creato"
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr "Segmento selezionato non trovato"
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr "Impostazioni segmento aggiornate"
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr "Impostazioni segmento non aggiornate"
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr "Segmento cancellato"
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr "Impossibile eliminare il segmento specifcato"
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr "Impossibile creare la regola"
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr "Regola creata"
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr "Impostazioni regola aggiornate"
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr "Impostazioni regola non aggiornate"
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr "Regola cancellata"
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr "Impossibile eliminare la regola specificata"
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "Usa TLS"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "usualmente selezionata per la porta 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "Usa STARTTLS"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "usualmente selezionate per le porte 587 e 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "Non usare crittografia"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Impostazioni aggiornate"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Tipo di trasporto mail invalido"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Chiave di accesso invalida"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "Credenziali AWS invalide"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Connessione rifiutata, controlla hostname e porta."
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"Non ho ricevuto il messaggio di saluto dal server. Questo può succedere "
+"quando ci si connette ad una porta TLS senza utilizzare TLS."
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "Non ho ricevuto il messaggio di saluto dal server."
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Tempo di connessione scaduto. Controlla il tuo firewall, le porte sono "
+"probabilmente chiuse."
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr ""
+"Autenticazione non accettata, il server richiede l'utilizzo di STARTTLS."
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr "Autenticazione fallita, controlla il nome utente e la password."
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "Verifica delle impostazioni di invio mail fallita."
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Il Server ha risposto con: \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr ""
+"Impostazioni di invio mail verificate, il software è pronto per inviare "
+"delle mail!"
+
+#: routes/subscription.js:33
+msgid "Not allowed by CORS"
+msgstr "Non permesso dalle impostazioni CORS"
+
+#: routes/subscription.js:61 routes/subscription.js:176
+#: routes/subscription.js:286 routes/subscription.js:382
+#: routes/subscription.js:459 routes/subscription.js:535
+#: routes/subscription.js:566 routes/subscription.js:626
+#: routes/subscription.js:682 routes/subscription.js:760
+#: routes/subscription.js:897
+msgid "Selected list not found"
+msgstr "Lista selezionata non trovata"
+
+#: routes/subscription.js:93
+msgid "Could not save subscription"
+msgstr "Impossibile salvare l'iscrizione"
+
+#: routes/subscription.js:118
+msgid "Subscriber info corrupted or missing"
+msgstr "Informazioni iscritto corrotte o mancanti"
+
+#: routes/subscription.js:136
+msgid "Email address changed"
+msgstr "Indirizzo email aggiornato"
+
+#: routes/subscription.js:179 routes/subscription.js:385
+msgid "The list does not allow public subscriptions."
+msgstr "L'iscrizione alla lista non è pubblica."
+
+#: routes/subscription.js:355 routes/subscription.js:357
+msgid "Email address not set"
+msgstr "Indirizzo email non impostato"
+
+#: routes/subscription.js:653
+msgid ""
+"An email with further instructions has been sent to the provided address"
+msgstr ""
+"Una email con ulteriori istruzioni è stata inviata all'indirizzo fornito"
+
+#: routes/subscription.js:861 routes/subscription.js:877
+msgid "Public key is not set"
+msgstr "la chiave pubblica non è impostata"
+
+#: routes/templates.js:84
+msgid "Could not create template"
+msgstr "Impossibile creare template"
+
+#: routes/templates.js:87
+msgid "Template created"
+msgstr "Template creato"
+
+#: routes/templates.js:126
+msgid "Template settings updated"
+msgstr "Impostazioni template aggiornate"
+
+#: routes/templates.js:128
+msgid "Template settings not updated"
+msgstr "Impostazioni template non aggiornate"
+
+#: routes/templates.js:144
+msgid "Template duplicated"
+msgstr "Template duplicato"
+
+#: routes/templates.js:146
+msgid "Could not duplicate specified template"
+msgstr "Impossibile duplicare il template specificato"
+
+#: routes/templates.js:157
+msgid "Template deleted"
+msgstr "Template cancellato"
+
+#: routes/templates.js:159
+msgid "Could not delete specified template"
+msgstr "Impossibile eliminare il template selezionato"
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr "Lista selezionata non trovata"
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr "Impossibile creare il trigger"
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr "Trigger \"%s\" creato"
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr "Impostazioni trigger aggiornate"
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr "Impostazioni trigger non aggiornate"
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr "Trigger cancellato"
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr "Impossibile eliminare il trigger specificato"
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr "Trigger non trovato con l'ID specificato"
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr "Trigger non trovato"
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+"Una mail con le istruzioni di ripristino password sono state inviate alla "
+"tua mail, se esiste nel sistema."
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr "Token sconosciuto o scaduto"
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "La tua password è stata cambiata con successo"
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr "Dati utente non trovati"
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr "Token di accesso aggiornati"
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr "Token di access non aggiornati"
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr "Informazioni account aggiornate"
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr "Informazioni account non aggiornate"
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr "Errore feed %s"
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr "Trovato un nuovo messaggio %s per la campagna dal feed"
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr "Nulla di nuovo dal feed"
+
+#: services/feedcheck.js:146
+msgid "RSS entry %s"
+msgstr "RSS %s"
+
+#: services/importer.js:249
+msgid "Could not access import file"
+msgstr "Impossibile accedere al file da importare"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr "Trigger %s sconosciuto"
diff --git a/languages/pl_PL.mo b/languages/pl_PL.mo
new file mode 100644
index 00000000..87fc07e4
Binary files /dev/null and b/languages/pl_PL.mo differ
diff --git a/languages/pl_PL.po b/languages/pl_PL.po
new file mode 100644
index 00000000..4e164b2f
--- /dev/null
+++ b/languages/pl_PL.po
@@ -0,0 +1,3739 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-03-07 21:44+0200\n"
+"PO-Revision-Date: 2019-05-09 14:02+0200\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.2.1\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
+"|| n%100>14) ? 1 : 2);\n"
+"Last-Translator: \n"
+"Language: pl_PL\n"
+
+#: views/archive/layout.hbs:1 views/layout.hbs:1
+#: views/subscription/layout.hbs:1 routes/index.js:11
+msgid "Self hosted email newsletter app"
+msgstr "Samodzielnie hostowana aplikacja e-mail newsletter"
+
+#: views/campaigns/bounced.hbs:1 views/campaigns/campaigns.hbs:1
+#: views/campaigns/clicked.hbs:1 views/campaigns/complained.hbs:1
+#: views/campaigns/create-rss.hbs:1 views/campaigns/create-triggered.hbs:1
+#: views/campaigns/create.hbs:1 views/campaigns/delivered.hbs:1
+#: views/campaigns/edit-rss.hbs:1 views/campaigns/edit-triggered.hbs:1
+#: views/campaigns/edit.hbs:1 views/campaigns/opened.hbs:1
+#: views/campaigns/unsubscribed.hbs:1 views/campaigns/upload-attachment.hbs:1
+#: views/campaigns/view.hbs:1 views/lists/create.hbs:1 views/lists/edit.hbs:1
+#: views/lists/fields/create.hbs:1 views/lists/fields/edit.hbs:1
+#: views/lists/fields/fields.hbs:1 views/lists/lists.hbs:1
+#: views/lists/segments/create.hbs:1 views/lists/segments/edit.hbs:1
+#: views/lists/segments/rule-configure.hbs:1
+#: views/lists/segments/rule-create.hbs:1 views/lists/segments/rule-edit.hbs:1
+#: views/lists/segments/segments.hbs:1 views/lists/segments/view.hbs:1
+#: views/lists/subscription/add.hbs:1 views/lists/subscription/edit.hbs:1
+#: views/lists/subscription/import-failed.hbs:1
+#: views/lists/subscription/import-preview.hbs:1
+#: views/lists/subscription/import.hbs:1 views/lists/view.hbs:1
+#: views/settings.hbs:1 views/templates/create.hbs:1 views/templates/edit.hbs:1
+#: views/templates/templates.hbs:1 views/triggers/create-select.hbs:1
+#: views/triggers/create.hbs:1 views/triggers/edit.hbs:1
+#: views/triggers/triggered.hbs:1 views/triggers/triggers.hbs:1
+#: views/users/account.hbs:1 views/users/api.hbs:1 views/users/forgot.hbs:1
+#: views/users/login.hbs:1 views/users/reset.hbs:1 app.js:169
+msgid "Home"
+msgstr "Strona główna"
+
+#: views/campaigns/bounced.hbs:2 views/campaigns/campaigns.hbs:2
+#: views/campaigns/campaigns.hbs:7 views/campaigns/clicked.hbs:2
+#: views/campaigns/complained.hbs:2 views/campaigns/create-rss.hbs:2
+#: views/campaigns/create-triggered.hbs:2 views/campaigns/create.hbs:2
+#: views/campaigns/delivered.hbs:2 views/campaigns/edit-rss.hbs:2
+#: views/campaigns/edit-triggered.hbs:2 views/campaigns/edit.hbs:2
+#: views/campaigns/opened.hbs:2 views/campaigns/unsubscribed.hbs:2
+#: views/campaigns/upload-attachment.hbs:2 views/campaigns/view.hbs:2
+#: lib/tools.js:119 routes/campaigns.js:35
+msgid "Campaigns"
+msgstr "Kampanie"
+
+#: views/campaigns/bounced.hbs:3 views/campaigns/bounced.hbs:4
+msgid "Bounced info"
+msgstr "Informacje o odrzuconych/odbiciach"
+
+#: views/campaigns/bounced.hbs:5 views/campaigns/clicked.hbs:5
+#: views/campaigns/complained.hbs:5 views/campaigns/delivered.hbs:5
+#: views/campaigns/edit-rss.hbs:5 views/campaigns/edit-triggered.hbs:5
+#: views/campaigns/edit.hbs:5 views/campaigns/opened.hbs:5
+#: views/campaigns/unsubscribed.hbs:5 views/campaigns/upload-attachment.hbs:6
+msgid "View campaign"
+msgstr "Zobacz kampanię"
+
+#: views/campaigns/bounced.hbs:6
+msgid "Subscribers who bounced and were unsubscribed:"
+msgstr "Subskrybenci, którzy odbili wiadomość i zrezygnowali z subskrypcji:"
+
+#: views/campaigns/bounced.hbs:7 views/campaigns/clicked.hbs:13
+#: views/campaigns/complained.hbs:7 views/campaigns/delivered.hbs:7
+#: views/campaigns/opened.hbs:7 views/campaigns/unsubscribed.hbs:7
+#: views/lists/subscription/import-failed.hbs:9 views/lists/view.hbs:18
+#: views/triggers/triggered.hbs:6
+msgid "Address"
+msgstr "Adres"
+
+#: views/campaigns/bounced.hbs:8 views/campaigns/clicked.hbs:14
+#: views/campaigns/complained.hbs:8 views/campaigns/delivered.hbs:8
+#: views/campaigns/opened.hbs:8 views/campaigns/unsubscribed.hbs:8
+#: views/lists/subscription/add.hbs:6 views/lists/subscription/edit.hbs:7
+#: views/lists/subscription/import-preview.hbs:7 views/lists/view.hbs:19
+#: views/subscription/manage.hbs:4 views/subscription/subscribe.hbs:4
+#: views/triggers/triggered.hbs:7
+msgid "First Name"
+msgstr "Imię"
+
+#: views/campaigns/bounced.hbs:9 views/campaigns/clicked.hbs:15
+#: views/campaigns/complained.hbs:9 views/campaigns/delivered.hbs:9
+#: views/campaigns/opened.hbs:9 views/campaigns/unsubscribed.hbs:9
+#: views/lists/subscription/add.hbs:7 views/lists/subscription/edit.hbs:8
+#: views/lists/subscription/import-preview.hbs:8 views/lists/view.hbs:20
+#: views/subscription/manage.hbs:5 views/subscription/subscribe.hbs:5
+#: views/triggers/triggered.hbs:8
+msgid "Last Name"
+msgstr "Nazwisko"
+
+#: views/campaigns/bounced.hbs:10 views/campaigns/complained.hbs:10
+#: views/campaigns/delivered.hbs:10 views/campaigns/unsubscribed.hbs:10
+msgid "SMTP response"
+msgstr "Odpowiedź SMTP"
+
+#: views/campaigns/bounced.hbs:11
+msgid "Bounce time"
+msgstr "Czas odbicia"
+
+#: views/campaigns/campaigns.hbs:3 views/campaigns/create-triggered.hbs:24
+#: views/campaigns/create.hbs:3 views/campaigns/create.hbs:4
+#: views/campaigns/create.hbs:27
+msgid "Create Campaign"
+msgstr "Utwórz Kampanię"
+
+#: views/campaigns/campaigns.hbs:4
+msgid "Regular Campaign"
+msgstr "Zwykła kampania"
+
+#: views/campaigns/campaigns.hbs:5
+msgid "RSS Campaign"
+msgstr "Kampania RSS"
+
+#: views/campaigns/campaigns.hbs:6
+msgid "Triggered Campaign"
+msgstr "Wywołana kampania"
+
+#: views/campaigns/campaigns.hbs:8 views/campaigns/create-rss.hbs:6
+#: views/campaigns/create-triggered.hbs:5 views/campaigns/create.hbs:5
+#: views/campaigns/edit-rss.hbs:8 views/campaigns/edit-triggered.hbs:9
+#: views/campaigns/edit.hbs:10 views/campaigns/view.hbs:71
+#: views/lists/create.hbs:5 views/lists/edit.hbs:6
+#: views/lists/fields/fields.hbs:6 views/lists/lists.hbs:5
+#: views/lists/segments/segments.hbs:6 views/templates/templates.hbs:5
+#: views/triggers/triggers.hbs:5
+msgid "Name"
+msgstr "Nazwa"
+
+#: views/campaigns/campaigns.hbs:9 views/campaigns/create-rss.hbs:8
+#: views/campaigns/create-triggered.hbs:7 views/campaigns/create.hbs:7
+#: views/campaigns/edit-rss.hbs:10 views/campaigns/edit-triggered.hbs:11
+#: views/campaigns/edit.hbs:12 views/campaigns/view.hbs:72
+#: views/lists/create.hbs:7 views/lists/edit.hbs:10 views/lists/lists.hbs:8
+#: views/partials/merge-tag-reference.hbs:4 views/templates/create.hbs:9
+#: views/templates/edit.hbs:8 views/templates/templates.hbs:6
+#: views/triggers/create.hbs:7 views/triggers/edit.hbs:8
+#: views/triggers/triggers.hbs:7
+msgid "Description"
+msgstr "Opis"
+
+#: views/campaigns/campaigns.hbs:10 views/campaigns/view.hbs:73
+#: views/lists/view.hbs:21 views/lists/view.hbs:29
+#: views/triggers/triggers.hbs:6
+msgid "Status"
+msgstr "Status"
+
+#: views/campaigns/campaigns.hbs:11 views/campaigns/view.hbs:74
+#: views/lists/view.hbs:22 views/lists/view.hbs:23
+msgid "Created"
+msgstr "Utworzono"
+
+#: views/campaigns/clicked.hbs:3 views/campaigns/clicked.hbs:4
+msgid "Link info"
+msgstr "Informacje o linkach"
+
+#: views/campaigns/clicked.hbs:6 views/campaigns/view.hbs:61
+msgid "URL"
+msgstr "URL"
+
+#: views/campaigns/clicked.hbs:7 views/campaigns/view.hbs:62
+msgid "Clicks"
+msgstr "Kliknięcia"
+
+#: views/campaigns/clicked.hbs:8 views/campaigns/view.hbs:63
+msgid "% of clicks"
+msgstr "% kliknięć"
+
+#: views/campaigns/clicked.hbs:9 views/campaigns/view.hbs:64
+msgid "% of messages"
+msgstr "% wiadomości"
+
+#: views/campaigns/clicked.hbs:10 views/campaigns/view.hbs:67
+msgid "Aggregated clicks"
+msgstr "Zagregowane kliknięcia"
+
+#: views/campaigns/clicked.hbs:11
+msgid "Subscribers who clicked on a link:"
+msgstr "Subskrybenci, którzy kliknęli link:"
+
+#: views/campaigns/clicked.hbs:12
+msgid "Subscribers who clicked on this link:"
+msgstr "Subskrybenci, którzy kliknęli ten link:"
+
+#: views/campaigns/clicked.hbs:16
+msgid "First click time"
+msgstr "Czas pierwszego kliknięcia"
+
+#: views/campaigns/clicked.hbs:17
+msgid "Click count"
+msgstr "Liczba kliknięć"
+
+#: views/campaigns/complained.hbs:3 views/campaigns/complained.hbs:4
+msgid "Complained info"
+msgstr "Informacje o skargach"
+
+#: views/campaigns/complained.hbs:6
+msgid "Subscribers who complained and were unsubscribed:"
+msgstr "Subskrybenci, którzy złożyli skargę i wypisali się:"
+
+#: views/campaigns/complained.hbs:11
+msgid "Complain time"
+msgstr "Czas skargi"
+
+#: views/campaigns/create-rss.hbs:3 views/campaigns/create-rss.hbs:4
+#: views/campaigns/create-rss.hbs:20
+msgid "Create RSS Campaign"
+msgstr "Utwórz kampanię RSS"
+
+#: views/campaigns/create-rss.hbs:5 views/campaigns/edit-rss.hbs:6
+msgid ""
+"RSS campaign sets up a tracker against selected RSS feed address. Whenever a "
+"new entry is found from this feed it is sent to selected list as an email "
+"message."
+msgstr ""
+"Kampania RSS ustawia moduł śledzący na wybrany adres RSS. Za każdym razem, "
+"gdy nowy wpis zostanie znaleziony z tego kanału, zostanie wysłany na wybraną "
+"listę jako wiadomość e-mail."
+
+#: views/campaigns/create-rss.hbs:7 views/campaigns/create-triggered.hbs:6
+#: views/campaigns/create.hbs:6 views/campaigns/edit-rss.hbs:9
+#: views/campaigns/edit-triggered.hbs:10 views/campaigns/edit.hbs:11
+msgid "Campaign Name"
+msgstr "Nazwa kampanii"
+
+#: views/campaigns/create-rss.hbs:9 views/campaigns/create-triggered.hbs:8
+#: views/campaigns/create.hbs:8 views/campaigns/edit-rss.hbs:11
+#: views/campaigns/edit-triggered.hbs:12 views/campaigns/edit.hbs:13
+#: views/lists/create.hbs:8 views/lists/edit.hbs:11
+#: views/templates/create.hbs:11 views/templates/edit.hbs:10
+#: views/triggers/create.hbs:9 views/triggers/edit.hbs:10
+msgid "HTML is allowed"
+msgstr "HTML dozwolony"
+
+#: views/campaigns/create-rss.hbs:10 views/campaigns/create-triggered.hbs:9
+#: views/campaigns/create.hbs:9 views/campaigns/edit-rss.hbs:12
+#: views/campaigns/edit-triggered.hbs:13 views/campaigns/edit.hbs:14
+#: views/campaigns/view.hbs:6 views/triggers/create-select.hbs:6
+#: views/triggers/create.hbs:10 views/triggers/edit.hbs:12
+#: views/triggers/triggers.hbs:8
+msgid "List"
+msgstr "Lista"
+
+#: views/campaigns/create-rss.hbs:11 views/campaigns/create-triggered.hbs:10
+#: views/campaigns/create-triggered.hbs:13 views/campaigns/create.hbs:10
+#: views/campaigns/create.hbs:14 views/campaigns/edit-rss.hbs:13
+#: views/campaigns/edit-triggered.hbs:14 views/campaigns/edit.hbs:15
+#: views/lists/fields/create.hbs:27 views/lists/fields/edit.hbs:28
+#: views/lists/segments/create.hbs:9 views/lists/segments/edit.hbs:10
+#: views/lists/segments/rule-create.hbs:7 views/lists/subscription/add.hbs:10
+#: views/lists/subscription/add.hbs:12 views/lists/subscription/edit.hbs:11
+#: views/lists/subscription/import-preview.hbs:5
+#: views/subscription/manage.hbs:10 views/subscription/subscribe.hbs:10
+#: views/templates/create.hbs:8 views/triggers/create-select.hbs:7
+#: views/triggers/create.hbs:17 views/triggers/create.hbs:20
+#: views/triggers/create.hbs:22 views/triggers/create.hbs:26
+#: views/triggers/edit.hbs:19 views/triggers/edit.hbs:22
+#: views/triggers/edit.hbs:24 views/triggers/edit.hbs:28
+msgid "Select"
+msgstr "Wybierz"
+
+#: views/campaigns/create-rss.hbs:12 views/campaigns/create-triggered.hbs:11
+#: views/campaigns/create.hbs:11 views/campaigns/edit-rss.hbs:14
+#: views/campaigns/edit-triggered.hbs:15 views/campaigns/edit.hbs:16
+#: views/triggers/create-select.hbs:8 views/triggers/create.hbs:11
+#: views/triggers/edit.hbs:13
+msgid "subscribers"
+msgstr "subskrybenci"
+
+#: views/campaigns/create-rss.hbs:13 views/campaigns/edit-rss.hbs:15
+msgid "RSS Feed Url"
+msgstr "Adres URL kanału RSS"
+
+#: views/campaigns/create-rss.hbs:14 views/campaigns/edit-rss.hbs:16
+msgid ""
+"New entries from this RSS URL are sent out to list subscribers as email "
+"messages"
+msgstr ""
+"Nowe wpisy z tego adresu RSS są wysyłane do listy subskrybentów, jak "
+"wiadomości e-mail"
+
+#: views/campaigns/create-rss.hbs:15 views/campaigns/create-triggered.hbs:17
+#: views/campaigns/create.hbs:18 views/campaigns/edit-rss.hbs:18
+#: views/campaigns/edit-triggered.hbs:16 views/campaigns/edit.hbs:17
+#: views/campaigns/view.hbs:12
+msgid "Email \"from name\""
+msgstr "E-mail nazwa \"from\""
+
+#: views/campaigns/create-rss.hbs:16 views/campaigns/create-triggered.hbs:18
+#: views/campaigns/create.hbs:19 views/campaigns/edit-rss.hbs:19
+#: views/campaigns/edit.hbs:18 views/settings.hbs:23
+msgid "This is the name your emails will come from"
+msgstr "This is the name your emails will come from"
+
+#: views/campaigns/create-rss.hbs:17 views/campaigns/create-triggered.hbs:19
+#: views/campaigns/create.hbs:20 views/campaigns/edit-rss.hbs:20
+#: views/campaigns/edit-triggered.hbs:18 views/campaigns/edit.hbs:19
+#: views/campaigns/view.hbs:13
+msgid "Email \"from\" address"
+msgstr "E-mail adres \"from\""
+
+#: views/campaigns/create-rss.hbs:18 views/campaigns/create-triggered.hbs:20
+#: views/campaigns/edit-rss.hbs:21 views/campaigns/edit-triggered.hbs:19
+#: views/settings.hbs:25
+msgid "This is the address people will send replies to"
+msgstr "To jest adres na który ludzie będą wysyłać odpowiedzi"
+
+#: views/campaigns/create-rss.hbs:19 views/campaigns/create-triggered.hbs:23
+#: views/campaigns/create.hbs:26 views/campaigns/edit-rss.hbs:22
+#: views/campaigns/edit-triggered.hbs:22 views/campaigns/edit.hbs:25
+msgid "Disable clicked/opened tracking"
+msgstr "Wyłącz kliknięte/otwarte śledzenie"
+
+#: views/campaigns/create-triggered.hbs:3
+#: views/campaigns/create-triggered.hbs:4
+msgid "Create Triggered Campaign"
+msgstr "Utwórz uruchamianą kampanię"
+
+#: views/campaigns/create-triggered.hbs:12 views/campaigns/create.hbs:12
+#: views/campaigns/edit-triggered.hbs:7 views/campaigns/edit.hbs:7
+#: views/lists/fields/create.hbs:31 views/lists/fields/edit.hbs:33
+#: views/templates/create.hbs:13
+msgid "Template"
+msgstr "Szablon"
+
+#: views/campaigns/create-triggered.hbs:14 views/campaigns/create.hbs:15
+msgid "Selecting a template creates a campaign specific copy from it"
+msgstr "Wybranie szablonu powoduje utworzenie z niego kopii dla kampanii"
+
+#: views/campaigns/create-triggered.hbs:15 views/campaigns/create.hbs:16
+msgid "Or alternatively use an URL as the message content source:"
+msgstr "Lub alternatywnie użyj adresu URL jako źródło treści wiadomości:"
+
+#: views/campaigns/create-triggered.hbs:16 views/campaigns/create.hbs:17
+#: views/campaigns/edit-triggered.hbs:25 views/campaigns/edit.hbs:28
+msgid ""
+"If a message is sent then this URL will be POSTed to using Merge Tags as "
+"POST body. Use this if you want to generate the HTML message yourself"
+msgstr ""
+"Jeśli wiadomość zostanie wysłana, ten adres URL zostanie wysłany POST do "
+"używania merge tagów jako treść POST. Użyj tej opcji, jeśli chcesz "
+"samodzielnie wygenerować wiadomość HTML"
+
+#: views/campaigns/create-triggered.hbs:21 views/campaigns/create.hbs:24
+#: views/campaigns/edit-triggered.hbs:20 views/campaigns/edit.hbs:23
+#: views/campaigns/view.hbs:15
+msgid "Email \"subject line\""
+msgstr "E-mail temat \"from\""
+
+#: views/campaigns/create-triggered.hbs:22 views/campaigns/create.hbs:25
+#: views/campaigns/edit-triggered.hbs:21 views/campaigns/edit.hbs:24
+#: views/settings.hbs:27
+msgid "Keep it relevant and non-spammy"
+msgstr "Zachowaj to, co istotne i nie spamuj"
+
+#: views/campaigns/create.hbs:13
+msgid "Select a template:"
+msgstr "Wybierz szablon:"
+
+#: views/campaigns/create.hbs:21 views/campaigns/edit.hbs:20
+msgid ""
+"This is the address people will send replies to unless reply-to address is "
+"set"
+msgstr ""
+"To jest adres, na który ludzie będą wysyłać odpowiedzi, chyba że ustawiono "
+"adres zwrotny"
+
+#: views/campaigns/create.hbs:22 views/campaigns/edit.hbs:21
+#: views/campaigns/view.hbs:14
+msgid "Email \"reply-to\" address"
+msgstr "Email \"Odpowiedz do\""
+
+#: views/campaigns/create.hbs:23 views/campaigns/edit.hbs:22
+msgid "If set, this is the address people will send replies to"
+msgstr ""
+"Jeśli jest ustawiony, jest to adres, na który ludzie będą wysyłać odpowiedzi"
+
+#: views/campaigns/delivered.hbs:3 views/campaigns/delivered.hbs:4
+msgid "Delivered info"
+msgstr "Informacje o dostarczonych"
+
+#: views/campaigns/delivered.hbs:6
+msgid "Subscribers who received the message and did not bounce/unsubscribe:"
+msgstr ""
+"Subskrybenci, którzy otrzymali wiadomość i nie odrzucili/nie anulowali "
+"subskrypcji:"
+
+#: views/campaigns/delivered.hbs:11
+msgid "Delivery time"
+msgstr "Czas dostarczenia"
+
+#: views/campaigns/edit-rss.hbs:3 views/campaigns/edit-rss.hbs:4
+msgid "Edit RSS Campaign"
+msgstr "Edytuj kampanię RSS"
+
+#: views/campaigns/edit-rss.hbs:7 views/campaigns/edit-triggered.hbs:8
+#: views/campaigns/edit.hbs:9 views/settings.hbs:4 views/users/account.hbs:6
+msgid "General Settings"
+msgstr "Ustawienia główne"
+
+#: views/campaigns/edit-rss.hbs:17
+msgid ""
+"Use special merge tag [RSS_ENTRY] to mark the position for the RSS post "
+"content. Additionally you can use any valid merge tag as well."
+msgstr ""
+"Użyj specjalnego merge tagu [RSS_ENTRY], aby oznaczyć pozycję treści "
+"wiadomości RSS. Dodatkowo mżesz użyć dowolnego innego merge tagu."
+
+#: views/campaigns/edit-rss.hbs:23 views/campaigns/edit-triggered.hbs:26
+#: views/campaigns/edit.hbs:34
+msgid "Delete Campaign"
+msgstr "Usuń kampanię"
+
+#: views/campaigns/edit-rss.hbs:24 views/campaigns/edit-triggered.hbs:27
+#: views/campaigns/edit.hbs:35 views/lists/edit.hbs:13
+#: views/lists/fields/edit.hbs:39 views/lists/segments/edit.hbs:14
+#: views/lists/segments/rule-edit.hbs:38 views/lists/subscription/edit.hbs:17
+#: views/settings.hbs:99 views/templates/edit.hbs:12 views/triggers/edit.hbs:30
+#: views/users/account.hbs:18
+msgid "Update"
+msgstr "Zaktualizuj"
+
+#: views/campaigns/edit-triggered.hbs:3 views/campaigns/edit-triggered.hbs:4
+msgid "Edit Triggered Campaign"
+msgstr "Edytuj kampanię uruchamianą"
+
+#: views/campaigns/edit-triggered.hbs:6 views/campaigns/edit.hbs:6
+msgid "General"
+msgstr "Główne"
+
+#: views/campaigns/edit-triggered.hbs:17
+msgid "his is the name your emails will come from"
+msgstr "Nazwa, z której będą wysyłane wszystkie e-maile."
+
+#: views/campaigns/edit-triggered.hbs:23 views/campaigns/edit.hbs:26
+msgid "Template Settings"
+msgstr "Ustawienia szablonu"
+
+#: views/campaigns/edit-triggered.hbs:24 views/campaigns/edit.hbs:27
+msgid "Template URL"
+msgstr "Adres URL szablonu"
+
+#: views/campaigns/edit.hbs:3 views/campaigns/edit.hbs:4
+#: views/campaigns/upload-attachment.hbs:3
+#: views/campaigns/upload-attachment.hbs:5 views/campaigns/view.hbs:3
+msgid "Edit Campaign"
+msgstr "Edytuj kampanie"
+
+#: views/campaigns/edit.hbs:8 views/campaigns/edit.hbs:29
+msgid "Attachments"
+msgstr "Załączniki"
+
+#: views/campaigns/edit.hbs:30
+msgid "File"
+msgstr "Plik"
+
+#: views/campaigns/edit.hbs:31
+msgid "Size"
+msgstr "Rozmiar"
+
+#: views/campaigns/edit.hbs:32 views/campaigns/view.hbs:66
+#: views/lists/fields/fields.hbs:12 views/lists/view.hbs:32
+msgid "No data available in table"
+msgstr "Brak danych w tabeli"
+
+#: views/campaigns/edit.hbs:33 views/campaigns/upload-attachment.hbs:4
+msgid "Add Attachment"
+msgstr "Dodaj załącznik"
+
+#: views/campaigns/opened.hbs:3 views/campaigns/opened.hbs:4
+msgid "Opened info"
+msgstr "Informacje o otwarciach"
+
+#: views/campaigns/opened.hbs:6
+msgid "Subscribers who opened this message:"
+msgstr "Subskrybenci, którzy otworzyli tę wiadomość:"
+
+#: views/campaigns/opened.hbs:10
+msgid "First open"
+msgstr "Pierwsze otwarcie"
+
+#: views/campaigns/opened.hbs:11
+msgid "Opened count"
+msgstr "Liczba otwarć"
+
+#: views/campaigns/unsubscribed.hbs:3 views/campaigns/unsubscribed.hbs:4
+msgid "Unsubscribed info"
+msgstr "Informacje o anulowaniach subskrypcji"
+
+#: views/campaigns/unsubscribed.hbs:6
+msgid "Subscribers who unsubscribed:"
+msgstr "Subskrybenci, którzy anulowali subskrypcję:"
+
+#: views/campaigns/unsubscribed.hbs:11 views/campaigns/view.hbs:26
+#: views/lists/subscription/import.hbs:10 routes/lists.js:171
+msgid "Unsubscribed"
+msgstr "Anulowano subskrypcję"
+
+#: views/campaigns/upload-attachment.hbs:7
+msgid "Upload"
+msgstr "Prześlij"
+
+#: views/campaigns/view.hbs:4
+msgid "Overview"
+msgstr "Przegląd"
+
+#: views/campaigns/view.hbs:5
+msgid "Links"
+msgstr "Linków"
+
+#: views/campaigns/view.hbs:7
+msgid "Feed URL"
+msgstr "Url czytnika"
+
+#: views/campaigns/view.hbs:8
+msgid "Last check"
+msgstr "Ostatnie sprawdzenie"
+
+#: views/campaigns/view.hbs:9
+msgid "Not yet checked"
+msgstr "Jeszcze nie sprawdzone"
+
+#: views/campaigns/view.hbs:10
+msgid "activate campaign to start checking feed for new messages"
+msgstr ""
+"aktywuj kampanię, aby rozpocząć sprawdzanie kanału dla nowych wiadomości"
+
+#: views/campaigns/view.hbs:11
+msgid "RSS status"
+msgstr "Status RSS"
+
+#: views/campaigns/view.hbs:16
+msgid "Preview campaign as"
+msgstr "Podgląd kampanii jako"
+
+#: views/campaigns/view.hbs:17
+msgid "Add new test user"
+msgstr "Dodaj użytkownika testowego"
+
+#: views/campaigns/view.hbs:18
+msgid "No test users yet, create one here"
+msgstr "Brak użytkowników testowych, utwórz je tutaj"
+
+#: views/campaigns/view.hbs:19
+msgid "Go"
+msgstr "Dalej"
+
+#: views/campaigns/view.hbs:20 lib/models/triggers.js:25
+msgid "Delivered"
+msgstr "Dostarczone"
+
+#: views/campaigns/view.hbs:21
+msgid "List subscribers who received this message"
+msgstr "Lista subskrybentów, którzy otrzymali tę wiadomość"
+
+#: views/campaigns/view.hbs:22 routes/lists.js:171
+msgid "Bounced"
+msgstr "Odbite"
+
+#: views/campaigns/view.hbs:23
+msgid "List subscribers who bounced"
+msgstr "Lista użytkowników którzy odbili"
+
+#: views/campaigns/view.hbs:24
+msgid "Complaints"
+msgstr "Skargi"
+
+#: views/campaigns/view.hbs:25
+msgid "List subscribers who complained for this message"
+msgstr "Lista subskrybentów, którzy złożyli skargę na tę wiadomość"
+
+#: views/campaigns/view.hbs:27
+msgid "List subscribers who unsubscribed after this message"
+msgstr "Lista subskrybentów, którzy anulowali subskrypcję po tej wiadomości"
+
+#: views/campaigns/view.hbs:28
+msgid "Opened"
+msgstr "Otwarto"
+
+#: views/campaigns/view.hbs:29
+msgid "List subscribers who opened this message"
+msgstr "Lista subskrybentów, którzy otworzyli tę wiadomość"
+
+#: views/campaigns/view.hbs:30
+msgid "Clicked"
+msgstr "Kliknięto"
+
+#: views/campaigns/view.hbs:31 views/campaigns/view.hbs:68
+msgid "List subscribers who clicked on a link"
+msgstr "Lista subskrybentów, którzy kliknęli w link"
+
+#: views/campaigns/view.hbs:32
+msgid ""
+"Are you sure? This action would start sending messages to the selected list"
+msgstr ""
+"Jesteś pewny? Ta czynność rozpocznie wysyłanie wiadomości do wybranej listy"
+
+#: views/campaigns/view.hbs:33
+msgid "Delay sending"
+msgstr "Opóźnienie wysyłania"
+
+#: views/campaigns/view.hbs:34
+msgid "hours"
+msgstr "godziny"
+
+#: views/campaigns/view.hbs:35
+msgid "minutes"
+msgstr "minuty"
+
+#: views/campaigns/view.hbs:36
+msgid "Send to subscribers:"
+msgstr "Wyślij do subskrybentów:"
+
+#: views/campaigns/view.hbs:37
+msgid "Are you sure? This action would reset scheduling"
+msgstr "Jesteś pewny? Ta czynność zresetuje harmonogram"
+
+#: views/campaigns/view.hbs:38
+msgid "Cancel"
+msgstr "Anuluj"
+
+#: views/campaigns/view.hbs:39
+msgid "Sending scheduled"
+msgstr "Wysyłanie harmonogramu"
+
+#: views/campaigns/view.hbs:40 views/campaigns/view.hbs:52
+msgid "Pause"
+msgstr "Pauza"
+
+#: views/campaigns/view.hbs:41 routes/campaigns.js:264
+msgid "Sending"
+msgstr "Wysyłanie"
+
+#: views/campaigns/view.hbs:42 views/campaigns/view.hbs:46
+msgid ""
+"Are you sure? This action would resume sending messages to the selected list"
+msgstr ""
+"Jesteś pewny? Ta czynność wznowi wysyłanie wiadomości do wybranej listy"
+
+#: views/campaigns/view.hbs:43 views/campaigns/view.hbs:47
+msgid "Are you sure? This action would reset all stats about current progress"
+msgstr ""
+"Jesteś pewny? Ta czynność zresetuje wszystkie statystyki dotyczące bieżącego "
+"postępu"
+
+#: views/campaigns/view.hbs:44
+msgid "Resume"
+msgstr "Wznów"
+
+#: views/campaigns/view.hbs:45 views/campaigns/view.hbs:49
+msgid "Reset"
+msgstr "Resetuj"
+
+#: views/campaigns/view.hbs:48
+msgid "Continue"
+msgstr "Kontynuuj"
+
+#: views/campaigns/view.hbs:50
+msgid ""
+"All messages sent! Hit \"Continue\" if you you want to send this campaign to "
+"new subscribers"
+msgstr ""
+"Wszystkie wiadomości wysłane! Kliknij \"Kontynuuj\", jeśli chcesz wysłać tę "
+"kampanię do nowych subskrybentów"
+
+#: views/campaigns/view.hbs:51
+msgid ""
+"Are you sure? This action would pause sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Jesteś pewny? Ta czynność wstrzyma wysyłanie wiadomości o nowych wpisach w "
+"kanale RSS do wybranej listy"
+
+#: views/campaigns/view.hbs:53 views/campaigns/view.hbs:57
+msgid "Campaign status:"
+msgstr "Status kampanii:"
+
+#: views/campaigns/view.hbs:54
+msgid "ACTIVE"
+msgstr "AKTYWNE"
+
+#: views/campaigns/view.hbs:55
+msgid ""
+"Are you sure? This action would start sending new entries in RSS feed as "
+"email messages to the selected list"
+msgstr ""
+"Jesteś pewny? Ta czynność rozpocznie wysyłanie wiadomości o nowych wpisach w "
+"kanale RSS do wybranej listy"
+
+#: views/campaigns/view.hbs:56
+msgid "Activate"
+msgstr "Aktywuj"
+
+#: views/campaigns/view.hbs:58
+msgid "INACTIVE"
+msgstr "NIEAKTYWNE"
+
+#: views/campaigns/view.hbs:59
+msgid ""
+"This is a triggered campaign. Messages are only sent to subscribers that hit "
+"some trigger that invokes this campaign"
+msgstr ""
+"To jest kampania wyzwalana. Wiadomości są wysyłane tylko do subskrybentów, "
+"którzy natrafili na jakiś wyzwalacz, który wywołuje tę kampanię"
+
+#: views/campaigns/view.hbs:60
+msgid "see more"
+msgstr "zobacz więcej"
+
+#: views/campaigns/view.hbs:65
+msgid "List subscribers who clicked this link"
+msgstr "Lista subskrybentów, którzy kliknęli link"
+
+#: views/campaigns/view.hbs:69
+msgid ""
+"Clicks are counted as unique subscribers that clicked on a specific link or "
+"on any link (in aggregated view)"
+msgstr ""
+"Kliknięcia są liczone jako unikalni subskrybenci, którzy kliknęli określony "
+"link lub dowolny link (w widoku zbiorczym)"
+
+#: views/campaigns/view.hbs:70
+msgid ""
+"If a new entry is found from campaign feed a new subcampaign is created of "
+"that entry and it will be listed here"
+msgstr ""
+"Jeśli zostanie znaleziony nowy wpis z kanału kampanii, zostanie utworzona "
+"nowa kampania podrzędna dla tego wpisu i zostanie ona tutaj wymieniona"
+
+#: views/emails/confirm-html.hbs:1 views/emails/confirm-html.hbs:2
+#: views/emails/confirm-text.hbs:1
+msgid "Please Confirm Subscription"
+msgstr "Proszę potwierdź subskrypcję"
+
+#: views/emails/confirm-html.hbs:3 views/emails/confirm-text.hbs:2
+msgid "Yes, subscribe me to this list"
+msgstr "Tak, zapisz mnie na listę"
+
+#: views/emails/confirm-html.hbs:4
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed if you don't click the confirmation link above."
+msgstr ""
+"Jeśli przez pomyłkę otrzymałeś tego e-maila, po prostu go usuń. Nie będziesz "
+"subskrybowany, jeśli nie klikniesz w link potwierdzający."
+
+#: views/emails/confirm-html.hbs:5 views/emails/confirm-text.hbs:4
+#: views/emails/subscription-confirmed-html.hbs:7
+#: views/emails/subscription-confirmed-text.hbs:7
+#: views/emails/unsubscribe-confirmed-html.hbs:5
+#: views/emails/unsubscribe-confirmed-text.hbs:5
+msgid "For questions about this list, please contact:"
+msgstr "W przypadku pytań dotyczących tej listy, prosimy o kontakt:"
+
+#: views/emails/confirm-text.hbs:3
+msgid ""
+"If you received this email by mistake, simply delete it. You won't be "
+"subscribed unless you click the confirmation link above."
+msgstr ""
+"Jeśli przez pomyłkę otrzymałeś tego e-maila, po prostu go usuń. Nie będziesz "
+"subskrybowany, chyba że klikniesz link powyżej."
+
+#: views/emails/password-reset-html.hbs:1
+#: views/emails/password-reset-html.hbs:2
+#: views/emails/password-reset-text.hbs:1
+msgid "Change your password"
+msgstr "Zmień hasło"
+
+#: views/emails/password-reset-html.hbs:3
+#: views/emails/password-reset-text.hbs:2
+msgid "We have received a password change request for your Mailtrain account:"
+msgstr "Otrzymaliśmy prośbę o zmianę hasła dla Twojego konta Mailtrain:"
+
+#: views/emails/password-reset-html.hbs:4
+#: views/emails/password-reset-text.hbs:3
+msgid "Reset password"
+msgstr "Zresetuj hasło"
+
+#: views/emails/password-reset-html.hbs:5
+#: views/emails/password-reset-text.hbs:4
+msgid ""
+"If you did not ask to change your password, then you can ignore this email "
+"and your password will not be changed."
+msgstr ""
+"Jeśli nie poprosiłeś o zmianę hasła, możesz zignorować ten e-mail, a Twoje "
+"hasło nie zostanie zmienione."
+
+#: views/emails/rss-html.hbs:1 views/emails/stationery-html.hbs:3
+#: views/emails/stationery-text.hbs:3
+msgid "Preferences"
+msgstr "Preferencje"
+
+#: views/emails/rss-html.hbs:2 views/emails/stationery-html.hbs:4
+#: views/emails/stationery-text.hbs:4 views/lists/subscription/edit.hbs:15
+#: views/subscription/manage.hbs:12 views/subscription/unsubscribe.hbs:1
+#: views/subscription/unsubscribe.hbs:4 routes/lists.js:253
+msgid "Unsubscribe"
+msgstr "Anuluj subskrypcję"
+
+#: views/emails/rss-html.hbs:3 views/emails/stationery-html.hbs:5
+#: views/emails/stationery-text.hbs:5
+msgid "View this email in your browser"
+msgstr "Zobacz ten email w Twojej przeglądarce"
+
+#: views/emails/stationery-html.hbs:1 views/emails/stationery-text.hbs:1
+msgid "Hey [FIRST_NAME/Customer],"
+msgstr "Cześć [FIRST_NAME/Customer],"
+
+#: views/emails/stationery-html.hbs:2 views/emails/stationery-text.hbs:2
+msgid "Cheers,"
+msgstr "Pozdrowienia,"
+
+#: views/emails/subscription-confirmed-html.hbs:1
+#: views/emails/subscription-confirmed-text.hbs:1
+#: views/subscription/subscribed.hbs:1
+msgid "Subscription Confirmed"
+msgstr "Subskrypcja została potwierdzona"
+
+#: views/emails/subscription-confirmed-html.hbs:2
+#: views/emails/subscription-confirmed-text.hbs:2
+#: views/subscription/subscribed.hbs:2
+msgid "Your subscription to our list has been confirmed."
+msgstr "Twoja subskrypcja naszej listy została potwierdzona."
+
+#: views/emails/subscription-confirmed-html.hbs:3
+#: views/emails/subscription-confirmed-text.hbs:3
+msgid "If you want to modify your subscription then you can:"
+msgstr "Jeśli chcesz zmodyfikować swoją subskrypcję, możesz:"
+
+#: views/emails/subscription-confirmed-html.hbs:4
+#: views/emails/subscription-confirmed-text.hbs:4
+#: views/subscription/subscribed.hbs:6
+msgid "manage your preferences"
+msgstr "zarządzaj swoimi preferencjami"
+
+#: views/emails/subscription-confirmed-html.hbs:5
+#: views/emails/subscription-confirmed-text.hbs:5
+#: views/subscription/subscribed.hbs:5 views/users/login.hbs:10
+msgid "or"
+msgstr "lub"
+
+#: views/emails/subscription-confirmed-html.hbs:6
+#: views/emails/subscription-confirmed-text.hbs:6
+msgid "unsubscribe here"
+msgstr "anuluj subskrypcję tutaj"
+
+#: views/emails/unsubscribe-confirmed-html.hbs:1
+#: views/emails/unsubscribe-confirmed-text.hbs:1
+msgid "You are now unsubscribed"
+msgstr "Anulowałeś subskrypcję"
+
+#: views/emails/unsubscribe-confirmed-html.hbs:2
+#: views/emails/unsubscribe-confirmed-text.hbs:2
+msgid "We have removed your email address from our list."
+msgstr "Usunęliśmy Twój adres e-mail z naszej listy."
+
+#: views/emails/unsubscribe-confirmed-html.hbs:3
+#: views/emails/unsubscribe-confirmed-text.hbs:3
+msgid "If you unsubscribed by mistake, you can re-subscribe at:"
+msgstr ""
+"Jeśli anulujesz subskrypcję przez pomyłkę, możesz ponownie zasubskrybować na:"
+
+#: views/emails/unsubscribe-confirmed-html.hbs:4
+#: views/emails/unsubscribe-confirmed-text.hbs:4
+#: views/lists/subscription/add.hbs:16 routes/lists.js:253
+msgid "Subscribe"
+msgstr "Subskrybuj"
+
+#: views/index.hbs:1
+msgid "Official Mailtrain Partners"
+msgstr "Oficjalni partnerzy Mailtrain"
+
+#: views/index.hbs:2
+msgid "Free, open source mail server solution"
+msgstr "Darmowe, o otwartym kodzie źródłowym rozwiązanie serwera poczty"
+
+#: views/index.hbs:3
+msgid ""
+"A reliable SMTP server, easy integration, and 12,000 messages a month free"
+msgstr ""
+"Niezawodny serwer SMTP, łatwa integracja i 12 000 wiadomości miesięcznie za "
+"darmo"
+
+#: views/index.hbs:4
+msgid "List management"
+msgstr "Zarządzanie listamie"
+
+#: views/index.hbs:5
+msgid ""
+"Mailtrain allows you to easily manage even very large lists. Million "
+"subscribers? Not a problem. You can add subscribers manually, through the "
+"API or import from a CSV file. All lists come with support for custom fields "
+"and merge tags as well."
+msgstr ""
+"Mailtrain pozwala w łatwy sposób zarządzać nawet bardzo dużymi listami. "
+"Milion subskrybentów? Żaden problem. Możesz dodawać subskrybentów ręcznie, "
+"za pośrednictwem interfejsu API lub importować z pliku CSV. Wszystkie listy "
+"zawierają również obsługę pól niestandardowych i znaczników scalających."
+
+#: views/index.hbs:6
+msgid "Custom fields"
+msgstr "Pola niestandardowe"
+
+#: views/index.hbs:7
+msgid ""
+"Text fields, numbers, drop downs or checkboxes, Mailtrain has them all. "
+"Every custom field can be included in the generated newsletters through "
+"merge tags."
+msgstr ""
+"Pola tekstowe, cyfry, listy rozwijane lub pola wyboru, Mailtrain ma je "
+"wszystkie. Każde niestandardowe pole może być zawarte w wygenerowanych "
+"newsletterach za pomocą merge tagów."
+
+#: views/index.hbs:8
+msgid "List segmentation"
+msgstr "Segmentacja listy"
+
+#: views/index.hbs:9
+msgid ""
+"Send messages only to list subscribers that match predefined segmentation "
+"rules. No need to create separate lists with small differences."
+msgstr ""
+"Wysyłaj wiadomości tylko dla subskrybentów, którzy pasują do "
+"predefiniowanych reguł segmentacji. Nie trzeba tworzyć oddzielnych list z "
+"małymi różnicami."
+
+#: views/index.hbs:10
+msgid "Donate to author"
+msgstr "Przekaż darowiznę autorowi"
+
+#: views/index.hbs:11
+msgid ""
+"If you really like Mailtrain or your business benefits from it financially "
+"then I would really appreciate a small donation to keep the Mailtrain "
+"development engines running. You can either use Bitcoin or PayPal for "
+"donations. My Bitcoin wallet is 15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM"
+"code>"
+msgstr ""
+"Jeśli naprawdę lubisz Mailtrain lub Twoja firma czerpie z teg korzyści "
+"finansowe będę naprawdę wdzięczny za niewielką darowiznę, aby utrzymać "
+"rozwój Mailtrain. Możesz użyć Bitcoin lub PayPal do darowizn. Mój portfel "
+"Bitcoin to 15Z8ADxhssKUiwP3jbbqJwA21744KMCfTM"
+
+#: views/index.hbs:12
+msgid "or donate using PayPal"
+msgstr "lub przekaż darowiznę za pomocą PayPal"
+
+#: views/index.hbs:13
+msgid "RSS Campaigns"
+msgstr "Kampanie RSS"
+
+#: views/index.hbs:14
+msgid ""
+"Setup Mailtrain to track RSS feeds and if a new entry is detected in a feed "
+"then Mailtrain auto-generates a new campaign using entry data as message "
+"contents and sends it to selected subscribers."
+msgstr ""
+"Przygotuj Mailtrain do śledzenia kanałów RSS i jeśli wykryty zostanie nowy "
+"wpis w kanale, Mailtrain automatycznie generuje nową kampanię, wykorzystując "
+"dane wejściowe jako treść wiadomości i wysyła je do wybranych subskrybentów."
+
+#: views/index.hbs:15
+msgid "GPG Encryption"
+msgstr "Szyfrowanie GPG"
+
+#: views/index.hbs:16
+msgid ""
+"If a list has a custom field for a GPG Public Key set then subscribers can "
+"upload their GPG public key to receive encrypted messages from the list."
+msgstr ""
+"Jeśli lista ma niestandardowe pole dla zestawu kluczy publicznych GPG, "
+"subskrybenci mogą przesłać swój klucz publiczny GPG, aby otrzymywać "
+"zaszyfrowane wiadomości z listy."
+
+#: views/index.hbs:17
+msgid "Click stats"
+msgstr "Statystyki kliknięć"
+
+#: views/index.hbs:18
+msgid ""
+"After a campaign is sent, check individual click statistics for every link "
+"included in the message."
+msgstr ""
+"Po wysłaniu kampanii sprawdź statystyki poszczególnych kliknięć dla każdego "
+"linku zawartego w wiadomości."
+
+#: views/index.hbs:19
+msgid "Open source"
+msgstr "Open source"
+
+#: views/index.hbs:20
+msgid "Mailtrain is available under GPLv3 license and completely open source."
+msgstr "Mailtrain jest dostępny na licencji GPLv3 i całkowicie open source."
+
+#: views/index.hbs:21
+msgid "Send via any provider"
+msgstr "Wyślij przez dowolnego dostawcę"
+
+#: views/index.hbs:22
+msgid ""
+"Mailtrain recommends SendPulse even though you "
+"can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+msgstr ""
+"Mailtrain recommends SendPulse even though you "
+"can use any provider that supports SMTP protocol to send out your "
+"newsletters. Bounce and complaints handling via webhooks is supported for "
+"SES, SparkPost, SendGrid and Mailgun, also for Postfix and ZoneMTA."
+"Odbieranie i obsługa skarg za pośrednictwem webhooków jest obsługiwane dla "
+"SES, SparkPost, SendGrid i Mailgun, także dla Postfix i ZoneMTA."
+
+#: views/index.hbs:23
+msgid "Trigger based automation"
+msgstr "Automatyzacja oparta na wyzwalaczach"
+
+#: views/index.hbs:24
+msgid ""
+"Define automation triggers to send specific messages when a user activates "
+"the trigger."
+msgstr ""
+"Zdefiniuj wyzwalacze automatyzacji, aby wysłać określone komunikaty, gdy "
+"użytkownik aktywuje wyzwalacz."
+
+#: views/layout.hbs:2
+msgid "Toggle navigation"
+msgstr "Przełącz nawigację"
+
+#: views/layout.hbs:3
+msgid "Wiki"
+msgstr "Wiki"
+
+#: views/layout.hbs:4
+msgid "Blog"
+msgstr "Blog"
+
+#: views/layout.hbs:5 views/users/account.hbs:2 views/users/account.hbs:3
+msgid "Account"
+msgstr "Konto"
+
+#: views/layout.hbs:6 views/settings.hbs:2 views/settings.hbs:3
+msgid "Settings"
+msgstr "Ustawienia"
+
+#: views/layout.hbs:7 views/users/api.hbs:2 views/users/api.hbs:3
+msgid "API"
+msgstr "API"
+
+#: views/layout.hbs:8
+msgid "Log out"
+msgstr "Wyloguj"
+
+#: views/layout.hbs:9 views/users/forgot.hbs:2 views/users/login.hbs:2
+#: views/users/login.hbs:3 views/users/login.hbs:9 views/users/reset.hbs:2
+msgid "Sign in"
+msgstr "Zaloguj się"
+
+#: views/layout.hbs:10
+msgid "Self hosted newsletter app built on top of Nodemailer"
+msgstr ""
+"Samodzielnie hostowana aplikacja e-mail newsletter zbudowana na bazie "
+"Nodemailera"
+
+#: views/layout.hbs:11 views/layout.hbs:13
+msgid "Source on GitHub"
+msgstr "Źródło na GitHub"
+
+#: views/layout.hbs:12
+msgid "Subscribe to our newsletter"
+msgstr "Zapisz się do naszego newslettera"
+
+#: views/lists/create.hbs:2 views/lists/edit.hbs:2
+#: views/lists/fields/create.hbs:2 views/lists/fields/edit.hbs:2
+#: views/lists/fields/fields.hbs:2 views/lists/lists.hbs:2
+#: views/lists/lists.hbs:4 views/lists/segments/create.hbs:2
+#: views/lists/segments/edit.hbs:2 views/lists/segments/rule-configure.hbs:2
+#: views/lists/segments/rule-create.hbs:2 views/lists/segments/rule-edit.hbs:2
+#: views/lists/segments/segments.hbs:2 views/lists/segments/view.hbs:2
+#: views/lists/subscription/add.hbs:2 views/lists/subscription/edit.hbs:2
+#: views/lists/subscription/import-failed.hbs:2
+#: views/lists/subscription/import-preview.hbs:2
+#: views/lists/subscription/import.hbs:2 views/lists/view.hbs:2
+#: lib/tools.js:111
+msgid "Lists"
+msgstr "Listy"
+
+#: views/lists/create.hbs:3 views/lists/create.hbs:4 views/lists/create.hbs:9
+#: views/lists/lists.hbs:3
+msgid "Create List"
+msgstr "Utwórz listę"
+
+#: views/lists/create.hbs:6 views/lists/edit.hbs:7
+msgid "List Name"
+msgstr "Nazwa listy"
+
+#: views/lists/edit.hbs:3 views/lists/edit.hbs:4 views/lists/view.hbs:7
+msgid "Edit List"
+msgstr "Edytuj listę"
+
+#: views/lists/edit.hbs:5
+msgid "View List"
+msgstr "Wyświetl listę"
+
+#: views/lists/edit.hbs:8
+msgid "List ID"
+msgstr "ID listy"
+
+#: views/lists/edit.hbs:9
+msgid "This is the list ID displayed to the subscribers"
+msgstr "To jest ID listy wyświetlany dla subskrybentów"
+
+#: views/lists/edit.hbs:12
+msgid "Delete List"
+msgstr "Usuń listę"
+
+#: views/lists/fields/create.hbs:3 views/lists/fields/edit.hbs:3
+#: views/lists/fields/fields.hbs:3 views/lists/fields/fields.hbs:5
+#: views/lists/view.hbs:5
+msgid "Custom Fields"
+msgstr "Pola niestandardowe"
+
+#: views/lists/fields/create.hbs:4
+msgid "Create Field"
+msgstr "Utwórz pole"
+
+#: views/lists/fields/create.hbs:5 views/lists/fields/fields.hbs:4
+msgid "Create Custom Field"
+msgstr "Utwórz pole niestandardowe"
+
+#: views/lists/fields/create.hbs:6 views/lists/fields/create.hbs:7
+#: views/lists/fields/edit.hbs:7 views/lists/fields/edit.hbs:8
+msgid "Field Name"
+msgstr "Nazwa pola"
+
+#: views/lists/fields/create.hbs:8 views/lists/fields/edit.hbs:9
+msgid "Field Type"
+msgstr "Typ pola"
+
+#: views/lists/fields/create.hbs:9 views/lists/fields/edit.hbs:10
+#: lib/models/fields.js:17
+msgid "Text"
+msgstr "Tekst"
+
+#: views/lists/fields/create.hbs:10 views/lists/fields/edit.hbs:11
+#: lib/models/fields.js:21
+msgid "Number"
+msgstr "Numer"
+
+#: views/lists/fields/create.hbs:11 views/lists/fields/edit.hbs:12
+#: lib/models/fields.js:18
+msgid "Website"
+msgstr "Strona www"
+
+#: views/lists/fields/create.hbs:12 views/lists/fields/edit.hbs:13
+#: lib/models/fields.js:20
+msgid "GPG Public Key"
+msgstr "Klucz publiczny GPG"
+
+#: views/lists/fields/create.hbs:13 views/lists/fields/edit.hbs:14
+#: lib/models/fields.js:19
+msgid "Multi-line text"
+msgstr "Tekst wielowierszowy"
+
+#: views/lists/fields/create.hbs:14 views/lists/fields/edit.hbs:15
+msgid "JSON"
+msgstr "JSON"
+
+#: views/lists/fields/create.hbs:15 views/lists/fields/edit.hbs:16
+msgid "Date"
+msgstr "Data"
+
+#: views/lists/fields/create.hbs:16 views/lists/fields/edit.hbs:17
+msgid "Date (MM/DD/YYYY)"
+msgstr "Data (MM/DD/YYYY)"
+
+#: views/lists/fields/create.hbs:17 views/lists/fields/edit.hbs:18
+#: lib/models/fields.js:26
+msgid "Date (DD/MM/YYYY)"
+msgstr "Data (DD/MM/YYYY)"
+
+#: views/lists/fields/create.hbs:18 views/lists/fields/edit.hbs:19
+msgid "Birthday"
+msgstr "Urodziny"
+
+#: views/lists/fields/create.hbs:19 views/lists/fields/edit.hbs:20
+#: lib/models/fields.js:27
+msgid "Birthday (MM/DD)"
+msgstr "Urodziny (MM/DD)"
+
+#: views/lists/fields/create.hbs:20 views/lists/fields/edit.hbs:21
+#: lib/models/fields.js:28
+msgid "Birthday (DD/MM)"
+msgstr "Urodziny (DD/MM)"
+
+#: views/lists/fields/create.hbs:21 views/lists/fields/edit.hbs:22
+msgid "Grouped"
+msgstr "Grouped."
+
+#: views/lists/fields/create.hbs:22 views/lists/fields/edit.hbs:23
+msgid "Drop Downs"
+msgstr "Listy rozwijane"
+
+#: views/lists/fields/create.hbs:23 views/lists/fields/edit.hbs:24
+#: lib/models/fields.js:22
+msgid "Radio Buttons"
+msgstr "Radio Buttons"
+
+#: views/lists/fields/create.hbs:24 views/lists/fields/edit.hbs:25
+#: lib/models/fields.js:23
+msgid "Checkboxes"
+msgstr "Checkboxes"
+
+#: views/lists/fields/create.hbs:25 views/lists/fields/edit.hbs:26
+msgid "Option for a group value"
+msgstr "Opcja dla wartości grupy"
+
+#: views/lists/fields/create.hbs:26 views/lists/fields/edit.hbs:27
+msgid "Group"
+msgstr "Grupa"
+
+#: views/lists/fields/create.hbs:28 views/lists/fields/edit.hbs:29
+msgid "Required for group options"
+msgstr "Wymagane w przypadku opcji grupowych"
+
+#: views/lists/fields/create.hbs:29 views/lists/fields/create.hbs:30
+#: views/lists/fields/edit.hbs:35 views/lists/fields/edit.hbs:36
+#: views/lists/fields/fields.hbs:9
+msgid "Default merge tag value"
+msgstr "Domyślna wartość merge tag"
+
+#: views/lists/fields/create.hbs:32 views/lists/fields/edit.hbs:34
+msgid ""
+"For group elements like checkboxes you can control the appearance of the "
+"merge tag with an optional template. The template uses handlebars syntax and "
+"you can find all values from {{values}} array, for example "
+"{{#each values}} {{this}} {{/each}}. If template is not defined "
+"then multiple values are joined with commas. You can also use this template "
+"to render JSON values (if the JSON is an array then the array is exposed as "
+"values, otherwise you can access the JSON keys directly)."
+msgstr ""
+"W przypadku elementów grupy, takich jak checkboxy, można kontrolować wygląd "
+"merge tagów za pomocą opcjonalnego szablonu. Szablon używa składni "
+"handlebars i możesz znaleźć wszystkie wartości z tablicy {{values}}"
+"code>, na przykład {{#each values}} {{this}} {{/each}} . Jeśli "
+"szablon nie jest zdefiniowany, wiele wartości jest łączonych przecinkami. "
+"Możesz również użyć tego szablonu do renderowania wartości JSON (jeśli JSON "
+"jest tablicą, wtedy tablica jest wyświetlana jako values, w "
+"przeciwnym razie możesz uzyskać bezpośredni dostęp do kluczy JSON)."
+
+#: views/lists/fields/create.hbs:33 views/lists/fields/edit.hbs:37
+msgid "Visible"
+msgstr "Widoczny"
+
+#: views/lists/fields/create.hbs:34
+msgid "Add Field"
+msgstr "Dodaj pole"
+
+#: views/lists/fields/edit.hbs:4
+msgid "Edit Field"
+msgstr "Edytuj pole"
+
+#: views/lists/fields/edit.hbs:5
+msgid "Edit Custom Field"
+msgstr "Edytuj pole niestandardowe"
+
+#: views/lists/fields/edit.hbs:6
+msgid "Back to fields"
+msgstr "Powrót do pól"
+
+#: views/lists/fields/edit.hbs:30 views/lists/fields/fields.hbs:8
+#: views/partials/merge-tag-reference.hbs:3
+msgid "Merge tag"
+msgstr "Merge tag"
+
+#: views/lists/fields/edit.hbs:31
+msgid "Merge Tag"
+msgstr "Merge Tag"
+
+#: views/lists/fields/edit.hbs:32
+msgid "Put this tag in your content:"
+msgstr "Umieść ten tag w swojej treści:"
+
+#: views/lists/fields/edit.hbs:38
+msgid "Delete Field"
+msgstr "Usuń pole"
+
+#: views/lists/fields/fields.hbs:7 views/lists/view.hbs:25
+msgid "Type"
+msgstr "Typ"
+
+#: views/lists/fields/fields.hbs:10 views/lists/fields/fields.hbs:11
+#: views/lists/lists.hbs:9 views/lists/segments/segments.hbs:8
+#: views/lists/segments/view.hbs:12 views/templates/templates.hbs:7
+#: views/triggers/triggers.hbs:14 routes/campaigns.js:287
+#: routes/campaigns.js:576 routes/campaigns.js:626 routes/lists.js:222
+#: routes/triggers.js:297
+msgid "Edit"
+msgstr "Edytuj"
+
+#: views/lists/lists.hbs:6
+msgid "ID"
+msgstr "ID"
+
+#: views/lists/lists.hbs:7
+msgid "Subscribers"
+msgstr "Subskrybenci"
+
+#: views/lists/segments/create.hbs:3 views/lists/segments/edit.hbs:3
+#: views/lists/segments/rule-configure.hbs:3
+#: views/lists/segments/rule-create.hbs:3 views/lists/segments/rule-edit.hbs:3
+#: views/lists/segments/segments.hbs:3 views/lists/segments/segments.hbs:5
+#: views/lists/segments/view.hbs:3 views/lists/view.hbs:6
+#: views/lists/view.hbs:13
+msgid "Segments"
+msgstr "Segmenty"
+
+#: views/lists/segments/create.hbs:4 views/lists/segments/create.hbs:5
+#: views/lists/segments/rule-configure.hbs:4
+#: views/lists/segments/rule-create.hbs:4 views/lists/segments/rule-edit.hbs:4
+#: views/lists/segments/segments.hbs:4
+msgid "Create Segment"
+msgstr "Utwórz segment"
+
+#: views/lists/segments/create.hbs:6 views/lists/segments/create.hbs:7
+#: views/lists/segments/edit.hbs:7 views/lists/segments/edit.hbs:8
+msgid "Segment Name"
+msgstr "Nazwa segmentu"
+
+#: views/lists/segments/create.hbs:8 views/lists/segments/edit.hbs:9
+msgid "Rule match"
+msgstr "Dopasowanie reguł"
+
+#: views/lists/segments/create.hbs:10 views/lists/segments/edit.hbs:11
+msgid "All rules must match"
+msgstr "Wszystkie reguły muszą się zgadzać"
+
+#: views/lists/segments/create.hbs:11 views/lists/segments/edit.hbs:12
+msgid "Any rule can match"
+msgstr "Każda reguła może się zgadzać"
+
+#: views/lists/segments/create.hbs:12
+msgid "Add Segment"
+msgstr "Dodaj segment"
+
+#: views/lists/segments/edit.hbs:4 views/lists/segments/edit.hbs:5
+#: views/lists/segments/view.hbs:6 views/lists/view.hbs:11
+msgid "Edit Segment"
+msgstr "Edytuj segment"
+
+#: views/lists/segments/edit.hbs:6
+msgid "Back to segments"
+msgstr "Powrót do segmentów"
+
+#: views/lists/segments/edit.hbs:13
+msgid "Delete Segment"
+msgstr "Usuń segment"
+
+#: views/lists/segments/rule-configure.hbs:5
+#: views/lists/segments/rule-create.hbs:5 views/lists/segments/rule-edit.hbs:5
+#: views/lists/segments/view.hbs:4
+msgid "Create Rule"
+msgstr "Utwórz regułę"
+
+#: views/lists/segments/rule-configure.hbs:6
+#: views/lists/segments/rule-create.hbs:6 views/lists/segments/rule-edit.hbs:6
+#: views/lists/segments/view.hbs:10
+msgid "Rule"
+msgstr "Reguła"
+
+#: views/lists/segments/rule-configure.hbs:7
+#: views/lists/segments/rule-configure.hbs:8
+#: views/lists/segments/rule-configure.hbs:10
+#: views/lists/segments/rule-configure.hbs:13
+#: views/lists/segments/rule-configure.hbs:25
+#: views/lists/segments/rule-configure.hbs:30
+#: views/lists/segments/rule-edit.hbs:7 views/lists/segments/rule-edit.hbs:8
+#: views/lists/segments/rule-edit.hbs:10 views/lists/segments/rule-edit.hbs:15
+#: views/lists/segments/rule-edit.hbs:29 views/lists/segments/rule-edit.hbs:34
+#: views/lists/segments/view.hbs:11
+msgid "Value"
+msgstr "Wartość"
+
+#: views/lists/segments/rule-configure.hbs:9
+#: views/lists/segments/rule-edit.hbs:9
+msgid ""
+"Use % for wildcard character, e.g. \"%test\" to match all values that end "
+"with \"test\""
+msgstr ""
+"Użyj % dla znaku wieloznacznego, np. \"%test\", aby dopasować wszystkie "
+"wartości, które kończą się na \"test\""
+
+#: views/lists/segments/rule-configure.hbs:11
+#: views/lists/segments/rule-configure.hbs:14
+#: views/lists/segments/rule-configure.hbs:26
+#: views/lists/segments/rule-edit.hbs:11 views/lists/segments/rule-edit.hbs:16
+#: views/lists/segments/rule-edit.hbs:30
+msgid "Use exact match"
+msgstr "Użyj ścisłego dopasowania"
+
+#: views/lists/segments/rule-configure.hbs:12
+#: views/lists/segments/rule-configure.hbs:15
+#: views/lists/segments/rule-configure.hbs:27
+#: views/lists/segments/rule-edit.hbs:12 views/lists/segments/rule-edit.hbs:17
+#: views/lists/segments/rule-edit.hbs:31
+msgid "Use range match"
+msgstr "Użyj dopasowania zakresu"
+
+#: views/lists/segments/rule-configure.hbs:16
+#: views/lists/segments/rule-edit.hbs:20
+msgid "Use relative range match"
+msgstr "Użyj względnego dopasowania zakresu"
+
+#: views/lists/segments/rule-configure.hbs:17
+#: views/lists/segments/rule-configure.hbs:28
+#: views/lists/segments/rule-edit.hbs:13 views/lists/segments/rule-edit.hbs:18
+#: views/lists/segments/rule-edit.hbs:21 views/lists/segments/rule-edit.hbs:32
+msgid "From"
+msgstr "Od"
+
+#: views/lists/segments/rule-configure.hbs:18
+#: views/lists/segments/rule-configure.hbs:22
+#: views/lists/segments/rule-edit.hbs:22 views/lists/segments/rule-edit.hbs:26
+msgid "days"
+msgstr "dni"
+
+#: views/lists/segments/rule-configure.hbs:19
+#: views/lists/segments/rule-configure.hbs:23
+#: views/lists/segments/rule-edit.hbs:23 views/lists/segments/rule-edit.hbs:27
+msgid "before today"
+msgstr "przed dzisiaj"
+
+#: views/lists/segments/rule-configure.hbs:20
+#: views/lists/segments/rule-configure.hbs:24
+#: views/lists/segments/rule-edit.hbs:24 views/lists/segments/rule-edit.hbs:28
+msgid "after today"
+msgstr "po dzisiaj"
+
+#: views/lists/segments/rule-configure.hbs:21
+#: views/lists/segments/rule-configure.hbs:29
+#: views/lists/segments/rule-edit.hbs:14 views/lists/segments/rule-edit.hbs:19
+#: views/lists/segments/rule-edit.hbs:25 views/lists/segments/rule-edit.hbs:33
+msgid "to"
+msgstr "do"
+
+#: views/lists/segments/rule-configure.hbs:31
+#: views/lists/segments/rule-edit.hbs:35 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Selected"
+msgstr "Wybrano"
+
+#: views/lists/segments/rule-configure.hbs:32
+#: views/lists/segments/rule-edit.hbs:36 lib/models/segments.js:156
+#: lib/models/segments.js:418
+msgid "Not selected"
+msgstr "Nie wybrano"
+
+#: views/lists/segments/rule-configure.hbs:33
+msgid "Add Rule"
+msgstr "Dodaj regułę"
+
+#: views/lists/segments/rule-create.hbs:8
+#: views/lists/subscription/import.hbs:12 views/triggers/create-select.hbs:9
+msgid "Next"
+msgstr "Dalej"
+
+#: views/lists/segments/rule-edit.hbs:37
+msgid "Delete Rule"
+msgstr "Usuń regułę"
+
+#: views/lists/segments/segments.hbs:7
+msgid "Match"
+msgstr "Dopasowanie"
+
+#: views/lists/segments/view.hbs:5 views/lists/view.hbs:12
+msgid "Segment"
+msgstr "Segment"
+
+#: views/lists/segments/view.hbs:7
+msgid "Match rules"
+msgstr "Reguły dopasowania"
+
+#: views/lists/segments/view.hbs:8
+msgid "Matching subscribers"
+msgstr "Dopasowani subskrybenci"
+
+#: views/lists/segments/view.hbs:9
+msgid "show"
+msgstr "pokaż"
+
+#: views/lists/subscription/add.hbs:3 views/lists/subscription/add.hbs:4
+msgid "Add subscriber"
+msgstr "Dodaj subskrybenta"
+
+#: views/lists/subscription/add.hbs:5 views/subscription/manage.hbs:2
+#: views/subscription/subscribe.hbs:3 views/users/account.hbs:7
+msgid "Email Address"
+msgstr "Adres e-mail"
+
+#: views/lists/subscription/add.hbs:8 views/lists/subscription/edit.hbs:9
+#: views/settings.hbs:82 views/settings.hbs:97 views/subscription/manage.hbs:7
+#: views/subscription/subscribe.hbs:7
+msgid "Begins with"
+msgstr "Zaczyna się"
+
+#: views/lists/subscription/add.hbs:9 views/lists/subscription/edit.hbs:10
+msgid ""
+"Insert a GPG public key that will be used to encrypt messages sent this "
+"subscriber"
+msgstr ""
+"Wstaw klucz publiczny GPG, który będzie używany do szyfrowania wiadomości "
+"wysłanych przez tego subskrybenta"
+
+#: views/lists/subscription/add.hbs:11 views/lists/subscription/edit.hbs:12
+#: views/lists/subscription/import-preview.hbs:9
+msgid "Timezone"
+msgstr "Strefa czasowa"
+
+#: views/lists/subscription/add.hbs:13 views/lists/subscription/edit.hbs:13
+msgid "Test user?"
+msgstr "Użytkownik testowy?"
+
+#: views/lists/subscription/add.hbs:14 views/lists/subscription/edit.hbs:14
+msgid ""
+"If checked then this subscription can be used for previewing campaign "
+"messages"
+msgstr ""
+"Jeśli ta opcja jest zaznaczona, można użyć tej subskrypcji do przeglądania "
+"wiadomości kampanii"
+
+#: views/lists/subscription/add.hbs:15
+msgid ""
+"This person will not receive a confirmation email so make sure that you have "
+"permission to email them."
+msgstr ""
+"Ta osoba nie otrzyma e-maila z potwierdzeniem, więc upewnij się, że masz "
+"uprawnienia do e-maila."
+
+#: views/lists/subscription/edit.hbs:3 views/lists/subscription/edit.hbs:4
+msgid "Edit subscriber"
+msgstr "Edytuj subskrybenta"
+
+#: views/lists/subscription/edit.hbs:5
+#: views/lists/subscription/import-failed.hbs:5
+msgid "Back to list"
+msgstr "Powrót do listy"
+
+#: views/lists/subscription/edit.hbs:6
+#: views/lists/subscription/import-preview.hbs:6
+#: views/subscription/unsubscribe.hbs:3 lib/helpers.js:26
+#: lib/models/segments.js:11
+msgid "Email address"
+msgstr "Adres e-mail"
+
+#: views/lists/subscription/edit.hbs:16
+msgid "Delete Subscription"
+msgstr "Usuń subskrypcję"
+
+#: views/lists/subscription/import-failed.hbs:3
+msgid "Import status"
+msgstr "Status importu"
+
+#: views/lists/subscription/import-failed.hbs:4
+msgid "Failed addresses"
+msgstr "Nieudane adresy"
+
+#: views/lists/subscription/import-failed.hbs:6
+msgid "see here"
+msgstr "zobacz tutaj"
+
+#: views/lists/subscription/import-failed.hbs:10
+msgid "Fail reason"
+msgstr "Przyczyna niepowodzenia"
+
+#: views/lists/subscription/import-preview.hbs:3
+#: views/lists/subscription/import-preview.hbs:4
+#: views/lists/subscription/import.hbs:3 views/lists/subscription/import.hbs:4
+msgid "Import subscribers"
+msgstr "Zaimportuj subskrybentów"
+
+#: views/lists/subscription/import-preview.hbs:10 views/users/api.hbs:27
+#: views/users/api.hbs:35 views/users/api.hbs:43 views/users/api.hbs:55
+msgid "Example"
+msgstr "Przykład"
+
+#: views/lists/subscription/import-preview.hbs:11
+msgid "Start import"
+msgstr "Rozpocznij importowanie"
+
+#: views/lists/subscription/import.hbs:5
+msgid "CSV File"
+msgstr "Plik CSV"
+
+#: views/lists/subscription/import.hbs:6
+msgid "CSV delimiter"
+msgstr "Separator CSV"
+
+#: views/lists/subscription/import.hbs:7
+msgid "Categorize the imported subscribers as"
+msgstr "Skategoryzuj importowanych subskrybentów jako"
+
+#: views/lists/subscription/import.hbs:8 routes/lists.js:171
+msgid "Subscribed"
+msgstr "Subskrybuje"
+
+#: views/lists/subscription/import.hbs:9
+msgid "Regular subscriber addresses"
+msgstr "Regularne adresy subskrybentów"
+
+#: views/lists/subscription/import.hbs:11
+msgid "Suppressed emails that will be unsubscribed from your list"
+msgstr "Pomijane e-maile, które zostaną wypisane z listy"
+
+#: views/lists/view.hbs:3
+msgid "Subscription Form"
+msgstr "Formularz subskrypcji"
+
+#: views/lists/view.hbs:4
+msgid "List Actions"
+msgstr "Lista akcji"
+
+#: views/lists/view.hbs:8 views/triggers/create-select.hbs:3
+#: views/triggers/create-select.hbs:4 views/triggers/create.hbs:3
+#: views/triggers/create.hbs:4 views/triggers/create.hbs:27
+#: views/triggers/triggers.hbs:3
+msgid "Create Trigger"
+msgstr "Utwórz wyzwalacz"
+
+#: views/lists/view.hbs:9
+msgid "Add Subscriber"
+msgstr "Dodaj subskrybenta"
+
+#: views/lists/view.hbs:10
+msgid "Import Subscribers"
+msgstr "Importuj subskrybentów"
+
+#: views/lists/view.hbs:14
+msgid "Create New Segment"
+msgstr "Utwórz nowy segment"
+
+#: views/lists/view.hbs:15
+msgid "Filter"
+msgstr "Filtr"
+
+#: views/lists/view.hbs:16
+msgid "Subscriptions"
+msgstr "Subskrypcje"
+
+#: views/lists/view.hbs:17
+msgid "Imports"
+msgstr "Import"
+
+#: views/lists/view.hbs:24 routes/campaigns.js:266 routes/lists.js:265
+msgid "Finished"
+msgstr "Skończone"
+
+#: views/lists/view.hbs:26
+msgid "Added"
+msgstr "Dodany"
+
+#: views/lists/view.hbs:27
+msgid "Updated"
+msgstr "Zaktualizowano"
+
+#: views/lists/view.hbs:28
+msgid "Failed"
+msgstr "Nie powiodło się"
+
+#: views/lists/view.hbs:30
+msgid ""
+"Are you sure? This action should only be called to resolve stalled imports"
+msgstr ""
+"Jesteś pewny? Ta czynność powinna byś wywołana tylko w celu rozwiązania "
+"impasu importu."
+
+#: views/lists/view.hbs:31
+msgid "Restart"
+msgstr "Uruchom ponownie"
+
+#: views/partials/codeeditor.hbs:1 views/partials/summernote.hbs:1
+msgid "Template content (HTML)"
+msgstr "Zawartość szablonu (HTML)"
+
+#: views/partials/html-preview.hbs:1
+msgid "Toggle HTML preview"
+msgstr "Przełącz podgląd HTML"
+
+#: views/partials/merge-tag-reference.hbs:1
+msgid "Merge tag reference"
+msgstr "Odniesienie merge tag"
+
+#: views/partials/merge-tag-reference.hbs:2
+msgid ""
+"Merge tags are tags that are replaced before sending out the message. The "
+"format of the merge tag is the following: [TAG_NAME] or "
+"[TAG_NAME/fallback] where fallback is an optional "
+"text value used when TAG_NAME is empty."
+msgstr ""
+"Merge tagi są tagami, które są zastępowane przed wysłaniem wiadomości. "
+"Format merge tagu jest następujący: [TAG_NAME] lub "
+"[TAG_NAME/fallback] gdzie fallback jest opcjonalną "
+"wartością tekstową używaną, gdy TAG_NAME jest pusty."
+
+#: views/partials/plaintext.hbs:1
+msgid "Template content (plaintext)"
+msgstr "Treść szablonu (zwykły tekst)"
+
+#: views/settings.hbs:5
+msgid "Service Address (URL)"
+msgstr "Adres usługi (URL)"
+
+#: views/settings.hbs:6
+msgid "Enter the URL this service can be reached from"
+msgstr "Wprowadź adres URL, z którego można uzyskać tę usługę"
+
+#: views/settings.hbs:7
+msgid "Admin Email"
+msgstr "E-mail Administratora"
+
+#: views/settings.hbs:8
+msgid ""
+"Enter the email address that will be used as \"from\" for system messages"
+msgstr ""
+"Wprowadź adres e-mail, który będzie używany jako \"from \" dla wiadomości "
+"systemowych"
+
+#: views/settings.hbs:9
+msgid "Disable WYSIWYG editor"
+msgstr "Wyłącz edytor WYSIWYG"
+
+#: views/settings.hbs:10
+msgid "If checked then message editor displays HTML code without the preview"
+msgstr "Jeśli zaznaczone, edytor wiadomości wyświetla kod HTML bez podglądu"
+
+#: views/settings.hbs:11
+msgid "Disable subscription confirmation messages"
+msgstr "Wyłącz wiadomości potwierdzające subskrypcję"
+
+#: views/settings.hbs:12
+msgid ""
+"If checked then do not send a confirmation message that states the "
+"subscriber is now subscribed or unsubscribed. This does not disable double "
+"opt-in messages."
+msgstr ""
+"Jeśli jest zaznaczone, nie wysyłaj wiadomości potwierdzającej, że "
+"subskrybent jest teraz subskrybowany lub nie subskrybowany. Nie wyłącza to "
+"podwójnych wiadomości opt-in."
+
+#: views/settings.hbs:13
+msgid "Tracking ID"
+msgstr "Identyfikator śledzenia"
+
+#: views/settings.hbs:14
+msgid "Enter Google Analytics tracking code"
+msgstr "Wpisz kod śledzenia Google Analytics"
+
+#: views/settings.hbs:15
+msgid "Frontpage shout out"
+msgstr ""
+
+#: views/settings.hbs:16
+msgid "HTML code shown in the front page header section"
+msgstr "Kod HTML wyświetlany w sekcji nagłówka na pierwszej stronie"
+
+#: views/settings.hbs:17
+msgid "Campaign defaults"
+msgstr "Domyślne ustawienia kampanii"
+
+#: views/settings.hbs:18
+msgid "Sender name"
+msgstr "Nazwa nadawcy"
+
+#: views/settings.hbs:19
+msgid "Sender name, eg. My Awesome Company Ltd."
+msgstr "Nazwa nadawcy, np. My Awesome Company Ltd."
+
+#: views/settings.hbs:20
+msgid "Default address"
+msgstr "Domyślny adres"
+
+#: views/settings.hbs:21
+msgid ""
+"Contact address to provide, eg. 1234 Main Street, Anywhere, MA 01234, USA"
+msgstr ""
+"Adres kontaktowy do dostarczenia, np. 1234 Main Street, Anywhere, MA 01234, "
+"USA"
+
+#: views/settings.hbs:22
+msgid "Default \"from name\""
+msgstr "Domyślna nazwa \"from\""
+
+#: views/settings.hbs:24
+msgid "Default \"from\" email"
+msgstr "Domyślny e-mail \"from\""
+
+#: views/settings.hbs:26
+msgid "Default \"subject line\""
+msgstr "Domyślny temat \"from\""
+
+#: views/settings.hbs:28
+msgid "Default homepage (URL)"
+msgstr "Domyślna strona główna (URL)"
+
+#: views/settings.hbs:29
+msgid "URL to redirect the subscribed users to, eg. http://example.com/"
+msgstr "Adres URL do przekierowania subskrybentów do, np. http://example.com/"
+
+#: views/settings.hbs:30
+msgid "Mailer Settings"
+msgstr "Ustawienia Mailera"
+
+#: views/settings.hbs:31
+msgid "These settings are required to send out e-mail messages"
+msgstr "Te ustawienia są wymagane do wysyłania wiadomości e-mail"
+
+#: views/settings.hbs:32
+msgid "SMTP"
+msgstr "SMTP"
+
+#: views/settings.hbs:33
+msgid "AWS SES"
+msgstr "AWS SES"
+
+#: views/settings.hbs:34
+msgid "Use SMTP for sending mail"
+msgstr "Użyj SMTP do wysyłania poczty"
+
+#: views/settings.hbs:35
+msgid "Hostname"
+msgstr "Nazwa hosta"
+
+#: views/settings.hbs:36
+msgid "Port"
+msgstr "Port"
+
+#: views/settings.hbs:37
+msgid "Port, eg. 465. Autodetected if left blank"
+msgstr "Port, np. 465. Autodetekcja, jeśli pozostanie pusta"
+
+#: views/settings.hbs:38
+msgid "Encryption"
+msgstr "Szyfrowanie"
+
+#: views/settings.hbs:39
+msgid "Disable SMTP authentication"
+msgstr "Wyłącz uwierzytelnianie SMTP"
+
+#: views/settings.hbs:40 views/users/forgot.hbs:9 views/users/login.hbs:4
+#: views/users/login.hbs:5
+msgid "Username"
+msgstr "Nazwa użytkownika"
+
+#: views/settings.hbs:41
+msgid "Username, eg. myaccount@example.com"
+msgstr "Nazwa użytkownika, np. myaccount@example.com"
+
+#: views/settings.hbs:42 views/settings.hbs:43 views/users/login.hbs:6
+#: views/users/login.hbs:7
+msgid "Password"
+msgstr "Hasło"
+
+#: views/settings.hbs:44
+msgid "Use SES API for sending mail"
+msgstr "Użyj interfejsu API SES do wysyłania poczty"
+
+#: views/settings.hbs:45
+msgid "Access Key"
+msgstr "Access Key"
+
+#: views/settings.hbs:46
+msgid "AWS Access Key Id"
+msgstr "AWS Access Key Id"
+
+#: views/settings.hbs:47
+msgid "Secret Key"
+msgstr "Secret Key"
+
+#: views/settings.hbs:48
+msgid "AWS Secret Access Key"
+msgstr "AWS Secret Access Key"
+
+#: views/settings.hbs:49
+msgid "Region"
+msgstr "Region"
+
+#: views/settings.hbs:50
+msgid "Checking"
+msgstr "Sprawdzanie"
+
+#: views/settings.hbs:51
+msgid "Check Mailer config"
+msgstr "Sprawdź konfigurację Mailera"
+
+#: views/settings.hbs:52
+msgid "Don't have an SMTP account yet? Create a free SendPulse account"
+msgstr "Nie masz jeszcze konta SMTP? Utwórz darmowe konto SendPulse"
+
+#: views/settings.hbs:53
+msgid "here"
+msgstr "tutaj"
+
+#: views/settings.hbs:54
+msgid "Advanced Mailer settings"
+msgstr "Zaawansowane ustawienia Mailera"
+
+#: views/settings.hbs:55
+msgid "Log SMTP transactions"
+msgstr "Loguj transakcje SMTP"
+
+#: views/settings.hbs:56
+msgid "Allow self-signed certificates"
+msgstr "Zezwalaj na certyfikaty z podpisem własnym"
+
+#: views/settings.hbs:57
+msgid "Max connections"
+msgstr "Maks. połączeń"
+
+#: views/settings.hbs:58
+msgid "The count of max connections, eg. 10"
+msgstr "Liczba maksymalnych połączeń, np. 10"
+
+#: views/settings.hbs:59
+msgid ""
+"The count of maximum simultaneous connections to make against the SMTP "
+"server (defaults to 5). This limit is per sending process."
+msgstr ""
+"Liczba maksymalnych równoczesnych połączeń z serwerem SMTP (domyślnie 5). "
+"Ten limit dotyczy procesu wysyłania."
+
+#: views/settings.hbs:60
+msgid "Max messages"
+msgstr "Maks. wiadomości"
+
+#: views/settings.hbs:61
+msgid "The count of max messages, eg. 100"
+msgstr "Liczba maksymalnych wiadomości, np. 100"
+
+#: views/settings.hbs:62
+msgid ""
+"he number of messages to send through a single connection before the "
+"connection is closed and reopened (defaults to 100)"
+msgstr ""
+"Liczba wiadomości do wysłania za pośrednictwem jednego połączenia, zanim "
+"połączenie zostanie zamknięty i ponownie otwarty (domyślnie 100)"
+
+#: views/settings.hbs:63
+msgid "Throttling"
+msgstr "Dławienie (Throttling)"
+
+#: views/settings.hbs:64
+msgid "Messages per hour eg. 1000"
+msgstr "Wiadomości na godzinę, np. 1000"
+
+#: views/settings.hbs:65
+msgid ""
+"Maximum number of messages to send in an hour. Leave empty or zero for no "
+"throttling. If your provider uses a different speed limit (messages/minute "
+"or messages/second) then convert this limit into messages/hour (1m/s => "
+"3600m/h). This limit is per sending process."
+msgstr ""
+"Maksymalna liczba wiadomości do wysłania w ciągu godziny. Pozostaw puste lub "
+"zero dla barku dławienia. Jeśli Twój dostawca wykorzystuje inny limit "
+"prędkości (wiadomości/minutę lub wiadomości/sekundę), zamień ten limit na "
+"wiadomości/godzinę (1m/s => 3600m/h). Ten limit dotyczy procesu wysyłania."
+
+#: views/settings.hbs:66
+msgid "VERP bounce handling"
+msgstr "Obsługa odbijania VERP"
+
+#: views/settings.hbs:67
+msgid ""
+"Mailtrain is able to use VERP based routing to detect bounces. In this case "
+"the message is sent to the recipient using a custom VERP address as the "
+"return path of the message. If the message is not accepted a bounce email is "
+"sent to this special VERP address and thus a bounce is detected."
+msgstr ""
+"Mailtrain może wykorzystywać routing oparty na VERP do wykrywania odbić. W "
+"takim przypadku wiadomość zostanie wysłana do adresata przy użyciu "
+"niestandardowego adresu VERP jako ścieżki powrotnej wiadomości. Jeśli "
+"wiadomość nie zostanie przyjęta, wiadomość odrzucona wiadomość zostanie "
+"wysłana na specjalny adres VERP, a tym samym wykryte zostanie odrzucenie."
+
+#: views/settings.hbs:68
+msgid ""
+"To get VERP working you need to set up a DNS MX record that points to your "
+"Mailtrain hostname. You must also ensure that Mailtrain VERP interface is "
+"available from port 25 of your server (port 25 usually requires root user "
+"privileges). This way if anyone tries to send email to someuser@verp-"
+"hostname then the email should end up to this server."
+msgstr ""
+"Aby uruchomić działanie VERP, musisz skonfigurować rekord MX DNS, który "
+"wskazuje twoją nazwę hosta Mailtrain. Musisz także upewnić się, że interfejs "
+"Mailtrain VERP jest dostępny z portu 25 serwera (port 25 zwykle wymaga "
+"uprawnień użytkownika root). W ten sposób, jeśli ktoś spróbuje wysłać "
+"wiadomość e-mail do someuser@verp-hostname, wówczas wiadomość e-mail powinna "
+"dotrzeć do tego serwera."
+
+#: views/settings.hbs:69
+msgid ""
+"VERP usually only works if you are using your own SMTP server. Regular relay "
+"services (SES, SparkPost, Gmail etc.) tend to remove the VERP address from "
+"the message."
+msgstr ""
+"VERP zwykle działa tylko wtedy, gdy używasz własnego serwera SMTP. Regularne "
+"usługi przekazywania (SES, SparkPost, Gmail itp.) Mają tendencję do usuwania "
+"adresu VERP z wiadomości."
+
+#: views/settings.hbs:70
+msgid "Use VERP to catch bounces"
+msgstr "Użyj VERP do wykrycia odbicia"
+
+#: views/settings.hbs:71
+msgid "Server hostname"
+msgstr "Nazwa hosta serwera"
+
+#: views/settings.hbs:72
+msgid "The VERP server hostname, eg. bounces.example.com"
+msgstr "Nazwa hosta serwera VERP, np. bounces.example.com"
+
+#: views/settings.hbs:73
+msgid ""
+"VERP bounce handling server hostname. This hostname is used in the SMTP "
+"envelope FROM address and the MX DNS records should point to this server"
+msgstr ""
+"Nazwa hosta serwera obsługi odrzutów VERP. Ta nazwa hosta jest używana w "
+"SMTP jako \"od\", a rekordy MX DNS powinny wskazywać na ten serwer"
+
+#: views/settings.hbs:74
+msgid ""
+"VERP bounce handling server is not enabled. Modify your server configuration "
+"file and restart server to enable it"
+msgstr ""
+"Serwer obsługi odrzutów VERP nie jest włączony. Zmodyfikuj plik "
+"konfiguracyjny serwera i zrestartuj serwer, aby go włączyć."
+
+#: views/settings.hbs:75
+msgid "GPG Signing"
+msgstr "Podpis GPG"
+
+#: views/settings.hbs:76
+msgid ""
+"Only messages that are encrypted can be signed. Subsribers who have not set "
+"up a GPG public key in their profile receive normal email messages. Users "
+"with GPG key set receive encrypted messages and if you have signing key also "
+"set, the messages are signed with this key."
+msgstr ""
+"Tylko wiadomości, które są zaszyfrowane, mogą być podpisane. Subskrybenci, "
+"którzy nie ustawili klucza publicznego GPG w swoim profilu, otrzymują zwykłe "
+"wiadomości e-mail. Użytkownicy z zestawem kluczy GPG otrzymują zaszyfrowane "
+"wiadomości i jeśli masz ustawiony również klucz podpisu, wiadomości są "
+"podpisywane tym kluczem."
+
+#: views/settings.hbs:77
+msgid ""
+"Do not use sensitive keys here. The private key and passphrase are not "
+"encrypted in the database."
+msgstr ""
+"Nie używaj tutaj wrażliwych kluczy. Klucz prywatny i hasło nie są szyfrowane "
+"w bazie danych."
+
+#: views/settings.hbs:78
+msgid "Private Key Passphrase"
+msgstr "Hasło klucza prywatnego"
+
+#: views/settings.hbs:79
+msgid "Passphrase for the key if set"
+msgstr "Hasło dla klucza, jeśli jest ustawione"
+
+#: views/settings.hbs:80
+msgid "Only fill this if your private key is encrypted with a passphrase"
+msgstr "Wypełnij to tylko, jeśli Twój klucz prywatny jest zaszyfrowany hasłem"
+
+#: views/settings.hbs:81
+msgid "GPG Private Key"
+msgstr "Klucz prywatny GPG"
+
+#: views/settings.hbs:83
+msgid ""
+"This value is optional. If you do not provide a private key GPG encrypted "
+"messages are sent without signing."
+msgstr ""
+"Ta wartość jest opcjonalna. Jeśli nie podasz klucza prywatnego GPG, "
+"zaszyfrowane wiadomości są wysyłane bez podpisu."
+
+#: views/settings.hbs:84
+msgid "DKIM Signing by ZoneMTA"
+msgstr "Podpisywanie DKIM przez ZoneMTA"
+
+#: views/settings.hbs:85
+msgid ""
+"If you are using ZoneMTA then Mailtrain can provide a DKIM key for signing "
+"all outgoing messages. Other services usually provide their own means to "
+"DKIM sign your messages"
+msgstr ""
+"Jeśli używasz ZoneMTA, Mailtrain może dostarczyć klucz DKIM do podpisania "
+"wszystkich wychodzących wiadomości. Inne usługi zwykle zapewniają własne "
+"środki do podpisywania wiadomości przez DKIM"
+
+#: views/settings.hbs:86
+msgid ""
+"Do not use sensitive keys here. The private key is not encrypted in the "
+"database."
+msgstr ""
+"Nie używaj tutaj wrażliwych kluczy. Klucz prywatny nie jest zaszyfrowany w "
+"bazie danych."
+
+#: views/settings.hbs:87
+msgid "ZoneMTA DKIM API Key"
+msgstr "Klucz API ZoneMTA DKIM"
+
+#: views/settings.hbs:88
+msgid "Some secret value"
+msgstr "Tajna wartość"
+
+#: views/settings.hbs:89
+msgid ""
+"Secret value known to ZoneMTA for requesting DKIM key information. If this "
+"value was generated by the Mailtrain installation script then you can keep "
+"it as it is"
+msgstr ""
+"Tajna wartość znana ZoneMTA dla żądań klucza DKIM. Jeśli ta wartość została "
+"wygenerowana przez skrypt instalacyjny Mailtrain, możesz zachować ją w "
+"niezmienionym stanie"
+
+#: views/settings.hbs:90
+msgid "DKIM domain"
+msgstr "Domena DKIM"
+
+#: views/settings.hbs:91
+msgid "Domain name for the DKIM key"
+msgstr "Nazwa domeny dla klucza DKIM"
+
+#: views/settings.hbs:92
+msgid "Leave blank to use the sender email address domain"
+msgstr "Pozostaw puste, aby użyć domeny adresu e-mail nadawcy"
+
+#: views/settings.hbs:93 views/settings.hbs:94
+msgid "DKIM key selector"
+msgstr "Selektor klucza DKIM"
+
+#: views/settings.hbs:95
+msgid "Signing is disabled without a valid selector value"
+msgstr "Podpisywanie jest wyłączone bez prawidłowej wartości selektora"
+
+#: views/settings.hbs:96
+msgid "DKIM Private Key"
+msgstr "Klucz prywatny DKIM"
+
+#: views/settings.hbs:98
+msgid ""
+"This value is optional. If you do not provide a private key then messages "
+"are not signed."
+msgstr ""
+"Ta wartość jest opcjonalna. Jeśli nie dostarczysz klucza prywatnego, "
+"wiadomości nie będą podpisane."
+
+#: views/subscription/confirm-notice.hbs:1 views/subscription/subscribe.hbs:1
+msgid "Warning!"
+msgstr "Ostrzeżenie!"
+
+#: views/subscription/confirm-notice.hbs:2
+msgid "If JavaScript was not enabled then no confirmation message was sent"
+msgstr "Jeśli JavaScript nie był włączony, nie wysłano żadnego potwierdzenia"
+
+#: views/subscription/confirm-notice.hbs:3
+msgid "Almost finished."
+msgstr "Prawie gotowe."
+
+#: views/subscription/confirm-notice.hbs:4
+msgid ""
+"We need to confirm your email address. To complete the subscription process, "
+"please click the link in the email we just sent you."
+msgstr ""
+"Musimy potwierdzić swój adres e-mail. Aby zakończyć proces subskrypcji, "
+"kliknij link w wiadomości e-mail, którą właśnie wysłaliśmy."
+
+#: views/subscription/confirm-notice.hbs:5
+#: views/subscription/unsubscribe-notice.hbs:3
+#: views/subscription/updated-notice.hbs:3
+msgid "return to our website"
+msgstr "powrót do strony"
+
+#: views/subscription/manage-address.hbs:1
+msgid "Update your Email Address"
+msgstr "Zaktualizuj swój adres e-mail"
+
+#: views/subscription/manage-address.hbs:2
+msgid "Existing Email Address"
+msgstr "Istniejący adres e-mail"
+
+#: views/subscription/manage-address.hbs:3
+msgid "New Email Address"
+msgstr "Nowy adres e-mail"
+
+#: views/subscription/manage-address.hbs:4
+msgid "Your new email address"
+msgstr "Twój nowy adres e-mail"
+
+#: views/subscription/manage-address.hbs:5
+msgid ""
+"You will receive a confirmation request to your new email address that you "
+"need to accept before your email is actually changed"
+msgstr ""
+"Otrzymasz prośbę o potwierdzenie na nowy adres e-mail, który musisz "
+"zaakceptować przed faktyczną zmianą adresu e-mail"
+
+#: views/subscription/manage-address.hbs:6
+msgid "Update Email Address"
+msgstr "Zaktualizuj adres e-mail"
+
+#: views/subscription/manage.hbs:1
+msgid "Update your preferences"
+msgstr "Zaktualizuj swoje preferencje"
+
+#: views/subscription/manage.hbs:3
+msgid "want to change it?"
+msgstr "chcesz to zmienić?"
+
+#: views/subscription/manage.hbs:6 views/subscription/subscribe.hbs:6
+msgid "Download signature verification key"
+msgstr "Pobierz klucz weryfikacji podpisu"
+
+#: views/subscription/manage.hbs:8 views/subscription/subscribe.hbs:8
+msgid ""
+"Insert your GPG public key here to encrypt messages sent to your address"
+msgstr ""
+"Wstaw tutaj swój publiczny klucz GPG, aby zaszyfrować wiadomości wysłane na "
+"Twój adres"
+
+#: views/subscription/manage.hbs:9 views/subscription/subscribe.hbs:9
+msgid "optional"
+msgstr "opcjonalny"
+
+#: views/subscription/manage.hbs:11
+msgid "Update Profile"
+msgstr "Zaktualizuj profil"
+
+#: views/subscription/subscribe.hbs:2
+msgid "JavaScript must be enabled in order for the subscription form to work"
+msgstr ""
+"Aby formularz subskrypcji działał, musi być włączona obsługa JavaScript"
+
+#: views/subscription/subscribe.hbs:11
+msgid "Subscribe to list"
+msgstr "Zapisz się do listy"
+
+#: views/subscription/subscribed.hbs:3
+msgid "Thank you for subscribing!"
+msgstr "Dziękujemy za subskrypcję!"
+
+#: views/subscription/subscribed.hbs:4
+msgid "continue to our website"
+msgstr "przejdź na naszą stronę internetową"
+
+#: views/subscription/unsubscribe-notice.hbs:1
+msgid "Unsubscribe Successful"
+msgstr "Anulowanie subskrypcji przebiegło pomyślnie"
+
+#: views/subscription/unsubscribe-notice.hbs:2
+msgid "You have been removed from:"
+msgstr "Zostałeś usunięty z:"
+
+#: views/subscription/unsubscribe.hbs:2
+msgid "Enter your email address to unsubscribe from:"
+msgstr "Wpisz swój adres e-mail, aby zrezygnować z subskrypcji:"
+
+#: views/subscription/updated-notice.hbs:1
+msgid "Profile Updated"
+msgstr "Profil zaktualizowany"
+
+#: views/subscription/updated-notice.hbs:2
+msgid "Your profile information has been updated."
+msgstr "Twoje informacje profilowe zostały zaktualizowane."
+
+#: views/templates/create.hbs:2 views/templates/edit.hbs:2
+#: views/templates/templates.hbs:2 views/templates/templates.hbs:4
+#: lib/tools.js:115
+msgid "Templates"
+msgstr "Szablony"
+
+#: views/templates/create.hbs:3 views/templates/create.hbs:4
+#: views/templates/create.hbs:12 views/templates/templates.hbs:3
+msgid "Create Template"
+msgstr "Utwórz szablon"
+
+#: views/templates/create.hbs:5 views/templates/edit.hbs:6
+msgid "Template name"
+msgstr "Nazwa szablonu"
+
+#: views/templates/create.hbs:6 views/templates/edit.hbs:7
+msgid "Name for this template, eg. Newsletter"
+msgstr "Nazwa tego szablonu, np. Newsletter"
+
+#: views/templates/create.hbs:7
+msgid "HTML Editor"
+msgstr "Edytor HTML"
+
+#: views/templates/create.hbs:10 views/templates/edit.hbs:9
+msgid "Optional comments about this template"
+msgstr "Opcjonalne komentarze na temat tego szablonu"
+
+#: views/templates/edit.hbs:3 views/templates/edit.hbs:4
+msgid "Edit Template"
+msgstr "Edytuj szablon"
+
+#: views/templates/edit.hbs:5
+msgid "Back to templates"
+msgstr "Powrót do szablonów"
+
+#: views/templates/edit.hbs:11
+msgid "Delete Template"
+msgstr "Usuń Szablon"
+
+#: views/triggers/create-select.hbs:2 views/triggers/create.hbs:2
+#: views/triggers/edit.hbs:2 views/triggers/triggered.hbs:2
+#: views/triggers/triggers.hbs:2 views/triggers/triggers.hbs:4
+msgid "Automation Triggers"
+msgstr "Automatyczne wyzwalacze"
+
+#: views/triggers/create-select.hbs:5
+msgid "Select a list for the trigger"
+msgstr "Wybierz listę dla wyzwalacza"
+
+#: views/triggers/create.hbs:5 views/triggers/edit.hbs:6
+msgid "Trigger name"
+msgstr "Nazwa wyzwalacza"
+
+#: views/triggers/create.hbs:6 views/triggers/edit.hbs:7
+msgid "Name for this trigger, eg. Inactive subscribers"
+msgstr "Nazwa tego wyzwalacza, np. Nieaktywni subskrybenci"
+
+#: views/triggers/create.hbs:8 views/triggers/edit.hbs:9
+msgid "Optional comments about this trigger"
+msgstr "Opcjonalne komentarze na temat tego wyzwalacza"
+
+#: views/triggers/create.hbs:12 views/triggers/edit.hbs:14
+msgid "Trigger rule"
+msgstr "Reguła wyzwalacza"
+
+#: views/triggers/create.hbs:13 views/triggers/edit.hbs:15
+msgid "Trigger fires"
+msgstr "Aktywacja wyzwalacza"
+
+#: views/triggers/create.hbs:14 views/triggers/edit.hbs:16
+msgid "days after:"
+msgstr "dni po:"
+
+#: views/triggers/create.hbs:15 views/triggers/edit.hbs:17
+msgid "Subscription"
+msgstr "Subskrypcja"
+
+#: views/triggers/create.hbs:16 views/triggers/create.hbs:21
+#: views/triggers/edit.hbs:18 views/triggers/edit.hbs:23
+msgid "Event"
+msgstr "Zdarzenie"
+
+#: views/triggers/create.hbs:18 views/triggers/create.hbs:19
+#: views/triggers/create.hbs:25 views/triggers/edit.hbs:20
+#: views/triggers/edit.hbs:21 views/triggers/edit.hbs:27
+msgid "Campaign"
+msgstr "Kampania"
+
+#: views/triggers/create.hbs:23 views/triggers/edit.hbs:25
+msgid "Trigger action"
+msgstr "Czynność wyzwalacza"
+
+#: views/triggers/create.hbs:24 views/triggers/edit.hbs:26
+msgid "Send campaign"
+msgstr "Wyślij kampanię"
+
+#: views/triggers/edit.hbs:3 views/triggers/edit.hbs:4
+msgid "Edit Trigger"
+msgstr "Edycja wyzwalacza"
+
+#: views/triggers/edit.hbs:5
+msgid "Back to triggers"
+msgstr "Powrót do wyzwalaczy"
+
+#: views/triggers/edit.hbs:11
+msgid "Trigger is enabled"
+msgstr "Wyzwalacz jest włączony"
+
+#: views/triggers/edit.hbs:29
+msgid "Delete Trigger"
+msgstr "Usuń wyzwalacz"
+
+#: views/triggers/triggered.hbs:3
+msgid "Triggered"
+msgstr "Wywołany"
+
+#: views/triggers/triggered.hbs:4
+msgid "Triggered subscribers"
+msgstr "Wywołani subskrybenci"
+
+#: views/triggers/triggered.hbs:5
+msgid "Subscribers who caused this trigger to fire"
+msgstr "Subskrybenci, którzy spowodowali uruchomienie tego wyzwalacza"
+
+#: views/triggers/triggered.hbs:9
+msgid "Triggered time"
+msgstr "Czas wywołanych"
+
+#: views/triggers/triggers.hbs:9
+msgid "Trigger"
+msgstr "Wyzwalacz"
+
+#: views/triggers/triggers.hbs:10
+msgid "Target Campaign"
+msgstr "Cel kampanii"
+
+#: views/triggers/triggers.hbs:11
+msgid "Triggered count"
+msgstr "Liczba wyzwoleń"
+
+#: views/triggers/triggers.hbs:12
+msgid "Enabled"
+msgstr "Włączone"
+
+#: views/triggers/triggers.hbs:13
+msgid "Disabled"
+msgstr "Wyłączone"
+
+#: views/users/account.hbs:4
+msgid "This account is managed through LDAP."
+msgstr "To konto jest zarządzane przez LDAP."
+
+#: views/users/account.hbs:5
+msgid "Associated Email Address"
+msgstr "Powiązany adres e-mail"
+
+#: views/users/account.hbs:8
+msgid "Your e-mail address"
+msgstr "Twój adres e-mail"
+
+#: views/users/account.hbs:9
+msgid ""
+"This address is used for account recovery in case you lose your password"
+msgstr "Ten adres służy do odzyskiwania konta na wypadek utraty hasła"
+
+#: views/users/account.hbs:10
+msgid "Password change"
+msgstr "Zmiana hasła"
+
+#: views/users/account.hbs:11
+msgid ""
+"You only need to fill out this form if you want to change your current "
+"password"
+msgstr "Wypełnij ten formularz, jeśli chcesz zmienić swoje obecne hasło"
+
+#: views/users/account.hbs:12 views/users/account.hbs:13
+msgid "Current Password"
+msgstr "Aktualne hasło"
+
+#: views/users/account.hbs:14 views/users/account.hbs:15
+#: views/users/reset.hbs:6 views/users/reset.hbs:7
+msgid "New Password"
+msgstr "Nowe hasło"
+
+#: views/users/account.hbs:16
+msgid "Confirm Password"
+msgstr "Powtórz hasło"
+
+#: views/users/account.hbs:17 views/users/reset.hbs:8
+msgid "Confirm New Password"
+msgstr "Potwierdź nowe hasło"
+
+#: views/users/api.hbs:4
+msgid "Are you sure? Resetting would invalidate the currently existing token."
+msgstr "Jesteś pewny? Zresetowanie unieważni istniejący token."
+
+#: views/users/api.hbs:5
+msgid "Are you sure?"
+msgstr "Jesteś pewny?"
+
+#: views/users/api.hbs:6
+msgid "Reset Access Token"
+msgstr "Zresetuj Access Token"
+
+#: views/users/api.hbs:7
+msgid "Generate Access Token"
+msgstr "Wygeneruj Access Token"
+
+#: views/users/api.hbs:8
+msgid "Personal access token:"
+msgstr "Osobisty Access Token:"
+
+#: views/users/api.hbs:9
+msgid "Access token not yet generated"
+msgstr "Access token nie został jeszcze wygenerowany"
+
+#: views/users/api.hbs:10
+msgid "Notes about the API"
+msgstr "Uwagi na temat interfejsu API"
+
+#: views/users/api.hbs:11
+msgid ""
+"API response is a JSON structure with error and data"
+"code> properties. If the response error has a value set then "
+"the request failed."
+msgstr ""
+"Odpowiedź API to struktura JSON z właściwościami error code> i "
+"data code>. Jeśli odpowiedź error code> ma ustawioną "
+"wartość, to żądanie nie powiodło się."
+
+#: views/users/api.hbs:12
+msgid ""
+"You need to define proper Content-Type when making a request. "
+"You can either use application/x-www-form-urlencoded for normal "
+"form data or application/json for a JSON payload. Using "
+"multipart/form-data is not supported."
+msgstr ""
+"Musisz zdefiniować właściwy Content-Type podczas wysyłania "
+"zapytania. Możesz użyć application/x-www-form-urlencoded dla "
+"normalnych danych formularza lub application/json dla JSON "
+"payload. Używanie multipart/form-data nie jest obsługiwane."
+
+#: views/users/api.hbs:13
+msgid "Add subscription"
+msgstr "Dodaj subskrypcję"
+
+#: views/users/api.hbs:14
+msgid ""
+"This API call either inserts a new subscription or updates existing. Fields "
+"not included are left as is, so if you update only LAST_NAME value, then "
+"FIRST_NAME is kept untouched for an existing subscription."
+msgstr ""
+"To wywołanie API wprowadza nową subskrypcję lub aktualizacje istniejące. "
+"Pola nieuwzględnione pozostają bez zmian, więc jeśli zaktualizujesz tylko "
+"wartość LAST_NAME, to FIRST_NAME pozostanie nietknięte dla istniejącej "
+"subskrypcji."
+
+#: views/users/api.hbs:15 views/users/api.hbs:17 views/users/api.hbs:30
+#: views/users/api.hbs:32 views/users/api.hbs:38 views/users/api.hbs:40
+#: views/users/api.hbs:46 views/users/api.hbs:48
+msgid "arguments"
+msgstr "argumenty"
+
+#: views/users/api.hbs:16 views/users/api.hbs:31 views/users/api.hbs:39
+#: views/users/api.hbs:47
+msgid "your personal access token"
+msgstr "twój osobisty token dostępu"
+
+#: views/users/api.hbs:18 views/users/api.hbs:33 views/users/api.hbs:41
+msgid "subscriber's email address"
+msgstr "subscriber's email addressadres e-mail subskrybenta"
+
+#: views/users/api.hbs:19 views/users/api.hbs:34 views/users/api.hbs:42
+#: views/users/api.hbs:50
+msgid "required"
+msgstr "wymagany"
+
+#: views/users/api.hbs:20
+msgid "subscriber's first name"
+msgstr "imię subskrybenta"
+
+#: views/users/api.hbs:21
+msgid "subscriber's last name"
+msgstr "nazwisko subskrybenta"
+
+#: views/users/api.hbs:22
+msgid ""
+"subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not "
+"set defaults to \"UTC\""
+msgstr ""
+"strefa czasowa subskrybenta (np. \"Europa/Tallinn\", \"PST\" lub \"UTC\"). "
+"Jeśli nie jest ustawiony domyślnie „UTC”"
+
+#: views/users/api.hbs:23
+msgid ""
+"custom field value. Use yes/no for option group values (checkboxes, radios, "
+"drop downs)"
+msgstr ""
+"niestandardowa wartość pola. Użyj wartości tak/nie dla wartości grup opcji "
+"(checkbox, radio, lista rozwijana)"
+
+#: views/users/api.hbs:24
+msgid "Additional POST arguments"
+msgstr "Dodatkowe argumenty POST"
+
+#: views/users/api.hbs:25
+msgid ""
+"set to \"yes\" if you want to make sure the email is marked as subscribed "
+"even if it was previously marked as unsubscribed. If the email was already "
+"unsubscribed/blocked then subscription status is not changed"
+msgstr ""
+"ustawić na \"tak \", jeśli chcesz się upewnić, że wiadomość e-mail została "
+"oznaczona jako zasubskrybowana, nawet jeśli została wcześniej oznaczona jako "
+"niesubskrybowana. Jeśli e-mail został już wypisany/zablokowane, status "
+"subskrypcji nie zostanie zmieniony"
+
+#: views/users/api.hbs:26
+msgid ""
+"set to \"yes\" if you want to send confirmation email to the subscriber "
+"before actually marking as subscribed"
+msgstr ""
+"ustaw na \"tak\", jeśli chcesz wysłać wiadomość e-mail z potwierdzeniem do "
+"subskrybenta, zanim faktycznie zostaniesz oznaczony jako zasubskrybowany"
+
+#: views/users/api.hbs:28
+msgid "Remove subscription"
+msgstr "Usuń subskrypcję"
+
+#: views/users/api.hbs:29
+msgid "This API call marks a subscription as unsubscribed"
+msgstr "To wywołanie API oznacza subskrypcję jako niesubskrybowaną"
+
+#: views/users/api.hbs:36
+msgid "Delete subscription"
+msgstr "Usuń subskrypcję"
+
+#: views/users/api.hbs:37
+msgid "This API call deletes a subscription"
+msgstr "To wywołanie API usuwa subskrypcję"
+
+#: views/users/api.hbs:44
+msgid "Add new custom field"
+msgstr "Dodaj nowe niestandardowe pole"
+
+#: views/users/api.hbs:45
+msgid "This API call creates a new custom field for a list."
+msgstr "To wywołanie API tworzy nowe niestandardowe pole dla listy."
+
+#: views/users/api.hbs:49
+msgid "field name"
+msgstr "nazwa pola"
+
+#: views/users/api.hbs:51
+msgid "one of the following types:"
+msgstr "jeden z następujących typów:"
+
+#: views/users/api.hbs:52
+msgid ""
+"If the type is 'option' then you also need to specify the parent element ID"
+msgstr "Jeśli typ to \"option\", musisz również podać ID elementu nadrzędnego"
+
+#: views/users/api.hbs:53
+msgid ""
+"Template for the group element. If not set, then values of the elements are "
+"joined with commas"
+msgstr ""
+"Szablon dla elementu grupy. Jeśli nie jest ustawione, wartości elementów są "
+"połączone przecinkami"
+
+#: views/users/api.hbs:54
+msgid ""
+"if not visible then the subscriber can not view or modify this value at the "
+"profile page"
+msgstr ""
+"jeśli niewidoczny, subskrybent nie może wyświetlić ani zmodyfikować tej "
+"wartości na stronie profilu"
+
+#: views/users/forgot.hbs:3 views/users/reset.hbs:3
+msgid "Password Reset"
+msgstr "Resetowanie hasła"
+
+#: views/users/forgot.hbs:4
+msgid "Reset your password?"
+msgstr "Nie pamiętasz hasła?"
+
+#: views/users/forgot.hbs:5
+msgid "Accounts are managed through LDAP."
+msgstr "Konta są zarządzane przez LDAP."
+
+#: views/users/forgot.hbs:6 views/users/reset.hbs:10
+msgid "Reset Password"
+msgstr "Resetuj hasło"
+
+#: views/users/forgot.hbs:7
+msgid ""
+"Please provide the username or email address that you used when you signed "
+"up for your Mailtrain account."
+msgstr ""
+"Podaj nazwę użytkownika lub adres e-mail użyty podczas rejestracji konta "
+"Mailtrain."
+
+#: views/users/forgot.hbs:8
+msgid "We will send you an email that will allow you to reset your password."
+msgstr "Wyślemy Ci wiadomość e-mail, która pozwoli Ci zresetować hasło."
+
+#: views/users/forgot.hbs:10
+msgid "Username or email address"
+msgstr "Nazwa użytkownika lub adres e-mail"
+
+#: views/users/forgot.hbs:11
+msgid "Send verification email"
+msgstr "Wyślij email weryfikacyjny"
+
+#: views/users/login.hbs:8
+msgid "Remember me"
+msgstr "Zapamiętaj mnie"
+
+#: views/users/login.hbs:11 views/users/login.hbs:12
+msgid "Forgot password?"
+msgstr "Zapomniałeś hasła?"
+
+#: views/users/reset.hbs:4
+msgid "Choose your new password"
+msgstr "Wybierz nowe hasło"
+
+#: views/users/reset.hbs:5
+msgid "Please enter a new password."
+msgstr "Wprowadź nowe hasło."
+
+#: lib/feed.js:31
+msgid "Bad status code %s"
+msgstr "Nieprawidłowy kod statusu %s"
+
+#: lib/helpers.js:17
+msgid "URL that points to the unsubscribe page"
+msgstr "Adres URL wskazujący stronę rezygnacji z subskrypcji"
+
+#: lib/helpers.js:20
+msgid "URL that points to the preferences page of the subscriber"
+msgstr "Adres URL wskazujący stronę preferencji subskrybenta"
+
+#: lib/helpers.js:23
+msgid "URL to preview the message in a browser"
+msgstr "URL, aby wyświetlić podgląd wiadomości w przeglądarce"
+
+#: lib/helpers.js:29 lib/models/segments.js:31
+msgid "First name"
+msgstr "Imię"
+
+#: lib/helpers.js:32 lib/models/segments.js:35
+msgid "Last name"
+msgstr "Nazwisko"
+
+#: lib/helpers.js:35
+msgid "Full name (first and last name combined)"
+msgstr "Imię i nazwisko"
+
+#: lib/helpers.js:38
+msgid "Unique ID that identifies the recipient"
+msgstr "Unikalny identyfikator identyfikujący odbiorcę"
+
+#: lib/helpers.js:41
+msgid "Unique ID that identifies the list used for this campaign"
+msgstr "Unikalny identyfikator identyfikujący listę użytą w tej kampanii"
+
+#: lib/helpers.js:44
+msgid "Unique ID that identifies current campaign"
+msgstr "Unikalny identyfikator identyfikujący bieżącą kampanię"
+
+#: lib/mailer.js:215
+msgid "Invalid mail transport"
+msgstr "Nieprawidłowy transport poczty"
+
+#: lib/models/campaigns.js:271 lib/models/campaigns.js:298
+#: lib/models/campaigns.js:371 lib/models/campaigns.js:494
+#: lib/models/campaigns.js:752 lib/models/campaigns.js:881
+msgid "Missing Campaign ID"
+msgstr "Brakujący identyfikator kampanii"
+
+#: lib/models/campaigns.js:407
+msgid "Emtpy or too large attahcment"
+msgstr "Pusty lub zbyt duży załącznik"
+
+#: lib/models/campaigns.js:573 lib/models/campaigns.js:761
+msgid "Campaign Name must be set"
+msgstr "Nazwa kampanii musi być ustawiona"
+
+#: lib/models/campaigns.js:577
+msgid "RSS URL must be set and needs to be a valid URL"
+msgstr ""
+"Adres URL kanału RSS musi być ustawiony i musi być prawidłowym adresem URL"
+
+#: lib/models/campaigns.js:730
+msgid "Selected template not found"
+msgstr "Nie znaleziono wybranego szablonu"
+
+#: lib/models/campaigns.js:1082
+msgid "Invalid or missing message ID"
+msgstr "Nieprawidłowy lub brakujący ID wiadomości"
+
+#: lib/models/fields.js:24
+msgid "Drop Down"
+msgstr "Lista rozwijana"
+
+#: lib/models/fields.js:25
+msgid "Date (MM/DD/YYY)"
+msgstr "Data (MM/DD/YYYY)"
+
+#: lib/models/fields.js:29
+msgid "JSON value for custom rendering"
+msgstr "Wartość JSON dla renderowania niestandardowego"
+
+#: lib/models/fields.js:30
+msgid "Option"
+msgstr "Opcja"
+
+#: lib/models/fields.js:53 lib/models/fields.js:98 lib/models/fields.js:123
+#: lib/models/lists.js:81 lib/models/lists.js:175 lib/models/lists.js:212
+#: lib/models/segments.js:43 lib/models/segments.js:176
+#: lib/models/subscriptions.js:88 lib/models/subscriptions.js:640
+#: lib/models/subscriptions.js:703 lib/models/subscriptions.js:889
+#: lib/models/subscriptions.js:992 lib/models/subscriptions.js:1046
+#: lib/models/subscriptions.js:1109 lib/models/subscriptions.js:1152
+msgid "Missing List ID"
+msgstr "Brakujący ID listy"
+
+#: lib/models/fields.js:129
+msgid "Option field requires a group to be selected"
+msgstr "Pole opcji wymaga wyboru grupy"
+
+#: lib/models/fields.js:149 lib/models/fields.js:199
+msgid "Missing Field ID"
+msgstr "Brakujący ID pola"
+
+#: lib/models/fields.js:153 lib/models/segments.js:185
+#: lib/models/segments.js:225
+msgid "Field Name must be set"
+msgstr "Nazwa pola musi być ustawiona"
+
+#: lib/models/fields.js:216
+msgid "Custom field not found"
+msgstr "Nie znaleziono pola niestandardowego"
+
+#: lib/models/fields.js:289
+msgid "Unknown column type %s"
+msgstr "Nieznany typ kolumny %s"
+
+#: lib/models/fields.js:293
+msgid "Missing column name"
+msgstr "Brakująca nazwa kolumny"
+
+#: lib/models/fields.js:297
+msgid "Missing list ID"
+msgstr "Brakujący ID listy"
+
+#: lib/models/fields.js:305
+msgid "Provided List ID not found"
+msgstr "Nie znaleziono ID listy dostarczonych"
+
+#: lib/models/links.js:328 routes/campaigns.js:541 routes/campaigns.js:590
+#: services/sender.js:304
+msgid "Campaign not found"
+msgstr "Nie znaleziono kampanii"
+
+#: lib/models/links.js:336 routes/lists.js:146 services/sender.js:311
+msgid "List not found"
+msgstr "Nie znaleziono listy"
+
+#: lib/models/links.js:344
+msgid "Subscription not found"
+msgstr "Nie znaleziono subskrypcji"
+
+#: lib/models/lists.js:117 lib/models/lists.js:179
+msgid "List Name must be set"
+msgstr "Nazwa listy musi być ustawiona"
+
+#: lib/models/lists.js:241
+msgid "Missing List CID"
+msgstr "Brakujący CID listy"
+
+#: lib/models/segments.js:15
+msgid "Signup country"
+msgstr "Kraj rejestracji"
+
+#: lib/models/segments.js:19 lib/models/triggers.js:11
+msgid "Sign up date"
+msgstr "Data rejestracji"
+
+#: lib/models/segments.js:23 lib/models/triggers.js:15
+msgid "Latest open"
+msgstr "Ostatnie otwarcie"
+
+#: lib/models/segments.js:27 lib/models/triggers.js:19
+msgid "Latest click"
+msgstr "Ostatnie kliknięcie"
+
+#: lib/models/segments.js:69 lib/models/segments.js:216
+#: lib/models/segments.js:256 lib/models/segments.js:278
+msgid "Missing Segment ID"
+msgstr "Brakujący ID segmentu"
+
+#: lib/models/segments.js:85 lib/models/segments.js:549
+#: lib/models/segments.js:658
+msgid "Segment not found"
+msgstr "Nie znaleziono segmentu"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days after today"
+msgstr "%s dni po dzisiejszym dniu"
+
+#: lib/models/segments.js:146 lib/models/segments.js:147
+#: lib/models/segments.js:408 lib/models/segments.js:409
+msgid "%s days before today"
+msgstr "%s dni przed dzisiejszym dniem"
+
+#: lib/models/segments.js:148 lib/models/segments.js:410
+msgid "today"
+msgstr "dziś"
+
+#: lib/models/segments.js:189 lib/models/segments.js:229
+msgid "Invalid segment rule type"
+msgstr "Nieprawidłowy typ reguły segmentu"
+
+#: lib/models/segments.js:289 lib/models/segments.js:454 routes/segments.js:266
+#: routes/segments.js:300 routes/segments.js:370 routes/segments.js:381
+msgid "Selected segment not found"
+msgstr "Nie znaleziono wybranego segmentu"
+
+#: lib/models/segments.js:294 lib/models/segments.js:459 routes/segments.js:272
+#: routes/segments.js:306 routes/segments.js:387
+msgid "Invalid rule type"
+msgstr "Nieprawidłowy typ reguły"
+
+#: lib/models/segments.js:358 lib/models/segments.js:434
+#: lib/models/segments.js:524
+msgid "Missing Rule ID"
+msgstr "Brakujący ID reguły"
+
+#: lib/models/segments.js:374
+msgid "Specified rule not found"
+msgstr "Nie znaleziono określonej reguły"
+
+#: lib/models/segments.js:385
+msgid "Specified segment not found"
+msgstr "Nie znaleziono określonego segmentu"
+
+#: lib/models/segments.js:445
+msgid "Selected rule not found"
+msgstr "Nie znaleziono wybranej reguły"
+
+#: lib/models/subscriptions.js:233
+msgid "%s: Please Confirm Subscription"
+msgstr "%s: Potwierdź subskrypcję"
+
+#: lib/models/subscriptions.js:324
+msgid "Could not save subscription"
+msgstr "Nie można zapisać subskrypcji"
+
+#: lib/models/subscriptions.js:507 lib/models/subscriptions.js:537
+msgid "Missing Subscription ID"
+msgstr "Brakujący ID subskrypcji"
+
+#: lib/models/subscriptions.js:565
+msgid "Missing Subscription email address"
+msgstr "Brak adresu e-mail subskrypcji"
+
+#: lib/models/subscriptions.js:644 lib/models/subscriptions.js:893
+#: lib/models/subscriptions.js:1156
+msgid "Missing subscription ID"
+msgstr "Brakujący ID subskrypcji"
+
+#: lib/models/subscriptions.js:707
+msgid "Missing email address"
+msgstr "Brakujący adres e-mail"
+
+#: lib/models/subscriptions.js:996 lib/models/subscriptions.js:1050
+#: lib/models/subscriptions.js:1086
+msgid "Missing Import ID"
+msgstr "Brakujący ID importu"
+
+#: lib/models/subscriptions.js:1178
+msgid "Unknown subscription ID"
+msgstr "Nieznany ID subskrypcji"
+
+#: lib/models/subscriptions.js:1183
+msgid "Nothing seems to be changed"
+msgstr "Wydaje się, że nic nie zostało zmienione"
+
+#: lib/models/subscriptions.js:1197
+msgid "This address is already registered by someone else"
+msgstr "Ten adres jest już zarejestrowany przez inną osobę"
+
+#: lib/models/templates.js:51 lib/models/templates.js:122
+#: lib/models/templates.js:163
+msgid "Missing Template ID"
+msgstr "Brakujący ID szablonu"
+
+#: lib/models/templates.js:80 lib/models/templates.js:126
+msgid "Template Name must be set"
+msgstr "Nazwa szablonu musi być ustawiona"
+
+#: lib/models/triggers.js:28
+msgid "Has Opened"
+msgstr "Otwarte"
+
+#: lib/models/triggers.js:31
+msgid "Has Clicked"
+msgstr "Kliknięte"
+
+#: lib/models/triggers.js:34
+msgid "Not Opened"
+msgstr "Nie otwarte"
+
+#: lib/models/triggers.js:37
+msgid "Not Clicked"
+msgstr "Nie kliknięte"
+
+#: lib/models/triggers.js:174 lib/models/triggers.js:211
+msgid "Missing or invalid list ID"
+msgstr "Brakujący lub nieprawidłowy ID listy"
+
+#: lib/models/triggers.js:178 lib/models/triggers.js:263
+msgid "Days in the past are not allowed"
+msgstr "Dni w przeszłości są niedozwolone"
+
+#: lib/models/triggers.js:182 lib/models/triggers.js:203
+#: lib/models/triggers.js:267 lib/models/triggers.js:288
+msgid "Missing or invalid trigger rule"
+msgstr "Brakująca lub nieprawidłowa reguła wyzwalacza"
+
+#: lib/models/triggers.js:189 lib/models/triggers.js:274
+msgid "Invalid subscription configuration"
+msgstr "ieprawidłowa konfiguracja subskrypcji"
+
+#: lib/models/triggers.js:196 lib/models/triggers.js:281
+msgid "Invalid campaign configuration"
+msgstr "Nieprawidłowa konfiguracja kampanii"
+
+#: lib/models/triggers.js:199 lib/models/triggers.js:284
+msgid "A campaing can not be a target for itself"
+msgstr "Kampania nie może być celem samym w sobie"
+
+#: lib/models/triggers.js:232
+msgid "Could not store trigger row"
+msgstr "Nie można zapisać wiersza wyzwalacza"
+
+#: lib/models/triggers.js:249
+msgid "Missing or invalid Trigger ID"
+msgstr "Brakujący lub nieprawidłowy ID wyzwalacza"
+
+#: lib/models/triggers.js:316
+msgid "Missing Trigger ID"
+msgstr "Brakujący ID wyzwalacza"
+
+#: lib/models/users.js:103
+msgid "Could not store user row"
+msgstr "Nie można zapisać wiersza użytkownika"
+
+#: lib/models/users.js:173
+msgid "Email Address must be set"
+msgstr "Adres e-mail musi być ustawiony"
+
+#: lib/models/users.js:184
+msgid "Failed to check user data"
+msgstr "Nie można sprawdzić danych użytkownika"
+
+#: lib/models/users.js:195
+msgid ""
+"Can't change email as another user with the same email address already exists"
+msgstr ""
+"Nie można zmienić adresu e-mail, ponieważ inny użytkownik o tym samym "
+"adresie e-mail już istnieje"
+
+#: lib/models/users.js:212
+msgid "Incorrect current password"
+msgstr "Nieprawidłowe aktualne hasło"
+
+#: lib/models/users.js:216
+msgid "New password not set"
+msgstr "Nowe hasło nie zostało ustawione"
+
+#: lib/models/users.js:220
+msgid "Passwords do not match"
+msgstr "Hasła nie pasują do siebie"
+
+#: lib/models/users.js:258
+msgid "User ID not set"
+msgstr "Nie ustawiono ID użytkownika"
+
+#: lib/models/users.js:286
+msgid "Username must be set"
+msgstr "Nazwa użytkownika musi być ustawiona"
+
+#: lib/models/users.js:323
+msgid "Mailer password change request"
+msgstr "Żądanie zmiany hasła Mailera"
+
+#: lib/models/users.js:347 lib/models/users.js:367
+msgid "Missing username or reset token"
+msgstr "Brakująca nazwa użytkownika lub token reset"
+
+#: lib/models/users.js:371
+msgid "Invalid new password"
+msgstr "Nieprawidłowe nowe hasło"
+
+#: lib/passport.js:38
+msgid "%s logged out"
+msgstr "%s Wylogowany"
+
+#: lib/passport.js:51
+msgid "Failed to authenticate user"
+msgstr "Nie udało się uwierzytelnić użytkownika"
+
+#: lib/passport.js:67
+msgid "Logged in as %s"
+msgstr "Zalogowano jako %s"
+
+#: lib/passport.js:125
+msgid "Incorrect username or password"
+msgstr "Nieprawidłowa nazwa użytkownika lub hasło"
+
+#: lib/tools.js:123
+msgid "Automation"
+msgstr "Automatyzacja"
+
+#: lib/tools.js:133
+msgid "Blocked email address \"%s\""
+msgstr "Zablokowany adres e-mail \"%s\""
+
+#: lib/tools.js:142
+msgid "Invalid email address \"%s\"."
+msgstr "Nieprawidłowy adres e-mail \"%s\"."
+
+#: lib/tools.js:145
+msgid "MX record not found for domain"
+msgstr "Nie znaleziono rekordu MX dla domeny"
+
+#: lib/tools.js:148
+msgid "Address domain not found"
+msgstr "Nie znaleziono domeny"
+
+#: lib/tools.js:151
+msgid "Address domain name is required"
+msgstr "Nazwa domeny adresu jest wymagana"
+
+#: routes/archive.js:31 routes/archive.js:43 routes/archive.js:55 app.js:211
+msgid "Not Found"
+msgstr "Nie znaleziono"
+
+#: routes/archive.js:110 services/sender.js:447
+msgid "Received status code %s from %s"
+msgstr "Otrzymano kod statusu %s z %s"
+
+#: routes/archive.js:134 routes/campaigns.js:131 routes/campaigns.js:295
+#: routes/campaigns.js:390 routes/campaigns.js:435 routes/campaigns.js:475
+#: routes/campaigns.js:739 routes/campaigns.js:762 routes/campaigns.js:781
+#: routes/campaigns.js:803 routes/triggers.js:146
+msgid "Could not find campaign with specified ID"
+msgstr "Nie można znaleźć kampanii z określonym ID"
+
+#: routes/archive.js:142 routes/campaigns.js:789
+msgid "Attachment not found"
+msgstr "Załącznik nie znaleziony"
+
+#: routes/campaigns.js:26 routes/fields.js:13 routes/lists.js:49
+#: routes/segments.js:13 routes/settings.js:23 routes/templates.js:17
+#: routes/triggers.js:18 routes/users.js:75 routes/users.js:120
+msgid "Need to be logged in to access restricted content"
+msgstr "Musisz być zalogowany, aby uzyskać dostęp do zastrzeżonych treści"
+
+#: routes/campaigns.js:117
+msgid "Could not create campaign"
+msgstr "Nie można utworzyć kampanii"
+
+#: routes/campaigns.js:120
+msgid "Campaign “%s” created"
+msgstr "Kampania “%s” utworzona"
+
+#: routes/campaigns.js:204
+msgid "content from an RSS entry"
+msgstr "treść z wpisu RSS"
+
+#: routes/campaigns.js:220
+msgid "Campaign settings updated"
+msgstr "Zaktualizowano ustawienia kampanii"
+
+#: routes/campaigns.js:222
+msgid "Campaign settings not updated"
+msgstr "Ustawienia kampanii nie zostały zaktualizowane"
+
+#: routes/campaigns.js:238 routes/campaigns.js:639
+msgid "Campaign deleted"
+msgstr "Kampania usunięta"
+
+#: routes/campaigns.js:240 routes/campaigns.js:641
+msgid "Could not delete specified campaign"
+msgstr "Nie można usunąć określonej kampanii"
+
+#: routes/campaigns.js:259
+msgid "Idling"
+msgstr "Bezczynność"
+
+#: routes/campaigns.js:262
+msgid "Scheduled"
+msgstr "Planowane"
+
+#: routes/campaigns.js:268
+msgid "Paused"
+msgstr "Wstrzymane"
+
+#: routes/campaigns.js:270
+msgid "Inactive"
+msgstr "Nieaktywny"
+
+#: routes/campaigns.js:272
+msgid "Active"
+msgstr "Aktywny"
+
+#: routes/campaigns.js:274
+msgid "Other"
+msgstr "Inny"
+
+#: routes/campaigns.js:429
+msgid "Unknown status selector"
+msgstr "Nieznany status selektora"
+
+#: routes/campaigns.js:657
+msgid "Scheduled sending"
+msgstr "Wysyłanie zaplanowanych"
+
+#: routes/campaigns.js:659
+msgid "Could not schedule sending"
+msgstr "Nie można zaplanować wysyłania"
+
+#: routes/campaigns.js:671
+msgid "Sending resumed"
+msgstr "Wysyłanie zostało wznowione"
+
+#: routes/campaigns.js:673
+msgid "Could not resume sending"
+msgstr "Nie można wznowić wysyłania"
+
+#: routes/campaigns.js:685
+msgid "Sending reset"
+msgstr "Wysyłam reset"
+
+#: routes/campaigns.js:687
+msgid "Could not reset sending"
+msgstr "Nie można zresetować wysyłania"
+
+#: routes/campaigns.js:699 routes/campaigns.js:727
+msgid "Sending paused"
+msgstr "Wysyłanie wstrzymane"
+
+#: routes/campaigns.js:701 routes/campaigns.js:729
+msgid "Could not pause sending"
+msgstr "Nie można wstrzymać wysyłania"
+
+#: routes/campaigns.js:713
+msgid "Sending activated"
+msgstr "Wysyłanie aktywowane"
+
+#: routes/campaigns.js:715
+msgid "Could not activate sending"
+msgstr "Nie można aktywować wysyłania"
+
+#: routes/campaigns.js:750
+msgid "Attachment uploaded"
+msgstr "Przesłano załącznik"
+
+#: routes/campaigns.js:752
+msgid "Could not store attachment"
+msgstr "Nie można zapisać załącznika"
+
+#: routes/campaigns.js:769
+msgid "Attachment deleted"
+msgstr "Załącznik usunięty"
+
+#: routes/campaigns.js:771
+msgid "Could not delete attachment"
+msgstr "Nie można usunąć załącznika"
+
+#: routes/fields.js:28 routes/fields.js:64 routes/fields.js:118
+#: routes/segments.js:28 routes/segments.js:59 routes/segments.js:102
+#: routes/segments.js:151 routes/segments.js:223 routes/segments.js:255
+#: routes/segments.js:289 routes/segments.js:336 routes/segments.js:359
+msgid "Selected list ID not found"
+msgstr "Nie znaleziono wybranego ID listy"
+
+#: routes/fields.js:102
+msgid "Could not create custom field"
+msgstr "Nie można utworzyć pola niestandardowego"
+
+#: routes/fields.js:129
+msgid "Selected field not found"
+msgstr "Nie znaleziono wybranego pola"
+
+#: routes/fields.js:165
+msgid "Field settings updated"
+msgstr "Zaktualizowano ustawienia pola"
+
+#: routes/fields.js:167
+msgid "Field settings not updated"
+msgstr "Ustawienia pola nie zostały zaktualizowane"
+
+#: routes/fields.js:183
+msgid "Custom field deleted"
+msgstr "Pole niestandardowe usunięte"
+
+#: routes/fields.js:185
+msgid "Could not delete specified field"
+msgstr "Nie można usunąć określonego pola"
+
+#: routes/links.js:40
+msgid "Oops, we couldn't find a link for the URL you clicked"
+msgstr "Ups, nie mogliśmy znaleźć linku dla URL który kliknąłeś"
+
+#: routes/lists.js:90
+msgid "Could not create list"
+msgstr "Nie można utworzyć listy"
+
+#: routes/lists.js:93
+msgid "List created"
+msgstr "Utworzono listę"
+
+#: routes/lists.js:101 routes/lists.js:236 routes/lists.js:301
+#: routes/lists.js:340 routes/lists.js:409 routes/lists.js:434
+#: routes/lists.js:479 routes/lists.js:501 routes/lists.js:530
+#: routes/lists.js:609 routes/lists.js:666 routes/lists.js:693
+msgid "Could not find list with specified ID"
+msgstr "Nie można znaleźć listy o określonym ID"
+
+#: routes/lists.js:115
+msgid "List settings updated"
+msgstr "Zaktualizowano ustawienia listy"
+
+#: routes/lists.js:117
+msgid "List settings not updated"
+msgstr "Nie zaktualizowano ustawień listy"
+
+#: routes/lists.js:133
+msgid "List deleted"
+msgstr "Lista usunięta"
+
+#: routes/lists.js:135
+msgid "Could not delete specified list"
+msgstr "Nie można usunąć określonej listy"
+
+#: routes/lists.js:171
+msgid "Unknown"
+msgstr "Nieznany"
+
+#: routes/lists.js:171
+msgid "Complained"
+msgstr "Skarżący"
+
+#: routes/lists.js:202
+msgid "Invalid key"
+msgstr "Klucz niewłaściwy"
+
+#: routes/lists.js:204
+msgid "Expired key"
+msgstr "Klucz wygasł"
+
+#: routes/lists.js:206
+msgid "Revoked key"
+msgstr "Klucz odwołany"
+
+#: routes/lists.js:256
+msgid "Initializing"
+msgstr "Inicjowanie"
+
+#: routes/lists.js:259
+msgid "Initialized"
+msgstr "Zainicjowano"
+
+#: routes/lists.js:262
+msgid "Importing"
+msgstr "Importowanie"
+
+#: routes/lists.js:268
+msgid "Errored"
+msgstr "Błędne"
+
+#: routes/lists.js:346 routes/lists.js:415 routes/lists.js:440
+msgid "Could not find subscriber with specified ID"
+msgstr "Nie można znaleźć subskrybenta o podanym ID"
+
+#: routes/lists.js:392
+msgid "Could not add subscription"
+msgstr "Nie można dodać subskrypcji"
+
+#: routes/lists.js:397
+msgid "%s was successfully added to your list"
+msgstr "%s został pomyślnie dodany do twojej listy"
+
+#: routes/lists.js:399
+msgid "%s was not added to your list"
+msgstr "%s nie został dodany do Twojej listy"
+
+#: routes/lists.js:421
+msgid "Could not unsubscribe user"
+msgstr "Nie można anulować subskrypcji użytkownika"
+
+#: routes/lists.js:424
+msgid "%s was successfully unsubscribed from your list"
+msgstr "%s został pomyślnie wypisany z listy"
+
+#: routes/lists.js:444
+msgid "%s was successfully removed from your list"
+msgstr "%s został pomyślnie usunięty z Twojej listy"
+
+#: routes/lists.js:456
+msgid "Another subscriber with email address %s already exists"
+msgstr "Inny subskrybent z adresem e-mail %s już istnieje"
+
+#: routes/lists.js:463
+msgid "Subscription settings updated"
+msgstr "Zaktualizowano ustawienia subskrypcji"
+
+#: routes/lists.js:465
+msgid "Subscription settings not updated"
+msgstr "Ustawienia subskrypcji nie zostały zaktualizowane"
+
+#: routes/lists.js:507 routes/lists.js:615 routes/lists.js:651
+#: routes/lists.js:679 routes/lists.js:699
+msgid "Could not find import data with specified ID"
+msgstr "Nie można znaleźć danych importu o podanym ID"
+
+#: routes/lists.js:538
+msgid "Could not process CSV"
+msgstr "Nie można przetworzyć pliku CSV"
+
+#: routes/lists.js:547
+msgid "Could not create importer"
+msgstr "Nie można utworzyć importera"
+
+#: routes/lists.js:598
+msgid "Empty file"
+msgstr "Pusty plik"
+
+#: routes/lists.js:655
+msgid "Import started"
+msgstr "Rozpoczęto importowanie"
+
+#: routes/lists.js:683
+msgid "Import restarted"
+msgstr "Import został zrestartowany"
+
+#: routes/segments.js:86
+msgid "Could not create segment"
+msgstr "Nie można utworzyć segmentu"
+
+#: routes/segments.js:89
+msgid "Segment created"
+msgstr "Utworzono segment"
+
+#: routes/segments.js:113
+msgid "Selected segment ID not found"
+msgstr "Nie znaleziono ID wybranego segmentu"
+
+#: routes/segments.js:188
+msgid "Segment settings updated"
+msgstr "Zaktualizowane ustawienia segmentów"
+
+#: routes/segments.js:190
+msgid "Segment settings not updated"
+msgstr "Ustawienia segmentu nie zostały zaktualizowane"
+
+#: routes/segments.js:206
+msgid "Segment deleted"
+msgstr "Segment usunięty"
+
+#: routes/segments.js:208
+msgid "Could not delete specified segment"
+msgstr "Nie można usunąć określonego segmentu"
+
+#: routes/segments.js:342
+msgid "Could not create rule"
+msgstr "Nie można utworzyć reguły"
+
+#: routes/segments.js:345
+msgid "Rule created"
+msgstr "Dodano regułę"
+
+#: routes/segments.js:410
+msgid "Rule settings updated"
+msgstr "Zaktualizowano ustawienia reguły"
+
+#: routes/segments.js:412
+msgid "Rule settings not updated"
+msgstr "Nie zaktualizowano ustawień reguły"
+
+#: routes/segments.js:428
+msgid "Rule deleted"
+msgstr "Usunięto regułę"
+
+#: routes/segments.js:430
+msgid "Could not delete specified rule"
+msgstr "Nie można usunąć określonej reguły"
+
+#: routes/settings.js:39
+msgid "Use TLS"
+msgstr "Użyj TLS"
+
+#: routes/settings.js:40
+msgid "usually selected for port 465"
+msgstr "zazwyczaj wybierany port 465"
+
+#: routes/settings.js:44
+msgid "Use STARTTLS"
+msgstr "Użyj STARTTLS"
+
+#: routes/settings.js:45
+msgid "usually selected for port 587 and 25"
+msgstr "zazwyczaj wybierany port 587 i 25"
+
+#: routes/settings.js:49
+msgid "Do not use encryption"
+msgstr "Nie używaj szyfrowania"
+
+#: routes/settings.js:115
+msgid "Settings updated"
+msgstr "Zaktualizowano ustawienia"
+
+#: routes/settings.js:173
+msgid "Invalid mail transport type"
+msgstr "Nieprawidłowy typ transportu poczty"
+
+#: routes/settings.js:184
+msgid "Invalid Access Key"
+msgstr "Nieprawidłowy klucz dostępu"
+
+#: routes/settings.js:187
+msgid "Invalid AWS credentials"
+msgstr "Nieprawidłowe dane uwierzytelniające AWS"
+
+#: routes/settings.js:190
+msgid "Connection refused, check hostname and port."
+msgstr "Połączenie odrzucone, sprawdź nazwę hosta i port."
+
+#: routes/settings.js:195
+msgid ""
+"Did not receive greeting message from server. This might happen when "
+"connecting to a TLS port without using TLS."
+msgstr ""
+"Nie otrzymano wiadomości powitalnej z serwera. Może się to zdarzyć podczas "
+"łączenia się z portem TLS bez korzystania z TLS."
+
+#: routes/settings.js:197
+msgid "Did not receive greeting message from server."
+msgstr "Nie otrzymano wiadomości powitalnej z serwera."
+
+#: routes/settings.js:200
+msgid ""
+"Connection timed out. Check your firewall settings, destination port is "
+"probably blocked."
+msgstr ""
+"Przekroczono limit czasu połączenia. Sprawdź ustawienia zapory, port "
+"docelowy jest prawdopodobnie zablokowany."
+
+#: routes/settings.js:205
+msgid "Authentication not accepted, server expects STARTTLS to be used."
+msgstr ""
+"Uwierzytelnianie nie jest akceptowane, serwer oczekuje, że zostanie użyty "
+"STARTTLS."
+
+#: routes/settings.js:207
+msgid "Authentication failed, check username and password."
+msgstr "Uwierzytelnianie nie powiodło się, sprawdź nazwę użytkownika i hasło."
+
+#: routes/settings.js:217
+msgid "Failed Mailer verification."
+msgstr "Weryfikacja Mailera nie powiodła się."
+
+#: routes/settings.js:217
+msgid "Server responded with: \"%s\""
+msgstr "Odpowiedź serwera: \"%s\""
+
+#: routes/settings.js:221
+msgid "Mailer settings verified, ready to send some mail!"
+msgstr "Ustawienia Mailera zweryfikowane, gotowe do wysłania wiadomości!"
+
+#: routes/subscription.js:22
+msgid "Selected subscription not found"
+msgstr "Nie znaleziono wybranej subskrypcji"
+
+#: routes/subscription.js:32 routes/subscription.js:103
+#: routes/subscription.js:141 routes/subscription.js:166
+#: routes/subscription.js:191 routes/subscription.js:232
+#: routes/subscription.js:270 routes/subscription.js:317
+#: routes/subscription.js:339 routes/subscription.js:368
+#: routes/subscription.js:392 routes/subscription.js:424
+msgid "Selected list not found"
+msgstr "Nie znaleziono wybranej listy"
+
+#: routes/subscription.js:78 routes/subscription.js:472
+msgid "%s: Subscription Confirmed"
+msgstr "%s: Potwierdzono subskrypcję"
+
+#: routes/subscription.js:217
+msgid "Email address not set"
+msgstr "Adres e-mail nie jest ustawiony"
+
+#: routes/subscription.js:255
+msgid "Could not store confirmation data"
+msgstr "Nie można zapisać danych potwierdzających"
+
+#: routes/subscription.js:284 routes/subscription.js:349
+#: routes/subscription.js:402
+msgid "Subscription not found from this list"
+msgstr "Nie znaleziono subskrypcji z tej listy"
+
+#: routes/subscription.js:383
+msgid "Email address updated, check your mailbox for verification instructions"
+msgstr ""
+"Adres e-mail zaktualizowany, sprawdź skrzynkę pocztową, aby uzyskać "
+"instrukcje dotyczące weryfikacji"
+
+#: routes/subscription.js:499 routes/subscription.js:515
+msgid "Public key is not set"
+msgstr "Klucz publiczny nie jest ustawiony"
+
+#: routes/templates.js:98
+msgid "Could not create template"
+msgstr "Nie można utworzyć szablonu"
+
+#: routes/templates.js:101
+msgid "Template created"
+msgstr "Szablon utworzony"
+
+#: routes/templates.js:109
+msgid "Could not find template with specified ID"
+msgstr "Nie można znaleźć szablonu z określonym ID"
+
+#: routes/templates.js:140
+msgid "Template settings updated"
+msgstr "Zaktualizowano ustawienia szablonu"
+
+#: routes/templates.js:142
+msgid "Template settings not updated"
+msgstr "Ustawienia szablonów nie zostały zaktualizowane"
+
+#: routes/templates.js:158
+msgid "Template deleted"
+msgstr "Szablon usunięty"
+
+#: routes/templates.js:160
+msgid "Could not delete specified template"
+msgstr "Nie można usunąć określonego szablonu"
+
+#: routes/triggers.js:62 routes/triggers.js:79 routes/triggers.js:154
+msgid "Could not find selected list"
+msgstr "Nie można znaleźć wybranej listy"
+
+#: routes/triggers.js:131
+msgid "Could not create trigger"
+msgstr "Nie można utworzyć wyzwalacza"
+
+#: routes/triggers.js:138
+msgid "Trigger “%s” created"
+msgstr "Wyzwalacz “%s” został utworzony"
+
+#: routes/triggers.js:214
+msgid "Trigger settings updated"
+msgstr "Zaktualizowano ustawienia wyzwalacza"
+
+#: routes/triggers.js:216
+msgid "Trigger settings not updated"
+msgstr "Ustawienia wyzwalacza nie zostały zaktualizowane"
+
+#: routes/triggers.js:228
+msgid "Trigger deleted"
+msgstr "Wyzwalacz został usunięty"
+
+#: routes/triggers.js:230
+msgid "Could not delete specified trigger"
+msgstr "Nie można usunąć określonego wyzwalacza"
+
+#: routes/triggers.js:242
+msgid "Could not find trigger with specified ID"
+msgstr "Nie można znaleźć wyzwalacza z określonym ID"
+
+#: routes/triggers.js:255
+msgid "Trigger not found"
+msgstr "Wyzwalacz nie został znaleziony"
+
+#: routes/users.js:32
+msgid ""
+"An email with password reset instructions has been sent to your email "
+"address, if it exists on our system."
+msgstr ""
+"E-mail z instrukcjami resetowania hasła został wysłany na Twój adres e-mail, "
+"jeśli istnieje w naszym systemie."
+
+#: routes/users.js:46 routes/users.js:64
+msgid "Unknown or expired reset token"
+msgstr "Token resetowania nieznany lub wygasł"
+
+#: routes/users.js:66
+msgid "Your password has been changed successfully"
+msgstr "Twoje hasło zostało zmienione"
+
+#: routes/users.js:87
+msgid "User data not found"
+msgstr "Nie znaleziono danych użytkownika"
+
+#: routes/users.js:110
+msgid "Access token updated"
+msgstr "Zaktualizowano token dostępu"
+
+#: routes/users.js:112
+msgid "Access token not updated"
+msgstr "Nie zaktualizowano tokenu dostępu"
+
+#: routes/users.js:139
+msgid "Account information updated"
+msgstr "Informacje o koncie zostały zaktualizowane"
+
+#: routes/users.js:141
+msgid "Account information not updated"
+msgstr "Informacje o koncie nie zostały zaktualizowane"
+
+#: services/feedcheck.js:51
+msgid "Feed error: %s"
+msgstr "RSS błąd: %s"
+
+#: services/feedcheck.js:54
+msgid "Found %s new campaign messages from feed"
+msgstr "Znaleziono %s nowych wiadomości kampanii z kanału"
+
+#: services/feedcheck.js:56
+msgid "Found nothing new from the feed"
+msgstr "Nie znaleziono nic nowego w kanale"
+
+#: services/feedcheck.js:143
+msgid "RSS entry %s"
+msgstr "Wpis RSS %s"
+
+#: services/importer.js:243
+msgid "Could not access import file"
+msgstr "Nie można uzyskać dostępu do pliku importu"
+
+#: services/triggers.js:51
+msgid "Unknown trigger type %s"
+msgstr "Nieznany typ wyzwalacza %s"
+
+#: views/subscription/widget-subscribe.hbs:3
+msgid "It looks like you are already subscribed to this list."
+msgstr "Wygląda na to, że już jesteś zapisany/a."
diff --git a/lib/db.js b/lib/db.js
index 2c3a7b21..44f17b0f 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -2,5 +2,113 @@
let config = require('config');
let mysql = require('mysql');
+let redis = require('redis');
+let Lock = require('redfour');
+let stringifyDate = require('json-stringify-date');
+let tools = require('./tools');
module.exports = mysql.createPool(config.mysql);
+if (config.redis && config.redis.enabled) {
+
+ module.exports.redis = redis.createClient(config.redis);
+
+ let queueLock = new Lock({
+ redis: config.redis,
+ namespace: 'mailtrain:lock'
+ });
+
+ module.exports.getLock = (id, callback) => {
+ queueLock.waitAcquireLock(id, 60 * 1000 /* Lock expires after 60sec */ , 10 * 1000 /* Wait for lock for up to 10sec */ , (err, lock) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!lock) {
+ return callback(null, false);
+ }
+ return callback(null, {
+ lock,
+ release(done) {
+ queueLock.releaseLock(lock, done);
+ }
+ });
+ });
+ };
+
+ module.exports.clearCache = (key, callback) => {
+ module.exports.redis.del('mailtrain:cache:' + key, err => callback(err));
+ };
+
+ module.exports.addToCache = (key, value, callback) => {
+ if (!value) {
+ return setImmediate(() => callback());
+ }
+ module.exports.redis.multi().
+ lpush('mailtrain:cache:' + key, stringifyDate.stringify(value)).
+ expire('mailtrain:cache:' + key, 24 * 3600).
+ exec(err => callback(err));
+ };
+
+ module.exports.getFromCache = (key, callback) => {
+ module.exports.redis.rpop('mailtrain:cache:' + key, (err, value) => {
+ if (err) {
+ return callback(err);
+ }
+ try {
+ value = stringifyDate.parse(value);
+ } catch (E) {
+ return callback(E);
+ }
+
+ return callback(null, value);
+ });
+ };
+
+} else {
+ // fakelock. does not lock anything
+ module.exports.getLock = (id, callback) => {
+ setImmediate(() => callback(null, {
+ lock: false,
+ release(done) {
+ setImmediate(done);
+ }
+ }));
+ };
+
+ let caches = new Map();
+
+ module.exports.clearCache = (key, callback) => {
+ caches.delete(key);
+ tools.workers.forEach(child => {
+ child.send({
+ cmd: 'db.clearCache',
+ key
+ });
+ });
+ setImmediate(() => callback());
+ };
+
+ process.on('message', m => {
+ if (m && m.cmd === 'db.clearCache' && m.key) {
+ caches.delete(m.key);
+ }
+ });
+
+ module.exports.addToCache = (key, value, callback) => {
+ if (!caches.has(key)) {
+ caches.set(key, []);
+ }
+ caches.get(key).push(value);
+ setImmediate(() => callback());
+ };
+
+ module.exports.getFromCache = (key, callback) => {
+ let value;
+ if (caches.has(key)) {
+ value = caches.get(key).shift();
+ if (!caches.get(key).length) {
+ caches.delete(key);
+ }
+ }
+ setImmediate(() => callback(null, value));
+ };
+}
diff --git a/lib/dbcheck.js b/lib/dbcheck.js
index 30b13b0c..93264800 100644
--- a/lib/dbcheck.js
+++ b/lib/dbcheck.js
@@ -21,10 +21,10 @@ let db = mysql.createPool(mysqlConfig);
function listTables(callback) {
db.getConnection((err, connection) => {
if (err) {
- if(err.code === 'ER_ACCESS_DENIED_ERROR'){
+ if (err.code === 'ER_ACCESS_DENIED_ERROR') {
err = new Error('Could not access the database. Check MySQL config and authentication credentials');
}
- if(err.code === 'ECONNREFUSED' || err.code === 'PROTOCOL_SEQUENCE_TIMEOUT'){
+ if (err.code === 'ECONNREFUSED' || err.code === 'PROTOCOL_SEQUENCE_TIMEOUT') {
err = new Error('Could not connect to the database. Check MySQL host and port configuration');
}
return callback(err);
@@ -107,13 +107,14 @@ function getSql(path, data, callback) {
if (err) {
return callback(err);
}
- let renderer = Handlebars.compile(source);
- return callback(null, renderer(data || {}));
+ const rendered = data ? Handlebars.compile(source)(data) : source;
+ return callback(null, rendered);
});
}
function runInitial(callback) {
- let fname = process.env.DB_FROM_START ? 'base.sql' : 'mailtrain.sql';
+ let dump = process.env.NODE_ENV === 'test' ? 'mailtrain-test.sql' : 'mailtrain.sql';
+ let fname = process.env.DB_FROM_START ? 'base.sql' : dump;
let path = pathlib.join(__dirname, '..', 'setup', 'sql', fname);
log.info('sql', 'Loading tables from %s', fname);
applyUpdate({
diff --git a/lib/editor-helpers.js b/lib/editor-helpers.js
new file mode 100644
index 00000000..e4c4e79f
--- /dev/null
+++ b/lib/editor-helpers.js
@@ -0,0 +1,79 @@
+'use strict';
+
+let _ = require('../lib/translate')._;
+let helpers = require('../lib/helpers');
+let templates = require('../lib/models/templates');
+let campaigns = require('../lib/models/campaigns');
+
+module.exports = {
+ getResource,
+ getMergeTagsForResource
+};
+
+function getResource(type, id, callback) {
+ if (type === 'template') {
+ templates.get(id, (err, template) => {
+ if (err || !template) {
+ return callback(err && err.message || err || _('Could not find template with specified ID'));
+ }
+
+ getMergeTagsForResource(template, (err, mergeTags) => {
+ if (err) {
+ return callback(err.message || err);
+ }
+
+ template.mergeTags = mergeTags;
+ return callback(null, template);
+ });
+ });
+
+ } else if (type === 'campaign') {
+ campaigns.get(id, false, (err, campaign) => {
+ if (err || !campaign) {
+ return callback(err && err.message || err || _('Could not find campaign with specified ID'));
+ }
+
+ getMergeTagsForResource(campaign, (err, mergeTags) => {
+ if (err) {
+ return callback(err.message || err);
+ }
+
+ campaign.mergeTags = mergeTags;
+ return callback(null, campaign);
+ });
+ });
+
+ } else {
+ return callback(_('Invalid resource type'));
+ }
+}
+
+function getMergeTagsForResource(resource, callback) {
+ helpers.getDefaultMergeTags((err, defaultMergeTags) => {
+ if (err) {
+ return callback(err.message || err);
+ }
+
+ if (!Number(resource.list)) {
+ return callback(null, defaultMergeTags);
+ }
+
+ helpers.getListMergeTags(resource.list, (err, listMergeTags) => {
+ if (err) {
+ return callback(err.message || err);
+ }
+
+ if (resource.type !== 2) {
+ return callback(null, defaultMergeTags.concat(listMergeTags));
+ }
+
+ helpers.getRSSMergeTags((err, rssMergeTags) => {
+ if (err) {
+ return callback(err.message || err);
+ }
+
+ callback(null, defaultMergeTags.concat(listMergeTags, rssMergeTags));
+ });
+ });
+ });
+}
diff --git a/lib/executor.js b/lib/executor.js
new file mode 100644
index 00000000..1cf1d959
--- /dev/null
+++ b/lib/executor.js
@@ -0,0 +1,83 @@
+'use strict';
+
+const fork = require('child_process').fork;
+const log = require('npmlog');
+const path = require('path');
+
+const requestCallbacks = {};
+let messageTid = 0;
+let executorProcess;
+
+module.exports = {
+ spawn,
+ start,
+ stop
+};
+
+function spawn(callback) {
+ log.info('Executor', 'Spawning executor process.');
+
+ executorProcess = fork(path.join(__dirname, '..', 'services', 'executor.js'), [], {
+ cwd: path.join(__dirname, '..'),
+ env: {NODE_ENV: process.env.NODE_ENV}
+ });
+
+ executorProcess.on('message', msg => {
+ if (msg) {
+ if (msg.type === 'process-started') {
+ let requestCallback = requestCallbacks[msg.tid];
+ if (requestCallback && requestCallback.startedCallback) {
+ requestCallback.startedCallback(msg.tid);
+ }
+
+ } else if (msg.type === 'process-failed') {
+ let requestCallback = requestCallbacks[msg.tid];
+ if (requestCallback && requestCallback.failedCallback) {
+ requestCallback.failedCallback(msg.msg);
+ }
+
+ delete requestCallbacks[msg.tid];
+
+ } else if (msg.type === 'process-finished') {
+ let requestCallback = requestCallbacks[msg.tid];
+ if (requestCallback && requestCallback.startedCallback) {
+ requestCallback.finishedCallback(msg.code, msg.signal);
+ }
+
+ delete requestCallbacks[msg.tid];
+
+ } else if (msg.type === 'executor-started') {
+ log.info('Executor', 'Executor process started.');
+ return callback();
+ }
+ }
+ });
+
+ executorProcess.on('close', (code, signal) => {
+ log.info('Executor', 'Executor process exited with code %s signal %s.', code, signal);
+ });
+}
+
+function start(type, data, startedCallback, finishedCallback, failedCallback) {
+ requestCallbacks[messageTid] = {
+ startedCallback,
+ finishedCallback,
+ failedCallback
+ };
+
+ executorProcess.send({
+ type: 'start-' + type,
+ data,
+ tid: messageTid
+ });
+
+ messageTid++;
+}
+
+function stop(tid) {
+ executorProcess.send({
+ type: 'stop-process',
+ tid
+ });
+}
+
diff --git a/lib/fakelang.js b/lib/fakelang.js
new file mode 100644
index 00000000..7a6027a1
--- /dev/null
+++ b/lib/fakelang.js
@@ -0,0 +1,26 @@
+'use strict';
+
+/* lloyd|2012|http://wtfpl.org */
+
+/* eslint-disable */
+
+module.exports = str => {
+ let from = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+\\|`~[{]};:'\",<.>/?";
+ let to = "ɐqɔpǝɟƃɥıɾʞʅɯuodbɹsʇnʌʍxʎz∀ԐↃᗡƎℲ⅁HIſӼ⅂WNOԀÒᴚS⊥∩ɅMX⅄Z0123456789¡@#$%ᵥ⅋⁎()-_=+\\|,~[{]};:,„´<.>/¿";
+
+ return str.replace(/(\{\{[^\}]+\}\}|%s)/g, '\x00\x04$1\x00').split('\x00').map(c => {
+ if (c.charAt(0) === '\x04') {
+ return c;
+ }
+ let r = '';
+ for (let i = 0, len = c.length; i < len; i++) {
+ let pos = from.indexOf(c.charAt(i));
+ if (pos < 0) {
+ r += c.charAt(i);
+ } else {
+ r += to.charAt(pos);
+ }
+ }
+ return r;
+ }).join('\x00').replace(/[\x00\x04]/g, '');
+}
diff --git a/lib/feed.js b/lib/feed.js
new file mode 100644
index 00000000..66bd2f20
--- /dev/null
+++ b/lib/feed.js
@@ -0,0 +1,68 @@
+'use strict';
+
+let FeedParser = require('feedparser');
+let request = require('request');
+let _ = require('./translate')._;
+let util = require('util');
+
+module.exports.fetch = (url, callback) => {
+ let req = request(url);
+ let feedparser = new FeedParser();
+ let returned = false;
+ let entries = [];
+
+ req.setHeader('user-agent', 'Mailtrain');
+ req.setHeader('accept', 'text/html,application/xhtml+xml');
+
+ req.on('error', err => {
+ if (returned) {
+ return;
+ }
+ returned = true;
+ callback(err);
+ });
+
+ req.on('response', res => {
+ if (returned) {
+ return;
+ }
+
+ if (res.statusCode !== 200) {
+ return req.emit('error', new Error(util.format(_('Bad status code %s'), res.statusCode)));
+ }
+
+ req.pipe(feedparser);
+ });
+
+ feedparser.on('error', err => {
+ if (returned) {
+ return;
+ }
+ returned = true;
+ callback(err);
+ });
+
+ feedparser.on('readable', () => {
+ let item;
+ while ((item = feedparser.read())) {
+ let entry = {
+ title: item.title,
+ date: item.date || item.pubdate || item.pubDate || new Date(),
+ guid: item.guid || item.link,
+ link: item.link,
+ content: item.description || item.summary,
+ summary: item.summary || item.description,
+ image_url: item.image.url
+ };
+ entries.push(entry);
+ }
+ });
+
+ feedparser.on('end', () => {
+ if (returned) {
+ return;
+ }
+ returned = true;
+ callback(null, entries);
+ });
+};
diff --git a/lib/file-helpers.js b/lib/file-helpers.js
new file mode 100644
index 00000000..deee31e1
--- /dev/null
+++ b/lib/file-helpers.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const path = require('path');
+
+function nameToFileName(name) {
+ return name.
+ trim().
+ toLowerCase().
+ replace(/[ .+/]/g, '-').
+ replace(/[^a-z0-9\-_]/gi, '').
+ replace(/--*/g, '-');
+}
+
+
+function getReportFileBase(report) {
+ return path.join(__dirname, '..', 'protected', 'reports', report.id + '-' + nameToFileName(report.name));
+}
+
+function getReportContentFile(report) {
+ return getReportFileBase(report) + '.out';
+}
+
+function getReportOutputFile(report) {
+ return getReportFileBase(report) + '.err';
+}
+
+
+module.exports = {
+ getReportContentFile,
+ getReportOutputFile,
+ nameToFileName
+};
diff --git a/lib/handlebars-helpers.js b/lib/handlebars-helpers.js
new file mode 100644
index 00000000..10a38741
--- /dev/null
+++ b/lib/handlebars-helpers.js
@@ -0,0 +1,49 @@
+'use strict';
+
+const util = require('util');
+
+const _ = require('../lib/translate')._;
+
+module.exports.registerHelpers = handlebars => {
+ // {{#translate}}abc{{/translate}}
+ handlebars.registerHelper('translate', function (context, options) { // eslint-disable-line prefer-arrow-callback
+ if (typeof options === 'undefined' && context) {
+ options = context;
+ context = false;
+ }
+
+ let result = _(options.fn(this)); // eslint-disable-line no-invalid-this
+
+ if (Array.isArray(context)) {
+ result = util.format(result, ...context);
+ }
+ return new handlebars.SafeString(result);
+ });
+
+
+ /* Credits to http://chrismontrois.net/2016/01/30/handlebars-switch/
+
+ {{#switch letter}}
+ {{#case "a"}}
+ A is for alpaca
+ {{/case}}
+ {{#case "b"}}
+ B is for bluebird
+ {{/case}}
+ {{/switch}}
+ */
+ /* eslint no-invalid-this: "off" */
+ handlebars.registerHelper('switch', function(value, options) {
+ this._switch_value_ = value;
+ const html = options.fn(this); // Process the body of the switch block
+ delete this._switch_value_;
+ return html;
+ });
+
+ handlebars.registerHelper('case', function(value, options) {
+ if (value === this._switch_value_) {
+ return options.fn(this);
+ }
+ });
+
+};
diff --git a/lib/helpers.js b/lib/helpers.js
new file mode 100644
index 00000000..786e3473
--- /dev/null
+++ b/lib/helpers.js
@@ -0,0 +1,295 @@
+'use strict';
+
+let config = require('config');
+let path = require('path');
+let fs = require('fs');
+let tools = require('./tools');
+let settings = require('./models/settings');
+let lists = require('./models/lists');
+let fields = require('./models/fields');
+let forms = require('./models/forms');
+let _ = require('./translate')._;
+let objectHash = require('object-hash');
+let mjml = require('mjml');
+let mjmlTemplates = new Map();
+let hbs = require('hbs');
+
+module.exports = {
+ getDefaultMergeTags,
+ getRSSMergeTags,
+ getListMergeTags,
+ captureFlashMessages,
+ injectCustomFormData,
+ injectCustomFormTemplates,
+ filterCustomFields,
+ getMjmlTemplate,
+ rollbackAndReleaseConnection
+};
+
+function getDefaultMergeTags(callback) {
+ // Using a callback for the sake of future-proofness
+ callback(null, [{
+ key: 'LINK_UNSUBSCRIBE',
+ value: _('URL that points to the unsubscribe page')
+ }, {
+ key: 'LINK_PREFERENCES',
+ value: _('URL that points to the preferences page of the subscriber')
+ }, {
+ key: 'LINK_BROWSER',
+ value: _('URL to preview the message in a browser')
+ }, {
+ key: 'EMAIL',
+ value: _('Email address')
+ }, {
+ key: 'FIRST_NAME',
+ value: _('First name')
+ }, {
+ key: 'LAST_NAME',
+ value: _('Last name')
+ }, {
+ key: 'FULL_NAME',
+ value: _('Full name (first and last name combined)')
+ }, {
+ key: 'SUBSCRIPTION_ID',
+ value: _('Unique ID that identifies the recipient')
+ }, {
+ key: 'LIST_ID',
+ value: _('Unique ID that identifies the list used for this campaign')
+ }, {
+ key: 'CAMPAIGN_ID',
+ value: _('Unique ID that identifies current campaign')
+ }]);
+}
+
+function getRSSMergeTags(callback) {
+ // Using a callback for the sake of future-proofness
+ callback(null, [{
+ key: 'RSS_ENTRY',
+ value: _('content from an RSS entry')
+ }, {
+ key: 'RSS_ENTRY_TITLE',
+ value: _('RSS entry title')
+ }, {
+ key: 'RSS_ENTRY_DATE',
+ value: _('RSS entry date')
+ }, {
+ key: 'RSS_ENTRY_LINK',
+ value: _('RSS entry link')
+ }, {
+ key: 'RSS_ENTRY_CONTENT',
+ value: _('content from an RSS entry')
+ }, {
+ key: 'RSS_ENTRY_SUMMARY',
+ value: _('RSS entry summary')
+ }, {
+ key: 'RSS_ENTRY_IMAGE_URL',
+ value: _('RSS entry image URL')
+ }]);
+}
+
+function getListMergeTags(listId, callback) {
+ lists.get(listId, (err, list) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!list) {
+ list = {
+ id: listId
+ };
+ }
+
+ fields.list(list.id, (err, fieldList) => {
+ if (err && !fieldList) {
+ fieldList = [];
+ }
+
+ let mergeTags = [];
+
+ fieldList.forEach(field => {
+ mergeTags.push({
+ key: field.key,
+ value: field.name
+ });
+ });
+
+ return callback(null, mergeTags);
+ });
+ });
+}
+
+function filterCustomFields(customFieldsIn = [], fieldIds = [], method = 'include') {
+ let customFields = customFieldsIn.slice();
+ fieldIds = typeof fieldIds === 'string' ? fieldIds.split(',') : fieldIds;
+
+ customFields.unshift({
+ id: 'email',
+ name: 'Email Address',
+ type: 'Email',
+ typeSubscriptionEmail: true
+ }, {
+ id: 'firstname',
+ name: 'First Name',
+ type: 'Text',
+ typeFirstName: true
+ }, {
+ id: 'lastname',
+ name: 'Last Name',
+ type: 'Text',
+ typeLastName: true
+ });
+
+ let filtered = [];
+
+ if (method === 'include') {
+ fieldIds.forEach(id => {
+ let field = customFields.find(f => f.id.toString() === id);
+ field && filtered.push(field);
+ });
+ } else {
+ customFields.forEach(field => {
+ !fieldIds.includes(field.id.toString()) && filtered.push(field);
+ });
+ }
+
+ return filtered;
+}
+
+function injectCustomFormData(customFormId, viewPath, data, callback) {
+
+ let injectDefaultData = data => {
+ data.customFields = filterCustomFields(data.customFields, [], 'exclude');
+ data.formInputStyle = '@import url(/subscription/form-input-style.css);';
+ return data;
+ };
+
+ if (Number(customFormId) < 1) {
+ return callback(null, injectDefaultData(data));
+ }
+
+ forms.get(customFormId, (err, form) => {
+ if (err) {
+ return callback(null, injectDefaultData(data));
+ }
+
+ let view = viewPath.split('/')[1];
+
+ if (view === 'web-subscribe') {
+ data.customFields = form.fieldsShownOnSubscribe
+ ? filterCustomFields(data.customFields, form.fieldsShownOnSubscribe)
+ : filterCustomFields(data.customFields, [], 'exclude');
+ } else if (view === 'web-manage') {
+ data.customFields = form.fieldsShownOnManage
+ ? filterCustomFields(data.customFields, form.fieldsShownOnManage)
+ : filterCustomFields(data.customFields, [], 'exclude');
+ }
+
+ let key = tools.fromDbKey(view);
+ data.template.template = form[key] || data.template.template;
+ data.template.layout = form.layout || data.template.layout;
+ data.formInputStyle = form.formInputStyle || '@import url(/subscription/form-input-style.css);';
+
+ settings.list(['ua_code'], (err, configItems) => {
+ if (err) {
+ return callback(err);
+ }
+
+ data.uaCode = configItems.uaCode;
+ data.customSubscriptionScripts = config.customsubscriptionscripts || [];
+ callback(null, data);
+ });
+ });
+}
+
+function injectCustomFormTemplates(customFormId, templates, callback) {
+ if (Number(customFormId) < 1) {
+ return callback(null, templates);
+ }
+
+ forms.get(customFormId, (err, form) => {
+ if (err) {
+ return callback(null, templates);
+ }
+
+ let lookUp = name => {
+ let key = tools.fromDbKey(
+ /subscription\/([^.]*)/.exec(name)[1]
+ );
+ return form[key] || name;
+ };
+
+ Object.keys(templates).forEach(key => {
+ let value = templates[key];
+
+ if (typeof value === 'string') {
+ templates[key] = lookUp(value);
+ }
+ if (typeof value === 'object' && value.template) {
+ templates[key].template = lookUp(value.template);
+ }
+ if (typeof value === 'object' && value.layout) {
+ templates[key].layout = lookUp(value.layout);
+ }
+ });
+
+ callback(null, templates);
+ });
+}
+
+function getMjmlTemplate(template, callback) {
+ if (!template) {
+ return callback(null, false);
+ }
+
+ let key = (typeof template === 'object') ? objectHash(template) : template;
+
+ if (mjmlTemplates.has(key)) {
+ return callback(null, mjmlTemplates.get(key));
+ }
+
+ let done = source => {
+ let compiled;
+ try {
+ compiled = mjml.mjml2html(source);
+ } catch (err) {
+ return callback(err);
+ }
+ if (compiled.errors.length) {
+ return callback(compiled.errors[0].message || compiled.errors[0]);
+ }
+ let renderer = hbs.handlebars.compile(compiled.html);
+ mjmlTemplates.set(key, renderer);
+ callback(null, renderer);
+ };
+
+ if (typeof template === 'object') {
+ tools.mergeTemplateIntoLayout(template.template, template.layout, (err, source) => {
+ if (err) {
+ return callback(err);
+ }
+ done(source);
+ });
+ } else {
+ fs.readFile(path.join(__dirname, '..', 'views', template), 'utf-8', (err, source) => {
+ if (err) {
+ return callback(err);
+ }
+ done(source);
+ });
+ }
+}
+
+function captureFlashMessages(req, res, callback) {
+ res.render('subscription/capture-flash-messages', { layout: null }, (err, flash) => {
+ if (err) {
+ return callback(err);
+ }
+ callback(null, flash);
+ });
+}
+
+function rollbackAndReleaseConnection(connection, callback) {
+ connection.rollback(() => {
+ connection.release();
+ return callback();
+ });
+}
diff --git a/lib/mailer.js b/lib/mailer.js
index 9ac3f861..4ef5ad0a 100644
--- a/lib/mailer.js
+++ b/lib/mailer.js
@@ -1,15 +1,37 @@
'use strict';
let log = require('npmlog');
-
+let config = require('config');
let nodemailer = require('nodemailer');
let openpgpEncrypt = require('nodemailer-openpgp').openpgpEncrypt;
let settings = require('./models/settings');
+let tools = require('./tools');
+let db = require('./db');
let Handlebars = require('handlebars');
let fs = require('fs');
let path = require('path');
let templates = new Map();
let htmlToText = require('html-to-text');
+let aws = require('aws-sdk');
+let objectHash = require('object-hash');
+let mjml = require('mjml');
+
+let _ = require('./translate')._;
+let util = require('util');
+
+Handlebars.registerHelper('translate', function (context, options) { // eslint-disable-line prefer-arrow-callback
+ if (typeof options === 'undefined' && context) {
+ options = context;
+ context = false;
+ }
+
+ let result = _(options.fn(this)); // eslint-disable-line no-invalid-this
+
+ if (Array.isArray(context)) {
+ result = util.format(result, ...context);
+ }
+ return new Handlebars.SafeString(result);
+});
module.exports.transport = false;
@@ -39,6 +61,11 @@ module.exports.sendMail = (mail, template, callback) => {
});
}
+ if (!mail.headers) {
+ mail.headers = {};
+ }
+ mail.headers['X-Sending-Zone'] = 'transactional';
+
getTemplate(template.html, (err, htmlRenderer) => {
if (err) {
return callback(err);
@@ -48,20 +75,47 @@ module.exports.sendMail = (mail, template, callback) => {
mail.html = htmlRenderer(template.data || {});
}
- getTemplate(template.text, (err, textRenderer) => {
+ tools.prepareHtml(mail.html, (err, prepareHtml) => {
if (err) {
- return callback(err);
+ // ignore
}
- if (textRenderer) {
- mail.text = textRenderer(template.data || {});
- } else if (mail.html) {
- mail.text = htmlToText.fromString(mail.html, {
- wordwrap: 130
- });
+ if (prepareHtml) {
+ mail.html = prepareHtml;
}
- module.exports.transport.sendMail(mail, callback);
+ getTemplate(template.text, (err, textRenderer) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (textRenderer) {
+ mail.text = textRenderer(template.data || {});
+ } else if (mail.html) {
+ mail.text = htmlToText.fromString(mail.html, {
+ wordwrap: 130
+ });
+ }
+
+ let tryCount = 0;
+ let trySend = () => {
+ tryCount++;
+
+ module.exports.transport.sendMail(mail, (err, info) => {
+ if (err) {
+ log.error('Mail', err);
+ if (err.responseCode && err.responseCode >= 400 && err.responseCode < 500 && tryCount <= 5) {
+ // temporary error, try again
+ log.verbose('Mail', 'Retrying after %s sec. ...', tryCount);
+ return setTimeout(trySend, tryCount * 1000);
+ }
+ return callback(err);
+ }
+ return callback(null, info);
+ });
+ };
+ setImmediate(trySend);
+ });
});
});
@@ -72,53 +126,171 @@ function getTemplate(template, callback) {
return callback(null, false);
}
- if (templates.has(template)) {
- return callback(null, templates.get(template));
+ let key = (typeof template === 'object') ? objectHash(template) : template;
+
+ if (templates.has(key)) {
+ return callback(null, templates.get(key));
}
- fs.readFile(path.join(__dirname, '..', 'views', template), 'utf-8', (err, source) => {
- if (err) {
- return callback(err);
+ let done = (source, isMjml = false) => {
+ if (isMjml) {
+ let compiled;
+ try {
+ compiled = mjml.mjml2html(source);
+ } catch (err) {
+ return callback(err);
+ }
+ if (compiled.errors.length) {
+ return callback(compiled.errors[0].message || compiled.errors[0]);
+ }
+ source = compiled.html;
}
let renderer = Handlebars.compile(source);
- templates.set(template, renderer);
- return callback(null, renderer);
- });
+ templates.set(key, renderer);
+ callback(null, renderer);
+ };
+
+ if (typeof template === 'object') {
+ tools.mergeTemplateIntoLayout(template.template, template.layout, (err, source) => {
+ if (err) {
+ return callback(err);
+ }
+ let isMjml = template.type === 'mjml';
+ done(source, isMjml);
+ });
+ } else {
+ fs.readFile(path.join(__dirname, '..', 'views', template), 'utf-8', (err, source) => {
+ if (err) {
+ return callback(err);
+ }
+ done(source);
+ });
+ }
}
function createMailer(callback) {
- settings.list(['smtpHostname', 'smtpPort', 'smtpEncryption', 'smtpUser', 'smtpPass', 'smtpLog', 'smtpDisableAuth', 'smtpMaxConnections', 'smtpMaxMessages', 'smtpSelfSigned', 'pgpPrivateKey', 'pgpPassphrase'], (err, configItems) => {
+ settings.list(['smtpHostname', 'smtpPort', 'smtpEncryption', 'smtpUser', 'smtpPass', 'smtpLog', 'smtpDisableAuth', 'smtpMaxConnections', 'smtpMaxMessages', 'smtpSelfSigned', 'pgpPrivateKey', 'pgpPassphrase', 'smtpThrottling', 'mailTransport', 'sesKey', 'sesSecret', 'sesRegion'], (err, configItems) => {
if (err) {
return callback(err);
}
- module.exports.transport = nodemailer.createTransport({
- pool: true,
- host: configItems.smtpHostname,
- port: Number(configItems.smtpPort) || false,
- secure: configItems.smtpEncryption === 'TLS',
- ignoreTLS: configItems.smtpEncryption === 'NONE',
- auth: configItems.smtpDisableAuth ? false : {
- user: configItems.smtpUser,
- pass: configItems.smtpPass
- },
- debug: !!configItems.smtpLog,
- logger: !configItems.smtpLog ? false : {
- debug: log.info.bind(log, 'Mail'),
- info: log.verbose.bind(log, 'Mail'),
- error: log.info.bind(log, 'Mail')
- },
- maxConnections: Number(configItems.smtpMaxConnections),
- maxMessages: Number(configItems.smtpMaxMessages),
- tls: {
- rejectUnauthorized: !configItems.smtpSelfSigned
- }
- });
+
+ let oldListeners = [];
+ if (module.exports.transport) {
+ oldListeners = module.exports.transport.listeners('idle');
+ module.exports.transport.removeAllListeners('idle');
+ module.exports.transport.removeAllListeners('stream');
+ module.exports.transport.checkThrottling = null;
+ }
+
+ let sendingRate = Number(configItems.smtpThrottling) || 0;
+ if (sendingRate) {
+ // convert to messages/second
+ sendingRate = sendingRate / 3600;
+ }
+
+ let transportOptions;
+
+ let logfunc = function () {
+ let args = [].slice.call(arguments);
+ let level = args.shift();
+ args.shift();
+ args.unshift('Mail');
+ log[level](...args);
+ };
+
+ if (configItems.mailTransport === 'smtp' || !configItems.mailTransport) {
+ transportOptions = {
+ pool: true,
+ host: configItems.smtpHostname,
+ port: Number(configItems.smtpPort) || false,
+ secure: configItems.smtpEncryption === 'TLS',
+ ignoreTLS: configItems.smtpEncryption === 'NONE',
+ auth: configItems.smtpDisableAuth ? false : {
+ user: configItems.smtpUser,
+ pass: configItems.smtpPass
+ },
+ debug: !!configItems.smtpLog,
+ logger: !configItems.smtpLog ? false : {
+ debug: logfunc.bind(null, 'verbose'),
+ info: logfunc.bind(null, 'info'),
+ error: logfunc.bind(null, 'error')
+ },
+ maxConnections: Number(configItems.smtpMaxConnections),
+ maxMessages: Number(configItems.smtpMaxMessages),
+ tls: {
+ rejectUnauthorized: !configItems.smtpSelfSigned
+ }
+ };
+ } else if (configItems.mailTransport === 'ses') {
+ transportOptions = {
+ SES: new aws.SES({
+ apiVersion: '2010-12-01',
+ accessKeyId: configItems.sesKey,
+ secretAccessKey: configItems.sesSecret,
+ region: configItems.sesRegion
+ }),
+ debug: !!configItems.smtpLog,
+ logger: !configItems.smtpLog ? false : {
+ debug: logfunc.bind(null, 'verbose'),
+ info: logfunc.bind(null, 'info'),
+ error: logfunc.bind(null, 'error')
+ },
+ maxConnections: Number(configItems.smtpMaxConnections),
+ sendingRate,
+ tls: {
+ rejectUnauthorized: !configItems.smtpSelfSigned
+ }
+ };
+ } else {
+ return callback(new Error(_('Invalid mail transport')));
+ }
+
+ module.exports.transport = nodemailer.createTransport(transportOptions, config.nodemailer);
+
module.exports.transport.use('stream', openpgpEncrypt({
signingKey: configItems.pgpPrivateKey,
passphrase: configItems.pgpPassphrase
}));
- return callback(null, module.exports.transport);
+ if (oldListeners.length) {
+ log.info('Mail', 'Reattaching %s idle listeners', oldListeners.length);
+ oldListeners.forEach(listener => module.exports.transport.on('idle', listener));
+ }
+
+
+ if (configItems.mailTransport === 'smtp' || !configItems.mailTransport) {
+
+ let throttling = Number(configItems.smtpThrottling) || 0;
+ if (throttling) {
+ throttling = 1 / (throttling / (3600 * 1000));
+ }
+
+ let lastCheck = Date.now();
+
+ module.exports.transport.checkThrottling = function (next) {
+ if (!throttling) {
+ return next();
+ }
+ let nextCheck = Date.now();
+ let checkDiff = (nextCheck - lastCheck);
+ if (checkDiff < throttling) {
+ log.verbose('Mail', 'Throttling next message in %s sec.', (throttling - checkDiff) / 1000);
+ setTimeout(() => {
+ lastCheck = Date.now();
+ next();
+ }, throttling - checkDiff);
+ } else {
+ lastCheck = nextCheck;
+ next();
+ }
+ };
+ } else {
+ module.exports.transport.checkThrottling = next => next();
+ }
+
+ db.clearCache('sender', () => {
+ callback(null, module.exports.transport);
+ });
});
}
diff --git a/lib/models/blacklist.js b/lib/models/blacklist.js
new file mode 100644
index 00000000..5aae8ccc
--- /dev/null
+++ b/lib/models/blacklist.js
@@ -0,0 +1,86 @@
+'use strict';
+
+let db = require('../db');
+
+module.exports.get = (start, limit, search, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+ search = '%' + search + '%';
+ connection.query('SELECT SQL_CALC_FOUND_ROWS `email` FROM blacklist WHERE `email` LIKE ? ORDER BY `email` LIMIT ? OFFSET ?', [search, limit, start], (err, rows) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ let emails = [];
+ rows.forEach(email => {
+ emails.push(email.email);
+ });
+ return callback(null, emails, total && total[0] && total[0].total);
+ });
+ });
+ });
+};
+
+module.exports.add = (email, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('INSERT IGNORE INTO `blacklist` (`email`) VALUES(?)', email, err => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.release();
+ return callback(null, null);
+
+ });
+ });
+};
+
+module.exports.delete = (email, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('DELETE FROM `blacklist` WHERE `email`=?', email, err => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.release();
+ return callback(null, null);
+
+ });
+ });
+};
+
+module.exports.isblacklisted = (email, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT `email` FROM blacklist WHERE `email`=?', email, (err, rows) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.release();
+ if (rows.length > 0) {
+ return callback(null, true);
+ } else {
+ return callback(null, false);
+ }
+ });
+ });
+};
diff --git a/lib/models/campaigns.js b/lib/models/campaigns.js
index 672541df..2db3a8d8 100644
--- a/lib/models/campaigns.js
+++ b/lib/models/campaigns.js
@@ -7,35 +7,102 @@ let templates = require('./templates');
let segments = require('./segments');
let subscriptions = require('./subscriptions');
let shortid = require('shortid');
+let isUrl = require('is-url');
+let feed = require('../feed');
+let log = require('npmlog');
+let mailer = require('../mailer');
+let humanize = require('humanize');
+let _ = require('../translate')._;
+let util = require('util');
+let tableHelpers = require('../table-helpers');
-let allowedKeys = ['description', 'from', 'address', 'subject', 'template', 'template_url', 'list', 'segment', 'html', 'text'];
+let allowedKeys = ['description', 'from', 'address', 'reply_to', 'subject', 'editor_name', 'editor_data', 'template', 'source_url', 'list', 'segment', 'html', 'text', 'click_tracking_disabled', 'open_tracking_disabled', 'unsubscribe'];
module.exports.list = (start, limit, callback) => {
+ tableHelpers.list('campaigns', ['*'], 'scheduled', null, start, limit, callback);
+};
+
+module.exports.filter = (request, parent, callback) => {
+ let queryData;
+ if (parent) {
+ queryData = {
+ // only find normal and RSS parent campaigns at this point
+ where: '`parent`=?',
+ values: [parent]
+ };
+ } else {
+ queryData = {
+ // only find normal and RSS parent campaigns at this point
+ where: '`type` IN (?,?,?)',
+ values: [1, 2, 4]
+ };
+ }
+
+ tableHelpers.filter('campaigns', ['*'], request, ['#', 'name', 'description', 'status', 'created'], ['name'], 'created DESC', queryData, callback);
+};
+
+module.exports.filterQuicklist = (request, callback) => {
+ tableHelpers.filter('campaigns', ['id', 'name', 'description', 'created'], request, ['#', 'name', 'description', 'created'], ['name'], 'name ASC', null, callback);
+};
+
+module.exports.filterClickedSubscribers = (campaign, linkId, request, columns, callback) => {
+ let queryData = {
+ where: 'campaign_tracker__' + campaign.id + '.list=? AND campaign_tracker__' + campaign.id + '.link=?',
+ values: [campaign.list, linkId]
+ };
+
+ tableHelpers.filter('subscription__' + campaign.list + ' JOIN campaign_tracker__' + campaign.id + ' ON campaign_tracker__' + campaign.id + '.subscriber=subscription__' + campaign.list + '.id', ['*'], request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback);
+};
+
+module.exports.statsClickedSubscribersByColumn = (campaign, linkId, request, column, limit, callback) => {
db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
- connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM campaigns ORDER BY name LIMIT ? OFFSET ?', [limit, start], (err, rows) => {
+ let query_template = 'SELECT ?? AS data, COUNT(*) AS cnt FROM `subscription__%d` JOIN `campaign_tracker__%d` ON `campaign_tracker__%d`.`list`=%d AND `campaign_tracker__%d`.`subscriber`=`subscription__%d`.`id` AND `campaign_tracker__%d`.`link`=%d GROUP BY ?? ORDER BY COUNT(??) DESC, ??';
+ let query = util.format(query_template, campaign.list, campaign.id, campaign.id, campaign.list, campaign.id, campaign.list, campaign.id, linkId);
+
+ connection.query(query, [column, column, column, column], (err, rows) => {
+ connection.release();
if (err) {
- connection.release();
return callback(err);
}
- connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
- connection.release();
- if (err) {
- return callback(err);
+
+ let data = {};
+ let dataList = [];
+ let total = 0;
+
+ rows.forEach((row, index) => {
+ if (index < limit) {
+ data[row.data] = row.cnt;
+ } else {
+ data.other = (data.other ? data.other : 0) + row.cnt;
}
- return callback(null, rows, total && total[0] && total[0].total);
+ total += row.cnt;
});
+ Object.keys(data).forEach(key => {
+ let name = key + ': ' + data[key];
+ dataList.push([name, data[key]]);
+ });
+ return callback(null, dataList, total);
});
});
};
+module.exports.filterStatusSubscribers = (campaign, status, request, columns, callback) => {
+ let queryData = {
+ where: 'campaign__' + campaign.id + '.list=? AND campaign__' + campaign.id + '.segment=? AND campaign__' + campaign.id + '.status=?',
+ values: [campaign.list, campaign.segment && campaign.segment.id || 0, status]
+ };
+
+ tableHelpers.filter('subscription__' + campaign.list + ' JOIN campaign__' + campaign.id + ' ON campaign__' + campaign.id + '.subscription=subscription__' + campaign.list + '.id', ['*'], request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback);
+};
+
module.exports.getByCid = (cid, callback) => {
cid = (cid || '').toString().trim();
if (!cid) {
- return callback(new Error('Missing Campaign ID'));
+ return callback(new Error(_('Missing Campaign ID')));
}
db.getConnection((err, connection) => {
if (err) {
@@ -62,7 +129,7 @@ module.exports.get = (id, withSegment, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Campaign ID'));
+ return callback(new Error(_('Missing Campaign ID')));
}
db.getConnection((err, connection) => {
@@ -82,34 +149,243 @@ module.exports.get = (id, withSegment, callback) => {
let campaign = tools.convertKeys(rows[0]);
- if (!campaign.segment || !withSegment) {
- return callback(null, campaign);
- } else {
- segments.get(campaign.segment, (err, segment) => {
- if (err || !segment) {
- // ignore
- return callback(null, campaign);
- }
- segments.subscribers(segment.id, true, (err, subscribers) => {
- if (err || !subscribers) {
- segment.subscribers = 0;
- } else {
- segment.subscribers = subscribers;
+ let handleSegment = () => {
+
+ if (!campaign.segment || !withSegment) {
+ return callback(null, campaign);
+ } else {
+ segments.get(campaign.segment, (err, segment) => {
+ if (err || !segment) {
+ // ignore
+ return callback(null, campaign);
}
- campaign.segment = segment;
- return callback(null, campaign);
+ segments.subscribers(segment.id, true, (err, subscribers) => {
+ if (err || !subscribers) {
+ segment.subscribers = 0;
+ } else {
+ segment.subscribers = subscribers;
+ }
+ campaign.segment = segment;
+ return callback(null, campaign);
+ });
});
- });
+ }
+ };
+
+ if (!campaign.parent) {
+ return handleSegment();
}
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+ connection.query('SELECT `id`, `cid`, `name` FROM campaigns WHERE id=?', [campaign.parent], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return handleSegment();
+ }
+
+ campaign.parent = tools.convertKeys(rows[0]);
+ return handleSegment();
+ });
+ });
});
});
};
-module.exports.create = (campaign, callback) => {
+module.exports.getAttachments = (campaign, callback) => {
+ campaign = Number(campaign) || 0;
+
+ if (campaign < 1) {
+ return callback(new Error(_('Missing Campaign ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let keys = ['id', 'filename', 'content_type', 'size', 'created'];
+
+ connection.query('SELECT `' + keys.join('`, `') + '` FROM `attachments` WHERE `campaign`=?', [campaign], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, []);
+ }
+
+ let attachments = rows.map((row, i) => {
+ row = tools.convertKeys(row);
+ row.index = i + 1;
+ row.size = humanize.filesize(Number(row.size) || 0);
+ return row;
+ });
+ return callback(null, attachments);
+ });
+ });
+};
+
+module.exports.addAttachment = (id, attachment, callback) => {
+
+ let size = attachment.content ? attachment.content.length : 0;
+
+ if (!size) {
+ return callback(new Error(_('Emtpy or too large attahcment')));
+ }
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let keys = ['campaign', 'size'];
+ let values = [id, size];
+
+ Object.keys(attachment).forEach(key => {
+ let value;
+ if (Buffer.isBuffer(attachment[key])) {
+ value = attachment[key];
+ } else {
+ value = typeof attachment[key] === 'number' ? attachment[key] : (attachment[key] || '').toString().trim();
+ }
+
+ key = tools.toDbKey(key);
+ keys.push(key);
+ values.push(value);
+ });
+
+ let query = 'INSERT INTO `attachments` (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')';
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let attachmentId = result && result.insertId || false;
+ return callback(null, attachmentId);
+ });
+ });
+};
+
+module.exports.deleteAttachment = (id, attachment, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'DELETE FROM `attachments` WHERE `id`=? AND `campaign`=? LIMIT 1';
+ connection.query(query, [attachment, id], (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let deleted = result && result.affectedRows || false;
+ return callback(null, deleted);
+ });
+ });
+};
+
+module.exports.getAttachment = (campaign, attachment, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'SELECT * FROM `attachments` WHERE `id`=? AND `campaign`=? LIMIT 1';
+ connection.query(query, [attachment, campaign], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ let attachment = tools.convertKeys(rows[0]);
+ return callback(null, attachment);
+ });
+ });
+};
+
+module.exports.getLinks = (id, linkId, callback) => {
+ if (!callback && typeof linkId === 'function') {
+ callback = linkId;
+ linkId = false;
+ }
+
+ id = Number(id) || 0;
+ linkId = Number(linkId) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing Campaign ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query;
+ let values;
+
+ if (!linkId) {
+ query = 'SELECT `id`, `url`, `clicks` FROM links WHERE `campaign`=? LIMIT 1000';
+ values = [id];
+ } else {
+ query = 'SELECT `id`, `url`, `clicks` FROM links WHERE `id`=? AND `campaign`=? LIMIT 1';
+ values = [linkId, id];
+ }
+
+ connection.query(query, values, (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, []);
+ }
+
+ let links = rows.map(
+ row => tools.convertKeys(row)
+ ).sort((a, b) => (
+ a.url.replace(/^https?:\/\/(www.)?/, '').toLowerCase()).localeCompare(b.url.replace(/^https?:\/\/(www.)?/, '').toLowerCase()));
+
+ return callback(null, links);
+ });
+
+ });
+};
+
+module.exports.duplicate = (id, callback) => module.exports.get(id, true, (err, campaign) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!campaign) {
+ return callback(new Error(_('Campaign does not exist')));
+ }
+ campaign.name = campaign.name + ' Copy';
+ return module.exports.create(campaign, false, callback);
+});
+
+module.exports.create = (campaign, opts, callback) => {
campaign = tools.convertKeys(campaign);
let name = (campaign.name || '').toString().trim();
+ campaign.openTrackingDisabled = campaign.openTrackingDisabled ? 1 : 0;
+ campaign.clickTrackingDisabled = campaign.clickTrackingDisabled ? 1 : 0;
+
+ opts = opts || {};
+
if (/^\d+:\d+$/.test(campaign.list)) {
campaign.segment = Number(campaign.list.split(':').pop());
campaign.list = Number(campaign.list.split(':').shift());
@@ -118,27 +394,80 @@ module.exports.create = (campaign, callback) => {
campaign.segment = 0;
}
+ switch ((campaign.type || '').toString().trim().toLowerCase()) {
+ case 'triggered':
+ campaign.type = 4;
+ break;
+ case 'rss':
+ campaign.type = 2;
+ break;
+ case 'entry':
+ if (opts.parent) {
+ campaign.type = 3;
+ } else {
+ campaign.type = 1;
+ }
+ break;
+ case 'normal':
+ default:
+ campaign.type = 1;
+ }
+
campaign.template = Number(campaign.template) || 0;
if (!name) {
- return callback(new Error('Campaign Name must be set'));
+ return callback(new Error(_('Campaign Name must be set')));
}
- lists.get(campaign.list, (err, list) => {
+ if (campaign.type === 2 && (!campaign.sourceUrl || !isUrl(campaign.sourceUrl))) {
+ return callback(new Error(_('RSS URL must be set and needs to be a valid URL')));
+ }
+
+ let getList = (listId, callback) => {
+ if (campaign.type === 4) {
+ return callback(null, false);
+ }
+
+ lists.get(listId, (err, list) => {
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, list || {
+ id: listId
+ });
+ });
+ };
+
+ getList(campaign.list, err => {
if (err) {
return callback(err);
}
- if (!list) {
- return callback(new Error('Selected list not found'));
+
+ let keys = ['name', 'type'];
+ let values = [name, campaign.type];
+
+ if (campaign.type === 2) {
+ keys.push('status');
+ values.push(5); // inactive
}
- let keys = ['name'];
- let values = [name];
+ if (campaign.type === 3) {
+ keys.push('status', 'parent');
+ values.push(2, opts.parent);
+ }
- let create = () => {
+ if (campaign.type === 4) {
+ keys.push('status');
+ values.push(6); // active
+ }
+
+ let create = next => {
Object.keys(campaign).forEach(key => {
let value = typeof campaign[key] === 'number' ? campaign[key] : (campaign[key] || '').toString().trim();
key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) {
keys.push(key);
values.push(value);
@@ -149,52 +478,117 @@ module.exports.create = (campaign, callback) => {
keys.push('cid');
values.push(cid);
- db.getConnection((err, connection) => {
+ tools.prepareHtml(campaign.html, (err, preparedHtml) => {
if (err) {
- return callback(err);
+ log.error('jsdom', err);
}
- let query = 'INSERT INTO campaigns (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')';
- connection.query(query, values, (err, result) => {
- connection.release();
+ if (!preparedHtml) {
+ preparedHtml = campaign.html;
+ }
+
+ keys.push('html_prepared');
+ values.push(preparedHtml);
+
+ db.getConnection((err, connection) => {
if (err) {
- return callback(err);
+ return next(err);
}
- let campaignId = result && result.insertId || false;
- if (!campaignId) {
- return callback(null, false);
- }
-
- // we are going to aqcuire a lot of log info, so we are putting
- // sending logs into separate tables
- createCampaignTables(campaignId, err => {
+ let query = 'INSERT INTO campaigns (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')';
+ connection.query(query, values, (err, result) => {
+ connection.release();
if (err) {
- // FIXME: rollback
- return callback(err);
+ return next(err);
}
- return callback(null, campaignId);
+
+ let campaignId = result && result.insertId || false;
+ if (!campaignId) {
+ return next(null, false);
+ }
+
+ // we are going to aqcuire a lot of log info, so we are putting
+ // sending logs into separate tables
+ createCampaignTables(campaignId, err => {
+ if (err) {
+ // FIXME: rollback
+ return next(err);
+ }
+ return next(null, campaignId);
+ });
});
});
});
};
- if (campaign.template) {
+ if (campaign.type === 2) {
+ feed.fetch(campaign.sourceUrl, (err, entries) => {
+ if (err) {
+ return callback(err);
+ }
+
+ mailer.getTemplate('emails/rss-html.hbs', (err, rendererHtml) => {
+ if (err) {
+ return callback(err);
+ }
+
+ campaign.html = rendererHtml();
+
+ create((err, campaignId) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!campaignId || !entries.length) {
+ return callback(null, campaignId);
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ // store references to already existing feed entries
+ // this is needed to detect new entries
+ let query = 'INSERT IGNORE INTO `rss` (`parent`,`guid`,`pubdate`) VALUES ' + entries.map(() => '(?,?,?)').join(',');
+
+ values = [];
+ entries.forEach(entry => {
+ values.push(campaignId, entry.guid, entry.date);
+ });
+
+ connection.query(query, values, err => {
+ connection.release();
+ if (err) {
+ // too late to report as failed
+ log.error('RSS', err);
+ }
+
+ return callback(null, campaignId);
+ });
+ });
+ });
+ });
+ });
+ return;
+ } else if (campaign.template) {
templates.get(campaign.template, (err, template) => {
if (err) {
return callback(err);
}
if (!template) {
- return callback(new Error('Selected template not found'));
+ return callback(new Error(_('Selected template not found')));
}
- keys = keys.concat(['html', 'text']);
- values = values.concat([template.html, template.text]);
+ campaign.editorName = template.editorName;
+ campaign.editorData = template.editorData;
+ campaign.html = template.html;
+ campaign.text = template.text;
- create();
+ create(callback);
});
+ return;
} else {
- create();
+ return create(callback);
}
});
};
@@ -204,14 +598,17 @@ module.exports.update = (id, updates, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Campaign ID'));
+ return callback(new Error(_('Missing Campaign ID')));
}
let campaign = tools.convertKeys(updates);
let name = (campaign.name || '').toString().trim();
+ campaign.openTrackingDisabled = campaign.openTrackingDisabled ? 1 : 0;
+ campaign.clickTrackingDisabled = campaign.clickTrackingDisabled ? 1 : 0;
+
if (!name) {
- return callback(new Error('Campaign Name must be set'));
+ return callback(new Error(_('Campaign Name must be set')));
}
if (/^\d+:\d+$/.test(campaign.list)) {
@@ -222,13 +619,21 @@ module.exports.update = (id, updates, callback) => {
campaign.segment = 0;
}
- lists.get(campaign.list, (err, list) => {
+ let getList = (listId, callback) => {
+ lists.get(listId, (err, list) => {
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, list || {
+ id: listId
+ });
+ });
+ };
+
+ getList(campaign.list, err => {
if (err) {
return callback(err);
}
- if (!list) {
- return callback(new Error('Selected list not found'));
- }
let keys = ['name'];
let values = [name];
@@ -236,25 +641,87 @@ module.exports.update = (id, updates, callback) => {
Object.keys(campaign).forEach(key => {
let value = typeof campaign[key] === 'number' ? campaign[key] : (campaign[key] || '').toString().trim();
key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) {
keys.push(key);
values.push(value);
}
});
- db.getConnection((err, connection) => {
+ tools.prepareHtml(campaign.html, (err, preparedHtml) => {
if (err) {
- return callback(err);
+ log.error('jsdom', err);
}
- values.push(id);
+ if (!preparedHtml) {
+ preparedHtml = campaign.html;
+ }
- connection.query('UPDATE campaigns SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
- connection.release();
+ keys.push('html_prepared');
+ values.push(preparedHtml);
+
+ db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
- return callback(null, result && result.affectedRows || false);
+
+ values.push(id);
+
+ connection.query('UPDATE campaigns SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+ let affected = result && result.affectedRows || false;
+
+ if (!affected) {
+ connection.release();
+ return callback(null, affected);
+ }
+
+ connection.query('SELECT `type`, `source_url` FROM campaigns WHERE id=? LIMIT 1', [id], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows[0] || rows[0].type !== 2) {
+ // if not RSS, then nothing to do here
+ return callback(null, affected);
+ }
+
+ // update seen rss entries to avoid sending old entries to subscribers
+ feed.fetch(rows[0].source_url, (err, entries) => {
+ if (err) {
+ return callback(err);
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'INSERT IGNORE INTO `rss` (`parent`,`guid`,`pubdate`) VALUES ' + entries.map(() => '(?,?,?)').join(',');
+
+ values = [];
+ entries.forEach(entry => {
+ values.push(id, entry.guid, entry.date);
+ });
+
+ connection.query(query, values, err => {
+ connection.release();
+ if (err) {
+ // too late to report as failed
+ log.error('RSS', err);
+ }
+ return callback(null, affected);
+ });
+ });
+ });
+ });
+ });
});
});
});
@@ -264,7 +731,7 @@ module.exports.delete = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Campaign ID'));
+ return callback(new Error(_('Missing Campaign ID')));
}
db.getConnection((err, connection) => {
@@ -273,24 +740,19 @@ module.exports.delete = (id, callback) => {
}
connection.query('DELETE FROM campaigns WHERE id=? LIMIT 1', [id], (err, result) => {
+ connection.release();
if (err) {
- connection.release();
return callback(err);
}
let affected = result && result.affectedRows || 0;
-
- connection.query('DELETE FROM links WHERE campaign=?', [id], err => {
- connection.release();
+ removeCampaignTables(id, err => {
if (err) {
return callback(err);
}
- removeCampaignTables(id, err => {
- if (err) {
- return callback(err);
- }
- return callback(null, affected);
+ db.clearCache('sender', () => {
+ callback(null, affected);
});
});
});
@@ -351,11 +813,13 @@ module.exports.pause = (id, callback) => {
// campaigns marked as status=4 are paused
connection.query('UPDATE campaigns SET `status`=4, `status_change`=NOW() WHERE id=? LIMIT 1', [id], err => {
+ connection.release();
if (err) {
- connection.release();
return callback(err);
}
- return callback(null, true);
+ db.clearCache('sender', () => {
+ callback(null, true);
+ });
});
});
});
@@ -367,7 +831,7 @@ module.exports.reset = (id, callback) => {
return callback(err);
}
- if (campaign.status !== 3 && !(campaign.status === 2 && campaign.scheduled > new Date())) {
+ if (campaign.status !== 3 && campaign.status !== 4 && !(campaign.status === 2 && campaign.scheduled > new Date())) {
return callback(null, false);
}
@@ -376,27 +840,30 @@ module.exports.reset = (id, callback) => {
return callback(err);
}
- connection.query('UPDATE campaigns SET `status`=1, `status_change`=NULL, `delivered`=0, `opened`=0, `clicks`=0, `bounced`=0, `complained`=0, `unsubscribed`=0 WHERE id=? LIMIT 1', [id], err => {
+ connection.query('UPDATE campaigns SET `status`=1, `status_change`=NULL, `delivered`=0, `opened`=0, `clicks`=0, `bounced`=0, `complained`=0, `unsubscribed`=0, `blacklisted`=0 WHERE id=? LIMIT 1', [id], err => {
if (err) {
connection.release();
return callback(err);
}
- connection.query('DELETE FROM links WHERE campaign=?', [id], err => {
- if (err) {
- connection.release();
- return callback(err);
- }
- connection.query('TRUNCATE TABLE `campaign__' + id + '`', [id], err => {
+
+ db.clearCache('sender', () => {
+ connection.query('UPDATE links SET `clicks`=0 WHERE campaign=?', [id], err => {
if (err) {
connection.release();
return callback(err);
}
- connection.query('TRUNCATE TABLE `campaign_tracker__' + id + '`', [id], err => {
- connection.release();
+ connection.query('TRUNCATE TABLE `campaign__' + id + '`', [id], err => {
if (err) {
+ connection.release();
return callback(err);
}
- return callback(null, true);
+ connection.query('TRUNCATE TABLE `campaign_tracker__' + id + '`', [id], err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
});
});
});
@@ -405,13 +872,67 @@ module.exports.reset = (id, callback) => {
});
};
+module.exports.activate = (id, callback) => {
+ module.exports.get(id, false, (err, campaign) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (campaign.status !== 5) {
+ return callback(null, false);
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ // campaigns marked as status=5 are paused
+ connection.query('UPDATE campaigns SET `status`=6, `status_change`=NOW() WHERE id=? LIMIT 1', [id], err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+ });
+ });
+};
+
+module.exports.inactivate = (id, callback) => {
+ module.exports.get(id, false, (err, campaign) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (campaign.status !== 6) {
+ return callback(null, false);
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ // campaigns marked as status=6 are paused
+ connection.query('UPDATE campaigns SET `status`=5, `status_change`=NOW() WHERE id=? LIMIT 1', [id], err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+ });
+ });
+};
+
module.exports.getMail = (campaignId, listId, subscriptionId, callback) => {
campaignId = Number(campaignId) || 0;
listId = Number(listId) || 0;
subscriptionId = Number(subscriptionId) || 0;
if (campaignId < 1 || listId < 1 || subscriptionId < 1) {
- return callback(new Error('Invalid or missing message ID'));
+ return callback(new Error(_('Invalid or missing message ID')));
}
db.getConnection((err, connection) => {
@@ -441,7 +962,7 @@ module.exports.findMailByResponse = (responseId, callback) => {
return callback(err);
}
- connection.query('SELECT id FROM campaigns', [], (err, campaignList) => {
+ connection.query('SELECT id FROM campaigns ORDER BY id DESC', [], (err, campaignList) => {
if (err) {
connection.release();
return callback(err);
@@ -546,13 +1067,13 @@ module.exports.updateMessage = (message, status, updateSubscription, callback) =
let statusCode;
if (status === 'unsubscribed') {
- statusCode = 2;
- }
- if (status === 'bounced') {
- statusCode = 3;
- }
- if (status === 'complained') {
- statusCode = 4;
+ statusCode = subscriptions.Status.UNSUBSCRIBED;
+ } else if (status === 'bounced') {
+ statusCode = subscriptions.Status.BOUNCED;
+ } else if (status === 'complained') {
+ statusCode = subscriptions.Status.COMPLAINED;
+ } else {
+ return callback(new Error(_('Unrecognized message status')));
}
let query = 'UPDATE `campaigns` SET `' + status + '`=`' + status + '`+1 WHERE id=? LIMIT 1';
@@ -566,7 +1087,7 @@ module.exports.updateMessage = (message, status, updateSubscription, callback) =
}
if (updateSubscription) {
- subscriptions.changeStatus(message.subscription, message.list, statusCode === 2 ? message.campaign : false, statusCode, callback);
+ subscriptions.changeStatus(message.list, message.subscription, statusCode === subscriptions.Status.UNSUBSCRIBED ? message.campaign : false, statusCode, callback);
} else {
return callback(null, true);
}
@@ -576,6 +1097,24 @@ module.exports.updateMessage = (message, status, updateSubscription, callback) =
});
};
+module.exports.updateMessageResponse = (message, response, response_id, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'UPDATE `campaign__' + message.campaign + '` SET `response`=?, `response_id`=? WHERE id=? LIMIT 1';
+ connection.query(query, [response, response_id, message.id], err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+
+ });
+};
+
function createCampaignTables(id, callback) {
let query = 'CREATE TABLE `campaign__' + id + '` LIKE campaign';
db.getConnection((err, connection) => {
diff --git a/lib/models/confirmations.js b/lib/models/confirmations.js
new file mode 100644
index 00000000..9cbceee6
--- /dev/null
+++ b/lib/models/confirmations.js
@@ -0,0 +1,91 @@
+'use strict';
+
+let db = require('../db');
+let shortid = require('shortid');
+let helpers = require('../helpers');
+let _ = require('../translate')._;
+
+/*
+ Adds new entry to the confirmations tables. Generates confirmation cid, which it returns.
+ */
+module.exports.addConfirmation = (listId, action, ip, data, callback) => {
+ let cid = shortid.generate();
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'INSERT INTO confirmations (cid, list, action, ip, data) VALUES (?,?,?,?,?)';
+ connection.query(query, [cid, listId, action, ip, JSON.stringify(data || {})], (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!result || !result.affectedRows) {
+ return callback(new Error(_('Could not store confirmation data')));
+ }
+
+ return callback(null, cid);
+ });
+ });
+};
+
+/*
+ Atomically retrieves confirmation from the database, removes it from the database and returns it.
+ */
+module.exports.takeConfirmation = (cid, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.beginTransaction(err => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+
+ let query = 'SELECT cid, list, action, ip, data FROM confirmations WHERE cid=? LIMIT 1';
+ connection.query(query, [cid], (err, rows) => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ if (!rows || !rows.length) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(null, false));
+ }
+
+ connection.query('DELETE FROM confirmations WHERE `cid`=? LIMIT 1', [cid], () => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ connection.commit(err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+ connection.release();
+
+ let data;
+ try {
+ data = JSON.parse(rows[0].data);
+ } catch (E) {
+ data = {};
+ }
+
+ const result = {
+ listId: rows[0].list,
+ action: rows[0].action,
+ ip: rows[0].ip,
+ data
+ };
+
+ return callback(null, result);
+ });
+ });
+ });
+ });
+ });
+};
diff --git a/lib/models/fields.js b/lib/models/fields.js
index b9076439..1b3dbe2b 100644
--- a/lib/models/fields.js
+++ b/lib/models/fields.js
@@ -5,31 +5,39 @@ let tools = require('../tools');
let slugify = require('slugify');
let lists = require('./lists');
let shortid = require('shortid');
+let Handlebars = require('handlebars');
+let _ = require('../translate')._;
+let util = require('util');
-let allowedKeys = ['name', 'key', 'default_value', 'group', 'visible'];
+let allowedKeys = ['name', 'description', 'key', 'default_value', 'group', 'group_template', 'visible'];
+let allowedTypes;
module.exports.grouped = ['radio', 'checkbox', 'dropdown'];
module.exports.types = {
- text: 'Text',
- website: 'Website',
- longtext: 'Multi-line text',
- gpg: 'GPG Public Key',
- number: 'Number',
- radio: 'Radio Buttons',
- checkbox: 'Checkboxes',
- dropdown: 'Drop Down',
- 'date-us': 'Date (MM/DD/YYY)',
- 'date-eur': 'Date (DD/MM/YYYY)',
- 'birthday-us': 'Birthday (MM/DD)',
- 'birthday-eur': 'Birthday (DD/MM)',
- option: 'Option'
+ text: _('Text'),
+ website: _('Website'),
+ longtext: _('Multi-line text'),
+ gpg: _('GPG Public Key'),
+ number: _('Number'),
+ radio: _('Radio Buttons'),
+ checkbox: _('Checkboxes'),
+ dropdown: _('Drop Down'),
+ 'date-us': _('Date (MM/DD/YYY)'),
+ 'date-eur': _('Date (DD/MM/YYYY)'),
+ 'birthday-us': _('Birthday (MM/DD)'),
+ 'birthday-eur': _('Birthday (DD/MM)'),
+ json: _('JSON value for custom rendering'),
+ option: _('Option')
};
+module.exports.allowedTypes = allowedTypes = Object.keys(module.exports.types);
+
module.exports.genericTypes = {
text: 'string',
website: 'string',
longtext: 'textarea',
gpg: 'textarea',
+ json: 'textarea',
number: 'number',
'date-us': 'date',
'date-eur': 'date',
@@ -42,7 +50,7 @@ module.exports.list = (listId, callback) => {
listId = Number(listId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
db.getConnection((err, connection) => {
@@ -50,7 +58,7 @@ module.exports.list = (listId, callback) => {
return callback(err);
}
- let query = 'SELECT * FROM custom_fields WHERE list=?';
+ let query = 'SELECT * FROM custom_fields WHERE list=? ORDER BY id';
connection.query(query, [listId], (err, rows) => {
connection.release();
if (err) {
@@ -87,7 +95,7 @@ module.exports.get = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
db.getConnection((err, connection) => {
@@ -101,7 +109,9 @@ module.exports.get = (id, callback) => {
if (err) {
return callback(err);
}
- return callback(null, rows && rows[0] && tools.convertKeys(rows[0]) || false);
+ let field = rows && rows[0] && tools.convertKeys(rows[0]) || false;
+ field.isGroup = module.exports.grouped.indexOf(field.type) >= 0 || field.type === 'json';
+ return callback(null, field);
});
});
};
@@ -110,20 +120,24 @@ module.exports.create = (listId, field, callback) => {
listId = Number(listId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
field = tools.convertKeys(field);
if (field.type === 'option' && !field.group) {
- return callback(new Error('Option field requires a group to be selected'));
+ return callback(new Error(_('Option field requires a group to be selected')));
}
if (field.type !== 'option') {
field.group = null;
}
- addCustomField(listId, field.name, field.defaultValue, field.type, field.group, field.visible, callback);
+ field.description = (field.description || '').toString().trim() || null;
+ field.defaultValue = (field.defaultValue || '').toString().trim() || null;
+ field.groupTemplate = (field.groupTemplate || '').toString().trim() || null;
+
+ addCustomField(listId, field.name, field.description, field.defaultValue, field.type, field.group, field.groupTemplate, field.visible, callback);
};
module.exports.update = (id, updates, callback) => {
@@ -133,17 +147,21 @@ module.exports.update = (id, updates, callback) => {
updates = tools.convertKeys(updates);
if (id < 1) {
- return callback(new Error('Missing Field ID'));
+ return callback(new Error(_('Missing Field ID')));
}
if (!(updates.name || '').toString().trim()) {
- return callback(new Error('Field Name must be set'));
+ return callback(new Error(_('Field Name must be set')));
}
if (updates.key) {
updates.key = slugify(updates.key, '_').toUpperCase();
}
+ updates.description = (updates.description || '').toString().trim() || null;
+ updates.defaultValue = (updates.defaultValue || '').toString().trim() || null;
+ updates.groupTemplate = (updates.groupTemplate || '').toString().trim() || null;
+
updates.visible = updates.visible ? 1 : 0;
let name = (updates.name || '').toString().trim();
@@ -180,7 +198,7 @@ module.exports.delete = (fieldId, callback) => {
fieldId = Number(fieldId) || 0;
if (fieldId < 1) {
- return callback(new Error('Missing Field ID'));
+ return callback(new Error(_('Missing Field ID')));
}
db.getConnection((err, connection) => {
@@ -197,7 +215,7 @@ module.exports.delete = (fieldId, callback) => {
if (!rows || !rows.length) {
connection.release();
- return callback(new Error('Custom field not found'));
+ return callback(new Error(_('Custom field not found')));
}
let field = tools.convertKeys(rows[0]);
@@ -261,25 +279,24 @@ module.exports.delete = (fieldId, callback) => {
});
};
-function addCustomField(listId, name, defaultValue, type, group, visible, callback) {
+function addCustomField(listId, name, description, defaultValue, type, group, groupTemplate, visible, callback) {
type = (type || '').toString().trim().toLowerCase();
group = Number(group) || null;
listId = Number(listId) || 0;
let column = null;
let key = slugify('merge ' + name, '_').toUpperCase();
- let allowedTypes = ['text', 'number', 'radio', 'checkbox', 'dropdown', 'date-us', 'date-eur', 'birthday-us', 'birthday-eur', 'website', 'option', 'gpg', 'longtext'];
if (allowedTypes.indexOf(type) < 0) {
- return callback(new Error('Unknown column type ' + type));
+ return callback(new Error(util.format(_('Unknown column type %s'), type)));
}
if (!name) {
- return callback(new Error('Missing column name'));
+ return callback(new Error(_('Missing column name')));
}
if (listId <= 0) {
- return callback(new Error('Missing list ID'));
+ return callback(new Error(_('Missing list ID')));
}
lists.get(listId, (err, list) => {
@@ -287,7 +304,7 @@ function addCustomField(listId, name, defaultValue, type, group, visible, callba
return callback(err);
}
if (!list) {
- return callback('Provided List ID not found');
+ return callback(_('Provided List ID not found'));
}
db.getConnection((err, connection) => {
@@ -296,11 +313,11 @@ function addCustomField(listId, name, defaultValue, type, group, visible, callba
}
if (module.exports.grouped.indexOf(type) < 0) {
- column = ('custom_' + slugify(name, '_') + '_' + shortid.generate()).toLowerCase().replace(/[^a-z0-9\_]/g, '');
+ column = ('custom_' + slugify(name, '_') + '_' + shortid.generate()).toLowerCase().replace(/[^a-z0-9_]/g, '');
}
- let query = 'INSERT INTO custom_fields (`list`, `name`, `key`,`default_value`, `type`, `group`, `column`, `visible`) VALUES(?,?,?,?,?,?,?,?)';
- connection.query(query, [listId, name, key, defaultValue, type, group, column, visible ? 1 : 0], (err, result) => {
+ let query = 'INSERT INTO custom_fields (`list`, `name`, `description`, `key`,`default_value`, `type`, `group`, `group_template`, `column`, `visible`) VALUES(?,?,?,?,?,?,?,?,?,?)';
+ connection.query(query, [listId, name, description, key, defaultValue, type, group, groupTemplate, column, visible ? 1 : 0], (err, result) => {
if (err) {
connection.release();
@@ -308,31 +325,37 @@ function addCustomField(listId, name, defaultValue, type, group, visible, callba
}
let fieldId = result && result.insertId;
+ let indexQuery;
switch (type) {
case 'text':
case 'website':
- query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` VARCHAR(255) DEFAULT NULL, ADD INDEX (' + column + ')';
+ query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` VARCHAR(255) DEFAULT NULL';
+ indexQuery = 'CREATE INDEX ' + column + '_index ON `subscription__' + listId + '` (`column`);';
break;
case 'gpg':
case 'longtext':
+ case 'json':
query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` TEXT DEFAULT NULL';
break;
case 'number':
- query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` INT(11) DEFAULT NULL, ADD INDEX (' + column + ')';
+ query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` INT(11) DEFAULT NULL';
+ indexQuery = 'CREATE INDEX ' + column + '_index ON `subscription__' + listId + '` (`column`);';
break;
case 'option':
- query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` TINYINT(4) UNSIGNED NOT NULL DEFAULT \'0\', ADD INDEX (' + column + ')';
+ query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` TINYINT(4) UNSIGNED NOT NULL DEFAULT \'0\'';
+ indexQuery = 'CREATE INDEX ' + column + '_index ON `subscription__' + listId + '` (`column`);';
break;
case 'date-us':
case 'date-eur':
case 'birthday-us':
case 'birthday-eur':
- query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` TIMESTAMP NULL DEFAULT NULL, ADD INDEX (' + column + ')';
+ query = 'ALTER TABLE `subscription__' + listId + '` ADD COLUMN `' + column + '` DATETIME NULL DEFAULT NULL';
+ indexQuery = 'CREATE INDEX ' + column + '_index ON `subscription__' + listId + '` (`column`);';
break;
default:
connection.release();
- return callback(null, true);
+ return callback(null, fieldId, key);
}
connection.query(query, err => {
@@ -340,15 +363,25 @@ function addCustomField(listId, name, defaultValue, type, group, visible, callba
connection.query('DELETE FROM custom_fields WHERE id=? LIMIT 1', [fieldId], () => connection.release());
return callback(err);
}
- connection.release();
- return callback(null, fieldId);
+ if (!indexQuery) {
+ connection.release();
+ return callback(null, fieldId, key);
+ } else {
+ connection.query(query, err => {
+ if (err) {
+ // ignore index errors
+ }
+ connection.release();
+ return callback(null, fieldId, key);
+ });
+ }
});
});
});
});
}
-module.exports.getRow = (fieldList, values, useDate, showAll) => {
+module.exports.getRow = (fieldList, values, useDate, showAll, onlyExisting) => {
let valueList = {};
let row = [];
@@ -363,6 +396,11 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
});
fieldList.filter(field => showAll || field.visible).forEach(field => {
+ if (onlyExisting && field.column && !valueList.hasOwnProperty(field.column)) {
+ // ignore missing values
+ return;
+ }
+ /* eslint-disable indent */
switch (field.type) {
case 'text':
case 'website':
@@ -370,14 +408,47 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
case 'longtext':
{
let item = {
+ id: field.id,
type: field.type,
name: field.name,
+ description: field.description,
column: field.column,
value: (valueList[field.column] || '').toString().trim(),
visible: !!field.visible,
mergeTag: field.key,
mergeValue: (valueList[field.column] || '').toString().trim() || field.defaultValue,
- ['type' + (field.type || '').toString().trim().replace(/(?:^|\-)([a-z])/g, (m, c) => c.toUpperCase())]: true
+ ['type' + (field.type || '').toString().trim().replace(/(?:^|-)([a-z])/g, (m, c) => c.toUpperCase())]: true
+ };
+ row.push(item);
+ break;
+ }
+ case 'json':
+ {
+ let value;
+ let json = (valueList[field.column] || '').toString().trim();
+ try {
+ let parsed = JSON.parse(json);
+ if (Array.isArray(parsed)) {
+ parsed = {
+ values: parsed
+ };
+ }
+ value = json ? render(field.groupTemplate, parsed) : '';
+ } catch (E) {
+ value = E.message;
+ }
+
+ let item = {
+ id: field.id,
+ type: field.type,
+ name: field.name,
+ description: field.description,
+ column: field.column,
+ value: (valueList[field.column] || '').toString().trim(),
+ visible: !!field.visible,
+ mergeTag: field.key,
+ mergeValue: value || field.defaultValue,
+ ['type' + (field.type || '').toString().trim().replace(/(?:^|-)([a-z])/g, (m, c) => c.toUpperCase())]: true
};
row.push(item);
break;
@@ -385,14 +456,16 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
case 'number':
{
let item = {
+ id: field.id,
type: field.type,
name: field.name,
+ description: field.description,
column: field.column,
value: Number(valueList[field.column]) || 0,
visible: !!field.visible,
mergeTag: field.key,
- mergeValue: Number(valueList[field.column]) || field.defaultValue || 0,
- ['type' + (field.type || '').toString().trim().replace(/(?:^|\-)([a-z])/g, (m, c) => c.toUpperCase())]: true
+ mergeValue: (Number(valueList[field.column]) || Number(field.defaultValue) || 0).toString(),
+ ['type' + (field.type || '').toString().trim().replace(/(?:^|-)([a-z])/g, (m, c) => c.toUpperCase())]: true
};
row.push(item);
break;
@@ -401,25 +474,46 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
case 'radio':
case 'checkbox':
{
+ let hasSelectedOption = (field.options || []).some(subField => subField.column && valueList[subField.column]);
let item = {
+ id: field.id,
type: field.type,
name: field.name,
+ description: field.description,
visible: !!field.visible,
key: 'group-g' + field.id,
mergeTag: field.key,
mergeValue: field.defaultValue,
- ['type' + (field.type || '').toString().trim().replace(/(?:^|\-)([a-z])/g, (m, c) => c.toUpperCase())]: true,
- options: (field.options || []).map(subField => ({
- type: subField.type,
- name: subField.name,
- column: subField.column,
- value: valueList[subField.column] ? 1 : 0,
- visible: !!subField.visible,
- mergeTag: subField.key,
- mergeValue: valueList[subField.column] ? subField.name : subField.defaultValue
- }))
+ ['type' + (field.type || '').toString().trim().replace(/(?:^|-)([a-z])/g, (m, c) => c.toUpperCase())]: true,
+ groupTemplate: field.groupTemplate,
+ options: (field.options || []).map(subField => {
+ if (onlyExisting && subField.column && !valueList.hasOwnProperty(subField.column)) {
+ if (hasSelectedOption && field.type !== 'checkbox') {
+ // Set all radio or dropdown options if a selection for the group is present
+ } else if (field.type === 'checkbox' && values['originGroupG' + field.id] === 'webform') {
+ // Set all checkbox options if origin is webform (subscribe, manage, or admin edit) #333
+ // Atomic updates via API call or CSV import still possible
+ } else {
+ // ignore missing values
+ return false;
+ }
+ }
+ return {
+ type: subField.type,
+ name: subField.name,
+ description: subField.description,
+ column: subField.column,
+ value: valueList[subField.column] ? 1 : 0,
+ visible: !!subField.visible,
+ mergeTag: subField.key,
+ mergeValue: valueList[subField.column] ? subField.name : subField.defaultValue
+ };
+ }).filter(subField => subField)
};
- item.value = item.options.filter(subField => showAll || subField.visible && subField.value).map(subField => subField.name).join(', ');
+ let subItems = item.options.filter(subField => (showAll || subField.visible) && subField.value).map(subField => subField.name);
+ item.value = field.groupTemplate ? render(field.groupTemplate, {
+ values: subItems
+ }) : subItems.join(', ');
item.mergeValue = item.value || field.defaultValue;
row.push(item);
break;
@@ -429,7 +523,7 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
case 'date-us':
case 'birthday-us':
{
- let isUs = /\-us$/.test(field.type);
+ let isUs = /-us$/.test(field.type);
let isYear = field.type.indexOf('date-') === 0;
let value = valueList[field.column];
let day, month, year;
@@ -442,18 +536,27 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
} else {
value = (value || '').toString().trim();
- let parts = value.match(/(\d+)\D+(\d+)(?:\D+(\d+))?/);
- if (!parts) {
- value = null;
+ // try international format first YYYY-MM-DD
+ let parts = value.match(/(\d{4})\D+(\d{2})(?:\D+(\d{2})\b)?/);
+ if (parts) {
+ year = Number(parts[1]) || 2000;
+ month = Number(parts[2]) || 0;
+ day = Number(parts[3]) || 0;
+ value = new Date(Date.UTC(year, month - 1, day));
} else {
- day = Number(parts[isUs ? 2 : 1]) || 0;
- month = Number(parts[isUs ? 1 : 2]) || 0;
- year = Number(parts[3]) || 2000;
-
- if (!day || !month) {
+ parts = value.match(/(\d+)\D+(\d+)(?:\D+(\d+)\b)?/);
+ if (!parts) {
value = null;
} else {
- value = new Date(Date.UTC(year, month - 1, day));
+ day = Number(parts[isUs ? 2 : 1]) || 0;
+ month = Number(parts[isUs ? 1 : 2]) || 0;
+ year = Number(parts[3]) || 2000;
+
+ if (!day || !month) {
+ value = null;
+ } else {
+ value = new Date(Date.UTC(year, month - 1, day));
+ }
}
}
}
@@ -473,19 +576,22 @@ module.exports.getRow = (fieldList, values, useDate, showAll) => {
}
let item = {
+ id: field.id,
type: field.type,
name: field.name,
+ description: field.description,
column: field.column,
value: useDate ? value : formatted,
visible: !!field.visible,
mergeTag: field.key,
mergeValue: (useDate ? value : formatted) || field.defaultValue,
- ['type' + (field.type || '').toString().trim().replace(/(?:^|\-)([a-z])/g, (m, c) => c.toUpperCase())]: true
+ ['type' + (field.type || '').toString().trim().replace(/(?:^|-)([a-z])/g, (m, c) => c.toUpperCase())]: true
};
row.push(item);
break;
}
}
+ /* eslint-enable indent */
});
return row;
@@ -511,3 +617,9 @@ module.exports.getValues = (row, showAll) => {
return result;
};
+
+
+function render(template, options) {
+ let renderer = Handlebars.compile(template);
+ return renderer(options);
+}
diff --git a/lib/models/forms.js b/lib/models/forms.js
new file mode 100644
index 00000000..9550077b
--- /dev/null
+++ b/lib/models/forms.js
@@ -0,0 +1,418 @@
+'use strict';
+
+let db = require('../db');
+let fs = require('fs');
+let path = require('path');
+let tools = require('../tools');
+let mjml = require('mjml');
+let _ = require('../translate')._;
+
+let allowedKeys = [
+ 'name',
+ 'description',
+ 'fields_shown_on_subscribe',
+ 'fields_shown_on_manage',
+ 'layout',
+ 'form_input_style',
+ 'web_subscribe',
+ 'web_confirm_subscription_notice',
+ 'mail_confirm_subscription_html',
+ 'mail_confirm_subscription_text',
+ 'mail_already_subscribed_html',
+ 'mail_already_subscribed_text',
+ 'web_subscribed_notice',
+ 'mail_subscription_confirmed_html',
+ 'mail_subscription_confirmed_text',
+ 'web_manage',
+ 'web_manage_address',
+ 'web_updated_notice',
+ 'web_unsubscribe',
+ 'web_confirm_unsubscription_notice',
+ 'mail_confirm_unsubscription_html',
+ 'mail_confirm_unsubscription_text',
+ 'mail_confirm_address_change_html',
+ 'mail_confirm_address_change_text',
+ 'web_unsubscribed_notice',
+ 'mail_unsubscription_confirmed_html',
+ 'mail_unsubscription_confirmed_text',
+ 'web_manual_unsubscribe_notice'
+];
+
+
+module.exports.list = (listId, callback) => {
+ listId = Number(listId) || 0;
+
+ if (listId < 1) {
+ return callback(new Error(_('Missing List ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM custom_forms WHERE list=? ORDER BY id', [listId], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let formList = rows && rows.map(row => tools.convertKeys(row)) || [];
+ return callback(null, formList);
+ });
+ });
+};
+
+module.exports.get = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing Form ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM custom_forms WHERE id=? LIMIT 1', [id], (err, rows) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+
+ let form = rows && rows[0] && tools.convertKeys(rows[0]) || false;
+
+ if (!form) {
+ connection.release();
+ return callback(new Error('Selected form not found'));
+ }
+
+ connection.query('SELECT * FROM custom_forms_data WHERE form=?', [id], (err, data_rows = []) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ data_rows.forEach(data_row => {
+ let modelKey = tools.fromDbKey(data_row.data_key);
+ form[modelKey] = data_row.data_value;
+ });
+
+ return callback(null, form);
+ });
+ });
+ });
+};
+
+
+module.exports.create = (listId, form, callback) => {
+ listId = Number(listId) || 0;
+
+ if (listId < 1) {
+ return callback(new Error(_('Missing Form ID')));
+ }
+
+ form = tools.convertKeys(form);
+ form = setDefaultValues(form);
+ form.name = (form.name || '').toString().trim();
+
+ if (!form.name) {
+ return callback(new Error(_('Form Name must be set')));
+ }
+
+ let keys = ['list'];
+ let values = [listId];
+
+ Object.keys(form).forEach(key => {
+ let value = form[key].trim();
+ key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+ if (allowedKeys.indexOf(key) >= 0) {
+ keys.push(key);
+ values.push(value);
+ }
+ });
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let filtered = filterKeysAndValues(keys, values, 'exclude', ['mail_', 'web_']);
+ let query = 'INSERT INTO custom_forms (' + filtered.keys.join(', ') + ') VALUES (' + filtered.values.map(() => '?').join(',') + ')';
+
+ connection.query(query, filtered.values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let formId = result && result.insertId;
+
+ if (!formId) {
+ return callback(new Error('Invalid custom_forms insertId'));
+ }
+
+ let jobs = 1;
+ let error = null;
+
+ let done = err => {
+ jobs--;
+ error = err ? err : error; // One's enough
+ jobs === 0 && callback(error, formId);
+ };
+
+ filtered = filterKeysAndValues(keys, values, 'include', ['mail_', 'web_']);
+
+ filtered.keys.forEach((key, index) => {
+ jobs++;
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return done(err);
+ }
+
+ connection.query('INSERT INTO custom_forms_data (form, data_key, data_value) VALUES (?, ?, ?)', [formId, key, filtered.values[index]], err => {
+ connection.release();
+ if (err) {
+ return done(err);
+ }
+
+ return done(null);
+ });
+ });
+ });
+
+ done(null);
+ });
+ });
+};
+
+module.exports.update = (id, updates, callback) => {
+ updates = updates || {};
+ id = Number(id) || 0;
+
+ updates = tools.convertKeys(updates);
+
+ if (id < 1) {
+ return callback(new Error(_('Missing Form ID')));
+ }
+
+ if (!(updates.name || '').toString().trim()) {
+ return callback(new Error(_('Form Name must be set')));
+ }
+
+ let keys = [];
+ let values = [];
+
+ Object.keys(updates).forEach(key => {
+ let value = typeof updates[key] === 'string' ? updates[key].trim() : updates[key];
+ key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+ if (allowedKeys.indexOf(key) >= 0) {
+ keys.push(key);
+ values.push(value);
+ }
+ });
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let filtered = filterKeysAndValues(keys, values, 'exclude', ['mail_', 'web_']);
+ let query = 'UPDATE custom_forms SET ' + filtered.keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1';
+
+ connection.query(query, filtered.values.concat(id), (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let affectedRows = result && result.affectedRows;
+
+ let jobs = 1;
+ let error = null;
+
+ let done = err => {
+ jobs--;
+ error = err ? err : error; // One's enough
+
+ if (jobs === 0) {
+ if (error) {
+ return callback(error);
+ }
+
+ // Save then validate, as otherwise their work get's lost ...
+ err = testForMjmlErrors(keys, values);
+ if (err) {
+ return callback(err);
+ }
+
+ return callback(null, affectedRows);
+ }
+ };
+
+ filtered = filterKeysAndValues(keys, values, 'include', ['mail_', 'web_']);
+
+ filtered.keys.forEach((key, index) => {
+ jobs++;
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return done(err);
+ }
+
+ connection.query('UPDATE custom_forms_data SET data_value=? WHERE data_key=? AND form=?', [filtered.values[index], key, id], err => {
+ connection.release();
+ if (err) {
+ return done(err);
+ }
+
+ return done(null);
+ });
+ });
+ });
+
+ done(null);
+ });
+ });
+};
+
+module.exports.delete = (formId, callback) => {
+ formId = Number(formId) || 0;
+
+ if (formId < 1) {
+ return callback(new Error(_('Missing Form ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM custom_forms WHERE id=? LIMIT 1', [formId], (err, rows) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ connection.release();
+ return callback(new Error(_('Custom form not found')));
+ }
+
+ connection.query('DELETE FROM custom_forms WHERE id=? LIMIT 1', [formId], err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+ });
+ });
+};
+
+function setDefaultValues(form) {
+ let getContents = fileName => {
+ try {
+ let basePath = path.join(__dirname, '..', '..');
+ let template = fs.readFileSync(path.join(basePath, fileName), 'utf8');
+ return template.replace(/\{\{#translate\}\}(.*?)\{\{\/translate\}\}/g, (m, s) => _(s));
+ } catch (err) {
+ return false;
+ }
+ };
+
+ allowedKeys.forEach(key => {
+ let modelKey = tools.fromDbKey(key);
+ let base = 'views/subscription/' + key.replace(/_/g, '-');
+
+ if (key.startsWith('mail') || key.startsWith('web')) {
+ form[modelKey] = getContents(base + '.mjml.hbs') || getContents(base + '.hbs') || '';
+ }
+ });
+
+ form.layout = getContents('views/subscription/layout.mjml.hbs') || '';
+ form.formInputStyle = getContents('public/subscription/form-input-style.css') || '@import url(/subscription/form-input-style.css);';
+
+ return form;
+}
+
+function filterKeysAndValues(keysIn, valuesIn, method = 'include', prefixes = []) {
+ let values = [];
+
+ let prefixMatch = key => (
+ prefixes.some(prefix => key.startsWith(prefix))
+ );
+
+ let keys = keysIn.filter((key, index) => {
+ if ((method === 'include' && prefixMatch(key)) || (method === 'exclude' && !prefixMatch(key))) {
+ values.push(valuesIn[index]);
+ return true;
+ }
+ return false;
+ });
+
+ return {
+ keys,
+ values
+ };
+}
+
+function testForMjmlErrors(keys, values) {
+
+ let errors = [];
+ let testLayout = '{{{body}}} ';
+
+ let hasMjmlError = (template, layout = testLayout) => {
+ let source = layout.replace(/\{\{\{body\}\}\}/g, template);
+ let compiled;
+
+ try {
+ compiled = mjml.mjml2html(source);
+ } catch (err) {
+ return err;
+ }
+
+ if (compiled.errors.length) {
+ return compiled.errors[0].message || compiled.errors[0];
+ }
+
+ return null;
+ };
+
+ keys.forEach((key, index) => {
+ if (key.startsWith('mail_') || key.startsWith('web_')) {
+
+ let template = values[index];
+ let err = hasMjmlError(template);
+
+ err && errors.push(key + ': ' + (err.message || err));
+ key === 'mail_confirm_html' && !template.includes('{{confirmUrl}}') && errors.push(key + ': Missing {{confirmUrl}}');
+
+ } else if (key === 'layout') {
+
+ let layout = values[index];
+ let err = hasMjmlError('', layout);
+
+ err && errors.push('layout: ' + (err.message || err));
+ !layout.includes('{{{body}}}') && errors.push('layout: {{{body}}} not found');
+ }
+ });
+
+
+ if (errors.length) {
+ errors.forEach((err, index) => {
+ errors[index] = (index + 1) + ') ' + err;
+ });
+ return 'Please fix these MJML errors:\n\n' + errors.join('\n');
+ }
+
+ return null;
+}
diff --git a/lib/models/links.js b/lib/models/links.js
index 7beeecd3..e7ce5591 100644
--- a/lib/models/links.js
+++ b/lib/models/links.js
@@ -3,6 +3,7 @@
let db = require('../db');
let shortid = require('shortid');
let util = require('util');
+let _ = require('../translate')._;
let geoip = require('geoip-ultralight');
let campaigns = require('./campaigns');
@@ -11,41 +12,40 @@ let lists = require('./lists');
let log = require('npmlog');
let urllib = require('url');
+let he = require('he');
+let ua_parser = require('device');
-module.exports.resolve = (campaignCid, linkCid, callback) => {
- campaigns.getByCid(campaignCid, (err, campaign) => {
+module.exports.resolve = (linkCid, callback) => {
+ db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
- if (!campaign) {
- return callback('Campaign not found');
- }
- db.getConnection((err, connection) => {
+ let query = 'SELECT id, url FROM links WHERE `cid`=? LIMIT 1';
+ connection.query(query, [linkCid], (err, rows) => {
+ connection.release();
if (err) {
return callback(err);
}
- let query = 'SELECT id, url FROM links WHERE `campaign`=? AND `cid`=? LIMIT 1';
- connection.query(query, [campaign.id, linkCid], (err, rows) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- if (rows && rows.length) {
- return callback(null, rows[0].id, rows[0].url);
- }
+ if (rows && rows.length) {
+ return callback(null, rows[0].id, rows[0].url);
+ }
- return callback(null, false);
- });
+ return callback(null, false);
});
});
};
-module.exports.countClick = (remoteIp, campaignCid, listCid, subscriptionCid, linkId, callback) => {
+module.exports.countClick = (remoteIp, useragent, campaignCid, listCid, subscriptionCid, linkId, callback) => {
getSubscriptionData(campaignCid, listCid, subscriptionCid, (err, data) => {
if (err) {
return callback(err);
}
+
+ if (!data || data.campaign.clickTrackingDisabled) {
+ return callback(null, false);
+ }
+
db.getConnection((err, connection) => {
if (err) {
return callback(err);
@@ -53,13 +53,14 @@ module.exports.countClick = (remoteIp, campaignCid, listCid, subscriptionCid, li
connection.beginTransaction(err => {
if (err) {
+ connection.release();
return callback(err);
}
let country = geoip.lookupCountry(remoteIp) || null;
-
- let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `country`) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE `count`=`count`+1';
- connection.query(query, [data.list.id, data.subscription.id, linkId, remoteIp, country], (err, result) => {
+ let device = ua_parser(useragent, { unknownUserAgentDeviceType: 'desktop', emptyUserAgentDeviceType: 'desktop' });
+ let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `device_type`, `country`) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `count`=`count`+1';
+ connection.query(query, [data.list.id, data.subscription.id, linkId, remoteIp, device.type, country], (err, result) => {
if (err && err.code !== 'ER_DUP_ENTRY') {
return connection.rollback(() => {
connection.release();
@@ -98,8 +99,8 @@ module.exports.countClick = (remoteIp, campaignCid, listCid, subscriptionCid, li
});
}
- let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `country`) VALUES (?,?,?,?,?)';
- connection.query(query, [data.list.id, data.subscription.id, 0, remoteIp, country], err => {
+ let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `device_type`, `country`) VALUES (?,?,?,?,?,?)';
+ connection.query(query, [data.list.id, data.subscription.id, 0, remoteIp, device.type, country], err => {
if (err && err.code !== 'ER_DUP_ENTRY') {
return connection.rollback(() => {
connection.release();
@@ -141,7 +142,7 @@ module.exports.countClick = (remoteIp, campaignCid, listCid, subscriptionCid, li
});
// also count clicks as open events in case beacon image was blocked
- module.exports.countOpen(remoteIp, campaignCid, listCid, subscriptionCid, () => false);
+ module.exports.countOpen(remoteIp, useragent, campaignCid, listCid, subscriptionCid, () => false);
});
});
});
@@ -151,12 +152,16 @@ module.exports.countClick = (remoteIp, campaignCid, listCid, subscriptionCid, li
});
};
-module.exports.countOpen = (remoteIp, campaignCid, listCid, subscriptionCid, callback) => {
+module.exports.countOpen = (remoteIp, useragent, campaignCid, listCid, subscriptionCid, callback) => {
getSubscriptionData(campaignCid, listCid, subscriptionCid, (err, data) => {
if (err) {
return callback(err);
}
+ if (!data || data.campaign.openTrackingDisabled) {
+ return callback(null, false);
+ }
+
db.getConnection((err, connection) => {
if (err) {
return callback(err);
@@ -164,13 +169,14 @@ module.exports.countOpen = (remoteIp, campaignCid, listCid, subscriptionCid, cal
connection.beginTransaction(err => {
if (err) {
+ connection.release();
return callback(err);
}
let country = geoip.lookupCountry(remoteIp) || null;
-
- let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `country`) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE `count`=`count`+1';
- connection.query(query, [data.list.id, data.subscription.id, -1, remoteIp, country], (err, result) => {
+ let device = ua_parser(useragent, { unknownUserAgentDeviceType: 'desktop', emptyUserAgentDeviceType: 'desktop' });
+ let query = 'INSERT INTO `campaign_tracker__' + data.campaign.id + '` (`list`, `subscriber`, `link`, `ip`, `device_type`, `country`) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE `count`=`count`+1';
+ connection.query(query, [data.list.id, data.subscription.id, -1, remoteIp, device.type, country], (err, result) => {
if (err && err.code !== 'ER_DUP_ENTRY') {
return connection.rollback(() => {
connection.release();
@@ -262,50 +268,64 @@ module.exports.add = (url, campaignId, callback) => {
};
module.exports.updateLinks = (campaign, list, subscription, serviceUrl, message, callback) => {
- let re = /(]* href\s*=[\s"']*)(http[^"'>\s]+)/gi;
- let urls = new Set();
- message.replace(re, (match, prefix, url) => {
- urls.add(url);
- });
-
- let map = new Map();
- let vals = urls.values();
-
- // insert tracking image
- let inserted = false;
- let imgUrl = urllib.resolve(serviceUrl, util.format('/links/%s/%s/%s', campaign.cid, list.cid, encodeURIComponent(subscription.cid)));
- let img = '
';
- message = message.replace(/<\/body\b/i, match => {
- inserted = true;
- return img + match;
- });
- if (!inserted) {
- message = message + img;
+ if ((campaign.openTrackingDisabled && campaign.clickTrackingDisabled) || !message || !message.trim()) {
+ // tracking is disabled, do not modify the message
+ return setImmediate(() => callback(null, message));
}
-
- let replaceUrls = () => {
- callback(null,
- message.replace(re, (match, prefix, url) =>
- prefix + (map.has(url) ? urllib.resolve(serviceUrl, util.format('/links/%s/%s/%s/%s', campaign.cid, list.cid, encodeURIComponent(subscription.cid), encodeURIComponent(map.get(url)))) : url)));
- };
-
- let storeNext = () => {
- let urlItem = vals.next();
- if (urlItem.done) {
- return replaceUrls();
- }
-
- module.exports.add(urlItem.value, campaign.id, (err, linkId, cid) => {
- if (err) {
- log.error('Link', err.stack);
- return storeNext();
- }
- map.set(urlItem.value, cid);
- return storeNext();
+
+ // insert tracking image
+ if (!campaign.openTrackingDisabled) {
+ let inserted = false;
+ let imgUrl = urllib.resolve(serviceUrl, util.format('/links/%s/%s/%s', campaign.cid, list.cid, encodeURIComponent(subscription.cid)));
+ let img = '
';
+ message = message.replace(/<\/body\b/i, match => {
+ inserted = true;
+ return img + match;
+ });
+ if (!inserted) {
+ message = message + img;
+ }
+ if (campaign.clickTrackingDisabled) {
+ return callback(null, message);
+ }
+ }
+
+ if (!campaign.clickTrackingDisabled) {
+ let re = /(]* href\s*=[\s"']*)(http[^"'>\s]+)/gi;
+ let urls = new Set();
+ (message || '').replace(re, (match, prefix, url) => {
+ urls.add(url);
});
- };
- storeNext();
+ let map = new Map();
+ let vals = urls.values();
+
+ let replaceUrls = () => {
+ callback(null,
+ message.replace(re, (match, prefix, url) =>
+ prefix + (map.has(url) ? urllib.resolve(serviceUrl, util.format('/links/%s/%s/%s/%s', campaign.cid, list.cid, encodeURIComponent(subscription.cid), encodeURIComponent(map.get(url)))) : url)));
+ };
+
+ let storeNext = () => {
+ let urlItem = vals.next();
+ if (urlItem.done) {
+ return replaceUrls();
+ }
+
+ module.exports.add(he.decode(urlItem.value, {
+ isAttributeValue: true
+ }), campaign.id, (err, linkId, cid) => {
+ if (err) {
+ log.error('Link', err);
+ return storeNext();
+ }
+ map.set(urlItem.value, cid);
+ return storeNext();
+ });
+ };
+
+ storeNext();
+ }
};
function getSubscriptionData(campaignCid, listCid, subscriptionCid, callback) {
@@ -314,7 +334,7 @@ function getSubscriptionData(campaignCid, listCid, subscriptionCid, callback) {
return callback(err);
}
if (!campaign) {
- return callback(new Error('Campaign not found'));
+ return callback(new Error(_('Campaign not found')));
}
lists.getByCid(listCid, (err, list) => {
@@ -322,7 +342,7 @@ function getSubscriptionData(campaignCid, listCid, subscriptionCid, callback) {
return callback(err);
}
if (!list) {
- return callback(new Error('Campaign not found'));
+ return callback(new Error(_('List not found')));
}
subscriptions.get(list.id, subscriptionCid, (err, subscription) => {
@@ -330,7 +350,7 @@ function getSubscriptionData(campaignCid, listCid, subscriptionCid, callback) {
return callback(err);
}
if (!subscription) {
- return callback(new Error('Subscription not found'));
+ return callback(new Error(_('Subscription not found')));
}
return callback(null, {
diff --git a/lib/models/lists.js b/lib/models/lists.js
index c464b702..6c0a498a 100644
--- a/lib/models/lists.js
+++ b/lib/models/lists.js
@@ -4,29 +4,33 @@ let db = require('../db');
let tools = require('../tools');
let shortid = require('shortid');
let segments = require('./segments');
+let subscriptions = require('./subscriptions');
+let _ = require('../translate')._;
+let tableHelpers = require('../table-helpers');
-let allowedKeys = ['description'];
+const UnsubscriptionMode = {
+ ONE_STEP: 0,
+ ONE_STEP_WITH_FORM: 1,
+ TWO_STEP: 2,
+ TWO_STEP_WITH_FORM: 3,
+ MANUAL: 4,
+ MAX: 5
+};
+
+module.exports.UnsubscriptionMode = UnsubscriptionMode;
+
+let allowedKeys = ['description', 'default_form', 'public_subscribe', 'unsubscription_mode', 'listunsubscribe_disabled'];
module.exports.list = (start, limit, callback) => {
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
+ tableHelpers.list('lists', ['*'], 'name', null, start, limit, callback);
+};
- connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM lists ORDER BY name LIMIT ? OFFSET ?', [limit, start], (err, rows) => {
- if (err) {
- connection.release();
- return callback(err);
- }
- connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- return callback(null, rows, total && total[0] && total[0].total);
- });
- });
- });
+module.exports.filter = (request, parent, callback) => {
+ tableHelpers.filter('lists', ['*'], request, ['#', 'name', 'cid', 'subscribers', 'description'], ['name'], 'name ASC', null, callback);
+};
+
+module.exports.filterQuicklist = (request, callback) => {
+ tableHelpers.filter('lists', ['id', 'name', 'subscribers'], request, ['#', 'name', 'subscribers'], ['name'], 'name ASC', null, callback);
};
module.exports.quicklist = callback => {
@@ -61,6 +65,37 @@ module.exports.quicklist = callback => {
});
};
+module.exports.getListsWithEmail = (email, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT id, name FROM lists', (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let lists = (rows || []).map(tools.convertKeys);
+ const results = [];
+ lists.forEach((list, index, arr) => {
+ subscriptions.getByEmail(list.id, email, (err, sub) => {
+ if (err) {
+ return callback(err);
+ }
+ if (sub) {
+ results.push(list.id);
+ }
+ if (index === arr.length - 1) {
+ return callback(null, lists.filter(list => results.includes(list.id)));
+ }
+ });
+ });
+ });
+ });
+};
+
module.exports.getByCid = (cid, callback) => {
resolveCid(cid, (err, id) => {
if (err) {
@@ -77,7 +112,7 @@ module.exports.get = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
db.getConnection((err, connection) => {
@@ -107,21 +142,84 @@ module.exports.get = (id, callback) => {
});
};
+module.exports.update = (id, updates, callback) => {
+ updates = updates || {};
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing List ID')));
+ }
+
+ const data = tools.convertKeys(updates);
+
+ const keys = [];
+ const values = [];
+
+ // The update can be only partial when executed from forms/:list
+ if (!data.customFormChangeOnly) {
+ data.publicSubscribe = data.publicSubscribe ? 1 : 0;
+ data.listunsubscribeDisabled = data.listunsubscribeDisabled ? 1 : 0;
+ data.unsubscriptionMode = Number(data.unsubscriptionMode);
+
+ let name = (data.name || '').toString().trim();
+
+ if (!name) {
+ return callback(new Error(_('List Name must be set')));
+ }
+
+ keys.push('name');
+ values.push(name);
+ }
+
+ Object.keys(data).forEach(key => {
+ let value = data[key].toString().trim();
+ key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+ if (allowedKeys.indexOf(key) >= 0) {
+ keys.push(key);
+ values.push(value);
+ }
+ });
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ values.push(id);
+
+ connection.query('UPDATE lists SET ' + keys.map(key => key + '=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, result && result.affectedRows || false);
+ });
+ });
+};
+
module.exports.create = (list, callback) => {
let data = tools.convertKeys(list);
+ data.publicSubscribe = data.publicSubscribe ? 1 : 0;
+
let name = (data.name || '').toString().trim();
if (!data) {
- return callback(new Error('List Name must be set'));
+ return callback(new Error(_('List Name must be set')));
}
let keys = ['name'];
let values = [name];
- Object.keys(list).forEach(key => {
- let value = list[key].trim();
+ Object.keys(data).forEach(key => {
+ let value = data[key].toString().trim();
key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
if (allowedKeys.indexOf(key) >= 0) {
keys.push(key);
values.push(value);
@@ -160,55 +258,11 @@ module.exports.create = (list, callback) => {
});
};
-module.exports.update = (id, updates, callback) => {
- updates = updates || {};
- id = Number(id) || 0;
-
- let data = tools.convertKeys(updates);
-
- let name = (data.name || '').toString().trim();
- let keys = ['name'];
- let values = [name];
-
- if (id < 1) {
- return callback(new Error('Missing List ID'));
- }
-
- if (!name) {
- return callback(new Error('List Name must be set'));
- }
-
- Object.keys(updates).forEach(key => {
- let value = updates[key].trim();
- key = tools.toDbKey(key);
- if (allowedKeys.indexOf(key) >= 0) {
- keys.push(key);
- values.push(value);
- }
- });
-
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- values.push(id);
-
- connection.query('UPDATE lists SET ' + keys.map(key => key + '=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- return callback(null, result && result.affectedRows || false);
- });
- });
-};
-
module.exports.delete = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
db.getConnection((err, connection) => {
@@ -237,7 +291,7 @@ module.exports.delete = (id, callback) => {
function resolveCid(cid, callback) {
cid = (cid || '').toString().trim();
if (!cid) {
- return callback(new Error('Missing List CID'));
+ return callback(new Error(_('Missing List CID')));
}
db.getConnection((err, connection) => {
diff --git a/lib/models/report-templates.js b/lib/models/report-templates.js
new file mode 100644
index 00000000..6dcb2c70
--- /dev/null
+++ b/lib/models/report-templates.js
@@ -0,0 +1,161 @@
+'use strict';
+
+const db = require('../db');
+const tableHelpers = require('../table-helpers');
+const tools = require('../tools');
+const _ = require('../translate')._;
+
+const allowedKeys = ['name', 'description', 'mime_type', 'user_fields', 'js', 'hbs'];
+
+module.exports.list = (start, limit, callback) => {
+ tableHelpers.list('report_templates', ['*'], 'name', null, start, limit, callback);
+};
+
+module.exports.quicklist = callback => {
+ tableHelpers.quicklist('report_templates', ['id', 'name'], 'name', callback);
+};
+
+module.exports.filter = (request, callback) => {
+ tableHelpers.filter('report_templates', ['*'], request, ['#', 'name', 'description', 'created'], ['name'], 'created DESC', null, callback);
+};
+
+module.exports.get = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing report template ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM report_templates WHERE id=?', [id], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ const template = tools.convertKeys(rows[0]);
+
+ const userFields = template.userFields.trim();
+ if (userFields !== '') {
+ try {
+ template.userFieldsObject = JSON.parse(userFields);
+ } catch (err) {
+ // This is to handle situation when for some reason we get corrupted JSON in the DB.
+ template.userFieldsObject = {};
+ template.userFields = '{}';
+ }
+ } else {
+ template.userFieldsObject = {};
+ }
+
+ return callback(null, template);
+ });
+ });
+};
+
+module.exports.createOrUpdate = (createMode, data, callback) => {
+ data = data || {};
+
+ const id = 'id' in data ? Number(data.id) : 0;
+
+ if (!createMode && id < 1) {
+ return callback(new Error(_('Missing report template ID')));
+ }
+
+ const template = tools.convertKeys(data);
+ const name = (template.name || '').toString().trim();
+
+ if (!name) {
+ return callback(new Error(_('Report template name must be set')));
+ }
+
+ const keys = ['name'];
+ const values = [name];
+
+ Object.keys(template).forEach(key => {
+ let value = typeof template[key] === 'number' ? template[key] : (template[key] || '').toString().trim();
+ key = tools.toDbKey(key);
+
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+
+ if (key === 'user_fields') {
+ value = value.trim();
+
+ if (value !== '') {
+ try {
+ JSON.parse(value);
+ } catch (err) {
+ return callback(err);
+ }
+ }
+ }
+
+ if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) {
+ keys.push(key);
+ values.push(value);
+ }
+ });
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query;
+
+ if (createMode) {
+ query = 'INSERT INTO report_templates (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')';
+ } else {
+ query = 'UPDATE report_templates SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1';
+ values.push(id);
+ }
+
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (createMode) {
+ return callback(null, result && result.insertId || false);
+ } else {
+ return callback(null, result && result.affectedRows || false);
+ }
+ });
+ });
+};
+
+module.exports.delete = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing report template ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('DELETE FROM report_templates WHERE id=? LIMIT 1', [id], (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ const affected = result && result.affectedRows || 0;
+ return callback(err, affected);
+ });
+ });
+};
+
diff --git a/lib/models/reports.js b/lib/models/reports.js
new file mode 100644
index 00000000..edfe665f
--- /dev/null
+++ b/lib/models/reports.js
@@ -0,0 +1,262 @@
+'use strict';
+
+const db = require('../db');
+const tableHelpers = require('../table-helpers');
+const fields = require('./fields');
+const reportTemplates = require('./report-templates');
+const tools = require('../tools');
+const _ = require('../translate')._;
+
+const allowedKeys = ['name', 'description', 'report_template', 'params'];
+
+const ReportState = {
+ SCHEDULED: 0,
+ PROCESSING: 1,
+ FINISHED: 2,
+ FAILED: 3,
+ MAX: 4
+};
+
+module.exports.ReportState = ReportState;
+
+module.exports.list = (start, limit, callback) => {
+ tableHelpers.list('reports', ['*'], 'name', null, start, limit, callback);
+};
+
+module.exports.listWithState = (state, start, limit, callback) => {
+ tableHelpers.list('reports', ['*'], 'name', { where: 'state=?', values: [state] }, start, limit, callback);
+};
+
+module.exports.filter = (request, callback) => {
+ tableHelpers.filter('reports JOIN report_templates ON reports.report_template = report_templates.id',
+ ['reports.id AS id', 'reports.name AS name', 'reports.description AS description', 'reports.state AS state', 'reports.report_template AS report_template', 'reports.params AS params', 'reports.last_run AS last_run', 'report_templates.name AS report_template_name', 'report_templates.mime_type AS mime_type' ],
+ request, ['#', 'name', 'report_templates.name', 'description', 'last_run'], ['name'], 'name ASC', null, callback);
+};
+
+module.exports.get = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing report ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM reports WHERE id=?', [id], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ const template = tools.convertKeys(rows[0]);
+
+ const params = template.params.trim();
+ if (params !== '') {
+ try {
+ template.paramsObject = JSON.parse(params);
+ } catch (err) {
+ return callback(err);
+ }
+ } else {
+ template.params = {};
+ }
+
+ return callback(null, template);
+ });
+ });
+};
+
+// This method is not supposed to be used for unsanitized inputs. It does not do any checks.
+module.exports.updateFields = (id, fieldValueMap, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ const clauses = [];
+ const values = [];
+ for (let key of Object.keys(fieldValueMap)) {
+ clauses.push(tools.toDbKey(key) + '=?');
+ values.push(fieldValueMap[key]);
+ }
+
+ values.push(id);
+
+ const query = 'UPDATE reports SET ' + clauses.join(', ') + ' WHERE id=? LIMIT 1';
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ return callback(null, result && result.affectedRows || false);
+ });
+ });
+};
+
+module.exports.createOrUpdate = (createMode, report, callback) => {
+ report = report || {};
+
+ const id = 'id' in report ? Number(report.id) : 0;
+
+ if (!createMode && id < 1) {
+ return callback(new Error(_('Missing report ID')));
+ }
+
+ const name = (report.name || '').toString().trim();
+
+ if (!name) {
+ return callback(new Error(_('Report name must be set')));
+ }
+
+ const reportTemplateId = Number(report.reportTemplate);
+ reportTemplates.get(reportTemplateId, (err, reportTemplate) => {
+ if (err) {
+ return callback(err);
+ }
+
+ const params = report.paramsObject;
+ for (const spec of reportTemplate.userFieldsObject) {
+ if (params[spec.id].length < spec.minOccurences) {
+ return callback(new Error(_('At least ' + spec.minOccurences + ' rows in "' + spec.name + '" have to be selected.')));
+ }
+
+ if (params[spec.id].length > spec.maxOccurences) {
+ return callback(new Error(_('At most ' + spec.minOccurences + ' rows in "' + spec.name + '" can be selected.')));
+ }
+ }
+
+ const keys = ['name', 'params'];
+ const values = [name, JSON.stringify(params)];
+
+
+ Object.keys(report).forEach(key => {
+ let value = typeof report[key] === 'number' ? report[key] : (report[key] || '').toString().trim();
+ key = tools.toDbKey(key);
+
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+
+ if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) {
+ keys.push(key);
+ values.push(value);
+ }
+ });
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query;
+
+ if (createMode) {
+ query = 'INSERT INTO reports (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(',') + ')';
+ } else {
+ query = 'UPDATE reports SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE id=? LIMIT 1';
+ values.push(id);
+ }
+
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (createMode) {
+ return callback(null, result && result.insertId || false);
+ } else {
+ return callback(null, result && result.affectedRows || false);
+ }
+ });
+ });
+ });
+};
+
+module.exports.delete = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing report ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('DELETE FROM reports WHERE id=? LIMIT 1', [id], (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ const affected = result && result.affectedRows || 0;
+ return callback(err, affected);
+ });
+ });
+};
+
+const campaignFieldsMapping = {
+ tracker_count: 'tracker.count',
+ country: 'tracker.country',
+ device_type: 'tracker.device_type',
+ status: 'campaign.status',
+ first_name: 'subscribers.first_name',
+ last_name: 'subscribers.last_name',
+ email: 'subscribers.email'
+};
+
+module.exports.getCampaignResults = (campaign, select, clause, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ fields.list(campaign.list, (err, fieldList) => {
+ if (err) {
+ return callback(err);
+ }
+
+ const fieldsMapping = fieldList.reduce((map, field) => {
+ map[customFieldName(field.key)] = 'subscribers.' + field.column;
+ return map;
+ }, Object.assign({}, campaignFieldsMapping));
+
+ let selFields = [];
+ for (let idx = 0; idx < select.length; idx++) {
+ const item = select[idx];
+ if (item in fieldsMapping) {
+ selFields.push(fieldsMapping[item] + ' AS ' + item);
+ } else if (item === '*') {
+ selFields = selFields.concat(Object.keys(fieldsMapping).map(item => fieldsMapping[item] + ' AS ' + item));
+ } else {
+ selFields.push(item);
+ }
+ }
+
+ const query = 'SELECT ' + selFields.join(', ') + ' FROM `subscription__' + campaign.list + '` subscribers INNER JOIN `campaign__' + campaign.id + '` campaign on subscribers.id=campaign.subscription LEFT JOIN `campaign_tracker__' + campaign.id + '` tracker on subscribers.id=tracker.subscriber ' + clause;
+
+ connection.query(query, (err, results) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ return callback(null, results);
+ });
+ });
+ });
+};
+
+function customFieldName(id) {
+ return id.replace(/MERGE_/, 'CUSTOM_').toLowerCase();
+}
diff --git a/lib/models/segments.js b/lib/models/segments.js
index 63025fb8..a2e891f9 100644
--- a/lib/models/segments.js
+++ b/lib/models/segments.js
@@ -3,34 +3,36 @@
let tools = require('../tools');
let db = require('../db');
let fields = require('./fields');
+let util = require('util');
+let _ = require('../translate')._;
module.exports.defaultColumns = [{
column: 'email',
- name: 'Email address',
+ name: _('Email address'),
type: 'string'
}, {
column: 'opt_in_country',
- name: 'Signup country',
+ name: _('Signup country'),
type: 'string'
}, {
column: 'created',
- name: 'Sign up date',
+ name: _('Sign up date'),
type: 'date'
}, {
column: 'latest_open',
- name: 'Latest open',
+ name: _('Latest open'),
type: 'date'
}, {
column: 'latest_click',
- name: 'Latest click',
+ name: _('Latest click'),
type: 'date'
}, {
column: 'first_name',
- name: 'First name',
+ name: _('First name'),
type: 'string'
}, {
column: 'last_name',
- name: 'Last name',
+ name: _('Last name'),
type: 'string'
}];
@@ -38,7 +40,7 @@ module.exports.list = (listId, callback) => {
listId = Number(listId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
@@ -64,7 +66,7 @@ module.exports.get = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Segment ID'));
+ return callback(new Error(_('Missing Segment ID')));
}
db.getConnection((err, connection) => {
@@ -80,7 +82,7 @@ module.exports.get = (id, callback) => {
}
if (!rows || !rows.length) {
connection.release();
- return callback(new Error('Segment not found'));
+ return callback(new Error(_('Segment not found')));
}
let segment = tools.convertKeys(rows[0]);
@@ -140,17 +142,21 @@ module.exports.get = (id, callback) => {
case 'number':
case 'date':
case 'birthday':
- if (rule.value.range) {
+ if (rule.value.relativeRange) {
+ let startString = rule.value.startDirection ? util.format(_('%s days after today'), rule.value.start) : util.format(_('%s days before today'), rule.value.start);
+ let endString = rule.value.endDirection ? util.format(_('%s days after today'), rule.value.end) : util.format(_('%s days before today'), rule.value.end);
+ rule.formatted = (rule.value.start ? startString : _('today')) + ' … ' + (rule.value.end ? endString : _('today'));
+ } else if (rule.value.range) {
rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || '');
} else {
rule.formatted = rule.value.value || '';
}
break;
case 'boolean':
- rule.formatted = rule.value.value ? 'Selected' : 'Not selected';
+ rule.formatted = rule.value.value ? _('Selected') : _('Not selected');
break;
default:
- rule.formatted = rule.value.value || '';
+ rule.formatted = (rule.value.negate ? '!= ' : '') + (rule.value.value || '');
}
return rule;
@@ -167,7 +173,7 @@ module.exports.create = (listId, segment, callback) => {
listId = Number(listId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
segment = tools.convertKeys(segment);
@@ -176,11 +182,11 @@ module.exports.create = (listId, segment, callback) => {
segment.type = Number(segment.type) || 0;
if (!segment.name) {
- return callback(new Error('Field Name must be set'));
+ return callback(new Error(_('Field Name must be set')));
}
if (segment.type <= 0) {
- return callback(new Error('Invalid segment rule type'));
+ return callback(new Error(_('Invalid segment rule type')));
}
let keys = ['list', 'name', 'type'];
@@ -207,7 +213,7 @@ module.exports.update = (id, updates, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Segment ID'));
+ return callback(new Error(_('Missing Segment ID')));
}
let segment = tools.convertKeys(updates);
@@ -216,11 +222,11 @@ module.exports.update = (id, updates, callback) => {
segment.type = Number(segment.type) || 0;
if (!segment.name) {
- return callback(new Error('Field Name must be set'));
+ return callback(new Error(_('Field Name must be set')));
}
if (segment.type <= 0) {
- return callback(new Error('Invalid segment rule type'));
+ return callback(new Error(_('Invalid segment rule type')));
}
let keys = ['name', 'type'];
@@ -247,7 +253,7 @@ module.exports.delete = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Segment ID'));
+ return callback(new Error(_('Missing Segment ID')));
}
db.getConnection((err, connection) => {
@@ -269,7 +275,7 @@ module.exports.createRule = (segmentId, rule, callback) => {
segmentId = Number(segmentId) || 0;
if (segmentId < 1) {
- return callback(new Error('Missing Segment ID'));
+ return callback(new Error(_('Missing Segment ID')));
}
rule = tools.convertKeys(rule);
@@ -280,12 +286,12 @@ module.exports.createRule = (segmentId, rule, callback) => {
}
if (!segment) {
- return callback(new Error('Selected segment not found'));
+ return callback(new Error(_('Selected segment not found')));
}
let column = segment.columns.filter(column => column.column === rule.column).pop();
if (!column) {
- return callback(new Error('Invalid rule type'));
+ return callback(new Error(_('Invalid rule type')));
}
let value;
@@ -294,7 +300,15 @@ module.exports.createRule = (segmentId, rule, callback) => {
case 'date':
case 'birthday':
case 'number':
- if (rule.range) {
+ if (column.type === 'date' && rule.range === 'relative') {
+ value = {
+ relativeRange: true,
+ start: Number(rule.startRelative) || 0,
+ startDirection: Number(rule.startDirection) ? 1 : 0,
+ end: Number(rule.endRelative) || 0,
+ endDirection: Number(rule.endDirection) ? 1 : 0
+ };
+ } else if (rule.range === 'yes') {
value = {
range: true,
start: rule.start,
@@ -313,6 +327,7 @@ module.exports.createRule = (segmentId, rule, callback) => {
break;
default:
value = {
+ negate: Number(rule.negate) ? 1 : 0,
value: rule.value
};
}
@@ -341,7 +356,7 @@ module.exports.getRule = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Rule ID'));
+ return callback(new Error(_('Missing Rule ID')));
}
db.getConnection((err, connection) => {
@@ -357,7 +372,7 @@ module.exports.getRule = (id, callback) => {
}
if (!rows || !rows.length) {
- return callback(new Error('Specified rule not found'));
+ return callback(new Error(_('Specified rule not found')));
}
let rule = tools.convertKeys(rows[0]);
@@ -368,7 +383,7 @@ module.exports.getRule = (id, callback) => {
}
if (!segment) {
- return callback(new Error('Specified segment not found'));
+ return callback(new Error(_('Specified segment not found')));
}
if (rule.value) {
@@ -389,17 +404,22 @@ module.exports.getRule = (id, callback) => {
case 'number':
case 'date':
case 'birthday':
- if (rule.value.range) {
+ if (rule.value.relativeRange) {
+
+ let startString = rule.value.startDirection ? util.format(_('%s days after today'), rule.value.start) : util.format(_('%s days before today'), rule.value.start);
+ let endString = rule.value.endDirection ? util.format(_('%s days after today'), rule.value.end) : util.format(_('%s days before today'), rule.value.end);
+ rule.formatted = (rule.value.start ? startString : _('today')) + ' … ' + (rule.value.end ? endString : _('today'));
+ } else if (rule.value.range) {
rule.formatted = (rule.value.start || '') + ' … ' + (rule.value.end || '');
} else {
rule.formatted = rule.value.value || '';
}
break;
case 'boolean':
- rule.formatted = rule.value.value ? 'Selected' : 'Not selected';
+ rule.formatted = rule.value.value ? _('Selected') : _('Not selected');
break;
default:
- rule.formatted = rule.value.value || '';
+ rule.formatted = (rule.value.negate ? '!= ' : '') + (rule.value.value || '');
}
return callback(null, rule);
@@ -412,7 +432,7 @@ module.exports.updateRule = (id, rule, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Rule ID'));
+ return callback(new Error(_('Missing Rule ID')));
}
rule = tools.convertKeys(rule);
@@ -423,7 +443,7 @@ module.exports.updateRule = (id, rule, callback) => {
}
if (!existingRule) {
- return callback(new Error('Selected rule not found'));
+ return callback(new Error(_('Selected rule not found')));
}
module.exports.get(existingRule.segment, (err, segment) => {
@@ -432,12 +452,12 @@ module.exports.updateRule = (id, rule, callback) => {
}
if (!segment) {
- return callback(new Error('Selected segment not found'));
+ return callback(new Error(_('Selected segment not found')));
}
let column = segment.columns.filter(column => column.column === existingRule.column).pop();
if (!column) {
- return callback(new Error('Invalid rule type'));
+ return callback(new Error(_('Invalid rule type')));
}
let value;
@@ -445,7 +465,15 @@ module.exports.updateRule = (id, rule, callback) => {
case 'date':
case 'birthday':
case 'number':
- if (rule.range) {
+ if (column.type === 'date' && rule.range === 'relative') {
+ value = {
+ relativeRange: true,
+ start: Number(rule.startRelative) || 0,
+ startDirection: Number(rule.startDirection) ? 1 : 0,
+ end: Number(rule.endRelative) || 0,
+ endDirection: Number(rule.endDirection) ? 1 : 0
+ };
+ } else if (rule.range === 'yes') {
value = {
range: true,
start: rule.start,
@@ -464,6 +492,7 @@ module.exports.updateRule = (id, rule, callback) => {
break;
default:
value = {
+ negate: Number(rule.negate) ? 1 : 0,
value: rule.value
};
}
@@ -494,7 +523,7 @@ module.exports.deleteRule = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Rule ID'));
+ return callback(new Error(_('Missing Rule ID')));
}
db.getConnection((err, connection) => {
@@ -512,19 +541,26 @@ module.exports.deleteRule = (id, callback) => {
});
};
-module.exports.getQuery = (id, callback) => {
+module.exports.getQuery = (id, prefix, callback) => {
module.exports.get(id, (err, segment) => {
if (err) {
return callback(err);
}
if (!segment) {
- return callback(new Error('Segment not found'));
+ return callback(new Error(_('Segment not found')));
}
+ prefix = prefix ? prefix + '.' : '';
+
let query = [];
let values = [];
+ let getRelativeDate = (days, direction) => {
+ let date = new Date(Date.now() + (direction ? 1 : -1) * days * 24 * 3600 * 1000);
+ return date.toISOString().substr(0, 10);
+ };
+
let getDate = (value, nextDay) => {
let parts = value.trim().split(/\D/);
let year = Number(parts.shift()) || 0;
@@ -538,47 +574,70 @@ module.exports.getQuery = (id, callback) => {
segment.rules.forEach(rule => {
switch (rule.columnType.type) {
- case 'string':
- query.push('`' + rule.columnType.column + '` LIKE ?');
+ case 'string': {
+ let condition = rule.value.negate ? 'NOT LIKE' : 'LIKE';
+ query.push(prefix + '`' + rule.columnType.column + '` ' + condition + ' ?');
values.push(rule.value.value);
break;
+ }
case 'boolean':
- query.push('`' + rule.columnType.column + '` = ?');
+ query.push(prefix + '`' + rule.columnType.column + '` = ?');
values.push(rule.value.value);
break;
case 'number':
if (rule.value.range) {
- query.push('`' + rule.columnType.column + '` >= ?');
- query.push('`' + rule.columnType.column + '` < ?');
- values.push(rule.value.start);
- values.push(rule.value.end);
+ let ruleval = '';
+ if (rule.value.start) {
+ ruleval = prefix + '`' + rule.columnType.column + '` >= ?';
+ values.push(rule.value.start);
+ }
+ if (rule.value.end) {
+ ruleval = (ruleval ? '(' + ruleval + ' AND ' : '') + prefix + '`' + rule.columnType.column + '` < ?' + (ruleval ? ')' : '');
+ values.push(rule.value.end);
+ }
+ if (ruleval) {
+ query.push(ruleval);
+ }
} else {
- query.push('`' + rule.columnType.column + '` = ?');
+ query.push(prefix + '`' + rule.columnType.column + '` = ?');
values.push(rule.value.value);
}
break;
case 'birthday':
if (rule.value.range) {
- query.push('`' + rule.columnType.column + '` >= ?');
- query.push('`' + rule.columnType.column + '` < ?');
- values.push(getDate('2000-' + rule.value.start));
- values.push(getDate('2000-' + rule.value.end, true));
+ let start = rule.value.start || '01-01';
+ let end = rule.value.end || '12-31';
+ query.push('(' + prefix + '`' + rule.columnType.column + '` >= ? AND ' + prefix + '`' + rule.columnType.column + '` < ?)');
+ values.push(getDate('2000-' + start));
+ values.push(getDate('2000-' + end, true));
} else {
- query.push('`' + rule.columnType.column + '` >= ?');
- query.push('`' + rule.columnType.column + '` < ?');
+ query.push('(' + prefix + '`' + rule.columnType.column + '` >= ? AND ' + prefix + '`' + rule.columnType.column + '` < ?)');
values.push(getDate('2000-' + rule.value.value));
values.push(getDate('2000-' + rule.value.value, true));
}
break;
case 'date':
- if (rule.value.range) {
- query.push('`' + rule.columnType.column + '` >= ?');
- query.push('`' + rule.columnType.column + '` < ?');
- values.push(getDate(rule.value.start));
- values.push(getDate(rule.value.end, true));
+ if (rule.value.relativeRange) {
+ query.push('(' + prefix + '`' + rule.columnType.column + '` >= ? AND ' + prefix + '`' + rule.columnType.column + '` < ?)');
+ // start
+ values.push(getDate(getRelativeDate(rule.value.start, rule.value.startDirection)));
+ // end
+ values.push(getDate(getRelativeDate(rule.value.end, rule.value.endDirection), true));
+ } else if (rule.value.range) {
+ let ruleval = '';
+ if (rule.value.start) {
+ ruleval = prefix + '`' + rule.columnType.column + '` >= ?';
+ values.push(getDate(rule.value.start));
+ }
+ if (rule.value.end) {
+ ruleval = (ruleval ? '(' + ruleval + ' AND ' : '') + prefix + '`' + rule.columnType.column + '` < ?' + (ruleval ? ')' : '');
+ values.push(getDate(rule.value.end, true));
+ }
+ if (ruleval) {
+ query.push(ruleval);
+ }
} else {
- query.push('`' + rule.columnType.column + '` >= ?');
- query.push('`' + rule.columnType.column + '` < ?');
+ query.push('(' + prefix + '`' + rule.columnType.column + '` >= ? AND ' + prefix + '`' + rule.columnType.column + '` < ?)');
values.push(getDate(rule.value.value));
values.push(getDate(rule.value.value, true));
}
@@ -600,9 +659,9 @@ module.exports.subscribers = (id, onlySubscribed, callback) => {
return callback(err);
}
if (!segment) {
- return callback(new Error('Segment not found'));
+ return callback(new Error(_('Segment not found')));
}
- module.exports.getQuery(id, (err, queryData) => {
+ module.exports.getQuery(id, false, (err, queryData) => {
if (err) {
return callback(err);
}
diff --git a/lib/models/settings.js b/lib/models/settings.js
index 77b9f391..9655ebd7 100644
--- a/lib/models/settings.js
+++ b/lib/models/settings.js
@@ -15,6 +15,8 @@ function listValues(filter, callback) {
filter = false;
}
+ // TODO: It would be good to cache the settings. It feels awkward to always go to DB to retrieve something what is essentially a constant
+
filter = [].concat(filter || []).map(key => tools.toDbKey(key));
db.getConnection((err, connection) => {
diff --git a/lib/models/subscriptions.js b/lib/models/subscriptions.js
index cae7cd8b..3a9a7f58 100644
--- a/lib/models/subscriptions.js
+++ b/lib/models/subscriptions.js
@@ -2,10 +2,23 @@
let db = require('../db');
let shortid = require('shortid');
+let striptags = require('striptags');
let tools = require('../tools');
+let helpers = require('../helpers');
let fields = require('./fields');
-let geoip = require('geoip-ultralight');
let segments = require('./segments');
+let _ = require('../translate')._;
+let tableHelpers = require('../table-helpers');
+
+const Status = {
+ SUBSCRIBED: 1,
+ UNSUBSCRIBED: 2,
+ BOUNCED: 3,
+ COMPLAINED: 4,
+ MAX: 5
+};
+
+module.exports.Status = Status;
module.exports.list = (listId, start, limit, callback) => {
listId = Number(listId) || 0;
@@ -13,25 +26,47 @@ module.exports.list = (listId, start, limit, callback) => {
return callback(new Error('Missing List ID'));
}
+ tableHelpers.list('subscription__' + listId, ['*'], 'email', null, start, limit, (err, rows, total) => {
+ if (!err) {
+ rows = rows.map(row => tools.convertKeys(row));
+ }
+ return callback(err, rows, total);
+ });
+};
+
+module.exports.listTestUsers = (listId, callback) => {
+ listId = Number(listId) || 0;
+
+ if (listId < 1) {
+ return callback(new Error('Missing List ID'));
+ }
+
db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
- connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` ORDER BY email LIMIT ? OFFSET ?', [limit, start], (err, rows) => {
+ connection.query('SELECT id, cid, email, first_name, last_name FROM `subscription__' + listId + '` WHERE is_test=1 LIMIT 100', (err, rows) => {
+ connection.release();
if (err) {
- connection.release();
return callback(err);
}
- connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- let subscriptions = rows.map(row => tools.convertKeys(row));
- return callback(null, subscriptions, total && total[0] && total[0].total);
+ if (!rows || !rows.length) {
+ return callback(null, []);
+ }
+
+ let subscribers = rows.map(subscriber => {
+ subscriber = tools.convertKeys(subscriber);
+ let fullName = [].concat(subscriber.firstName || []).concat(subscriber.lastName || []).join(' ');
+ if (fullName) {
+ subscriber.displayName = fullName + ' <' + subscriber.email + '>';
+ } else {
+ subscriber.displayName = subscriber.email;
+ }
+ return subscriber;
});
+ return callback(null, subscribers);
});
});
};
@@ -41,183 +76,34 @@ module.exports.filter = (listId, request, columns, segmentId, callback) => {
segmentId = Number(segmentId) || 0;
if (!listId) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
- let processQuery = queryData => {
-
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- let query = 'SELECT COUNT(id) AS total FROM `subscription__' + listId + '`';
- let values = [];
-
- if (queryData.where) {
- query += ' WHERE ' + queryData.where;
- values = values.concat(queryData.values || []);
- }
-
- connection.query(query, values, (err, total) => {
- if (err) {
- connection.release();
- return callback(err);
- }
- total = total && total[0] && total[0].total || 0;
-
- let ordering = [];
-
- if (request.order && request.order.length) {
-
- request.order.forEach(order => {
- let orderField = columns[Number(order.column)];
- let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC';
- if (orderField) {
- ordering.push('`' + orderField + '` ' + orderDirection);
- }
- });
- }
-
- if (!ordering.length) {
- ordering.push('`email` ASC');
- }
-
- let args = [Number(request.length) || 50, Number(request.start) || 0];
- let query;
-
- if (request.search && request.search.value) {
- query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` WHERE email LIKE ? OR first_name LIKE ? OR last_name LIKE ? ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?';
-
- let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%';
- args = [searchVal, searchVal, searchVal].concat(queryData.values || []).concat(args);
- } else {
- query = 'SELECT SQL_CALC_FOUND_ROWS * FROM `subscription__' + listId + '` WHERE 1 ' + (queryData.where ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?';
- args = [].concat(queryData.values || []).concat(args);
- }
-
- connection.query(query, args, (err, rows) => {
- if (err) {
- connection.release();
- return callback(err);
- }
- connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => {
- connection.release();
- if (err) {
- return callback(err);
- }
-
- let subscriptions = rows.map(row => tools.convertKeys(row));
-
- filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0;
- return callback(null, subscriptions, total, filteredTotal);
- });
- });
- });
- });
- };
-
if (segmentId) {
- segments.getQuery(segmentId, (err, queryData) => {
+ segments.getQuery(segmentId, false, (err, queryData) => {
if (err) {
return callback(err);
}
- processQuery(queryData);
+
+ tableHelpers.filter('subscription__' + listId, ['*'], request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback);
});
} else {
- processQuery(false);
+ tableHelpers.filter('subscription__' + listId, ['*'], request, columns, ['email', 'first_name', 'last_name'], 'email ASC', null, callback);
}
};
-module.exports.addConfirmation = (listId, email, data, callback) => {
- let cid = shortid.generate();
-
- tools.validateEmail(email, false, err => {
- if (err) {
- return callback(err);
- }
-
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- let query = 'INSERT INTO confirmations (cid, list, email, data) VALUES (?,?,?,?)';
- connection.query(query, [cid, listId, email, JSON.stringify(data || {})], (err, result) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- return callback(null, result && cid || false);
- });
- });
- });
-};
-
-module.exports.subscribe = (cid, optInIp, callback) => {
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- let query = 'SELECT * FROM confirmations WHERE cid=? LIMIT 1';
- connection.query(query, [cid], (err, rows) => {
- connection.release();
- if (err) {
- return callback(err);
- }
-
- if (!rows || !rows.length) {
- return callback(null, false);
- }
-
- let subscription;
- let listId = rows[0].list;
- let email = rows[0].email;
- try {
- subscription = JSON.parse(rows[0].data);
- } catch (E) {
- subscription = {};
- }
-
- subscription.cid = cid;
- subscription.list = listId;
- subscription.email = email;
-
- let optInCountry = geoip.lookupCountry(optInIp) || null;
- module.exports.insert(listId, {
- email,
- cid,
- optInIp,
- optInCountry,
- status: 1
- }, subscription, err => {
- if (err) {
- return callback(err);
- }
-
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
- connection.query('DELETE FROM confirmations WHERE `cid`=? LIMIT 1', [cid], () => {
- connection.release();
- callback(null, subscription);
- });
- });
- });
- });
- });
-};
-
-module.exports.insert = (listId, meta, subscription, callback) => {
-
+/*
+ Adds a new subscription. Returns error if a subscription with the same email address is already present and is not unsubscribed.
+ If it is unsubscribed, the existing subscription is changed based on the provided data.
+ If meta.partial is true, it updates even an active subscription.
+ */
+module.exports.insert = (listId, meta, subscriptionData, callback) => {
meta = tools.convertKeys(meta);
- subscription = tools.convertKeys(subscription);
+ subscriptionData = tools.convertKeys(subscriptionData);
- meta.email = meta.email || subscription.email;
+ meta.email = meta.email || subscriptionData.email;
meta.cid = meta.cid || shortid.generate();
fields.list(listId, (err, fieldList) => {
@@ -230,21 +116,29 @@ module.exports.insert = (listId, meta, subscription, callback) => {
let keys = [];
let values = [];
- let allowedKeys = ['first_name', 'last_name'];
- Object.keys(subscription).forEach(key => {
- let value = subscription[key];
+ let allowedKeys = ['first_name', 'last_name', 'tz', 'is_test'];
+ Object.keys(subscriptionData).forEach(key => {
+ let value = subscriptionData[key];
key = tools.toDbKey(key);
+ if (key === 'tz') {
+ value = (value || '').toString().toLowerCase().trim();
+ }
+ if (key === 'is_test') {
+ value = value ? '1' : '0';
+ }
if (allowedKeys.indexOf(key) >= 0) {
keys.push(key);
values.push(value);
}
});
- fields.getValues(fields.getRow(fieldList, subscription, true, true), true).forEach(field => {
+ fields.getValues(fields.getRow(fieldList, subscriptionData, true, true, !!meta.partial), true).forEach(field => {
keys.push(field.key);
values.push(field.value);
});
+ values = values.map(v => typeof v === 'string' ? striptags(v) : v);
+
db.getConnection((err, connection) => {
if (err) {
return callback(err);
@@ -252,16 +146,14 @@ module.exports.insert = (listId, meta, subscription, callback) => {
connection.beginTransaction(err => {
if (err) {
+ connection.release();
return callback(err);
}
- let query = 'SELECT id, status FROM `subscription__' + listId + '` WHERE email=? OR cid=? LIMIT 1';
+ let query = 'SELECT `id`, `status`, `cid` FROM `subscription__' + listId + '` WHERE `email`=? OR `cid`=? LIMIT 1';
connection.query(query, [meta.email, meta.cid], (err, rows) => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
let query;
@@ -269,15 +161,38 @@ module.exports.insert = (listId, meta, subscription, callback) => {
let existing = rows && rows[0] || false;
let entryId = existing ? existing.id : false;
- meta.status = meta.status || (existing ? existing.status : 1);
+ meta.cid = existing ? rows[0].cid : meta.cid;
+
+ // meta.status may be 'undefined' or '0' when adding a subscription via API call or CSV import. In both cases meta.partial is 'true'.
+ // This must either update an existing subscription without changing its status or insert a new subscription with status SUBSCRIBED.
+ meta.status = meta.status || (existing ? existing.status : Status.SUBSCRIBED);
let statusChange = !existing || existing.status !== meta.status;
let statusDirection;
+ if (existing && existing.status === Status.SUBSCRIBED && !meta.partial) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(new Error(_('Email address already registered'))));
+ }
+
if (statusChange) {
keys.push('status', 'status_change');
values.push(meta.status, new Date());
- statusDirection = !existing ? (meta.status === 1 ? '+' : '-') : (existing.status === 1 ? '-' : '+');
+ statusDirection = !existing ? (meta.status === Status.SUBSCRIBED ? '+' : false) : (existing.status === Status.SUBSCRIBED ? '-' : '+');
+ }
+
+ if (!keys.length) {
+ // nothing to update
+ return connection.commit(err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+ connection.release();
+ return callback(null, {
+ entryId,
+ cid: meta.cid,
+ inserted: !existing
+ });
+ });
}
if (!existing) {
@@ -293,32 +208,24 @@ module.exports.insert = (listId, meta, subscription, callback) => {
connection.query(query, queryArgs, (err, result) => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
entryId = result.insertId || entryId;
- if (statusChange) {
+ if (statusChange && statusDirection) {
connection.query('UPDATE lists SET `subscribers`=`subscribers`' + statusDirection + '1 WHERE id=?', [listId], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, {
entryId,
+ cid: meta.cid,
inserted: !existing
});
});
@@ -326,14 +233,12 @@ module.exports.insert = (listId, meta, subscription, callback) => {
} else {
connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, {
entryId,
+ cid: meta.cid,
inserted: !existing
});
});
@@ -349,7 +254,7 @@ module.exports.get = (listId, cid, callback) => {
cid = (cid || '').toString().trim();
if (!cid) {
- return callback(new Error('Missing Subbscription ID'));
+ return callback(new Error(_('Missing Subscription ID')));
}
db.getConnection((err, connection) => {
@@ -368,6 +273,66 @@ module.exports.get = (listId, cid, callback) => {
}
let subscription = tools.convertKeys(rows[0]);
+ // ensure list id in response
+ subscription.list = subscription.list || listId;
+ return callback(null, subscription);
+ });
+ });
+};
+
+module.exports.getById = (listId, id, callback) => {
+ id = Number(id) || 0;
+
+ if (!id) {
+ return callback(new Error(_('Missing Subscription ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM `subscription__' + listId + '` WHERE id=?', [id], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ let subscription = tools.convertKeys(rows[0]);
+ // ensure list id in response
+ subscription.list = subscription.list || listId;
+ return callback(null, subscription);
+ });
+ });
+};
+
+module.exports.getByEmail = (listId, email, callback) => {
+ if (!email) {
+ return callback(new Error(_('Missing Subscription email address')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM `subscription__' + listId + '` WHERE email=?', [email], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ let subscription = tools.convertKeys(rows[0]);
+ // ensure list id in response
+ subscription.list = subscription.list || listId;
return callback(null, subscription);
});
});
@@ -392,10 +357,11 @@ module.exports.getWithMergeTags = (listId, cid, callback) => {
EMAIL: subscription.email,
FIRST_NAME: subscription.firstName,
LAST_NAME: subscription.lastName,
- FULL_NAME: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' ')
+ FULL_NAME: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' '),
+ TIMEZONE: subscription.tz || ''
};
- fields.getRow(fieldList, subscription, true, true).forEach(field => {
+ fields.getRow(fieldList, subscription, false, true).forEach(field => {
if (field.mergeTag) {
subscription.mergeTags[field.mergeTag] = field.mergeValue || '';
}
@@ -421,11 +387,11 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => {
let values = [];
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
if (!cid) {
- return callback(new Error('Missing subscription ID'));
+ return callback(new Error(_('Missing Subscription ID')));
}
fields.list(listId, (err, fieldList) => {
@@ -433,7 +399,7 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => {
return callback(err);
}
- let allowedKeys = ['first_name', 'last_name'];
+ let allowedKeys = ['first_name', 'last_name', 'tz', 'is_test'];
if (allowEmail) {
allowedKeys.unshift('email');
@@ -442,13 +408,16 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => {
Object.keys(updates).forEach(key => {
let value = updates[key];
key = tools.toDbKey(key);
+ if (key === 'tz') {
+ value = (value || '').toString().toLowerCase().trim();
+ }
if (allowedKeys.indexOf(key) >= 0) {
keys.push(key);
values.push(value);
}
});
- fields.getValues(fields.getRow(fieldList, updates, true, true), true).forEach(field => {
+ fields.getValues(fields.getRow(fieldList, updates, true, true, true), true).forEach(field => {
keys.push(field.key);
values.push(field.value);
});
@@ -457,6 +426,8 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => {
return callback(null, false);
}
+ values = values.map(v => typeof v === 'string' ? striptags(v) : v);
+
db.getConnection((err, connection) => {
if (err) {
return callback(err);
@@ -474,68 +445,24 @@ module.exports.update = (listId, cid, updates, allowEmail, callback) => {
});
};
-module.exports.unsubscribe = (listId, email, campaignId, callback) => {
- listId = Number(listId) || 0;
- email = (email || '').toString().trim();
-
- campaignId = (campaignId || '').toString().trim() || false;
-
- if (listId < 1) {
- return callback(new Error('Missing List ID'));
- }
-
- if (!email) {
- return callback(new Error('Missing email address'));
- }
-
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- connection.query('SELECT * FROM `subscription__' + listId + '` WHERE `email`=?', [email], (err, rows) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- if (!rows || !rows.length || rows[0].status !== 1) {
- return callback(null, false);
- }
-
- let subscription = tools.convertKeys(rows[0]);
- module.exports.changeStatus(subscription.id, listId, campaignId, 2, err => {
- if (err) {
- return callback(err);
- }
- return callback(null, subscription);
- });
- });
- });
-};
-
-module.exports.changeStatus = (id, listId, campaignId, status, callback) => {
+module.exports.changeStatus = (listId, id, campaignId, status, callback) => {
db.getConnection((err, connection) => {
if (err) {
return callback(err);
}
connection.beginTransaction(err => {
if (err) {
+ connection.release();
return callback(err);
}
connection.query('SELECT `status` FROM `subscription__' + listId + '` WHERE id=? LIMIT 1', [id], (err, rows) => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
if (!rows || !rows.length) {
- return connection.rollback(() => {
- connection.release();
- return callback(null, false);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(null, false));
}
let oldStatus = rows[0].status;
@@ -543,31 +470,22 @@ module.exports.changeStatus = (id, listId, campaignId, status, callback) => {
let statusDirection;
if (!statusChange) {
- return connection.rollback(() => {
- connection.release();
- return callback(null, true);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(null, true));
}
- if (statusChange && oldStatus === 1 || status === 1) {
- statusDirection = status === 1 ? '+' : '-';
+ if (statusChange && oldStatus === Status.SUBSCRIBED || status === Status.SUBSCRIBED) {
+ statusDirection = status === Status.SUBSCRIBED ? '+' : '-';
}
connection.query('UPDATE `subscription__' + listId + '` SET `status`=?, `status_change`=NOW() WHERE id=? LIMIT 1', [status, id], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
if (!statusDirection) {
return connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, true);
@@ -576,41 +494,61 @@ module.exports.changeStatus = (id, listId, campaignId, status, callback) => {
connection.query('UPDATE `lists` SET `subscribers`=`subscribers`' + statusDirection + '1 WHERE id=? LIMIT 1', [listId], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
- if (!campaignId) {
+ // status change is not related to a campaign or it marks message as bounced etc.
+ if (!campaignId || status !== Status.SUBSCRIBED && status !== Status.UNSUBSCRIBED) {
return connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, true);
});
}
- connection.query('UPDATE `campaigns` SET `unsubscribed`=`unsubscribed`+1 WHERE `cid`=? LIMIT 1', [campaignId], err => {
+ connection.query('SELECT `id` FROM `campaigns` WHERE `cid`=? LIMIT 1', [campaignId], (err, rows) => {
if (err) {
- return connection.rollback(() => {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ let campaign = rows && rows[0] || false;
+
+ if (!campaign) {
+ // should not happend
+ return connection.commit(err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
connection.release();
- return callback(err);
+ return callback(null, true);
});
}
- return connection.commit(err => {
+
+ // we should see only unsubscribe events here but you never know
+ connection.query('UPDATE `campaigns` SET `unsubscribed`=`unsubscribed`' + (status === Status.UNSUBSCRIBED ? '+' : '-') + '1 WHERE `cid`=? LIMIT 1', [campaignId], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
- connection.release();
- return callback(null, true);
+
+ let query = 'UPDATE `campaign__' + campaign.id + '` SET `status`=? WHERE `list`=? AND `subscription`=? LIMIT 1';
+ let values = [status, listId, id];
+
+ // Updated tracker status
+ connection.query(query, values, err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ return connection.commit(err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+ connection.release();
+ return callback(null, true);
+ });
+ });
});
});
});
@@ -625,11 +563,11 @@ module.exports.delete = (listId, cid, callback) => {
cid = (cid || '').toString().trim();
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
if (!cid) {
- return callback(new Error('Missing subscription ID'));
+ return callback(new Error(_('Missing subscription ID')));
}
db.getConnection((err, connection) => {
@@ -651,24 +589,19 @@ module.exports.delete = (listId, cid, callback) => {
connection.beginTransaction(err => {
if (err) {
+ connection.release();
return callback(err);
}
connection.query('DELETE FROM `subscription__' + listId + '` WHERE cid=? LIMIT 1', [cid], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
- if (subscription.status !== 1) {
+ if (subscription.status !== Status.SUBSCRIBED) {
return connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, subscription.email);
@@ -677,17 +610,11 @@ module.exports.delete = (listId, cid, callback) => {
connection.query('UPDATE lists SET subscribers=subscribers-1 WHERE id=? LIMIT 1', [listId], err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.commit(err => {
if (err) {
- return connection.rollback(() => {
- connection.release();
- return callback(err);
- });
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
}
connection.release();
return callback(null, subscription.email);
@@ -699,9 +626,9 @@ module.exports.delete = (listId, cid, callback) => {
});
};
-module.exports.createImport = (listId, type, path, size, delimiter, mapping, callback) => {
+module.exports.createImport = (listId, type, path, size, delimiter, emailcheck, mapping, callback) => {
listId = Number(listId) || 0;
- type = Number(type) || 1;
+ type = Number(type) || 0;
if (listId < 1) {
return callback(new Error('Missing List ID'));
@@ -711,8 +638,8 @@ module.exports.createImport = (listId, type, path, size, delimiter, mapping, cal
if (err) {
return callback(err);
}
- let query = 'INSERT INTO importer (`list`, `type`, `path`, `size`, `delimiter`, `mapping`) VALUES(?,?,?,?,?,?)';
- connection.query(query, [listId, type, path, size, delimiter, JSON.stringify(mapping)], (err, result) => {
+ let query = 'INSERT INTO importer (`list`, `type`, `path`, `size`, `delimiter`, `emailcheck`, `mapping`) VALUES(?,?,?,?,?,?,?)';
+ connection.query(query, [listId, type, path, size, delimiter, emailcheck, JSON.stringify(mapping)], (err, result) => {
connection.release();
if (err) {
return callback(err);
@@ -727,11 +654,11 @@ module.exports.updateImport = (listId, importId, data, callback) => {
importId = Number(importId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
if (importId < 1) {
- return callback(new Error('Missing Import ID'));
+ return callback(new Error(_('Missing Import ID')));
}
let keys = [];
@@ -767,11 +694,10 @@ module.exports.updateImport = (listId, importId, data, callback) => {
connection.release();
return callback(null, affected);
});
- return;
+ } else {
+ connection.release();
+ return callback(null, affected);
}
-
- connection.release();
- return callback(null, affected);
});
});
};
@@ -781,11 +707,11 @@ module.exports.getImport = (listId, importId, callback) => {
importId = Number(importId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
if (importId < 1) {
- return callback(new Error('Missing Import ID'));
+ return callback(new Error(_('Missing Import ID')));
}
db.getConnection((err, connection) => {
@@ -821,7 +747,7 @@ module.exports.getFailedImports = (importId, callback) => {
importId = Number(importId) || 0;
if (importId < 1) {
- return callback(new Error('Missing Import ID'));
+ return callback(new Error(_('Missing Import ID')));
}
db.getConnection((err, connection) => {
@@ -844,7 +770,7 @@ module.exports.listImports = (listId, callback) => {
listId = Number(listId) || 0;
if (listId < 1) {
- return callback(new Error('Missing List ID'));
+ return callback(new Error(_('Missing List ID')));
}
db.getConnection((err, connection) => {
@@ -878,3 +804,130 @@ module.exports.listImports = (listId, callback) => {
});
});
};
+
+/*
+Performs checks before update of an address. This includes finding the existing subscriber, validating the new email
+and checking whether the new email does not conflict with other subscribers.
+ */
+module.exports.updateAddressCheck = (list, cid, emailNew, ip, callback) => {
+ cid = (cid || '').toString().trim();
+
+ if (!list || !list.id) {
+ return callback(new Error(_('Missing List ID')));
+ }
+
+ if (!cid) {
+ return callback(new Error(_('Missing subscription ID')));
+ }
+
+ tools.validateEmail(emailNew, false, err => {
+ if (err) {
+ return callback(err);
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'SELECT * FROM `subscription__' + list.id + '` WHERE `cid`=? AND `status`=' + Status.SUBSCRIBED + ' LIMIT 1';
+ let args = [cid];
+ connection.query(query, args, (err, rows) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+ if (!rows || !rows.length) {
+ connection.release();
+ return callback(new Error(_('Unknown subscription ID')));
+ }
+
+ if (rows[0].email === emailNew) {
+ connection.release();
+ return callback(new Error(_('Nothing seems to be changed')));
+ }
+
+ let old = rows[0];
+
+ let query = 'SELECT `id` FROM `subscription__' + list.id + '` WHERE `email`=? AND `cid`<>? AND `status`=' + Status.SUBSCRIBED + ' LIMIT 1';
+ let args = [emailNew, cid];
+ connection.query(query, args, (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (rows && rows.length > 0) {
+ return callback(null, old, false);
+ } else {
+ return callback(null, old, true);
+ }
+ });
+ });
+ });
+ });
+};
+
+
+/*
+ Updates address in subscription__xxx
+ */
+module.exports.updateAddress = (listId, subscriptionId, emailNew, callback) => {
+ // update email address instead of adding new
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+ connection.beginTransaction(err => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+
+ let query = 'SELECT `id` FROM `subscription__' + listId + '` WHERE `email`=? AND `id`<>? AND `status`=' + Status.SUBSCRIBED + ' LIMIT 1';
+ let args = [emailNew, subscriptionId];
+ connection.query(query, args, (err, rows) => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ if (rows && rows.length > 0) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(new Error(_('Email address already registered'))));
+ }
+
+ let query = 'DELETE FROM `subscription__' + listId + '` WHERE `email`=? AND `id`<>?';
+ let args = [emailNew, subscriptionId];
+ connection.query(query, args, err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ let query = 'UPDATE `subscription__' + listId + '` SET `email`=? WHERE `id`=? AND `status`=' + Status.SUBSCRIBED + ' LIMIT 1';
+ let args = [emailNew, subscriptionId];
+ connection.query(query, args, (err, result) => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+
+ if (!result || !result.affectedRows) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(new Error(_('Subscription not found in this list'))));
+ }
+
+ return connection.commit(err => {
+ if (err) {
+ return helpers.rollbackAndReleaseConnection(connection, () => callback(err));
+ }
+ connection.release();
+
+ return callback();
+ });
+ });
+ });
+ });
+ });
+ });
+
+};
+
+module.exports.getUnsubscriptionMode = (list, subscriptionId) => list.unsubscriptionMode; // eslint-disable-line no-unused-vars
+// TODO: Once the unsubscription mode is customizable per segment, then this will be a good place to process it.
diff --git a/lib/models/templates.js b/lib/models/templates.js
index ea54cac3..b0f0099e 100644
--- a/lib/models/templates.js
+++ b/lib/models/templates.js
@@ -2,52 +2,28 @@
let db = require('../db');
let tools = require('../tools');
+let _ = require('../translate')._;
+let tableHelpers = require('../table-helpers');
-let allowedKeys = ['description', 'html', 'text'];
+let allowedKeys = ['description', 'editor_name', 'editor_data', 'html', 'text'];
module.exports.list = (start, limit, callback) => {
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
+ tableHelpers.list('templates', ['*'], 'name', null, start, limit, callback);
+};
- connection.query('SELECT SQL_CALC_FOUND_ROWS * FROM templates ORDER BY name LIMIT ? OFFSET ?', [limit, start], (err, rows) => {
- if (err) {
- connection.release();
- return callback(err);
- }
- connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- return callback(null, rows, total && total[0] && total[0].total);
- });
- });
- });
+module.exports.filter = (request, parent, callback) => {
+ tableHelpers.filter('templates', ['*'], request, ['#', 'name', 'description'], ['name'], 'name ASC', null, callback);
};
module.exports.quicklist = callback => {
- db.getConnection((err, connection) => {
- if (err) {
- return callback(err);
- }
-
- connection.query('SELECT id, name FROM templates ORDER BY name LIMIT 1000', (err, rows) => {
- connection.release();
- if (err) {
- return callback(err);
- }
- return callback(null, (rows || []).map(tools.convertKeys));
- });
- });
+ tableHelpers.quicklist('templates', ['id', 'name'], 'name', callback);
};
module.exports.get = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Template ID'));
+ return callback(new Error(_('Missing Template ID')));
}
db.getConnection((err, connection) => {
@@ -76,7 +52,7 @@ module.exports.create = (template, callback) => {
let data = tools.convertKeys(template);
if (!(data.name || '').toString().trim()) {
- return callback(new Error('Template Name must be set'));
+ return callback(new Error(_('Template Name must be set')));
}
let name = (template.name || '').toString().trim();
@@ -85,12 +61,17 @@ module.exports.create = (template, callback) => {
let values = [name];
Object.keys(template).forEach(key => {
- let value = template[key].trim();
+ let value = template[key];
key = tools.toDbKey(key);
- if (allowedKeys.indexOf(key) >= 0) {
- keys.push(key);
- values.push(value);
+ if (!allowedKeys.includes(key)) {
+ return;
}
+ value = value.trim();
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
+ keys.push(key);
+ values.push(value);
});
db.getConnection((err, connection) => {
@@ -118,11 +99,11 @@ module.exports.update = (id, updates, callback) => {
let data = tools.convertKeys(updates);
if (id < 1) {
- return callback(new Error('Missing Template ID'));
+ return callback(new Error(_('Missing Template ID')));
}
if (!(data.name || '').toString().trim()) {
- return callback(new Error('Template Name must be set'));
+ return callback(new Error(_('Template Name must be set')));
}
let name = (updates.name || '').toString().trim();
@@ -132,6 +113,9 @@ module.exports.update = (id, updates, callback) => {
Object.keys(updates).forEach(key => {
let value = updates[key].trim();
key = tools.toDbKey(key);
+ if (key === 'description') {
+ value = tools.purifyHTML(value);
+ }
if (allowedKeys.indexOf(key) >= 0) {
keys.push(key);
values.push(value);
@@ -155,11 +139,22 @@ module.exports.update = (id, updates, callback) => {
});
};
+module.exports.duplicate = (id, callback) => module.exports.get(id, (err, template) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!template) {
+ return callback(new Error(_('Template does not exist')));
+ }
+ template.name = template.name + ' Copy';
+ return module.exports.create(template, callback);
+});
+
module.exports.delete = (id, callback) => {
id = Number(id) || 0;
if (id < 1) {
- return callback(new Error('Missing Template ID'));
+ return callback(new Error(_('Missing Template ID')));
}
db.getConnection((err, connection) => {
diff --git a/lib/models/triggers.js b/lib/models/triggers.js
new file mode 100644
index 00000000..b87125c4
--- /dev/null
+++ b/lib/models/triggers.js
@@ -0,0 +1,427 @@
+'use strict';
+
+let log = require('npmlog');
+let tools = require('../tools');
+let db = require('../db');
+let lists = require('./lists');
+let segments = require('./segments');
+let util = require('util');
+let _ = require('../translate')._;
+let tableHelpers = require('../table-helpers');
+
+module.exports.defaultColumns = [{
+ column: 'created',
+ name: _('Sign up date'),
+ type: 'date'
+}, {
+ column: 'latest_open',
+ name: _('Latest open'),
+ type: 'date'
+}, {
+ column: 'latest_click',
+ name: _('Latest click'),
+ type: 'date'
+}];
+
+module.exports.defaultCampaignEvents = [{
+ option: 'delivered',
+ name: _('Delivered')
+}, {
+ option: 'opened',
+ name: _('Has Opened')
+}, {
+ option: 'clicked',
+ name: _('Has Clicked')
+}, {
+ option: 'not_opened',
+ name: _('Not Opened')
+}, {
+ option: 'not_clicked',
+ name: _('Not Clicked')
+}];
+
+let defaultColumnMap = {};
+let defaultEventMap = {};
+module.exports.defaultColumns.forEach(col => defaultColumnMap[col.column] = col.name);
+module.exports.defaultCampaignEvents.forEach(evt => defaultEventMap[evt.option] = evt.name);
+
+module.exports.list = callback => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let tableFields = [
+ '`triggers`.`id` AS `id`',
+ '`triggers`.`name` AS `name`',
+ '`triggers`.`description` AS `description`',
+ '`triggers`.`enabled` AS `enabled`',
+ '`triggers`.`list` AS `list`',
+ '`triggers`.`segment` AS `segment`',
+ '`lists`.`name` AS `list_name`',
+ '`segments`.`name` AS `segment_name`',
+ '`source`.`id` AS `source_campaign`',
+ '`source`.`name` AS `source_campaign_name`',
+ '`dest`.`id` AS `dest_campaign`',
+ '`dest`.`name` AS `dest_campaign_name`',
+ '`triggers`.`count` AS `count`',
+ '`custom_fields`.`id` AS `column_id`',
+ '`triggers`.`column` AS `column`',
+ '`custom_fields`.`name` AS `column_name`',
+ '`triggers`.`rule` AS `rule`',
+ '`triggers`.`seconds` AS `seconds`',
+ '`triggers`.`created` AS `created`'
+ ];
+
+ let query = 'SELECT ' + tableFields.join(', ') + ' FROM `triggers` LEFT JOIN `campaigns` `source` ON `source`.`id`=`triggers`.`source_campaign` LEFT JOIN `campaigns` `dest` ON `dest`.`id`=`triggers`.`dest_campaign` LEFT JOIN `lists` ON `lists`.`id`=`triggers`.`list` LEFT JOIN `segments` ON `segments`.`id`=`triggers`.`segment` LEFT JOIN `custom_fields` ON `custom_fields`.`list` = `triggers`.`list` AND `custom_fields`.`column`=`triggers`.`column` ORDER BY `triggers`.`name`';
+ connection.query(query, (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let triggers = (rows || []).map(tools.convertKeys).map(row => {
+ if (row.rule === 'subscription' && row.column && !row.columnName) {
+ row.columnName = defaultColumnMap[row.column];
+ }
+
+ let days = Math.round(row.seconds / (24 * 3600));
+ row.formatted = util.format('%s days after %s', days, row.rule === 'subscription' ? row.columnName : (util.format('%s %s', defaultEventMap[row.column], row.sourceCampaign, row.sourceCampaignName)));
+
+ return row;
+ });
+ return callback(null, triggers);
+ });
+ });
+};
+
+module.exports.getQuery = (id, callback) => {
+ module.exports.get(id, (err, trigger) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let limit = 300;
+
+ // time..NOW..time + 24h, 24 hour window after trigger target to detect it
+ //We need a 24 hour window for triggers as the format for dates added via the API are stored as 00:00:00
+ let treshold = 3600 * 24;
+
+ let intervalQuery = (column, seconds, treshold) => column + ' <= NOW() - INTERVAL ' + seconds + ' SECOND AND ' + column + ' >= NOW() - INTERVAL ' + (treshold + seconds) + ' SECOND';
+
+
+ let getSegmentQuery = (segmentId, next) => {
+ segmentId = Number(segmentId);
+ if (!segmentId) {
+ return next(null, {
+ where: '',
+ values: []
+ });
+ }
+
+ segments.getQuery(segmentId, 'subscription', next);
+ };
+
+ getSegmentQuery(trigger.segment, (err, queryData) => {
+ if (err) {
+ log.err('Triggers', err);
+ return null;
+ }
+
+ let query = false;
+ let querySegmentSubscription = '';
+ let querySegmentTriggertable = '';
+ if (trigger.segment > 0)
+ {
+ querySegmentSubscription = (queryData.where ? ' AND (' + queryData.where + ')' : '');
+ querySegmentTriggertable = ' AND triggertable.`segment` = ' + trigger.segment;
+ }
+
+ switch (trigger.rule) {
+ case 'subscription':
+ query = 'SELECT id FROM `subscription__' + trigger.list + '` subscription WHERE status=1 AND ' + intervalQuery('`' + trigger.column + '`', trigger.seconds, treshold) + ' ' + querySegmentSubscription + ' AND id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ case 'campaign':
+ switch (trigger.column) {
+ case 'delivered':
+ query = 'SELECT subscription.id AS id FROM `subscription__' + trigger.list + '` subscription LEFT JOIN `campaign__' + trigger.sourceCampaign + '` campaign ON campaign.list=' + trigger.list + ' AND subscription.id=campaign.subscription WHERE campaign.status=1 AND ' + intervalQuery('`campaign`.`created`', trigger.seconds, treshold) + ' ' + querySegmentSubscription + ' AND subscription.id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ case 'not_clicked':
+ query = 'SELECT subscription.id AS id FROM `subscription__' + trigger.list + '` subscription LEFT JOIN `campaign__' + trigger.sourceCampaign + '` campaign ON campaign.list=' + trigger.list + ' AND subscription.id=campaign.subscription LEFT JOIN `campaign_tracker__' + trigger.sourceCampaign + '` tracker ON tracker.list=campaign.list AND tracker.subscriber=subscription.id AND tracker.link=0 WHERE campaign.status=1 AND ' + intervalQuery('`campaign`.`created`', trigger.seconds, treshold) + ' AND tracker.created IS NULL ' + querySegmentSubscription + ' AND subscription.id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ case 'not_opened':
+ query = 'SELECT subscription.id AS id FROM `subscription__' + trigger.list + '` subscription LEFT JOIN `campaign__' + trigger.sourceCampaign + '` campaign ON campaign.list=' + trigger.list + ' AND subscription.id=campaign.subscription LEFT JOIN `campaign_tracker__' + trigger.sourceCampaign + '` tracker ON tracker.list=campaign.list AND tracker.subscriber=subscription.id AND tracker.link=-1 WHERE campaign.status=1 AND ' + intervalQuery('`campaign`.`created`', trigger.seconds, treshold) + ' AND tracker.created IS NULL ' + querySegmentSubscription + ' AND subscription.id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ case 'clicked':
+ query = 'SELECT subscription.id AS id FROM `subscription__' + trigger.list + '` subscription LEFT JOIN `campaign__' + trigger.sourceCampaign + '` campaign ON campaign.list=' + trigger.list + ' AND subscription.id=campaign.subscription LEFT JOIN `campaign_tracker__' + trigger.sourceCampaign + '` tracker ON tracker.list=campaign.list AND tracker.subscriber=subscription.id AND tracker.link=0 WHERE campaign.status=1 AND ' + intervalQuery('`tracker`.`created`', trigger.seconds, treshold) + ' ' + querySegmentSubscription + ' AND subscription.id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ case 'opened':
+ query = 'SELECT subscription.id AS id FROM `subscription__' + trigger.list + '` subscription LEFT JOIN `campaign__' + trigger.sourceCampaign + '` campaign ON campaign.list=' + trigger.list + ' AND subscription.id=campaign.subscription LEFT JOIN `campaign_tracker__' + trigger.sourceCampaign + '` tracker ON tracker.list=campaign.list AND tracker.subscriber=subscription.id AND tracker.link=-1 WHERE campaign.status=1 AND ' + intervalQuery('`tracker`.`created`', trigger.seconds, treshold) + ' ' + querySegmentSubscription + ' AND subscription.id NOT IN (SELECT subscription FROM `trigger__' + id + '` triggertable WHERE triggertable.`list` = ' + trigger.list + ' ' + querySegmentTriggertable + ' AND triggertable.`subscription` = subscription.`id`) LIMIT ' + limit;
+ break;
+ }
+ break;
+ }
+
+ if (trigger.segment > 0) {
+ let values = queryData.values.concat([trigger.list, trigger.segment]);
+ for (let i = 0; i < values.length; i++) {
+ query = query.replace('?', db.escape(values[i]));
+ }
+ }
+
+ callback(null, query);
+
+ });
+
+ });
+};
+
+module.exports.get = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error('Missing Trigger ID'));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT * FROM triggers WHERE id=?', [id], (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows || !rows.length) {
+ return callback(null, false);
+ }
+
+ let trigger = tools.convertKeys(rows[0]);
+ return callback(null, trigger);
+ });
+ });
+};
+
+module.exports.create = (trigger, callback) => {
+
+ trigger = tools.convertKeys(trigger);
+ let name = (trigger.name || '').toString().trim();
+ let description = (trigger.description || '').toString().trim();
+ let listId = Number(trigger.list) || 0;
+ let segmentId = Number(trigger.segmentId) || 0;
+ let seconds = (Number(trigger.days) || 0) * 24 * 3600;
+ let rule = (trigger.rule || '').toString().toLowerCase().trim();
+ let destCampaign = Number(trigger.destCampaign) || 0;
+ let sourceCampaign = null;
+ let column;
+
+ if (!listId) {
+ return callback(new Error(_('Missing or invalid list ID')));
+ }
+
+ if (seconds < 0) {
+ return callback(new Error(_('Days in the past are not allowed')));
+ }
+
+ if (!rule || ['campaign', 'subscription'].indexOf(rule) < 0) {
+ return callback(new Error(_('Missing or invalid trigger rule')));
+ }
+
+ switch (rule) {
+ case 'subscription':
+ column = (trigger.column || '').toString().toLowerCase().trim();
+ if (!column) {
+ return callback(new Error(_('Invalid subscription configuration')));
+ }
+ break;
+ case 'campaign':
+ column = (trigger.campaignOption || '').toString().toLowerCase().trim();
+ sourceCampaign = Number(trigger.sourceCampaign) || 0;
+ if (!column || !sourceCampaign) {
+ return callback(new Error(_('Invalid campaign configuration')));
+ }
+ if (sourceCampaign === destCampaign) {
+ return callback(new Error(_('A campaing can not be a target for itself')));
+ }
+ break;
+ default:
+ return callback(new Error(_('Missing or invalid trigger rule')));
+ }
+
+ lists.get(listId, (err, list) => {
+ if (err) {
+ return callback(err);
+ }
+ if (!list) {
+ return callback(new Error(_('Missing or invalid list ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let keys = ['name', 'description', 'list', 'segment', 'source_campaign', 'rule', 'column', 'seconds', 'dest_campaign', 'last_check'];
+ let values = [name, description, list.id, segmentId, sourceCampaign, rule, column, seconds, destCampaign];
+
+ let query = 'INSERT INTO `triggers` (`' + keys.join('`, `') + '`) VALUES (' + values.map(() => '?').join(', ') + ', NOW())';
+
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let id = result && result.insertId;
+ if (!id) {
+ return callback(new Error(_('Could not store trigger row')));
+ }
+
+ createTriggerTable(id, err => {
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, id);
+ });
+ });
+ });
+ });
+};
+
+module.exports.update = (id, trigger, callback) => {
+ id = Number(id) || 0;
+ if (id < 1) {
+ return callback(new Error(_('Missing or invalid Trigger ID')));
+ }
+
+ trigger = tools.convertKeys(trigger);
+ let name = (trigger.name || '').toString().trim();
+ let description = (trigger.description || '').toString().trim();
+ let enabled = trigger.enabled ? 1 : 0;
+ let seconds = (Number(trigger.days) || 0) * 24 * 3600;
+ let rule = (trigger.rule || '').toString().toLowerCase().trim();
+ let destCampaign = Number(trigger.destCampaign) || 0;
+ let sourceCampaign = null;
+ let column;
+
+ if (seconds < 0) {
+ return callback(new Error(_('Days in the past are not allowed')));
+ }
+
+ if (!rule || ['campaign', 'subscription'].indexOf(rule) < 0) {
+ return callback(new Error(_('Missing or invalid trigger rule')));
+ }
+
+ switch (rule) {
+ case 'subscription':
+ column = (trigger.column || '').toString().toLowerCase().trim();
+ if (!column) {
+ return callback(new Error(_('Invalid subscription configuration')));
+ }
+ break;
+ case 'campaign':
+ column = (trigger.campaignOption || '').toString().toLowerCase().trim();
+ sourceCampaign = Number(trigger.sourceCampaign) || 0;
+ if (!column || !sourceCampaign) {
+ return callback(new Error(_('Invalid campaign configuration')));
+ }
+ if (sourceCampaign === destCampaign) {
+ return callback(new Error(_('A campaing can not be a target for itself')));
+ }
+ break;
+ default:
+ return callback(new Error(_('Missing or invalid trigger rule')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let keys = ['name', 'description', 'enabled', 'source_campaign', 'rule', 'column', 'seconds', 'dest_campaign'];
+ let values = [name, description, enabled, sourceCampaign, rule, column, seconds, destCampaign];
+
+ let query = 'UPDATE `triggers` SET ' + keys.map(key => '`' + key + '`=?').join(', ') + ' WHERE `id`=? LIMIT 1';
+
+ connection.query(query, values.concat(id), (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ return callback(null, result && result.affectedRows);
+ });
+ });
+};
+
+module.exports.delete = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (id < 1) {
+ return callback(new Error(_('Missing Trigger ID')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('DELETE FROM triggers WHERE id=? LIMIT 1', [id], (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ let affected = result && result.affectedRows || 0;
+ removeTriggerTable(id, err => {
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, affected);
+ });
+ });
+ });
+};
+
+module.exports.filterSubscribers = (trigger, request, columns, callback) => {
+ let queryData = {
+ where: 'trigger__' + trigger.id + '.list=?',
+ values: [trigger.list]
+ };
+
+ tableHelpers.filter('subscription__' + trigger.list + ' JOIN trigger__' + trigger.id + ' ON trigger__' + trigger.id + '.subscription=subscription__' + trigger.list + '.id', ['*'], request, columns, ['email', 'first_name', 'last_name'], 'email ASC', queryData, callback);
+};
+
+function createTriggerTable(id, callback) {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+ let query = 'CREATE TABLE `trigger__' + id + '` LIKE `trigger`';
+ connection.query(query, err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+ });
+}
+
+function removeTriggerTable(id, callback) {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+ let query = 'DROP TABLE IF EXISTS `trigger__' + id + '`';
+ connection.query(query, err => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, true);
+ });
+ });
+}
diff --git a/lib/models/users.js b/lib/models/users.js
index 6631d292..b16106c9 100644
--- a/lib/models/users.js
+++ b/lib/models/users.js
@@ -9,6 +9,7 @@ let mailer = require('../mailer');
let settings = require('./settings');
let crypto = require('crypto');
let urllib = require('url');
+let _ = require('../translate')._;
/**
* Fetches user by ID value
@@ -21,7 +22,7 @@ module.exports.get = (id, callback) => {
if (err) {
return callback(err);
}
- connection.query('SELECT id, username, email FROM users WHERE id=? LIMIT 1', [id], (err, rows) => {
+ connection.query('SELECT `id`, `username`, `email`, `access_token` FROM `users` WHERE `id`=? LIMIT 1', [id], (err, rows) => {
connection.release();
if (err) {
@@ -38,6 +39,75 @@ module.exports.get = (id, callback) => {
});
};
+module.exports.findByAccessToken = (accessToken, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT `id`, `username`, `email`, `access_token` FROM `users` WHERE `access_token`=? LIMIT 1', [accessToken], (err, rows) => {
+ connection.release();
+
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows.length) {
+ return callback(null, false);
+ }
+
+ let user = tools.convertKeys(rows[0]);
+ return callback(null, user);
+ });
+ });
+};
+
+module.exports.findByUsername = (username, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT `id`, `username`, `email`, `access_token` FROM `users` WHERE `username`=? LIMIT 1', [username], (err, rows) => {
+ connection.release();
+
+ if (err) {
+ return callback(err);
+ }
+
+ if (!rows.length) {
+ return callback(null, false);
+ }
+
+ let user = tools.convertKeys(rows[0]);
+ return callback(null, user);
+ });
+ });
+};
+
+module.exports.add = (username, password, email, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('INSERT INTO `users` (`username`, `password`, `email`, `created`) VALUES (?, ?, ?, NOW())', [username, password, email], (err, result) => {
+ connection.release();
+
+ if (err) {
+ return callback(err);
+ }
+
+ let id = result && result.insertId;
+ if (!id) {
+ return callback(new Error(_('Could not store user row')));
+ }
+
+ return callback(null, id);
+ });
+ });
+};
+
/**
* Fetches user by username and password
*
@@ -47,8 +117,12 @@ module.exports.get = (id, callback) => {
*/
module.exports.authenticate = (username, password, callback) => {
+ if (password === '') {
+ return callback(null, false);
+ }
+
let login = (connection, callback) => {
- connection.query('SELECT id, password FROM users WHERE username=? OR email=? LIMIT 1', [username, username], (err, rows) => {
+ connection.query('SELECT `id`, `password`, `access_token` FROM `users` WHERE `username`=? OR email=? LIMIT 1', [username, username], (err, rows) => {
if (err) {
return callback(err);
}
@@ -64,8 +138,10 @@ module.exports.authenticate = (username, password, callback) => {
if (!result) {
return callback(null, false);
}
+
+ let user = tools.convertKeys(rows[0]);
return callback(null, {
- id: rows[0].id,
+ id: user.id,
username
});
});
@@ -94,7 +170,7 @@ module.exports.authenticate = (username, password, callback) => {
module.exports.update = (id, updates, callback) => {
if (!updates.email) {
- return callback(new Error('Email Address must be set'));
+ return callback(new Error(_('Email Address must be set')));
}
let update = (connection, callback) => {
@@ -105,7 +181,7 @@ module.exports.update = (id, updates, callback) => {
}
if (!rows.length) {
- return callback('Failed to check user data');
+ return callback(_('Failed to check user data'));
}
let keys = ['email'];
@@ -116,7 +192,7 @@ module.exports.update = (id, updates, callback) => {
connection.query('UPDATE users SET ' + keys.map(key => key + '=?').join(', ') + ' WHERE id=? LIMIT 1', values, (err, result) => {
if (err) {
if (err.code === 'ER_DUP_ENTRY') {
- err = new Error('Can\'t change email as another user with the same email address already exists');
+ err = new Error(_('Can\'t change email as another user with the same email address already exists'));
}
return callback(err);
}
@@ -133,15 +209,15 @@ module.exports.update = (id, updates, callback) => {
return callback(err);
}
if (!result) {
- return callback('Incorrect current password');
+ return callback(_('Incorrect current password'));
}
if (!updates.password) {
- return callback(new Error('New password not set'));
+ return callback(new Error(_('New password not set')));
}
if (updates.password !== updates.password2) {
- return callback(new Error('Passwords do not match'));
+ return callback(new Error(_('Passwords do not match')));
}
bcrypt.hash(updates.password, null, null, (err, hash) => {
@@ -175,11 +251,39 @@ module.exports.update = (id, updates, callback) => {
});
};
+module.exports.resetToken = (id, callback) => {
+ id = Number(id) || 0;
+
+ if (!id) {
+ return callback(new Error(_('User ID not set')));
+ }
+
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let token = crypto.randomBytes(20).toString('hex').toLowerCase();
+ let query = 'UPDATE users SET `access_token`=? WHERE id=? LIMIT 1';
+ let values = [token, id];
+
+ connection.query(query, values, (err, result) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, result.affectedRows);
+ });
+ });
+
+};
+
+
module.exports.sendReset = (username, callback) => {
username = (username || '').toString().trim();
if (!username) {
- return callback(new Error('Username must be set'));
+ return callback(new Error(_('Username must be set')));
}
db.getConnection((err, connection) => {
@@ -216,7 +320,7 @@ module.exports.sendReset = (username, callback) => {
to: {
address: rows[0].email
},
- subject: 'Mailer password change request'
+ subject: _('Mailer password change request')
}, {
html: 'emails/password-reset-html.hbs',
text: 'emails/password-reset-text.hbs',
@@ -227,7 +331,7 @@ module.exports.sendReset = (username, callback) => {
}
}, err => {
if (err) {
- log.error('Mail', err.stack); // eslint-disable-line no-console
+ log.error('Mail', err); // eslint-disable-line no-console
}
});
@@ -240,7 +344,7 @@ module.exports.sendReset = (username, callback) => {
module.exports.checkResetToken = (username, resetToken, callback) => {
if (!username || !resetToken) {
- return callback(new Error('Missing username or reset token'));
+ return callback(new Error(_('Missing username or reset token')));
}
db.getConnection((err, connection) => {
if (err) {
@@ -260,11 +364,11 @@ module.exports.resetPassword = (data, callback) => {
let updates = tools.convertKeys(data);
if (!updates.username || !updates.resetToken) {
- return callback(new Error('Missing username or reset token'));
+ return callback(new Error(_('Missing username or reset token')));
}
if (!updates.password || !updates.password2 || updates.password !== updates.password2) {
- return callback(new Error('Invalid new password'));
+ return callback(new Error(_('Invalid new password')));
}
bcrypt.hash(updates.password, null, null, (err, hash) => {
diff --git a/lib/passport.js b/lib/passport.js
index 111f24a1..364d34fe 100644
--- a/lib/passport.js
+++ b/lib/passport.js
@@ -1,12 +1,36 @@
'use strict';
let config = require('config');
+let log = require('npmlog');
+let _ = require('./translate')._;
+let util = require('util');
+
let passport = require('passport');
+let fs = require('fs');
let LocalStrategy = require('passport-local').Strategy;
+
let csrf = require('csurf');
let bodyParser = require('body-parser');
let users = require('./models/users');
+let LdapStrategy;
+try {
+ LdapStrategy = require('passport-ldapjs').Strategy; // eslint-disable-line global-require
+} catch (E) {
+ if (config.ldap.enabled) {
+ log.info('LDAP', 'Module "passport-ldapjs" not installed. It will not be used for LDAP auth.');
+ }
+}
+
+let LdapAuthStrategy;
+try {
+ LdapAuthStrategy = require('passport-ldapauth').Strategy; // eslint-disable-line global-require
+} catch (E) {
+ if (config.ldapauth.enabled) {
+ log.info('LDAP', 'Module "passport-ldapauth" not installed. It will not be used for LDAP auth.');
+ }
+}
+
module.exports.csrfProtection = csrf({
cookie: true
});
@@ -23,20 +47,22 @@ module.exports.setup = app => {
module.exports.logout = (req, res) => {
if (req.user) {
- req.flash('info', req.user.username + ' logged out');
+ req.flash('info', util.format(_('%s logged out'), req.user.username));
req.logout();
}
res.redirect('/');
};
module.exports.login = (req, res, next) => {
- passport.authenticate('local', (err, user, info) => {
+ let authMode = config.ldapauth.enabled ? 'ldapauth' : config.ldap.enabled ? 'ldap' : 'local';
+ passport.authenticate(authMode, (err, user, info) => {
if (err) {
req.flash('danger', err.message);
return next(err);
}
if (!user) {
- req.flash('danger', info && info.message || 'Failed to authenticate user');
+ log.warn('auth', `[client ${req.ip}] authentication failure`);
+ req.flash('danger', info && info.message || _('Failed to authenticate user'));
return res.redirect('/users/login' + (req.body.next ? '?next=' + encodeURIComponent(req.body.next) : ''));
}
req.logIn(user, err => {
@@ -52,27 +78,124 @@ module.exports.login = (req, res, next) => {
req.session.cookie.expires = false;
}
- req.flash('success', 'Logged in as ' + user.username);
+ req.flash('success', util.format(_('Logged in as %s'), user.username));
return res.redirect(req.body.next || '/');
});
})(req, res, next);
};
-passport.use(new LocalStrategy((username, password, done) => {
- users.authenticate(username, password, (err, user) => {
- if (err) {
- return done(err);
- }
+if (config.ldap.enabled && LdapStrategy) {
+ log.info('Using LDAP auth (passport-ldapjs)');
- if (!user) {
- return done(null, false, {
- message: 'Incorrect username or password'
- });
- }
+ let opts = {
+ server: {
+ url: config.ldap.url,
+ tlsOptions: {
+ ca: config.ldap.ca ? [
+ fs.readFileSync(config.ldap.ca)
+ ] : undefined
+ }
+ },
+ base: config.ldap.baseDN,
+ search: {
+ filter: config.ldap.filter,
+ attributes: [config.ldap.uidTag, 'mail'],
+ scope: 'sub'
+ },
+ uidTag: config.ldap.uidTag,
+ bindUser: config.ldap.bindUser,
+ bindPassword: config.ldap.bindPassword
+ };
- return done(null, user);
- });
-}));
+ passport.use(new LdapStrategy(opts, (profile, done) => {
+ users.findByUsername(profile[config.ldap.uidTag], (err, user) => {
+ if (err) {
+ return done(err);
+ }
+
+ if (!user) {
+ // password is empty for ldap
+ users.add(profile[config.ldap.uidTag], '', profile.mail, (err, id) => {
+ if (err) {
+ return done(err);
+ }
+
+ return done(null, {
+ id,
+ username: profile[config.ldap.uidTag]
+ });
+ });
+ } else {
+ return done(null, {
+ id: user.id,
+ username: user.username
+ });
+ }
+ });
+ }));
+} else if (config.ldapauth.enabled && LdapAuthStrategy) {
+ log.info('Using LDAP auth (passport-ldapauth)');
+ let opts = {
+ server: {
+ url: config.ldapauth.url,
+ searchBase: config.ldapauth.baseDN,
+ searchFilter: config.ldapauth.filter,
+ searchAttributes: [config.ldapauth.uidTag, 'mail'],
+ bindDN: config.ldapauth.bindUser,
+ bindCredentials: config.ldapauth.bindPassword,
+ tlsOptions: {
+ ca: config.ldapauth.ca ? [
+ fs.readFileSync(config.ldapauth.ca)
+ ] : undefined
+ }
+ }
+ };
+
+ passport.use(new LdapAuthStrategy(opts, (profile, done) => {
+ users.findByUsername(profile[config.ldapauth.uidTag], (err, user) => {
+ if (err) {
+ return done(err);
+ }
+
+ if (!user) {
+ // password is empty for ldap
+ users.add(profile[config.ldapauth.uidTag], '', profile.mail, (err, id) => {
+ if (err) {
+ return done(err);
+ }
+
+ return done(null, {
+ id,
+ username: profile[config.ldapauth.uidTag]
+ });
+ });
+ } else {
+ return done(null, {
+ id: user.id,
+ username: user.username
+ });
+ }
+ });
+ }));
+} else {
+ log.info('Using local auth');
+
+ passport.use(new LocalStrategy((username, password, done) => {
+ users.authenticate(username, password, (err, user) => {
+ if (err) {
+ return done(err);
+ }
+
+ if (!user) {
+ return done(null, false, {
+ message: _('Incorrect username or password')
+ });
+ }
+
+ return done(null, user);
+ });
+ }));
+}
passport.serializeUser((user, done) => {
done(null, user.id);
diff --git a/lib/privilege-helpers.js b/lib/privilege-helpers.js
new file mode 100644
index 00000000..07d39844
--- /dev/null
+++ b/lib/privilege-helpers.js
@@ -0,0 +1,77 @@
+'use strict';
+
+const log = require('npmlog');
+const config = require('config');
+
+const fs = require('fs');
+
+const tryRequire = require('try-require');
+const posix = tryRequire('posix');
+
+function _getConfigUidGid(prefix, defaultUid, defaultGid) {
+ let uid = defaultUid;
+ let gid = defaultGid;
+
+ if (posix) {
+ try {
+ if (config.user) {
+ uid = posix.getpwnam(config[prefix + 'user']).uid;
+ }
+ } catch (err) {
+ log.info('PrivilegeHelpers', 'Failed to resolve user id "%s"', config[prefix + 'user']);
+ }
+
+ try {
+ if (config.user) {
+ gid = posix.getpwnam(config[prefix + 'group']).gid;
+ }
+ } catch (err) {
+ log.info('PrivilegeHelpers', 'Failed to resolve group id "%s"', config[prefix + 'group']);
+ }
+ } else {
+ log.info('PrivilegeHelpers', 'Posix module not installed. Cannot resolve uid/gid');
+ }
+
+ return { uid, gid };
+}
+
+function getConfigUidGid() {
+ return _getConfigUidGid('', process.getuid(), process.getgid());
+}
+
+function getConfigROUidGid() {
+ let rwIds = getConfigUidGid();
+ return _getConfigUidGid('ro', rwIds.uid, rwIds.gid);
+}
+
+function ensureMailtrainOwner(file, callback) {
+ const ids = getConfigUidGid();
+ fs.chown(file, ids.uid, ids.gid, callback);
+}
+
+function dropRootPrivileges() {
+ if (config.group) {
+ try {
+ process.setgid(config.group);
+ log.info('PrivilegeHelpers', 'Changed group to "%s" (%s)', config.group, process.getgid());
+ } catch (E) {
+ log.info('PrivilegeHelpers', 'Failed to change group to "%s" (%s)', config.group, E.message);
+ }
+ }
+
+ if (config.user) {
+ try {
+ process.setuid(config.user);
+ log.info('PrivilegeHelpers', 'Changed user to "%s" (%s)', config.user, process.getuid());
+ } catch (E) {
+ log.info('PrivilegeHelpers', 'Failed to change user to "%s" (%s)', config.user, E.message);
+ }
+ }
+}
+
+module.exports = {
+ dropRootPrivileges,
+ ensureMailtrainOwner,
+ getConfigUidGid,
+ getConfigROUidGid
+};
diff --git a/lib/report-processor.js b/lib/report-processor.js
new file mode 100644
index 00000000..82653849
--- /dev/null
+++ b/lib/report-processor.js
@@ -0,0 +1,147 @@
+'use strict';
+
+const log = require('npmlog');
+const reports = require('./models/reports');
+const executor = require('./executor');
+
+let runningWorkersCount = 0;
+let maxWorkersCount = 1;
+
+let workers = {};
+
+function startWorker(report) {
+
+ function onStarted(tid) {
+ log.info('ReportProcessor', 'Worker process for "%s" started with tid %s. Current worker count is %s.', report.name, tid, runningWorkersCount);
+ workers[report.id] = tid;
+ }
+
+ function onFinished(code, signal) {
+ runningWorkersCount--;
+ log.info('ReportProcessor', 'Worker process for "%s" (tid %s) exited with code %s signal %s. Current worker count is %s.', report.name, workers[report.id], code, signal, runningWorkersCount);
+ delete workers[report.id];
+
+ const fields = {};
+ if (code === 0) {
+ fields.state = reports.ReportState.FINISHED;
+ fields.lastRun = new Date();
+ } else {
+ fields.state = reports.ReportState.FAILED;
+ }
+
+ reports.updateFields(report.id, fields, err => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ }
+
+ setImmediate(startWorkers);
+ });
+ }
+
+ function onFailed(msg) {
+ runningWorkersCount--;
+ log.error('ReportProcessor', 'Executing worker process for "%s" (tid %s) failed with message "%s". Current worker count is %s.', report.name, workers[report.id], msg, runningWorkersCount);
+ delete workers[report.id];
+
+ const fields = {
+ state: reports.ReportState.FAILED
+ };
+
+ reports.updateFields(report.id, fields, err => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ }
+
+ setImmediate(startWorkers);
+ });
+ }
+
+ const reportData = {
+ id: report.id,
+ name: report.name
+ };
+
+ runningWorkersCount++;
+ executor.start('report-processor-worker', reportData, onStarted, onFinished, onFailed);
+}
+
+function startWorkers() {
+ reports.listWithState(reports.ReportState.SCHEDULED, 0, maxWorkersCount - runningWorkersCount, (err, reportList) => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ return;
+ }
+
+ for (let report of reportList) {
+ reports.updateFields(report.id, { state: reports.ReportState.PROCESSING }, err => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ return;
+ }
+
+ startWorker(report);
+ });
+ }
+ });
+}
+
+module.exports.start = (reportId, callback) => {
+ if (!workers[reportId]) {
+ log.info('ReportProcessor', 'Scheduling report id: %s', reportId);
+ reports.updateFields(reportId, { state: reports.ReportState.SCHEDULED, lastRun: null}, err => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (runningWorkersCount < maxWorkersCount) {
+ log.info('ReportProcessor', 'Starting worker because runningWorkersCount=%s maxWorkersCount=%s', runningWorkersCount, maxWorkersCount);
+
+ startWorkers();
+ } else {
+ log.info('ReportProcessor', 'Not starting worker because runningWorkersCount=%s maxWorkersCount=%s', runningWorkersCount, maxWorkersCount);
+ }
+
+ callback(null);
+ });
+ } else {
+ log.info('ReportProcessor', 'Worker for report id: %s is already running.', reportId);
+ }
+};
+
+module.exports.stop = (reportId, callback) => {
+ const tid = workers[reportId];
+ if (tid) {
+ log.info('ReportProcessor', 'Killing worker for report id: %s', reportId);
+ executor.stop(tid);
+ reports.updateFields(reportId, { state: reports.ReportState.FAILED}, callback);
+ } else {
+ log.info('ReportProcessor', 'No running worker found for report id: %s', reportId);
+ }
+};
+
+module.exports.init = callback => {
+ reports.listWithState(reports.ReportState.PROCESSING, 0, 0, (err, reportList) => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ }
+
+ function scheduleReport() {
+ if (reportList.length > 0) {
+ const report = reportList.shift();
+
+ reports.updateFields(report.id, { state: reports.ReportState.SCHEDULED}, err => {
+ if (err) {
+ log.error('ReportProcessor', err);
+ }
+
+ scheduleReport();
+ });
+ }
+
+ startWorkers();
+ return callback();
+ }
+
+ scheduleReport();
+ });
+};
diff --git a/lib/subscription-mail-helpers.js b/lib/subscription-mail-helpers.js
new file mode 100644
index 00000000..71ed13af
--- /dev/null
+++ b/lib/subscription-mail-helpers.js
@@ -0,0 +1,155 @@
+'use strict';
+
+const log = require('npmlog');
+let fields = require('./models/fields');
+let settings = require('./models/settings');
+let mailer = require('./mailer');
+let urllib = require('url');
+let helpers = require('./helpers');
+let _ = require('./translate')._;
+let util = require('util');
+
+
+module.exports = {
+ sendAlreadySubscribed,
+ sendConfirmAddressChange,
+ sendConfirmSubscription,
+ sendConfirmUnsubscription,
+ sendSubscriptionConfirmed,
+ sendUnsubscriptionConfirmed
+};
+
+function sendSubscriptionConfirmed(list, email, subscription, callback) {
+ const relativeUrls = {
+ preferencesUrl: '/subscription/' + list.cid + '/manage/' + subscription.cid,
+ unsubscribeUrl: '/subscription/' + list.cid + '/unsubscribe/' + subscription.cid
+ };
+
+ sendMail(list, email, 'subscription-confirmed', _('%s: Subscription Confirmed'), relativeUrls, {}, subscription, callback);
+}
+
+function sendAlreadySubscribed(list, email, subscription, callback) {
+ const mailOpts = {
+ ignoreDisableConfirmations: true
+ };
+ const relativeUrls = {
+ preferencesUrl: '/subscription/' + list.cid + '/manage/' + subscription.cid,
+ unsubscribeUrl: '/subscription/' + list.cid + '/unsubscribe/' + subscription.cid
+ };
+ sendMail(list, email, 'already-subscribed', _('%s: Email Address Already Registered'), relativeUrls, mailOpts, subscription, callback);
+}
+
+function sendConfirmAddressChange(list, email, cid, subscription, callback) {
+ const mailOpts = {
+ ignoreDisableConfirmations: true
+ };
+ const relativeUrls = {
+ confirmUrl: '/subscription/confirm/change-address/' + cid
+ };
+ sendMail(list, email, 'confirm-address-change', _('%s: Please Confirm Email Change in Subscription'), relativeUrls, mailOpts, subscription, callback);
+}
+
+function sendConfirmSubscription(list, email, cid, subscription, callback) {
+ const mailOpts = {
+ ignoreDisableConfirmations: true
+ };
+ const relativeUrls = {
+ confirmUrl: '/subscription/confirm/subscribe/' + cid
+ };
+ sendMail(list, email, 'confirm-subscription', _('%s: Please Confirm Subscription'), relativeUrls, mailOpts, subscription, callback);
+}
+
+function sendConfirmUnsubscription(list, email, cid, subscription, callback) {
+ const mailOpts = {
+ ignoreDisableConfirmations: true
+ };
+ const relativeUrls = {
+ confirmUrl: '/subscription/confirm/unsubscribe/' + cid
+ };
+ sendMail(list, email, 'confirm-unsubscription', _('%s: Please Confirm Unsubscription'), relativeUrls, mailOpts, subscription, callback);
+}
+
+function sendUnsubscriptionConfirmed(list, email, subscription, callback) {
+ const relativeUrls = {
+ subscribeUrl: '/subscription/' + list.cid + '?cid=' + subscription.cid
+ };
+ sendMail(list, email, 'unsubscription-confirmed', _('%s: Unsubscription Confirmed'), relativeUrls, {}, subscription, callback);
+}
+
+
+function sendMail(list, email, template, subject, relativeUrls, mailOpts, subscription, callback) {
+ fields.list(list.id, (err, fieldList) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let encryptionKeys = [];
+ fields.getRow(fieldList, subscription).forEach(field => {
+ if (field.type === 'gpg' && field.value) {
+ encryptionKeys.push(field.value.trim());
+ }
+ });
+
+ settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'defaultPostaddress', 'serviceUrl', 'disableConfirmations'], (err, configItems) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (!mailOpts.ignoreDisableConfirmations && configItems.disableConfirmations) {
+ return callback();
+ }
+
+ const data = {
+ title: list.name,
+ homepage: configItems.defaultHomepage || configItems.serviceUrl,
+ contactAddress: configItems.defaultAddress,
+ defaultPostaddress: configItems.defaultPostaddress
+ };
+
+ for (let relativeUrlKey in relativeUrls) {
+ data[relativeUrlKey] = urllib.resolve(configItems.serviceUrl, relativeUrls[relativeUrlKey]);
+ }
+
+ let text = {
+ template: 'subscription/mail-' + template + '-text.hbs'
+ };
+
+ let html = {
+ template: 'subscription/mail-' + template + '-html.mjml.hbs',
+ layout: 'subscription/layout.mjml.hbs',
+ type: 'mjml'
+ };
+
+ helpers.injectCustomFormTemplates(list.defaultForm, { text, html }, (err, tmpl) => {
+ if (!err && tmpl) {
+ text = tmpl.text || text;
+ html = tmpl.html || html;
+ }
+
+ mailer.sendMail({
+ from: {
+ name: configItems.defaultFrom,
+ address: configItems.defaultAddress
+ },
+ to: {
+ name: [].concat(subscription.firstName || []).concat(subscription.lastName || []).join(' '),
+ address: email
+ },
+ subject: util.format(subject, list.name),
+ encryptionKeys
+ }, {
+ html,
+ text,
+ data
+ }, err => {
+ if (err) {
+ log.error('Subscription', err);
+ }
+ });
+
+ callback();
+
+ });
+ });
+ });
+}
diff --git a/lib/table-helpers.js b/lib/table-helpers.js
new file mode 100644
index 00000000..1176eba2
--- /dev/null
+++ b/lib/table-helpers.js
@@ -0,0 +1,134 @@
+'use strict';
+
+const db = require('./db');
+const tools = require('./tools');
+
+module.exports.list = (source, fields, orderBy, queryData, start, limit, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let limitQuery = '';
+ let limitValues = [];
+ if (limit) {
+ limitQuery = ' LIMIT ?';
+ limitValues.push(limit);
+
+ if (start) {
+ limitQuery += ' OFFSET ?';
+ limitValues.push(start);
+ }
+ }
+
+ let whereClause = '';
+ let whereValues = [];
+
+ if (queryData) {
+ whereClause = ' WHERE ' + queryData.where;
+ whereValues = queryData.values;
+ }
+
+ connection.query('SELECT SQL_CALC_FOUND_ROWS ' + fields.join(', ') + ' FROM ' + source + whereClause + ' ORDER BY ' + orderBy + ' DESC' + limitQuery, whereValues.concat(limitValues), (err, rows) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+ connection.query('SELECT FOUND_ROWS() AS total', (err, total) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, rows, total && total[0] && total[0].total);
+ });
+ });
+ });
+};
+
+module.exports.quicklist = (source, fields, orderBy, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ connection.query('SELECT ' + fields.join(', ') + ' FROM ' + source + ' ORDER BY ' + orderBy + ' LIMIT 1000', (err, rows) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+ return callback(null, (rows || []).map(tools.convertKeys));
+ });
+ });
+};
+
+module.exports.filter = (source, fields, request, columns, searchFields, defaultOrdering, queryData, callback) => {
+ db.getConnection((err, connection) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let query = 'SELECT COUNT(*) AS total FROM ' + source;
+ let values = [];
+
+ if (queryData) {
+ query += ' WHERE ' + queryData.where;
+ values = values.concat(queryData.values || []);
+ }
+
+ connection.query(query, values, (err, total) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+ total = total && total[0] && total[0].total || 0;
+
+ let ordering = [];
+
+ if (request.order && request.order.length) {
+
+ request.order.forEach(order => {
+ let orderField = columns[Number(order.column)];
+ let orderDirection = (order.dir || '').toString().toLowerCase() === 'desc' ? 'DESC' : 'ASC';
+ if (orderField) {
+ ordering.push(orderField + ' ' + orderDirection);
+ }
+ });
+ }
+
+ if (!ordering.length) {
+ ordering.push(defaultOrdering);
+ }
+
+ let searchWhere = '';
+ let searchArgs = [];
+
+ if (request.search && request.search.value) {
+ let searchVal = '%' + request.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%';
+
+ searchWhere = searchFields.map(field => field + ' LIKE ?').join(' OR ');
+ searchArgs = searchFields.map(() => searchVal);
+ }
+
+ let query = 'SELECT SQL_CALC_FOUND_ROWS ' + fields.join(', ') + ' FROM ' + source +' WHERE ' + (searchWhere ? '(' + searchWhere + ')': '1') + (queryData ? ' AND (' + queryData.where + ')' : '') + ' ORDER BY ' + ordering.join(', ') + ' LIMIT ? OFFSET ?';
+ let args = searchArgs.concat(queryData ? queryData.values : []).concat([Number(request.length) || 50, Number(request.start) || 0]);
+
+ connection.query(query, args, (err, rows) => {
+ if (err) {
+ connection.release();
+ return callback(err);
+ }
+ connection.query('SELECT FOUND_ROWS() AS total', (err, filteredTotal) => {
+ connection.release();
+ if (err) {
+ return callback(err);
+ }
+
+ rows = rows.map(row => tools.convertKeys(row));
+
+ filteredTotal = filteredTotal && filteredTotal[0] && filteredTotal[0].total || 0;
+ return callback(null, rows, total, filteredTotal);
+ });
+ });
+ });
+ });
+};
diff --git a/lib/tools.js b/lib/tools.js
index 6a8a98c8..b0d16822 100644
--- a/lib/tools.js
+++ b/lib/tools.js
@@ -1,9 +1,19 @@
'use strict';
+const config = require('config');
+let fs = require('fs');
+let path = require('path');
let db = require('./db');
let slugify = require('slugify');
let Isemail = require('isemail');
let urllib = require('url');
+let juice = require('juice');
+let jsdom = require('jsdom');
+let he = require('he');
+let _ = require('./translate')._;
+let util = require('util');
+let createDOMPurify = require('dompurify');
+let htmlToText = require('html-to-text');
let blockedUsers = ['abuse', 'admin', 'billing', 'compliance', 'devnull', 'dns', 'ftp', 'hostmaster', 'inoc', 'ispfeedback', 'ispsupport', 'listrequest', 'list', 'maildaemon', 'noc', 'noreply', 'noreply', 'null', 'phish', 'phishing', 'postmaster', 'privacy', 'registrar', 'root', 'security', 'spam', 'support', 'sysadmin', 'tech', 'undisclosedrecipients', 'unsubscribe', 'usenet', 'uucp', 'webmaster', 'www'];
@@ -16,21 +26,31 @@ module.exports = {
updateMenu,
validateEmail,
formatMessage,
- getMessageLinks
+ getMessageLinks,
+ prepareHtml,
+ purifyHTML,
+ mergeTemplateIntoLayout,
+ workers: new Set()
};
function toDbKey(key) {
return key.
- replace(/[^a-z0-9\-_]/gi, '').
- replace(/\-+/g, '_').
- replace(/[A-Z]+/g, c => '_' + c.toLowerCase()).
- replace(/^_+|_+$/g, '').
- replace(/_+/g, '_').
- trim();
+ replace(/[^a-z0-9\-_]/gi, '').
+ replace(/-+/g, '_').
+ replace(/[A-Z]/g, c => '_' + c.toLowerCase()).
+ replace(/^_+|_+$/g, '').
+ replace(/_+/g, '_').
+ trim();
}
function fromDbKey(key) {
- return key.replace(/[_\-]([a-z])/g, (m, c) => c.toUpperCase());
+ let prefix = '';
+ if (key.startsWith('_')) {
+ key = key.substring(1);
+ prefix = '_';
+
+ }
+ return prefix + key.replace(/[_-]([a-z])/g, (m, c) => c.toUpperCase());
}
function convertKeys(obj, options) {
@@ -41,7 +61,7 @@ function convertKeys(obj, options) {
if (options.skip && options.skip.indexOf(lKey) >= 0) {
return;
}
- if (options.keep && options.skip.indexOf(lKey) < 0) {
+ if (options.keep && options.keep.indexOf(lKey) < 0) {
return;
}
response[lKey] = obj[key];
@@ -51,9 +71,9 @@ function convertKeys(obj, options) {
function queryParams(obj) {
return Object.keys(obj).
- filter(key => key !== '_csrf').
- map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])).
- join('&');
+ filter(key => key !== '_csrf').
+ map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])).
+ join('&');
}
function createSlug(table, name, callback) {
@@ -102,25 +122,36 @@ function updateMenu(res) {
}
res.locals.menu.push({
- title: 'Lists',
+ title: _('Lists'),
url: '/lists',
key: 'lists'
}, {
- title: 'Templates',
+ title: _('Templates'),
url: '/templates',
key: 'templates'
}, {
- title: 'Campaigns',
+ title: _('Campaigns'),
url: '/campaigns',
key: 'campaigns'
+ }, {
+ title: _('Automation'),
+ url: '/triggers',
+ key: 'triggers'
});
+
+ if (config.reports && config.reports.enabled === true) {
+ res.locals.menu.push({
+ title: _('Reports'),
+ url: '/reports',
+ key: 'reports'
+ });
+ }
}
function validateEmail(address, checkBlocked, callback) {
-
let user = (address || '').toString().split('@').shift().toLowerCase().replace(/[^a-z0-9]/g, '');
if (checkBlocked && blockedUsers.indexOf(user) >= 0) {
- return callback(new Error('Blocked email address "' + address + '"'));
+ return callback(new Error(util.format(_('Blocked email address "%s"'), address)));
}
Isemail.validate(address, {
@@ -129,16 +160,16 @@ function validateEmail(address, checkBlocked, callback) {
}, result => {
if (result !== 0) {
- let message = 'Invalid email address "' + address + '"';
+ let message = util.format(_('Invalid email address "%s".'), address);
switch (result) {
case 5:
- message += '. MX record not found for domain';
+ message += ' ' + _('MX record not found for domain');
break;
case 6:
- message += '. Address domain not found';
+ message += ' ' + _('Address domain not found');
break;
case 12:
- message += '. Address domain name is required';
+ message += ' ' + _('Address domain name is required');
break;
}
return callback(new Error(message));
@@ -150,31 +181,143 @@ function validateEmail(address, checkBlocked, callback) {
function getMessageLinks(serviceUrl, campaign, list, subscription) {
return {
- LINK_UNSUBSCRIBE: urllib.resolve(serviceUrl, '/subscription/' + list.cid + '/unsubscribe/' + subscription.cid + '?auto=yes&c=' + campaign.cid),
+ LINK_UNSUBSCRIBE: campaign.unsubscribe ? campaign.unsubscribe : urllib.resolve(serviceUrl, '/subscription/' + list.cid + '/unsubscribe/' + subscription.cid + '?c=' + campaign.cid),
LINK_PREFERENCES: urllib.resolve(serviceUrl, '/subscription/' + list.cid + '/manage/' + subscription.cid),
- LINK_BROWSER: urllib.resolve(serviceUrl, '/archive/' + campaign.cid + '/' + list.cid + '/' + subscription.cid)
+ LINK_BROWSER: urllib.resolve(serviceUrl, '/archive/' + campaign.cid + '/' + list.cid + '/' + subscription.cid),
+ CAMPAIGN_ID: campaign.cid,
+ LIST_ID: list.cid,
+ SUBSCRIPTION_ID: subscription.cid
};
}
-function formatMessage(serviceUrl, campaign, list, subscription, message, filter) {
+function formatMessage(serviceUrl, campaign, list, subscription, message, filter, isHTML) {
filter = typeof filter === 'function' ? filter : (str => str);
let links = getMessageLinks(serviceUrl, campaign, list, subscription);
- let getValue = key => {
+ let getTagValue = key => {
key = (key || '').toString().toUpperCase().trim();
if (links.hasOwnProperty(key)) {
return links[key];
}
if (subscription.mergeTags.hasOwnProperty(key)) {
- return subscription.mergeTags[key];
+ let value = (subscription.mergeTags[key] || '').toString();
+ let containsHTML = /<[a-z][\s\S]*>/.test(value);
+ return isHTML ? he.encode((containsHTML ? value : value.replace(/(?:\r\n|\r|\n)/g, '
')), {
+ useNamedReferences: true,
+ allowUnsafeSymbols: true
+ }) : (containsHTML ? htmlToText.fromString(value) : value);
}
return false;
};
- return message.replace(/\[([a-z0-9_]+)(?:\/([^\]]+))?\]/ig, (match, identifier, fallback) => {
- identifier = identifier.toUpperCase();
- let value = (getValue(identifier) || fallback || '').trim();
- return value ? filter(value) : match;
+ let tagReplace = message =>
+ message.replace(/\[([a-z0-9_]+)(?:\/([^\]]+))?\]/ig, (match, identifier, fallback) => {
+ identifier = identifier.toUpperCase();
+ let value = getTagValue(identifier);
+ if (value === false) {
+ return match;
+ }
+ value = (value || fallback || '').trim();
+ return filter(value);
+ });
+
+ return tagReplace(tagReplace(message));
+}
+
+function prepareHtml(html, callback) {
+ if (!(html || '').toString().trim()) {
+ return callback(null, false);
+ }
+ jsdom.env(false, false, {
+ html,
+ features: {
+ FetchExternalResources: false, // disables resource loading over HTTP / filesystem
+ ProcessExternalResources: false // do not execute JS within script blocks
+ }
+ }, (err, win) => {
+ if (err) {
+ return callback(err);
+ }
+
+ let head = win.document.querySelector('head');
+ let hasCharsetTag = false;
+ let metaTags = win.document.querySelectorAll('meta');
+ if (metaTags) {
+ for (let i = 0; i < metaTags.length; i++) {
+ if (metaTags[i].hasAttribute('charset')) {
+ metaTags[i].setAttribute('charset', 'utf-8');
+ hasCharsetTag = true;
+ break;
+ }
+ }
+ }
+ if (!hasCharsetTag) {
+ let charsetTag = win.document.createElement('meta');
+ charsetTag.setAttribute('charset', 'utf-8');
+ head.appendChild(charsetTag);
+ }
+ let preparedHtml = '' + win.document.documentElement.innerHTML + '';
+
+ return callback(null, juice(preparedHtml));
});
}
+
+function purifyHTML(html) {
+ let win = jsdom.jsdom('', {
+ features: {
+ FetchExternalResources: false, // disables resource loading over HTTP / filesystem
+ ProcessExternalResources: false // do not execute JS within script blocks
+ }
+ }).defaultView;
+ let DOMPurify = createDOMPurify(win);
+ return DOMPurify.sanitize(html);
+}
+
+// TODO Simplify!
+function mergeTemplateIntoLayout(template, layout, callback) {
+
+ layout = layout || '{{{body}}}';
+
+ let readFile = (relPath, callback) => {
+ fs.readFile(path.join(__dirname, '..', 'views', relPath), 'utf-8', (err, source) => {
+ if (err) {
+ return callback(err);
+ }
+ callback(null, source);
+ });
+ };
+
+ let done = (template, layout) => {
+ let source = layout.replace(/\{\{\{body\}\}\}/g, template);
+ return callback(null, source);
+ };
+
+ if (layout.endsWith('.hbs')) {
+ readFile(layout, (err, layout) => {
+ if (err) {
+ return callback(err);
+ }
+ // Please dont end your custom messages with .hbs ...
+ if (template.endsWith('.hbs')) {
+ readFile(template, (err, template) => {
+ if (err) {
+ return callback(err);
+ }
+ return done(template, layout);
+ });
+ } else {
+ return done(template, layout);
+ }
+ });
+ } else if (template.endsWith('.hbs')) {
+ readFile(template, (err, template) => {
+ if (err) {
+ return callback(err);
+ }
+ return done(template, layout);
+ });
+ } else {
+ return done(template, layout);
+ }
+}
diff --git a/lib/translate.js b/lib/translate.js
new file mode 100644
index 00000000..9abd9a6f
--- /dev/null
+++ b/lib/translate.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const config = require('config');
+
+const Gettext = require('node-gettext');
+const gt = new Gettext();
+const fs = require('fs');
+const path = require('path');
+const log = require('npmlog');
+const gettextParser = require('gettext-parser');
+const fakelang = require('./fakelang');
+
+const language = config.language || 'en';
+
+[].concat(config.language || []).forEach(lang => {
+ let data;
+ let file = path.join(__dirname, '..', 'languages', lang + '.mo');
+ try {
+ data = gettextParser.mo.parse(fs.readFileSync(file));
+ } catch (E) {
+ // ignore
+ }
+ if (data) {
+ gt.addTranslations(lang, lang, data);
+ gt.setTextDomain(lang);
+ gt.setLocale(lang);
+ log.info('LANG', 'Loaded language file for %s', lang);
+ }
+});
+
+module.exports._ = str => {
+ if (typeof str !== 'string') {
+ str = String(str);
+ }
+
+ if (language === 'zz') {
+ return fakelang(str);
+ }
+
+ return gt.dgettext(language, str);
+};
diff --git a/meta.json b/meta.json
index b4a9b4a7..f48d12cd 100644
--- a/meta.json
+++ b/meta.json
@@ -1,3 +1,3 @@
{
- "schemaVersion": 4
+ "schemaVersion": 34
}
diff --git a/nitrous-post-create.sh b/nitrous-post-create.sh
deleted file mode 100755
index 47841ed5..00000000
--- a/nitrous-post-create.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-export DEBIAN_FRONTEND=noninteractive
-
-sudo apt-add-respository ppa:chris-lea/redis-server
-
-sudo apt-get update
-sudo -E apt-get -q -y install mysql-server pwgen redis-server
-sudo apt-get clean
-
-MYSQL_PASSWORD=`pwgen -1`
-
-mysql -u root -e "CREATE USER 'mailtrain'@'localhost' IDENTIFIED BY '$MYSQL_PASSWORD';"
-mysql -u root -e "GRANT ALL PRIVILEGES ON mailtrain.* TO 'mailtrain'@'%' WITH GRANT OPTION;"
-mysql -u mailtrain --password="$MYSQL_PASSWORD" -e "CREATE database mailtrain;"
-
-cat >> config/production.toml < setup/sql/mailtrain.sql",
- "sqldrop": "node setup/sql/drop.js"
+ "sqldump": "node setup/sql/dump.js | sed -e '/^\\/\\*.*\\*\\/;$/d' -e 's/.[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]./NOW()/g' > setup/sql/mailtrain${DUMP_NAME_SUFFIX}.sql",
+ "sqldrop": "node setup/sql/drop.js",
+ "sqlgen": "npm run sqldrop && DB_FROM_START=Y npm run sqlinit && npm run sqldump",
+ "langs:hbs": "jsxgettext -L handlebars -k translate -o langs/hbs.pot views/layout.hbs views/index.hbs",
+ "langs:js": "jsxgettext -o languages/js.pot routes/index.js",
+ "langs": "npm run langs:hbs && npm run langs:js",
+ "sqldumptest": "NODE_ENV=test DUMP_NAME_SUFFIX=-test npm run sqldump",
+ "sqlresettest": "NODE_ENV=test npm run sqldrop && NODE_ENV=test npm run sqlinit",
+ "starttest": "NODE_ENV=test node index.js",
+ "_e2e": "NODE_ENV=test node test/e2e/index.js",
+ "e2e": "npm run sqlresettest && npm run _e2e"
},
"repository": {
"type": "git",
- "url": "git://github.com/andris9/mailtrain.git"
+ "url": "git://github.com/Mailtrain-org/mailtrain.git"
},
"author": "Andris Reinman",
"license": "GPL-3.0",
- "homepage": "http://mailtrain.org",
+ "homepage": "https://mailtrain.org/",
"engines": {
"node": ">=5.0.0"
},
"devDependencies": {
+ "babel-eslint": "^8.0.0",
+ "bluebird": "^3.5.0",
+ "chai": "^4.1.2",
+ "eslint-config-nodemailer": "^1.2.0",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-nodeunit": "^1.0.0",
- "grunt-eslint": "^18.1.0"
+ "grunt-eslint": "^20.1.0",
+ "jsxgettext-andris": "^0.9.0-patch.1",
+ "lodash": "^4.17.4",
+ "mocha": "^3.5.3",
+ "phantomjs-prebuilt": "^2.1.15",
+ "selenium-webdriver": "^3.5.0",
+ "url-pattern": "^1.0.3"
+ },
+ "optionalDependencies": {
+ "posix": "^4.1.1"
},
"dependencies": {
+ "async": "^2.5.0",
+ "aws-sdk": "^2.122.0",
"bcrypt-nodejs": "0.0.3",
- "body-parser": "^1.15.0",
- "bounce-handler": "^7.3.2-fork.0",
- "compression": "^1.6.1",
- "config": "^1.20.1",
+ "body-parser": "^1.18.2",
+ "bounce-handler": "^7.3.2-fork.2",
+ "compression": "^1.7.0",
+ "config": "^1.26.2",
"connect-flash": "^0.1.1",
- "connect-redis": "^3.0.2",
- "cookie-parser": "^1.4.1",
- "csurf": "^1.8.3",
- "csv-parse": "^1.0.4",
+ "connect-redis": "^3.3.0",
+ "cookie-parser": "^1.4.3",
+ "cors": "^2.8.4",
+ "csurf": "^1.9.0",
+ "csv-parse": "^1.2.3",
+ "device": "^0.3.8",
+ "dompurify": "^1.0.2",
"escape-html": "^1.0.3",
- "express": "^4.13.4",
- "express-session": "^1.13.0",
- "geoip-ultralight": "^0.1.3",
- "handlebars": "^4.0.5",
- "hbs": "^4.0.0",
- "html-to-text": "^2.1.0",
+ "escape-string-regexp": "^1.0.5",
+ "express": "^4.15.5",
+ "express-session": "^1.15.5",
+ "faker": "^4.1.0",
+ "feedparser": "^2.2.1",
+ "fs-extra": "^4.0.2",
+ "geoip-ultralight": "^0.1.5",
+ "gettext-parser": "^1.3.0",
+ "gm": "^1.23.0",
+ "handlebars": "^4.0.10",
+ "hbs": "^4.0.1",
+ "he": "^1.1.1",
+ "html-to-text": "^3.3.0",
"humanize": "0.0.9",
- "isemail": "^2.1.0",
- "morgan": "^1.7.0",
- "multer": "^1.1.0",
- "mysql": "^2.10.2",
- "nodemailer": "^2.3.2",
- "nodemailer-openpgp": "^1.0.2",
- "npmlog": "^2.0.3",
- "openpgp": "^2.2.2",
- "passport": "^0.3.2",
+ "is-url": "^1.2.2",
+ "isemail": "^2.2.1",
+ "jquery-file-upload-middleware": "^0.1.8",
+ "jsdom": "^9.12.0",
+ "json-stringify-date": "^0.1.4",
+ "juice": "^4.1.1",
+ "libmime": "^3.1.0",
+ "mailparser": "^2.0.5",
+ "marked": "^0.3.6",
+ "memory-cache": "^0.2.0",
+ "mjml": "3.3.5",
+ "mkdirp": "^0.5.1",
+ "moment-timezone": "^0.5.13",
+ "morgan": "^1.8.2",
+ "multer": "^1.3.0",
+ "multiparty": "^4.1.3",
+ "mysql": "^2.14.1",
+ "node-gettext": "^2.0.0",
+ "node-mocks-http": "^1.6.5",
+ "nodemailer": "^4.1.1",
+ "nodemailer-openpgp": "^1.1.0",
+ "npmlog": "^4.1.2",
+ "object-hash": "^1.1.8",
+ "openpgp": "^2.5.11",
+ "passport": "^0.4.0",
"passport-local": "^1.0.0",
- "request": "^2.72.0",
- "serve-favicon": "^2.3.0",
- "shortid": "^2.2.6",
- "slugify": "^0.1.1",
- "smtp-server": "^1.9.0",
- "striptags": "^2.1.1",
- "toml": "^2.3.0"
+ "passport-ldapauth": "^2.0.0",
+ "premailer-api": "^1.0.4",
+ "redfour": "^1.0.2",
+ "redis": "^2.8.0",
+ "request": "^2.82.0",
+ "request-promise": "^4.2.2",
+ "serve-favicon": "^2.4.4",
+ "shortid": "^2.2.8",
+ "slugify": "^1.2.1",
+ "smtp-server": "^3.1.0",
+ "striptags": "^3.1.0",
+ "toml": "^2.3.3",
+ "try-require": "^1.2.1"
}
}
diff --git a/protected/reports/.gitignore b/protected/reports/.gitignore
new file mode 100644
index 00000000..d5b76284
--- /dev/null
+++ b/protected/reports/.gitignore
@@ -0,0 +1,3 @@
+*
+!.gitignore
+!README.md
\ No newline at end of file
diff --git a/protected/reports/README.md b/protected/reports/README.md
new file mode 100644
index 00000000..0420f4d0
--- /dev/null
+++ b/protected/reports/README.md
@@ -0,0 +1 @@
+This directory serves for generated reports.
\ No newline at end of file
diff --git a/public/ace/mode-css.js b/public/ace/mode-css.js
new file mode 100644
index 00000000..84cd16c6
--- /dev/null
+++ b/public/ace/mode-css.js
@@ -0,0 +1 @@
+ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-shadow|box-sizing|caption-side|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|hanging-punctuation|height|justify-content|left|letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|min-height|min-width|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|order|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|perspective-origin|position|quotes|resize|right|tab-size|table-layout|text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-indent|text-justify|text-overflow|text-shadow|text-transform|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|vertical-align|visibility|white-space|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0);this.$rules={start:[{token:"comment",regex:"\\/\\*",push:"comment"},{token:"paren.lparen",regex:"\\{",push:"ruleset"},{token:"string",regex:"@.*?{",push:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{caseInsensitive:!0}],media:[{token:"comment",regex:"\\/\\*",push:"comment"},{token:"paren.lparen",regex:"\\{",push:"ruleset"},{token:"string",regex:"\\}",next:"pop"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{caseInsensitive:!0}],comment:[{token:"comment",regex:"\\*\\/",next:"pop"},{defaultToken:"comment"}],ruleset:[{token:"paren.rparen",regex:"\\}",next:"pop"},{token:"comment",regex:"\\/\\*",push:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:["support.function","string","support.function"],regex:"(url\\()(.*)(\\))"},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"},{caseInsensitive:!0}]},this.normalizeRules()};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/css_completions",["require","exports","module"],function(e,t,n){"use strict";var r={background:{"#$0":1},"background-color":{"#$0":1,transparent:1,fixed:1},"background-image":{"url('/$0')":1},"background-repeat":{repeat:1,"repeat-x":1,"repeat-y":1,"no-repeat":1,inherit:1},"background-position":{bottom:2,center:2,left:2,right:2,top:2,inherit:2},"background-attachment":{scroll:1,fixed:1},"background-size":{cover:1,contain:1},"background-clip":{"border-box":1,"padding-box":1,"content-box":1},"background-origin":{"border-box":1,"padding-box":1,"content-box":1},border:{"solid $0":1,"dashed $0":1,"dotted $0":1,"#$0":1},"border-color":{"#$0":1},"border-style":{solid:2,dashed:2,dotted:2,"double":2,groove:2,hidden:2,inherit:2,inset:2,none:2,outset:2,ridged:2},"border-collapse":{collapse:1,separate:1},bottom:{px:1,em:1,"%":1},clear:{left:1,right:1,both:1,none:1},color:{"#$0":1,"rgb(#$00,0,0)":1},cursor:{"default":1,pointer:1,move:1,text:1,wait:1,help:1,progress:1,"n-resize":1,"ne-resize":1,"e-resize":1,"se-resize":1,"s-resize":1,"sw-resize":1,"w-resize":1,"nw-resize":1},display:{none:1,block:1,inline:1,"inline-block":1,"table-cell":1},"empty-cells":{show:1,hide:1},"float":{left:1,right:1,none:1},"font-family":{Arial:2,"Comic Sans MS":2,Consolas:2,"Courier New":2,Courier:2,Georgia:2,Monospace:2,"Sans-Serif":2,"Segoe UI":2,Tahoma:2,"Times New Roman":2,"Trebuchet MS":2,Verdana:1},"font-size":{px:1,em:1,"%":1},"font-weight":{bold:1,normal:1},"font-style":{italic:1,normal:1},"font-variant":{normal:1,"small-caps":1},height:{px:1,em:1,"%":1},left:{px:1,em:1,"%":1},"letter-spacing":{normal:1},"line-height":{normal:1},"list-style-type":{none:1,disc:1,circle:1,square:1,decimal:1,"decimal-leading-zero":1,"lower-roman":1,"upper-roman":1,"lower-greek":1,"lower-latin":1,"upper-latin":1,georgian:1,"lower-alpha":1,"upper-alpha":1},margin:{px:1,em:1,"%":1},"margin-right":{px:1,em:1,"%":1},"margin-left":{px:1,em:1,"%":1},"margin-top":{px:1,em:1,"%":1},"margin-bottom":{px:1,em:1,"%":1},"max-height":{px:1,em:1,"%":1},"max-width":{px:1,em:1,"%":1},"min-height":{px:1,em:1,"%":1},"min-width":{px:1,em:1,"%":1},overflow:{hidden:1,visible:1,auto:1,scroll:1},"overflow-x":{hidden:1,visible:1,auto:1,scroll:1},"overflow-y":{hidden:1,visible:1,auto:1,scroll:1},padding:{px:1,em:1,"%":1},"padding-top":{px:1,em:1,"%":1},"padding-right":{px:1,em:1,"%":1},"padding-bottom":{px:1,em:1,"%":1},"padding-left":{px:1,em:1,"%":1},"page-break-after":{auto:1,always:1,avoid:1,left:1,right:1},"page-break-before":{auto:1,always:1,avoid:1,left:1,right:1},position:{absolute:1,relative:1,fixed:1,"static":1},right:{px:1,em:1,"%":1},"table-layout":{fixed:1,auto:1},"text-decoration":{none:1,underline:1,"line-through":1,blink:1},"text-align":{left:1,right:1,center:1,justify:1},"text-transform":{capitalize:1,uppercase:1,lowercase:1,none:1},top:{px:1,em:1,"%":1},"vertical-align":{top:1,bottom:1},visibility:{hidden:1,visible:1},"white-space":{nowrap:1,normal:1,pre:1,"pre-line":1,"pre-wrap":1},width:{px:1,em:1,"%":1},"word-spacing":{normal:1},filter:{"alpha(opacity=$0100)":1},"text-shadow":{"$02px 2px 2px #777":1},"text-overflow":{"ellipsis-word":1,clip:1,ellipsis:1},"-moz-border-radius":1,"-moz-border-radius-topright":1,"-moz-border-radius-bottomright":1,"-moz-border-radius-topleft":1,"-moz-border-radius-bottomleft":1,"-webkit-border-radius":1,"-webkit-border-top-right-radius":1,"-webkit-border-top-left-radius":1,"-webkit-border-bottom-right-radius":1,"-webkit-border-bottom-left-radius":1,"-moz-box-shadow":1,"-webkit-box-shadow":1,transform:{"rotate($00deg)":1,"skew($00deg)":1},"-moz-transform":{"rotate($00deg)":1,"skew($00deg)":1},"-webkit-transform":{"rotate($00deg)":1,"skew($00deg)":1}},i=function(){};(function(){this.completionsDefined=!1,this.defineCompletions=function(){if(document){var e=document.createElement("c").style;for(var t in e){if(typeof e[t]!="string")continue;var n=t.replace(/[A-Z]/g,function(e){return"-"+e.toLowerCase()});r.hasOwnProperty(n)||(r[n]=1)}}this.completionsDefined=!0},this.getCompletions=function(e,t,n,r){this.completionsDefined||this.defineCompletions();var i=t.getTokenAt(n.row,n.column);if(!i)return[];if(e==="ruleset"){var s=t.getLine(n.row).substr(0,n.column);return/:[^;]+$/.test(s)?(/([\w\-]+):[^:]*$/.test(s),this.getPropertyValueCompletions(e,t,n,r)):this.getPropertyCompletions(e,t,n,r)}return[]},this.getPropertyCompletions=function(e,t,n,i){var s=Object.keys(r);return s.map(function(e){return{caption:e,snippet:e+": $0",meta:"property",score:Number.MAX_VALUE}})},this.getPropertyValueCompletions=function(e,t,n,i){var s=t.getLine(n.row).substr(0,n.column),o=(/([\w\-]+):[^:]*$/.exec(s)||{})[1];if(!o)return[];var u=[];return o in r&&typeof r[o]=="object"&&(u=Object.keys(r[o])),u.map(function(e){return{caption:e,snippet:e,meta:"property value",score:Number.MAX_VALUE}})}}).call(i.prototype),t.CssCompletions=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},h=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){c(n);var a=n.getSelectionRange(),l=r.doc.getTextRange(a);if(l!==""&&l!=="{"&&n.getWrapBehavioursEnabled())return h(a,l,"{","}");if(p.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){c(n);var d=u.substring(s.column,s.column+1);if(d=="}"){var v=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(v!==null&&p.isAutoInsertedClosing(s,u,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(i=="\n"||i=="\r\n"){c(n);var m="";p.isMaybeInsertedClosing(s,u)&&(m=o.stringRepeat("}",f.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var d=u.substring(s.column,s.column+1);if(d==="}"){var g=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!g)return null;var y=this.$getIndent(r.getLine(g.row))}else{if(!m){p.clearMaybeInsertedClosing();return}var y=this.$getIndent(u)}var b=y+r.getTabString();return{text:"\n"+b+"\n"+y+m,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"(",")");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"[","]");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){c(n);var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return h(o,u,s,s);if(!u){var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column),p=f.substring(a.column,a.column+1),d=r.getTokenAt(a.row,a.column),v=r.getTokenAt(a.row,a.column+1);if(l=="\\"&&d&&/escape/.test(d.type))return null;var m=d&&/string|escape/.test(d.type),g=!v||/string|escape/.test(v.type),y;if(p==s)y=m!==g;else{if(m&&!g)return null;if(m&&g)return null;var b=r.$mode.tokenRe;b.lastIndex=0;var w=b.test(l);b.lastIndex=0;var E=b.test(l);if(w||E)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;y=!0}return{text:y?s+s:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(p,i),t.CstyleBehaviour=p}),ace.define("ace/mode/behaviour/css",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=function(){this.inherit(s),this.add("colon","insertion",function(e,t,n,r,i){if(i===":"){var s=n.getCursorPosition(),u=new o(r,s.row,s.column),a=u.getCurrentToken();a&&a.value.match(/\s+/)&&(a=u.stepBackward());if(a&&a.type==="support.type"){var f=r.doc.getLine(s.row),l=f.substring(s.column,s.column+1);if(l===":")return{text:"",selection:[1,1]};if(!f.substring(s.column).match(/^\s*;/))return{text:":;",selection:[1,1]}}}}),this.add("colon","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s===":"){var u=n.getCursorPosition(),a=new o(r,u.row,u.column),f=a.getCurrentToken();f&&f.value.match(/\s+/)&&(f=a.stepBackward());if(f&&f.type==="support.type"){var l=r.doc.getLine(i.start.row),c=l.substring(i.end.column,i.end.column+1);if(c===";")return i.end.column++,i}}}),this.add("semicolon","insertion",function(e,t,n,r,i){if(i===";"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+1);if(u===";")return{text:"",selection:[1,1]}}})};r.inherits(u,s),t.CssBehaviour=u}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/css_completions","ace/mode/behaviour/css","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./css_highlight_rules").CssHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../worker/worker_client").WorkerClient,a=e("./css_completions").CssCompletions,f=e("./behaviour/css").CssBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new f,this.$completer=new a,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.getCompletions=function(e,t,n,r){return this.$completer.getCompletions(e,t,n,r)},this.createWorker=function(e){var t=new u(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/css"}.call(c.prototype),t.Mode=c})
\ No newline at end of file
diff --git a/public/ace/mode-handlebars.js b/public/ace/mode-handlebars.js
new file mode 100644
index 00000000..bd345d55
--- /dev/null
+++ b/public/ace/mode-handlebars.js
@@ -0,0 +1 @@
+ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},s.getTagRule(),{defaultToken:"comment.doc",caseInsensitive:!0}]}};r.inherits(s,i),s.getTagRule=function(e){return{token:"comment.doc.tag.storage.type",regex:"\\b(?:TODO|FIXME|XXX|HACK)\\b"}},s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";function a(){var e=o.replace("\\d","\\d\\-"),t={onMatch:function(e,t,n){var r=e.charAt(1)=="/"?2:1;if(r==1)t!=this.nextState?n.unshift(this.next,this.nextState,0):n.unshift(this.next),n[2]++;else if(r==2&&t==this.nextState){n[1]--;if(!n[1]||n[1]<0)n.shift(),n.shift()}return[{type:"meta.tag.punctuation."+(r==1?"":"end-")+"tag-open.xml",value:e.slice(0,r)},{type:"meta.tag.tag-name.xml",value:e.substr(r)}]},regex:"?"+e+"",next:"jsxAttributes",nextState:"jsx"};this.$rules.start.unshift(t);var n={regex:"{",token:"paren.quasi.start",push:"start"};this.$rules.jsx=[n,t,{include:"reference"},{defaultToken:"string"}],this.$rules.jsxAttributes=[{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",onMatch:function(e,t,n){return t==n[0]&&n.shift(),e.length==2&&(n[0]==this.nextState&&n[1]--,(!n[1]||n[1]<0)&&n.splice(0,2)),this.next=n[0]||"start",[{type:this.token,value:e}]},nextState:"jsx"},n,f("jsxAttributes"),{token:"entity.other.attribute-name.xml",regex:e},{token:"keyword.operator.attribute-equals.xml",regex:"="},{token:"text.tag-whitespace.xml",regex:"\\s+"},{token:"string.attribute-value.xml",regex:"'",stateName:"jsx_attr_q",push:[{token:"string.attribute-value.xml",regex:"'",next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},{token:"string.attribute-value.xml",regex:'"',stateName:"jsx_attr_qq",push:[{token:"string.attribute-value.xml",regex:'"',next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},t],this.$rules.reference=[{token:"constant.language.escape.reference.xml",regex:"(?:[0-9]+;)|(?:[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}]}function f(e){return[{token:"comment",regex:/\/\*/,next:[i.getTagRule(),{token:"comment",regex:"\\*\\/",next:e||"pop"},{defaultToken:"comment",caseInsensitive:!0}]},{token:"comment",regex:"\\/\\/",next:[i.getTagRule(),{token:"comment",regex:"$|^",next:e||"pop"},{defaultToken:"comment",caseInsensitive:!0}]}]}var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o="[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b",u=function(e){var t=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert","constant.language.boolean":"true|false"},"identifier"),n="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|u{[0-9a-fA-F]{1,6}}|[0-2][0-7]{0,2}|3[0-7][0-7]?|[4-7][0-7]?|.)";this.$rules={no_regex:[i.getStartRule("doc-start"),f("no_regex"),{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0(?:[xX][0-9a-fA-F]+|[bB][01]+)\b/},{token:"constant.numeric",regex:/[+-]?\d[\d_]*(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+o+")(\\.)(prototype)(\\.)("+o+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+o+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"keyword",regex:"(?:"+n+")\\b",next:"start"},{token:["support.constant"],regex:/that\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/},{token:t,regex:o},{token:"punctuation.operator",regex:/[.](?![.])/,next:"property"},{token:"keyword.operator",regex:/--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/,next:"start"},{token:"punctuation.operator",regex:/[?:,;.]/,next:"start"},{token:"paren.lparen",regex:/[\[({]/,next:"start"},{token:"paren.rparen",regex:/[\])}]/},{token:"comment",regex:/^#!.*$/}],property:[{token:"text",regex:"\\s+"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",next:"function_arguments"},{token:"punctuation.operator",regex:/[.](?![.])/},{token:"support.function",regex:/(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:"support.function.dom",regex:/(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:"support.constant",regex:/(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:"identifier",regex:o},{regex:"",token:"empty",next:"no_regex"}],start:[i.getStartRule("doc-start"),f("start"),{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+|^$",next:"start"},{token:"empty",regex:"",next:"no_regex"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/[sxngimy]*",next:"no_regex"},{token:"invalid",regex:/\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/},{token:"constant.language.delimiter",regex:/\|/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp"}],regex_character_class:[{token:"regexp.charclass.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp.charachterclass"}],function_arguments:[{token:"variable.parameter",regex:o},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"no_regex"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"no_regex"},{defaultToken:"string"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"no_regex"},{defaultToken:"string"}]};if(!e||!e.noES6)this.$rules.no_regex.unshift({regex:"[{}]",onMatch:function(e,t,n){this.next=e=="{"?this.nextState:"";if(e=="{"&&n.length)n.unshift("start",t);else if(e=="}"&&n.length){n.shift(),this.next=n.shift();if(this.next.indexOf("string")!=-1||this.next.indexOf("jsx")!=-1)return"paren.quasi.end"}return e=="{"?"paren.lparen":"paren.rparen"},nextState:"start"},{token:"string.quasi.start",regex:/`/,push:[{token:"constant.language.escape",regex:r},{token:"paren.quasi.start",regex:/\${/,push:"start"},{token:"string.quasi.end",regex:/`/,next:"pop"},{defaultToken:"string.quasi"}]}),(!e||!e.noJSX)&&a.call(this);this.embedRules(i,"doc-",[i.getEndRule("no_regex")]),this.normalizeRules()};r.inherits(u,s),t.JavaScriptHighlightRules=u}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},h=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){c(n);var a=n.getSelectionRange(),l=r.doc.getTextRange(a);if(l!==""&&l!=="{"&&n.getWrapBehavioursEnabled())return h(a,l,"{","}");if(p.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){c(n);var d=u.substring(s.column,s.column+1);if(d=="}"){var v=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(v!==null&&p.isAutoInsertedClosing(s,u,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(i=="\n"||i=="\r\n"){c(n);var m="";p.isMaybeInsertedClosing(s,u)&&(m=o.stringRepeat("}",f.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var d=u.substring(s.column,s.column+1);if(d==="}"){var g=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!g)return null;var y=this.$getIndent(r.getLine(g.row))}else{if(!m){p.clearMaybeInsertedClosing();return}var y=this.$getIndent(u)}var b=y+r.getTabString();return{text:"\n"+b+"\n"+y+m,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"(",")");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"[","]");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){c(n);var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return h(o,u,s,s);if(!u){var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column),p=f.substring(a.column,a.column+1),d=r.getTokenAt(a.row,a.column),v=r.getTokenAt(a.row,a.column+1);if(l=="\\"&&d&&/escape/.test(d.type))return null;var m=d&&/string|escape/.test(d.type),g=!v||/string|escape/.test(v.type),y;if(p==s)y=m!==g;else{if(m&&!g)return null;if(m&&g)return null;var b=r.$mode.tokenRe;b.lastIndex=0;var w=b.test(l);b.lastIndex=0;var E=b.test(l);if(w||E)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;y=!0}return{text:y?s+s:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(p,i),t.CstyleBehaviour=p}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../range").Range,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.lineCommentStart="//",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="no_regex"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||o=="no_regex")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/javascript"}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-shadow|box-sizing|caption-side|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|hanging-punctuation|height|justify-content|left|letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|min-height|min-width|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|order|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|perspective-origin|position|quotes|resize|right|tab-size|table-layout|text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-indent|text-justify|text-overflow|text-shadow|text-transform|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|vertical-align|visibility|white-space|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0);this.$rules={start:[{token:"comment",regex:"\\/\\*",push:"comment"},{token:"paren.lparen",regex:"\\{",push:"ruleset"},{token:"string",regex:"@.*?{",push:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{caseInsensitive:!0}],media:[{token:"comment",regex:"\\/\\*",push:"comment"},{token:"paren.lparen",regex:"\\{",push:"ruleset"},{token:"string",regex:"\\}",next:"pop"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{caseInsensitive:!0}],comment:[{token:"comment",regex:"\\*\\/",next:"pop"},{defaultToken:"comment"}],ruleset:[{token:"paren.rparen",regex:"\\}",next:"pop"},{token:"comment",regex:"\\/\\*",push:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:["support.function","string","support.function"],regex:"(url\\()(.*)(\\))"},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"},{caseInsensitive:!0}]},this.normalizeRules()};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/css_completions",["require","exports","module"],function(e,t,n){"use strict";var r={background:{"#$0":1},"background-color":{"#$0":1,transparent:1,fixed:1},"background-image":{"url('/$0')":1},"background-repeat":{repeat:1,"repeat-x":1,"repeat-y":1,"no-repeat":1,inherit:1},"background-position":{bottom:2,center:2,left:2,right:2,top:2,inherit:2},"background-attachment":{scroll:1,fixed:1},"background-size":{cover:1,contain:1},"background-clip":{"border-box":1,"padding-box":1,"content-box":1},"background-origin":{"border-box":1,"padding-box":1,"content-box":1},border:{"solid $0":1,"dashed $0":1,"dotted $0":1,"#$0":1},"border-color":{"#$0":1},"border-style":{solid:2,dashed:2,dotted:2,"double":2,groove:2,hidden:2,inherit:2,inset:2,none:2,outset:2,ridged:2},"border-collapse":{collapse:1,separate:1},bottom:{px:1,em:1,"%":1},clear:{left:1,right:1,both:1,none:1},color:{"#$0":1,"rgb(#$00,0,0)":1},cursor:{"default":1,pointer:1,move:1,text:1,wait:1,help:1,progress:1,"n-resize":1,"ne-resize":1,"e-resize":1,"se-resize":1,"s-resize":1,"sw-resize":1,"w-resize":1,"nw-resize":1},display:{none:1,block:1,inline:1,"inline-block":1,"table-cell":1},"empty-cells":{show:1,hide:1},"float":{left:1,right:1,none:1},"font-family":{Arial:2,"Comic Sans MS":2,Consolas:2,"Courier New":2,Courier:2,Georgia:2,Monospace:2,"Sans-Serif":2,"Segoe UI":2,Tahoma:2,"Times New Roman":2,"Trebuchet MS":2,Verdana:1},"font-size":{px:1,em:1,"%":1},"font-weight":{bold:1,normal:1},"font-style":{italic:1,normal:1},"font-variant":{normal:1,"small-caps":1},height:{px:1,em:1,"%":1},left:{px:1,em:1,"%":1},"letter-spacing":{normal:1},"line-height":{normal:1},"list-style-type":{none:1,disc:1,circle:1,square:1,decimal:1,"decimal-leading-zero":1,"lower-roman":1,"upper-roman":1,"lower-greek":1,"lower-latin":1,"upper-latin":1,georgian:1,"lower-alpha":1,"upper-alpha":1},margin:{px:1,em:1,"%":1},"margin-right":{px:1,em:1,"%":1},"margin-left":{px:1,em:1,"%":1},"margin-top":{px:1,em:1,"%":1},"margin-bottom":{px:1,em:1,"%":1},"max-height":{px:1,em:1,"%":1},"max-width":{px:1,em:1,"%":1},"min-height":{px:1,em:1,"%":1},"min-width":{px:1,em:1,"%":1},overflow:{hidden:1,visible:1,auto:1,scroll:1},"overflow-x":{hidden:1,visible:1,auto:1,scroll:1},"overflow-y":{hidden:1,visible:1,auto:1,scroll:1},padding:{px:1,em:1,"%":1},"padding-top":{px:1,em:1,"%":1},"padding-right":{px:1,em:1,"%":1},"padding-bottom":{px:1,em:1,"%":1},"padding-left":{px:1,em:1,"%":1},"page-break-after":{auto:1,always:1,avoid:1,left:1,right:1},"page-break-before":{auto:1,always:1,avoid:1,left:1,right:1},position:{absolute:1,relative:1,fixed:1,"static":1},right:{px:1,em:1,"%":1},"table-layout":{fixed:1,auto:1},"text-decoration":{none:1,underline:1,"line-through":1,blink:1},"text-align":{left:1,right:1,center:1,justify:1},"text-transform":{capitalize:1,uppercase:1,lowercase:1,none:1},top:{px:1,em:1,"%":1},"vertical-align":{top:1,bottom:1},visibility:{hidden:1,visible:1},"white-space":{nowrap:1,normal:1,pre:1,"pre-line":1,"pre-wrap":1},width:{px:1,em:1,"%":1},"word-spacing":{normal:1},filter:{"alpha(opacity=$0100)":1},"text-shadow":{"$02px 2px 2px #777":1},"text-overflow":{"ellipsis-word":1,clip:1,ellipsis:1},"-moz-border-radius":1,"-moz-border-radius-topright":1,"-moz-border-radius-bottomright":1,"-moz-border-radius-topleft":1,"-moz-border-radius-bottomleft":1,"-webkit-border-radius":1,"-webkit-border-top-right-radius":1,"-webkit-border-top-left-radius":1,"-webkit-border-bottom-right-radius":1,"-webkit-border-bottom-left-radius":1,"-moz-box-shadow":1,"-webkit-box-shadow":1,transform:{"rotate($00deg)":1,"skew($00deg)":1},"-moz-transform":{"rotate($00deg)":1,"skew($00deg)":1},"-webkit-transform":{"rotate($00deg)":1,"skew($00deg)":1}},i=function(){};(function(){this.completionsDefined=!1,this.defineCompletions=function(){if(document){var e=document.createElement("c").style;for(var t in e){if(typeof e[t]!="string")continue;var n=t.replace(/[A-Z]/g,function(e){return"-"+e.toLowerCase()});r.hasOwnProperty(n)||(r[n]=1)}}this.completionsDefined=!0},this.getCompletions=function(e,t,n,r){this.completionsDefined||this.defineCompletions();var i=t.getTokenAt(n.row,n.column);if(!i)return[];if(e==="ruleset"){var s=t.getLine(n.row).substr(0,n.column);return/:[^;]+$/.test(s)?(/([\w\-]+):[^:]*$/.test(s),this.getPropertyValueCompletions(e,t,n,r)):this.getPropertyCompletions(e,t,n,r)}return[]},this.getPropertyCompletions=function(e,t,n,i){var s=Object.keys(r);return s.map(function(e){return{caption:e,snippet:e+": $0",meta:"property",score:Number.MAX_VALUE}})},this.getPropertyValueCompletions=function(e,t,n,i){var s=t.getLine(n.row).substr(0,n.column),o=(/([\w\-]+):[^:]*$/.exec(s)||{})[1];if(!o)return[];var u=[];return o in r&&typeof r[o]=="object"&&(u=Object.keys(r[o])),u.map(function(e){return{caption:e,snippet:e,meta:"property value",score:Number.MAX_VALUE}})}}).call(i.prototype),t.CssCompletions=i}),ace.define("ace/mode/behaviour/css",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("./cstyle").CstyleBehaviour,o=e("../../token_iterator").TokenIterator,u=function(){this.inherit(s),this.add("colon","insertion",function(e,t,n,r,i){if(i===":"){var s=n.getCursorPosition(),u=new o(r,s.row,s.column),a=u.getCurrentToken();a&&a.value.match(/\s+/)&&(a=u.stepBackward());if(a&&a.type==="support.type"){var f=r.doc.getLine(s.row),l=f.substring(s.column,s.column+1);if(l===":")return{text:"",selection:[1,1]};if(!f.substring(s.column).match(/^\s*;/))return{text:":;",selection:[1,1]}}}}),this.add("colon","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s===":"){var u=n.getCursorPosition(),a=new o(r,u.row,u.column),f=a.getCurrentToken();f&&f.value.match(/\s+/)&&(f=a.stepBackward());if(f&&f.type==="support.type"){var l=r.doc.getLine(i.start.row),c=l.substring(i.end.column,i.end.column+1);if(c===";")return i.end.column++,i}}}),this.add("semicolon","insertion",function(e,t,n,r,i){if(i===";"){var s=n.getCursorPosition(),o=r.doc.getLine(s.row),u=o.substring(s.column,s.column+1);if(u===";")return{text:"",selection:[1,1]}}})};r.inherits(u,s),t.CssBehaviour=u}),ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/css_completions","ace/mode/behaviour/css","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./css_highlight_rules").CssHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../worker/worker_client").WorkerClient,a=e("./css_completions").CssCompletions,f=e("./behaviour/css").CssBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new f,this.$completer=new a,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.getCompletions=function(e,t,n,r){return this.$completer.getCompletions(e,t,n,r)},this.createWorker=function(e){var t=new u(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/css"}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(e){var t="[_:a-zA-Z\u00c0-\uffff][-_:.a-zA-Z0-9\u00c0-\uffff]*";this.$rules={start:[{token:"string.cdata.xml",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:["punctuation.xml-decl.xml","keyword.xml-decl.xml"],regex:"(<\\?)(xml)(?=[\\s])",next:"xml_decl",caseInsensitive:!0},{token:["punctuation.instruction.xml","keyword.instruction.xml"],regex:"(<\\?)("+t+")",next:"processing_instruction"},{token:"comment.xml",regex:"<\\!--",next:"comment"},{token:["xml-pe.doctype.xml","xml-pe.doctype.xml"],regex:"(<\\!)(DOCTYPE)(?=[\\s])",next:"doctype",caseInsensitive:!0},{include:"tag"},{token:"text.end-tag-open.xml",regex:""},{token:"text.tag-open.xml",regex:"<"},{include:"reference"},{defaultToken:"text.xml"}],xml_decl:[{token:"entity.other.attribute-name.decl-attribute-name.xml",regex:"(?:"+t+":)?"+t+""},{token:"keyword.operator.decl-attribute-equals.xml",regex:"="},{include:"whitespace"},{include:"string"},{token:"punctuation.xml-decl.xml",regex:"\\?>",next:"start"}],processing_instruction:[{token:"punctuation.instruction.xml",regex:"\\?>",next:"start"},{defaultToken:"instruction.xml"}],doctype:[{include:"whitespace"},{include:"string"},{token:"xml-pe.doctype.xml",regex:">",next:"start"},{token:"xml-pe.xml",regex:"[-_a-zA-Z0-9:]+"},{token:"punctuation.int-subset",regex:"\\[",push:"int_subset"}],int_subset:[{token:"text.xml",regex:"\\s+"},{token:"punctuation.int-subset.xml",regex:"]",next:"pop"},{token:["punctuation.markup-decl.xml","keyword.markup-decl.xml"],regex:"(<\\!)("+t+")",push:[{token:"text",regex:"\\s+"},{token:"punctuation.markup-decl.xml",regex:">",next:"pop"},{include:"string"}]}],cdata:[{token:"string.cdata.xml",regex:"\\]\\]>",next:"start"},{token:"text.xml",regex:"\\s+"},{token:"text.xml",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment.xml",regex:"-->",next:"start"},{defaultToken:"comment.xml"}],reference:[{token:"constant.language.escape.reference.xml",regex:"(?:[0-9]+;)|(?:[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}],attr_reference:[{token:"constant.language.escape.reference.attribute-value.xml",regex:"(?:[0-9]+;)|(?:[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}],tag:[{token:["meta.tag.punctuation.tag-open.xml","meta.tag.punctuation.end-tag-open.xml","meta.tag.tag-name.xml"],regex:"(?:(<)|())((?:"+t+":)?"+t+")",next:[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:"start"}]}],tag_whitespace:[{token:"text.tag-whitespace.xml",regex:"\\s+"}],whitespace:[{token:"text.whitespace.xml",regex:"\\s+"}],string:[{token:"string.xml",regex:"'",push:[{token:"string.xml",regex:"'",next:"pop"},{defaultToken:"string.xml"}]},{token:"string.xml",regex:'"',push:[{token:"string.xml",regex:'"',next:"pop"},{defaultToken:"string.xml"}]}],attributes:[{token:"entity.other.attribute-name.xml",regex:"(?:"+t+":)?"+t+""},{token:"keyword.operator.attribute-equals.xml",regex:"="},{include:"tag_whitespace"},{include:"attribute_value"}],attribute_value:[{token:"string.attribute-value.xml",regex:"'",push:[{token:"string.attribute-value.xml",regex:"'",next:"pop"},{include:"attr_reference"},{defaultToken:"string.attribute-value.xml"}]},{token:"string.attribute-value.xml",regex:'"',push:[{token:"string.attribute-value.xml",regex:'"',next:"pop"},{include:"attr_reference"},{defaultToken:"string.attribute-value.xml"}]}]},this.constructor===s&&this.normalizeRules()};(function(){this.embedTagRules=function(e,t,n){this.$rules.tag.unshift({token:["meta.tag.punctuation.tag-open.xml","meta.tag."+n+".tag-name.xml"],regex:"(<)("+n+"(?=\\s|>|$))",next:[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:t+"start"}]}),this.$rules[n+"-end"]=[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:"start",onMatch:function(e,t,n){return n.splice(0),this.token}}],this.embedRules(e,t,[{token:["meta.tag.punctuation.end-tag-open.xml","meta.tag."+n+".tag-name.xml"],regex:"()("+n+"(?=\\s|>|$))",next:n+"-end"},{token:"string.cdata.xml",regex:"<\\!\\[CDATA\\["},{token:"string.cdata.xml",regex:"\\]\\]>"}])}}).call(i.prototype),r.inherits(s,i),t.XmlHighlightRules=s}),ace.define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./css_highlight_rules").CssHighlightRules,o=e("./javascript_highlight_rules").JavaScriptHighlightRules,u=e("./xml_highlight_rules").XmlHighlightRules,a=i.createMap({a:"anchor",button:"form",form:"form",img:"image",input:"form",label:"form",option:"form",script:"script",select:"form",textarea:"form",style:"style",table:"table",tbody:"table",td:"table",tfoot:"table",th:"table",tr:"table"}),f=function(){u.call(this),this.addRules({attributes:[{include:"tag_whitespace"},{token:"entity.other.attribute-name.xml",regex:"[-_a-zA-Z0-9:.]+"},{token:"keyword.operator.attribute-equals.xml",regex:"=",push:[{include:"tag_whitespace"},{token:"string.unquoted.attribute-value.html",regex:"[^<>='\"`\\s]+",next:"pop"},{token:"empty",regex:"",next:"pop"}]},{include:"attribute_value"}],tag:[{token:function(e,t){var n=a[t];return["meta.tag.punctuation."+(e=="<"?"":"end-")+"tag-open.xml","meta.tag"+(n?"."+n:"")+".tag-name.xml"]},regex:"(?)([-_a-zA-Z0-9:.]+)",next:"tag_stuff"}],tag_stuff:[{include:"attributes"},{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",next:"start"}]}),this.embedTagRules(s,"css-","style"),this.embedTagRules((new o({noJSX:!0})).getRules(),"js-","script"),this.constructor===f&&this.normalizeRules()};r.inherits(f,u),t.HtmlHighlightRules=f}),ace.define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";function u(e,t){return e.type.lastIndexOf(t+".xml")>-1}var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),a=function(){this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var o=i,a=r.doc.getTextRange(n.getSelectionRange());if(a!==""&&a!=="'"&&a!='"'&&n.getWrapBehavioursEnabled())return{text:o+a+o,selection:!1};var f=n.getCursorPosition(),l=r.doc.getLine(f.row),c=l.substring(f.column,f.column+1),h=new s(r,f.row,f.column),p=h.getCurrentToken();if(c==o&&(u(p,"attribute-value")||u(p,"string")))return{text:"",selection:[1,1]};p||(p=h.stepBackward());if(!p)return;while(u(p,"tag-whitespace")||u(p,"whitespace"))p=h.stepBackward();var d=!c||c.match(/\s/);if(u(p,"attribute-equals")&&(d||c==">")||u(p,"decl-attribute-equals")&&(d||c=="?"))return{text:o+o,selection:[1,1]}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}}),this.add("autoclosing","insertion",function(e,t,n,r,i){if(i==">"){var o=n.getCursorPosition(),a=new s(r,o.row,o.column),f=a.getCurrentToken()||a.stepBackward();if(!f||!(u(f,"tag-name")||u(f,"tag-whitespace")||u(f,"attribute-name")||u(f,"attribute-equals")||u(f,"attribute-value")))return;if(u(f,"reference.attribute-value"))return;if(u(f,"attribute-value")){var l=f.value.charAt(0);if(l=='"'||l=="'"){var c=f.value.charAt(f.value.length-1),h=a.getCurrentTokenColumn()+f.value.length;if(h>o.column||h==o.column&&l!=c)return}}while(!u(f,"tag-name"))f=a.stepBackward();var p=a.getCurrentTokenRow(),d=a.getCurrentTokenColumn();if(u(a.stepBackward(),"end-tag-open"))return;var v=f.value;p==o.row&&(v=v.substring(0,o.column-d));if(this.voidElements.hasOwnProperty(v.toLowerCase()))return;return{text:">"+v+">",selection:[1,1]}}}),this.add("autoindent","insertion",function(e,t,n,r,i){if(i=="\n"){var o=n.getCursorPosition(),u=r.getLine(o.row),a=new s(r,o.row,o.column),f=a.getCurrentToken();if(f&&f.type.indexOf("tag-close")!==-1){if(f.value=="/>")return;while(f&&f.type.indexOf("tag-name")===-1)f=a.stepBackward();if(!f)return;var l=f.value,c=a.getCurrentTokenRow();f=a.stepBackward();if(!f||f.type.indexOf("end-tag")!==-1)return;if(this.voidElements&&!this.voidElements[l]){var h=r.getTokenAt(o.row,o.column+1),u=r.getLine(c),p=this.$getIndent(u),d=p+r.getTabString();return h&&h.value===""?{text:"\n"+d+"\n"+p,selection:[1,d.length,1,d.length]}:{text:"\n"+d}}}}})};r.inherits(a,i),t.XmlBehaviour=a}),ace.define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=t.FoldMode=function(e,t){this.defaultMode=e,this.subModes=t};r.inherits(s,i),function(){this.$getMode=function(e){typeof e!="string"&&(e=e[0]);for(var t in this.subModes)if(e.indexOf(t)===0)return this.subModes[t];return null},this.$tryMode=function(e,t,n,r){var i=this.$getMode(e);return i?i.getFoldWidget(t,n,r):""},this.getFoldWidget=function(e,t,n){return this.$tryMode(e.getState(n-1),e,t,n)||this.$tryMode(e.getState(n),e,t,n)||this.defaultMode.getFoldWidget(e,t,n)},this.getFoldWidgetRange=function(e,t,n){var r=this.$getMode(e.getState(n-1));if(!r||!r.getFoldWidget(e,t,n))r=this.$getMode(e.getState(n));if(!r||!r.getFoldWidget(e,t,n))r=this.defaultMode;return r.getFoldWidgetRange(e,t,n)}}.call(s.prototype)}),ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(e,t,n){"use strict";function l(e,t){return e.type.lastIndexOf(t+".xml")>-1}var r=e("../../lib/oop"),i=e("../../lib/lang"),s=e("../../range").Range,o=e("./fold_mode").FoldMode,u=e("../../token_iterator").TokenIterator,a=t.FoldMode=function(e,t){o.call(this),this.voidElements=e||{},this.optionalEndTags=r.mixin({},this.voidElements),t&&r.mixin(this.optionalEndTags,t)};r.inherits(a,o);var f=function(){this.tagName="",this.closing=!1,this.selfClosing=!1,this.start={row:0,column:0},this.end={row:0,column:0}};(function(){this.getFoldWidget=function(e,t,n){var r=this._getFirstTagInLine(e,n);return r?r.closing||!r.tagName&&r.selfClosing?t=="markbeginend"?"end":"":!r.tagName||r.selfClosing||this.voidElements.hasOwnProperty(r.tagName.toLowerCase())?"":this._findEndTagInLine(e,n,r.tagName,r.end.column)?"":"start":""},this._getFirstTagInLine=function(e,t){var n=e.getTokens(t),r=new f;for(var i=0;i ";break}}return r}if(l(s,"tag-close"))return r.selfClosing=s.value=="/>",r;r.start.column+=s.value.length}return null},this._findEndTagInLine=function(e,t,n,r){var i=e.getTokens(t),s=0;for(var o=0;o",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length,e.stepForward(),n;while(t=e.stepForward());return null},this._readTagBackward=function(e){var t=e.getCurrentToken();if(!t)return null;var n=new f;do{if(l(t,"tag-open"))return n.closing=l(t,"end-tag-open"),n.start.row=e.getCurrentTokenRow(),n.start.column=e.getCurrentTokenColumn(),e.stepBackward(),n;l(t,"tag-name")?n.tagName=t.value:l(t,"tag-close")&&(n.selfClosing=t.value=="/>",n.end.row=e.getCurrentTokenRow(),n.end.column=e.getCurrentTokenColumn()+t.value.length)}while(t=e.stepBackward());return null},this._pop=function(e,t){while(e.length){var n=e[e.length-1];if(!t||n.tagName==t.tagName)return e.pop();if(this.optionalEndTags.hasOwnProperty(n.tagName)){e.pop();continue}return null}},this.getFoldWidgetRange=function(e,t,n){var r=this._getFirstTagInLine(e,n);if(!r)return null;var i=r.closing||r.selfClosing,o=[],a;if(!i){var f=new u(e,n,r.start.column),l={row:n,column:r.start.column+r.tagName.length+2};r.start.row==r.end.row&&(l.column=r.end.column);while(a=this._readTagForward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(a.closing){this._pop(o,a);if(o.length==0)return s.fromPoints(l,a.start)}else o.push(a)}}else{var f=new u(e,n,r.end.column),c={row:n,column:r.start.column};while(a=this._readTagBackward(f)){if(a.selfClosing){if(!o.length)return a.start.column+=a.tagName.length+2,a.end.column-=2,s.fromPoints(a.start,a.end);continue}if(!a.closing){this._pop(o,a);if(o.length==0)return a.start.column+=a.tagName.length+2,a.start.row==a.end.row&&a.start.column-1}function l(e,t){var n=new r(e,t.row,t.column),i=n.getCurrentToken();while(i&&!f(i,"tag-name"))i=n.stepBackward();if(i)return i.value}function c(e,t){var n=new r(e,t.row,t.column),i=n.getCurrentToken();while(i&&!f(i,"attribute-name"))i=n.stepBackward();if(i)return i.value}var r=e("../token_iterator").TokenIterator,i=["accesskey","class","contenteditable","contextmenu","dir","draggable","dropzone","hidden","id","inert","itemid","itemprop","itemref","itemscope","itemtype","lang","spellcheck","style","tabindex","title","translate"],s=["onabort","onblur","oncancel","oncanplay","oncanplaythrough","onchange","onclick","onclose","oncontextmenu","oncuechange","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchange","onemptied","onended","onerror","onfocus","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmousedown","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onpause","onplay","onplaying","onprogress","onratechange","onreset","onscroll","onseeked","onseeking","onselect","onshow","onstalled","onsubmit","onsuspend","ontimeupdate","onvolumechange","onwaiting"],o=i.concat(s),u={html:{manifest:1},head:{},title:{},base:{href:1,target:1},link:{href:1,hreflang:1,rel:{stylesheet:1,icon:1},media:{all:1,screen:1,print:1},type:{"text/css":1,"image/png":1,"image/jpeg":1,"image/gif":1},sizes:1},meta:{"http-equiv":{"content-type":1},name:{description:1,keywords:1},content:{"text/html; charset=UTF-8":1},charset:1},style:{type:1,media:{all:1,screen:1,print:1},scoped:1},script:{charset:1,type:{"text/javascript":1},src:1,defer:1,async:1},noscript:{href:1},body:{onafterprint:1,onbeforeprint:1,onbeforeunload:1,onhashchange:1,onmessage:1,onoffline:1,onpopstate:1,onredo:1,onresize:1,onstorage:1,onundo:1,onunload:1},section:{},nav:{},article:{pubdate:1},aside:{},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},header:{},footer:{},address:{},main:{},p:{},hr:{},pre:{},blockquote:{cite:1},ol:{start:1,reversed:1},ul:{},li:{value:1},dl:{},dt:{},dd:{},figure:{},figcaption:{},div:{},a:{href:1,target:{_blank:1,top:1},ping:1,rel:{nofollow:1,alternate:1,author:1,bookmark:1,help:1,license:1,next:1,noreferrer:1,prefetch:1,prev:1,search:1,tag:1},media:1,hreflang:1,type:1},em:{},strong:{},small:{},s:{},cite:{},q:{cite:1},dfn:{},abbr:{},data:{},time:{datetime:1},code:{},"var":{},samp:{},kbd:{},sub:{},sup:{},i:{},b:{},u:{},mark:{},ruby:{},rt:{},rp:{},bdi:{},bdo:{},span:{},br:{},wbr:{},ins:{cite:1,datetime:1},del:{cite:1,datetime:1},img:{alt:1,src:1,height:1,width:1,usemap:1,ismap:1},iframe:{name:1,src:1,height:1,width:1,sandbox:{"allow-same-origin":1,"allow-top-navigation":1,"allow-forms":1,"allow-scripts":1},seamless:{seamless:1}},embed:{src:1,height:1,width:1,type:1},object:{param:1,data:1,type:1,height:1,width:1,usemap:1,name:1,form:1,classid:1},param:{name:1,value:1},video:{src:1,autobuffer:1,autoplay:{autoplay:1},loop:{loop:1},controls:{controls:1},width:1,height:1,poster:1,muted:{muted:1},preload:{auto:1,metadata:1,none:1}},audio:{src:1,autobuffer:1,autoplay:{autoplay:1},loop:{loop:1},controls:{controls:1},muted:{muted:1},preload:{auto:1,metadata:1,none:1}},source:{src:1,type:1,media:1},track:{kind:1,src:1,srclang:1,label:1,"default":1},canvas:{width:1,height:1},map:{name:1},area:{shape:1,coords:1,href:1,hreflang:1,alt:1,target:1,media:1,rel:1,ping:1,type:1},svg:{},math:{},table:{summary:1},caption:{},colgroup:{span:1},col:{span:1},tbody:{},thead:{},tfoot:{},tr:{},td:{headers:1,rowspan:1,colspan:1},th:{headers:1,rowspan:1,colspan:1,scope:1},form:{"accept-charset":1,action:1,autocomplete:1,enctype:{"multipart/form-data":1,"application/x-www-form-urlencoded":1},method:{get:1,post:1},name:1,novalidate:1,target:{_blank:1,top:1}},fieldset:{disabled:1,form:1,name:1},legend:{},label:{form:1,"for":1},input:{type:{text:1,password:1,hidden:1,checkbox:1,submit:1,radio:1,file:1,button:1,reset:1,image:31,color:1,date:1,datetime:1,"datetime-local":1,email:1,month:1,number:1,range:1,search:1,tel:1,time:1,url:1,week:1},accept:1,alt:1,autocomplete:{on:1,off:1},autofocus:{autofocus:1},checked:{checked:1},disabled:{disabled:1},form:1,formaction:1,formenctype:{"application/x-www-form-urlencoded":1,"multipart/form-data":1,"text/plain":1},formmethod:{get:1,post:1},formnovalidate:{formnovalidate:1},formtarget:{_blank:1,_self:1,_parent:1,_top:1},height:1,list:1,max:1,maxlength:1,min:1,multiple:{multiple:1},pattern:1,placeholder:1,readonly:{readonly:1},required:{required:1},size:1,src:1,step:1,width:1,files:1,value:1},button:{autofocus:1,disabled:{disabled:1},form:1,formaction:1,formenctype:1,formmethod:1,formnovalidate:1,formtarget:1,name:1,value:1,type:{button:1,submit:1}},select:{autofocus:1,disabled:1,form:1,multiple:{multiple:1},name:1,size:1,readonly:{readonly:1}},datalist:{},optgroup:{disabled:1,label:1},option:{disabled:1,selected:1,label:1,value:1},textarea:{autofocus:{autofocus:1},disabled:{disabled:1},form:1,maxlength:1,name:1,placeholder:1,readonly:{readonly:1},required:{required:1},rows:1,cols:1,wrap:{on:1,off:1,hard:1,soft:1}},keygen:{autofocus:1,challenge:{challenge:1},disabled:{disabled:1},form:1,keytype:{rsa:1,dsa:1,ec:1},name:1},output:{"for":1,form:1,name:1},progress:{value:1,max:1},meter:{value:1,min:1,max:1,low:1,high:1,optimum:1},details:{open:1},summary:{},command:{type:1,label:1,icon:1,disabled:1,checked:1,radiogroup:1,command:1},menu:{type:1,label:1},dialog:{open:1}},a=Object.keys(u),h=function(){};(function(){this.getCompletions=function(e,t,n,r){var i=t.getTokenAt(n.row,n.column);if(!i)return[];if(f(i,"tag-name")||f(i,"tag-open")||f(i,"end-tag-open"))return this.getTagCompletions(e,t,n,r);if(f(i,"tag-whitespace")||f(i,"attribute-name"))return this.getAttributeCompletions(e,t,n,r);if(f(i,"attribute-value"))return this.getAttributeValueCompletions(e,t,n,r);var s=t.getLine(n.row).substr(0,n.column);return/&[A-z]*$/i.test(s)?this.getHTMLEntityCompletions(e,t,n,r):[]},this.getTagCompletions=function(e,t,n,r){return a.map(function(e){return{value:e,meta:"tag",score:Number.MAX_VALUE}})},this.getAttributeCompletions=function(e,t,n,r){var i=l(t,n);if(!i)return[];var s=o;return i in u&&(s=s.concat(Object.keys(u[i]))),s.map(function(e){return{caption:e,snippet:e+'="$0"',meta:"attribute",score:Number.MAX_VALUE}})},this.getAttributeValueCompletions=function(e,t,n,r){var i=l(t,n),s=c(t,n);if(!i)return[];var o=[];return i in u&&s in u[i]&&typeof u[i][s]=="object"&&(o=Object.keys(u[i][s])),o.map(function(e){return{caption:e,snippet:e,meta:"attribute value",score:Number.MAX_VALUE}})},this.getHTMLEntityCompletions=function(e,t,n,r){var i=["Aacute;","aacute;","Acirc;","acirc;","acute;","AElig;","aelig;","Agrave;","agrave;","alefsym;","Alpha;","alpha;","amp;","and;","ang;","Aring;","aring;","asymp;","Atilde;","atilde;","Auml;","auml;","bdquo;","Beta;","beta;","brvbar;","bull;","cap;","Ccedil;","ccedil;","cedil;","cent;","Chi;","chi;","circ;","clubs;","cong;","copy;","crarr;","cup;","curren;","Dagger;","dagger;","dArr;","darr;","deg;","Delta;","delta;","diams;","divide;","Eacute;","eacute;","Ecirc;","ecirc;","Egrave;","egrave;","empty;","emsp;","ensp;","Epsilon;","epsilon;","equiv;","Eta;","eta;","ETH;","eth;","Euml;","euml;","euro;","exist;","fnof;","forall;","frac12;","frac14;","frac34;","frasl;","Gamma;","gamma;","ge;","gt;","hArr;","harr;","hearts;","hellip;","Iacute;","iacute;","Icirc;","icirc;","iexcl;","Igrave;","igrave;","image;","infin;","int;","Iota;","iota;","iquest;","isin;","Iuml;","iuml;","Kappa;","kappa;","Lambda;","lambda;","lang;","laquo;","lArr;","larr;","lceil;","ldquo;","le;","lfloor;","lowast;","loz;","lrm;","lsaquo;","lsquo;","lt;","macr;","mdash;","micro;","middot;","minus;","Mu;","mu;","nabla;","nbsp;","ndash;","ne;","ni;","not;","notin;","nsub;","Ntilde;","ntilde;","Nu;","nu;","Oacute;","oacute;","Ocirc;","ocirc;","OElig;","oelig;","Ograve;","ograve;","oline;","Omega;","omega;","Omicron;","omicron;","oplus;","or;","ordf;","ordm;","Oslash;","oslash;","Otilde;","otilde;","otimes;","Ouml;","ouml;","para;","part;","permil;","perp;","Phi;","phi;","Pi;","pi;","piv;","plusmn;","pound;","Prime;","prime;","prod;","prop;","Psi;","psi;","quot;","radic;","rang;","raquo;","rArr;","rarr;","rceil;","rdquo;","real;","reg;","rfloor;","Rho;","rho;","rlm;","rsaquo;","rsquo;","sbquo;","Scaron;","scaron;","sdot;","sect;","shy;","Sigma;","sigma;","sigmaf;","sim;","spades;","sub;","sube;","sum;","sup;","sup1;","sup2;","sup3;","supe;","szlig;","Tau;","tau;","there4;","Theta;","theta;","thetasym;","thinsp;","THORN;","thorn;","tilde;","times;","trade;","Uacute;","uacute;","uArr;","uarr;","Ucirc;","ucirc;","Ugrave;","ugrave;","uml;","upsih;","Upsilon;","upsilon;","Uuml;","uuml;","weierp;","Xi;","xi;","Yacute;","yacute;","yen;","Yuml;","yuml;","Zeta;","zeta;","zwj;","zwnj;"];return i.map(function(e){return{caption:e,snippet:e,meta:"html entity",score:Number.MAX_VALUE}})}}).call(h.prototype),t.HtmlCompletions=h}),ace.define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html","ace/mode/html_completions","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text").Mode,o=e("./javascript").Mode,u=e("./css").Mode,a=e("./html_highlight_rules").HtmlHighlightRules,f=e("./behaviour/xml").XmlBehaviour,l=e("./folding/html").FoldMode,c=e("./html_completions").HtmlCompletions,h=e("../worker/worker_client").WorkerClient,p=["area","base","br","col","embed","hr","img","input","keygen","link","meta","menuitem","param","source","track","wbr"],d=["li","dt","dd","p","rt","rp","optgroup","option","colgroup","td","th"],v=function(e){this.fragmentContext=e&&e.fragmentContext,this.HighlightRules=a,this.$behaviour=new f,this.$completer=new c,this.createModeDelegates({"js-":o,"css-":u}),this.foldingRules=new l(this.voidElements,i.arrayToMap(d))};r.inherits(v,s),function(){this.blockComment={start:""},this.voidElements=i.arrayToMap(p),this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.getCompletions=function(e,t,n,r){return this.$completer.getCompletions(e,t,n,r)},this.createWorker=function(e){if(this.constructor!=v)return;var t=new h(["ace"],"ace/mode/html_worker","Worker");return t.attachToDocument(e.getDocument()),this.fragmentContext&&t.call("setOptions",[{context:this.fragmentContext}]),t.on("error",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/html"}.call(v.prototype),t.Mode=v}),ace.define("ace/mode/handlebars_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/html_highlight_rules"],function(e,t,n){"use strict";function s(e,t){return t.splice(0,3),t.shift()||"start"}var r=e("../lib/oop"),i=e("./html_highlight_rules").HtmlHighlightRules,o=function(){i.call(this);var e={regex:"(?={{)",push:"handlebars"};for(var t in this.$rules)this.$rules[t].unshift(e);this.$rules.handlebars=[{token:"comment.start",regex:"{{!--",push:[{token:"comment.end",regex:"--}}",next:s},{defaultToken:"comment"}]},{token:"comment.start",regex:"{{!",push:[{token:"comment.end",regex:"}}",next:s},{defaultToken:"comment"}]},{token:"support.function",regex:"{{{",push:[{token:"support.function",regex:"}}}",next:s},{token:"variable.parameter",regex:"[a-zA-Z_$][a-zA-Z0-9_$]*"}]},{token:"storage.type.start",regex:"{{[#\\^/&]?",push:[{token:"storage.type.end",regex:"}}",next:s},{token:"variable.parameter",regex:"[a-zA-Z_$][a-zA-Z0-9_$]*"}]}],this.normalizeRules()};r.inherits(o,i),t.HandlebarsHighlightRules=o}),ace.define("ace/mode/behaviour/html",["require","exports","module","ace/lib/oop","ace/mode/behaviour/xml"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour/xml").XmlBehaviour,s=function(){i.call(this)};r.inherits(s,i),t.HtmlBehaviour=s}),ace.define("ace/mode/handlebars",["require","exports","module","ace/lib/oop","ace/mode/html","ace/mode/handlebars_highlight_rules","ace/mode/behaviour/html","ace/mode/folding/html"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./html").Mode,s=e("./handlebars_highlight_rules").HandlebarsHighlightRules,o=e("./behaviour/html").HtmlBehaviour,u=e("./folding/html").FoldMode,a=function(){i.call(this),this.HighlightRules=s,this.$behaviour=new o,this.foldingRules=new u};r.inherits(a,i),function(){this.blockComment={start:"{{!--",end:"--}}"},this.$id="ace/mode/handlebars"}.call(a.prototype),t.Mode=a})
\ No newline at end of file
diff --git a/public/ace/mode-javascript.js b/public/ace/mode-javascript.js
new file mode 100644
index 00000000..26a8bdc8
--- /dev/null
+++ b/public/ace/mode-javascript.js
@@ -0,0 +1 @@
+ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},s.getTagRule(),{defaultToken:"comment.doc",caseInsensitive:!0}]}};r.inherits(s,i),s.getTagRule=function(e){return{token:"comment.doc.tag.storage.type",regex:"\\b(?:TODO|FIXME|XXX|HACK)\\b"}},s.getStartRule=function(e){return{token:"comment.doc",regex:"\\/\\*(?=\\*)",next:e}},s.getEndRule=function(e){return{token:"comment.doc",regex:"\\*\\/",next:e}},t.DocCommentHighlightRules=s}),ace.define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";function a(){var e=o.replace("\\d","\\d\\-"),t={onMatch:function(e,t,n){var r=e.charAt(1)=="/"?2:1;if(r==1)t!=this.nextState?n.unshift(this.next,this.nextState,0):n.unshift(this.next),n[2]++;else if(r==2&&t==this.nextState){n[1]--;if(!n[1]||n[1]<0)n.shift(),n.shift()}return[{type:"meta.tag.punctuation."+(r==1?"":"end-")+"tag-open.xml",value:e.slice(0,r)},{type:"meta.tag.tag-name.xml",value:e.substr(r)}]},regex:"?"+e+"",next:"jsxAttributes",nextState:"jsx"};this.$rules.start.unshift(t);var n={regex:"{",token:"paren.quasi.start",push:"start"};this.$rules.jsx=[n,t,{include:"reference"},{defaultToken:"string"}],this.$rules.jsxAttributes=[{token:"meta.tag.punctuation.tag-close.xml",regex:"/?>",onMatch:function(e,t,n){return t==n[0]&&n.shift(),e.length==2&&(n[0]==this.nextState&&n[1]--,(!n[1]||n[1]<0)&&n.splice(0,2)),this.next=n[0]||"start",[{type:this.token,value:e}]},nextState:"jsx"},n,f("jsxAttributes"),{token:"entity.other.attribute-name.xml",regex:e},{token:"keyword.operator.attribute-equals.xml",regex:"="},{token:"text.tag-whitespace.xml",regex:"\\s+"},{token:"string.attribute-value.xml",regex:"'",stateName:"jsx_attr_q",push:[{token:"string.attribute-value.xml",regex:"'",next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},{token:"string.attribute-value.xml",regex:'"',stateName:"jsx_attr_qq",push:[{token:"string.attribute-value.xml",regex:'"',next:"pop"},{include:"reference"},{defaultToken:"string.attribute-value.xml"}]},t],this.$rules.reference=[{token:"constant.language.escape.reference.xml",regex:"(?:[0-9]+;)|(?:[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"}]}function f(e){return[{token:"comment",regex:/\/\*/,next:[i.getTagRule(),{token:"comment",regex:"\\*\\/",next:e||"pop"},{defaultToken:"comment",caseInsensitive:!0}]},{token:"comment",regex:"\\/\\/",next:[i.getTagRule(),{token:"comment",regex:"$|^",next:e||"pop"},{defaultToken:"comment",caseInsensitive:!0}]}]}var r=e("../lib/oop"),i=e("./doc_comment_highlight_rules").DocCommentHighlightRules,s=e("./text_highlight_rules").TextHighlightRules,o="[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b",u=function(e){var t=this.createKeywordMapper({"variable.language":"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document",keyword:"const|yield|import|get|set|break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|__parent__|__count__|escape|unescape|with|__proto__|class|enum|extends|super|export|implements|private|public|interface|package|protected|static","storage.type":"const|let|var|function","constant.language":"null|Infinity|NaN|undefined","support.function":"alert","constant.language.boolean":"true|false"},"identifier"),n="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void",r="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|u{[0-9a-fA-F]{1,6}}|[0-2][0-7]{0,2}|3[0-7][0-7]?|[4-7][0-7]?|.)";this.$rules={no_regex:[i.getStartRule("doc-start"),f("no_regex"),{token:"string",regex:"'(?=.)",next:"qstring"},{token:"string",regex:'"(?=.)',next:"qqstring"},{token:"constant.numeric",regex:/0(?:[xX][0-9a-fA-F]+|[bB][01]+)\b/},{token:"constant.numeric",regex:/[+-]?\d[\d_]*(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator"],regex:"("+o+")(\\.)(prototype)(\\.)("+o+")(\\s*)(=)",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()",next:"function_arguments"},{token:["storage.type","text","entity.name.function","text","paren.lparen"],regex:"(function)(\\s+)("+o+")(\\s*)(\\()",next:"function_arguments"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen"],regex:"("+o+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:["text","text","storage.type","text","paren.lparen"],regex:"(:)(\\s*)(function)(\\s*)(\\()",next:"function_arguments"},{token:"keyword",regex:"(?:"+n+")\\b",next:"start"},{token:["support.constant"],regex:/that\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/},{token:t,regex:o},{token:"punctuation.operator",regex:/[.](?![.])/,next:"property"},{token:"keyword.operator",regex:/--|\+\+|\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/,next:"start"},{token:"punctuation.operator",regex:/[?:,;.]/,next:"start"},{token:"paren.lparen",regex:/[\[({]/,next:"start"},{token:"paren.rparen",regex:/[\])}]/},{token:"comment",regex:/^#!.*$/}],property:[{token:"text",regex:"\\s+"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","entity.name.function","text","paren.lparen"],regex:"("+o+")(\\.)("+o+")(\\s*)(=)(\\s*)(function)(?:(\\s+)(\\w+))?(\\s*)(\\()",next:"function_arguments"},{token:"punctuation.operator",regex:/[.](?![.])/},{token:"support.function",regex:/(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:"support.function.dom",regex:/(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:"support.constant",regex:/(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:"identifier",regex:o},{regex:"",token:"empty",next:"no_regex"}],start:[i.getStartRule("doc-start"),f("start"),{token:"string.regexp",regex:"\\/",next:"regex"},{token:"text",regex:"\\s+|^$",next:"start"},{token:"empty",regex:"",next:"no_regex"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"string.regexp",regex:"/[sxngimy]*",next:"no_regex"},{token:"invalid",regex:/\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/},{token:"constant.language.escape",regex:/\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/},{token:"constant.language.delimiter",regex:/\|/},{token:"constant.language.escape",regex:/\[\^?/,next:"regex_character_class"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp"}],regex_character_class:[{token:"regexp.charclass.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"},{token:"constant.language.escape",regex:"]",next:"regex"},{token:"constant.language.escape",regex:"-"},{token:"empty",regex:"$",next:"no_regex"},{defaultToken:"string.regexp.charachterclass"}],function_arguments:[{token:"variable.parameter",regex:o},{token:"punctuation.operator",regex:"[, ]+"},{token:"punctuation.operator",regex:"$"},{token:"empty",regex:"",next:"no_regex"}],qqstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qqstring"},{token:"string",regex:'"|$',next:"no_regex"},{defaultToken:"string"}],qstring:[{token:"constant.language.escape",regex:r},{token:"string",regex:"\\\\$",next:"qstring"},{token:"string",regex:"'|$",next:"no_regex"},{defaultToken:"string"}]};if(!e||!e.noES6)this.$rules.no_regex.unshift({regex:"[{}]",onMatch:function(e,t,n){this.next=e=="{"?this.nextState:"";if(e=="{"&&n.length)n.unshift("start",t);else if(e=="}"&&n.length){n.shift(),this.next=n.shift();if(this.next.indexOf("string")!=-1||this.next.indexOf("jsx")!=-1)return"paren.quasi.end"}return e=="{"?"paren.lparen":"paren.rparen"},nextState:"start"},{token:"string.quasi.start",regex:/`/,push:[{token:"constant.language.escape",regex:r},{token:"paren.quasi.start",regex:/\${/,push:"start"},{token:"string.quasi.end",regex:/`/,next:"pop"},{defaultToken:"string.quasi"}]}),(!e||!e.noJSX)&&a.call(this);this.embedRules(i,"doc-",[i.getEndRule("no_regex")]),this.normalizeRules()};r.inherits(u,s),t.JavaScriptHighlightRules=u}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},h=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){c(n);var a=n.getSelectionRange(),l=r.doc.getTextRange(a);if(l!==""&&l!=="{"&&n.getWrapBehavioursEnabled())return h(a,l,"{","}");if(p.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){c(n);var d=u.substring(s.column,s.column+1);if(d=="}"){var v=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(v!==null&&p.isAutoInsertedClosing(s,u,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(i=="\n"||i=="\r\n"){c(n);var m="";p.isMaybeInsertedClosing(s,u)&&(m=o.stringRepeat("}",f.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var d=u.substring(s.column,s.column+1);if(d==="}"){var g=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!g)return null;var y=this.$getIndent(r.getLine(g.row))}else{if(!m){p.clearMaybeInsertedClosing();return}var y=this.$getIndent(u)}var b=y+r.getTabString();return{text:"\n"+b+"\n"+y+m,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"(",")");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"[","]");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){c(n);var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return h(o,u,s,s);if(!u){var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column),p=f.substring(a.column,a.column+1),d=r.getTokenAt(a.row,a.column),v=r.getTokenAt(a.row,a.column+1);if(l=="\\"&&d&&/escape/.test(d.type))return null;var m=d&&/string|escape/.test(d.type),g=!v||/string|escape/.test(v.type),y;if(p==s)y=m!==g;else{if(m&&!g)return null;if(m&&g)return null;var b=r.$mode.tokenRe;b.lastIndex=0;var w=b.test(l);b.lastIndex=0;var E=b.test(l);if(w||E)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;y=!0}return{text:y?s+s:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(p,i),t.CstyleBehaviour=p}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),ace.define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./javascript_highlight_rules").JavaScriptHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("../range").Range,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.lineCommentStart="//",this.blockComment={start:"/*",end:"*/"},this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.getTokenizer().getLineTokens(t,e),s=i.tokens,o=i.state;if(s.length&&s[s.length-1].type=="comment")return r;if(e=="start"||e=="no_regex"){var u=t.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);u&&(r+=n)}else if(e=="doc-start"){if(o=="start"||o=="no_regex")return"";var u=t.match(/^\s*(\/?)\*/);u&&(u[1]&&(r+=" "),r+="* ")}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/javascript_worker","JavaScriptWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/javascript"}.call(c.prototype),t.Mode=c})
\ No newline at end of file
diff --git a/public/ace/mode-json.js b/public/ace/mode-json.js
new file mode 100644
index 00000000..f6226b80
--- /dev/null
+++ b/public/ace/mode-json.js
@@ -0,0 +1 @@
+ace.define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f,l={},c=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:"",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:"",maybeInsertedLineEnd:""}},h=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},p=function(){this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){c(n);var a=n.getSelectionRange(),l=r.doc.getTextRange(a);if(l!==""&&l!=="{"&&n.getWrapBehavioursEnabled())return h(a,l,"{","}");if(p.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])||n.inMultiSelectMode?(p.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(p.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){c(n);var d=u.substring(s.column,s.column+1);if(d=="}"){var v=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(v!==null&&p.isAutoInsertedClosing(s,u,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else{if(i=="\n"||i=="\r\n"){c(n);var m="";p.isMaybeInsertedClosing(s,u)&&(m=o.stringRepeat("}",f.maybeInsertedBrackets),p.clearMaybeInsertedClosing());var d=u.substring(s.column,s.column+1);if(d==="}"){var g=r.findMatchingBracket({row:s.row,column:s.column+1},"}");if(!g)return null;var y=this.$getIndent(r.getLine(g.row))}else{if(!m){p.clearMaybeInsertedClosing();return}var y=this.$getIndent(u)}var b=y+r.getTabString();return{text:"\n"+b+"\n"+y+m,selection:[1,b.length,1,b.length]}}p.clearMaybeInsertedClosing()}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"(",")");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){c(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return h(s,o,"[","]");if(p.isSaneInsertion(n,r))return p.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){c(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&p.isAutoInsertedClosing(u,a,i))return p.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){c(n);var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return h(o,u,s,s);if(!u){var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column),p=f.substring(a.column,a.column+1),d=r.getTokenAt(a.row,a.column),v=r.getTokenAt(a.row,a.column+1);if(l=="\\"&&d&&/escape/.test(d.type))return null;var m=d&&/string|escape/.test(d.type),g=!v||/string|escape/.test(v.type),y;if(p==s)y=m!==g;else{if(m&&!g)return null;if(m&&g)return null;var b=r.$mode.tokenRe;b.lastIndex=0;var w=b.test(l);b.lastIndex=0;var E=b.test(l);if(w||E)return null;if(p&&!/[\s;,.})\]\\]/.test(p))return null;y=!0}return{text:y?s+s:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){c(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};p.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},p.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},p.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},p.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},p.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},p.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},p.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},p.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(p,i),t.CstyleBehaviour=p}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(e){e&&(this.foldingStartMarker=new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/,"|"+e.start)),this.foldingStopMarker=new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/,"|"+e.end)))};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.singleLineBlockCommentRe=/^\s*(\/\*).*\*\/\s*$/,this.tripleStarBlockCommentRe=/^\s*(\/\*\*\*).*\*\/\s*$/,this.startRegionRe=/^\s*(\/\*|\/\/)#?region\b/,this._getFoldWidgetBase=this.getFoldWidget,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);if(this.singleLineBlockCommentRe.test(r)&&!this.startRegionRe.test(r)&&!this.tripleStarBlockCommentRe.test(r))return"";var i=this._getFoldWidgetBase(e,t,n);return!i&&this.startRegionRe.test(r)?"start":i},this.getFoldWidgetRange=function(e,t,n,r){var i=e.getLine(n);if(this.startRegionRe.test(i))return this.getCommentRegionBlock(e,i,n);var s=i.match(this.foldingStartMarker);if(s){var o=s.index;if(s[1])return this.openingBracketBlock(e,s[1],n,o);var u=e.getCommentFoldRange(n,o+s[0].length,1);return u&&!u.isMultiLine()&&(r?u=this.getSectionRange(e,n):t!="all"&&(u=null)),u}if(t==="markbegin")return;var s=i.match(this.foldingStopMarker);if(s){var o=s.index+s[0].length;return s[1]?this.closingBracketBlock(e,s[1],n,o):e.getCommentFoldRange(n,o,-1)}},this.getSectionRange=function(e,t){var n=e.getLine(t),r=n.search(/\S/),s=t,o=n.length;t+=1;var u=t,a=e.getLength();while(++tf)break;var l=this.getFoldWidgetRange(e,"all",t);if(l){if(l.start.row<=s)break;if(l.isMultiLine())t=l.end.row;else if(r==f)break}u=t}return new i(s,o,u,e.getLine(u).length)},this.getCommentRegionBlock=function(e,t,n){var r=t.search(/\s*$/),s=e.getLength(),o=n,u=/^\s*(?:\/\*|\/\/|--)#?(end)?region\b/,a=1;while(++no)return new i(o,r,l,t.length)}}.call(o.prototype)}),ace.define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./json_highlight_rules").JsonHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./behaviour/cstyle").CstyleBehaviour,a=e("./folding/cstyle").FoldMode,f=e("../worker/worker_client").WorkerClient,l=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=new u,this.foldingRules=new a};r.inherits(l,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new f(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("annotate",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t},this.$id="ace/mode/json"}.call(l.prototype),t.Mode=l})
\ No newline at end of file
diff --git a/public/ace/mode-plain_text.js b/public/ace/mode-plain_text.js
new file mode 100644
index 00000000..21cf21da
--- /dev/null
+++ b/public/ace/mode-plain_text.js
@@ -0,0 +1 @@
+ace.define("ace/mode/plain_text",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/text_highlight_rules","ace/mode/behaviour"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./text_highlight_rules").TextHighlightRules,o=e("./behaviour").Behaviour,u=function(){this.HighlightRules=s,this.$behaviour=new o};r.inherits(u,i),function(){this.type="text",this.getNextLineIndent=function(e,t,n){return""},this.$id="ace/mode/plain_text"}.call(u.prototype),t.Mode=u})
diff --git a/public/ace/worker-css.js b/public/ace/worker-css.js
new file mode 100644
index 00000000..408c6bd0
--- /dev/null
+++ b/public/ace/worker-css.js
@@ -0,0 +1 @@
+"no use strict";(function(e){function t(e,t){var n=e,r="";while(n){var i=t[n];if(typeof i=="string")return i+r;if(i)return i.location.replace(/\/*$/,"/")+(r||i.main||i.name);if(i===!1)return"";var s=n.lastIndexOf("/");if(s===-1)break;r=n.substr(s)+r,n=n.slice(0,s)}return e}if(typeof e.window!="undefined"&&e.document)return;if(e.require&&e.define)return;e.console||(e.console=function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},e.console.error=e.console.warn=e.console.log=e.console.trace=e.console),e.window=e,e.ace=e,e.onerror=function(e,t,n,r,i){postMessage({type:"error",data:{message:e,data:i.data,file:t,line:n,col:r,stack:i.stack}})},e.normalizeModule=function(t,n){if(n.indexOf("!")!==-1){var r=n.split("!");return e.normalizeModule(t,r[0])+"!"+e.normalizeModule(t,r[1])}if(n.charAt(0)=="."){var i=t.split("/").slice(0,-1).join("/");n=(i?i+"/":"")+n;while(n.indexOf(".")!==-1&&s!=n){var s=n;n=n.replace(/^\.\//,"").replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return n},e.require=function(r,i){i||(i=r,r=null);if(!i.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");i=e.normalizeModule(r,i);var s=e.require.modules[i];if(s)return s.initialized||(s.initialized=!0,s.exports=s.factory().exports),s.exports;if(!e.require.tlns)return console.log("unable to load "+i);var o=t(i,e.require.tlns);return o.slice(-3)!=".js"&&(o+=".js"),e.require.id=i,e.require.modules[i]={},importScripts(o),e.require(r,i)},e.require.modules={},e.require.tlns={},e.define=function(t,n,r){arguments.length==2?(r=n,typeof t!="string"&&(n=t,t=e.require.id)):arguments.length==1&&(r=t,n=[],t=e.require.id);if(typeof r!="function"){e.require.modules[t]={exports:r,initialized:!0};return}n.length||(n=["require","exports","module"]);var i=function(n){return e.require(t,n)};e.require.modules[t]={exports:{},factory:function(){var e=this,t=r.apply(this,n.map(function(t){switch(t){case"require":return i;case"exports":return e.exports;case"module":return e;default:return i(t)}}));return t&&(e.exports=t),e}}},e.define.amd={},require.tlns={},e.initBaseUrls=function(t){for(var n in t)require.tlns[n]=t[n]},e.initSender=function(){var n=e.require("ace/lib/event_emitter").EventEmitter,r=e.require("ace/lib/oop"),i=function(){};return function(){r.implement(this,n),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(i.prototype),new i};var n=e.main=null,r=e.sender=null;e.onmessage=function(t){var i=t.data;if(i.event&&r)r._signal(i.event,i.data);else if(i.command)if(n[i.command])n[i.command].apply(n,i.args);else{if(!e[i.command])throw new Error("Unknown command:"+i.command);e[i.command].apply(e,i.args)}else if(i.init){e.initBaseUrls(i.tlns),require("ace/lib/es5-shim"),r=e.sender=e.initSender();var s=require(i.module)[i.classname];n=e.main=new s(r)}}})(this),ace.define("ace/lib/oop",["require","exports","module"],function(e,t,n){"use strict";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,n){"use strict";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.rowt)var r={row:t+1,column:0};else if(this.start.row=0&&t.row=0&&t.column<=e[t.row].length}function s(e,t){t.action!="insert"&&t.action!="remove"&&r(t,"delta.action must be 'insert' or 'remove'"),t.lines instanceof Array||r(t,"delta.lines must be an Array"),(!t.start||!t.end)&&r(t,"delta.start/end must be an present");var n=t.start;i(e,t.start)||r(t,"delta.start must be contained in document");var s=t.end;t.action=="remove"&&!i(e,s)&&r(t,"delta.end must contained in document for 'remove' actions");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,"delta.range must match delta lines")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||"";switch(t.action){case"insert":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case"remove":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){"use strict";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;othis.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){"use strict";var r=e("./lib/oop"),i=e("./apply_delta").applyDelta,s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=e("./anchor").Anchor,a=function(e){this.$lines=[""],e.length===0?this.$lines=[""]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},"aaa".split(/a/).length===0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);this.$autoNewLine=t?t[1]:"\n",this._signal("changeNewLineMode")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";default:return this.$autoNewLine||"\n"}},this.$autoNewLine="",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal("changeNewLineMode")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||"").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."),this.insertMergedLines(e,["",""])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:"insert",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e0,r=t=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:"remove",lines:["",""]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action=="insert";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal("change",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(""),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action=="insert"?"remove":"insert",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i=0&&this._ltIndex-1&&!t[u.type].hide&&(u.channel=t[u.type].channel,this._token=u,this._lt.push(u),this._ltIndexCache.push(this._lt.length-this._ltIndex+i),this._lt.length>5&&this._lt.shift(),this._ltIndexCache.length>5&&this._ltIndexCache.shift(),this._ltIndex=this._lt.length),a=t[u.type],a&&(a.hide||a.channel!==undefined&&e!==a.channel)?this.get(e):u.type},LA:function(e){var t=e,n;if(e>0){if(e>5)throw new Error("Too much lookahead.");while(t)n=this.get(),t--;while(tthis._tokenData.length?"UNKNOWN_TOKEN":this._tokenData[e].name},tokenType:function(e){return this._tokenData[e]||-1},unget:function(){if(!this._ltIndexCache.length)throw new Error("Too much lookahead.");this._ltIndex-=this._ltIndexCache.pop(),this._token=this._lt[this._ltIndex-1]}},parserlib.util={StringReader:t,SyntaxError:n,SyntaxUnit:r,EventTarget:e,TokenStreamBase:i}})(),function(){function Combinator(e,t,n){SyntaxUnit.call(this,e,t,n,Parser.COMBINATOR_TYPE),this.type="unknown",/^\s+$/.test(e)?this.type="descendant":e==">"?this.type="child":e=="+"?this.type="adjacent-sibling":e=="~"&&(this.type="sibling")}function MediaFeature(e,t){SyntaxUnit.call(this,"("+e+(t!==null?":"+t:"")+")",e.startLine,e.startCol,Parser.MEDIA_FEATURE_TYPE),this.name=e,this.value=t}function MediaQuery(e,t,n,r,i){SyntaxUnit.call(this,(e?e+" ":"")+(t?t:"")+(t&&n.length>0?" and ":"")+n.join(" and "),r,i,Parser.MEDIA_QUERY_TYPE),this.modifier=e,this.mediaType=t,this.features=n}function Parser(e){EventTarget.call(this),this.options=e||{},this._tokenStream=null}function PropertyName(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.PROPERTY_NAME_TYPE),this.hack=t}function PropertyValue(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.PROPERTY_VALUE_TYPE),this.parts=e}function PropertyValueIterator(e){this._i=0,this._parts=e.parts,this._marks=[],this.value=e}function PropertyValuePart(text,line,col){SyntaxUnit.call(this,text,line,col,Parser.PROPERTY_VALUE_PART_TYPE),this.type="unknown";var temp;if(/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){this.type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2;switch(this.units.toLowerCase()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc":case"ch":case"vh":case"vw":case"vmax":case"vmin":this.type="length";break;case"deg":case"rad":case"grad":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz":case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution"}}else/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?\d+)$/i.test(text)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i.test(text)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test(text)?(this.type="color",temp=RegExp.$1,temp.length==3?(this.red=parseInt(temp.charAt(0)+temp.charAt(0),16),this.green=parseInt(temp.charAt(1)+temp.charAt(1),16),this.blue=parseInt(temp.charAt(2)+temp.charAt(2),16)):(this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(["']?([^\)"']+)["']?\)/i.test(text)?(this.type="uri",this.uri=RegExp.$1):/^([^\(]+)\(/i.test(text)?(this.type="function",this.name=RegExp.$1,this.value=text):/^["'][^"']*["']/.test(text)?(this.type="string",this.value=eval(text)):Colors[text.toLowerCase()]?(this.type="color",temp=Colors[text.toLowerCase()].substring(1),this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16)):/^[\,\/]$/.test(text)?(this.type="operator",this.value=text):/^[a-z\-_\u0080-\uFFFF][a-z0-9\-_\u0080-\uFFFF]*$/i.test(text)&&(this.type="identifier",this.value=text)}function Selector(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.SELECTOR_TYPE),this.parts=e,this.specificity=Specificity.calculate(this)}function SelectorPart(e,t,n,r,i){SyntaxUnit.call(this,n,r,i,Parser.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}function SelectorSubPart(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.SELECTOR_SUB_PART_TYPE),this.type=t,this.args=[]}function Specificity(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function isHexDigit(e){return e!==null&&h.test(e)}function isDigit(e){return e!==null&&/\d/.test(e)}function isWhitespace(e){return e!==null&&/\s/.test(e)}function isNewLine(e){return e!==null&&nl.test(e)}function isNameStart(e){return e!==null&&/[a-z_\u0080-\uFFFF\\]/i.test(e)}function isNameChar(e){return e!==null&&(isNameStart(e)||/[0-9\-\\]/.test(e))}function isIdentStart(e){return e!==null&&(isNameStart(e)||/\-\\/.test(e))}function mix(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function TokenStream(e){TokenStreamBase.call(this,e,Tokens)}function ValidationError(e,t,n){this.col=n,this.line=t,this.message=e}var EventTarget=parserlib.util.EventTarget,TokenStreamBase=parserlib.util.TokenStreamBase,StringReader=parserlib.util.StringReader,SyntaxError=parserlib.util.SyntaxError,SyntaxUnit=parserlib.util.SyntaxUnit,Colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgrey:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",grey:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgrey:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32",activeBorder:"Active window border.",activecaption:"Active window caption.",appworkspace:"Background color of multiple document interface.",background:"Desktop background.",buttonface:"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.",buttonhighlight:"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",buttonshadow:"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",buttontext:"Text on push buttons.",captiontext:"Text in caption, size box, and scrollbar arrow box.",graytext:"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.",greytext:"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.",highlight:"Item(s) selected in a control.",highlighttext:"Text of item(s) selected in a control.",inactiveborder:"Inactive window border.",inactivecaption:"Inactive window caption.",inactivecaptiontext:"Color of text in an inactive caption.",infobackground:"Background color for tooltip controls.",infotext:"Text color for tooltip controls.",menu:"Menu background.",menutext:"Text in menus.",scrollbar:"Scroll bar gray area.",threeddarkshadow:"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedface:"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedhighlight:"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedlightshadow:"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",threedshadow:"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",window:"Window background.",windowframe:"Window frame.",windowtext:"Text in windows."};Combinator.prototype=new SyntaxUnit,Combinator.prototype.constructor=Combinator,MediaFeature.prototype=new SyntaxUnit,MediaFeature.prototype.constructor=MediaFeature,MediaQuery.prototype=new SyntaxUnit,MediaQuery.prototype.constructor=MediaQuery,Parser.DEFAULT_TYPE=0,Parser.COMBINATOR_TYPE=1,Parser.MEDIA_FEATURE_TYPE=2,Parser.MEDIA_QUERY_TYPE=3,Parser.PROPERTY_NAME_TYPE=4,Parser.PROPERTY_VALUE_TYPE=5,Parser.PROPERTY_VALUE_PART_TYPE=6,Parser.SELECTOR_TYPE=7,Parser.SELECTOR_PART_TYPE=8,Parser.SELECTOR_SUB_PART_TYPE=9,Parser.prototype=function(){var e=new EventTarget,t,n={constructor:Parser,DEFAULT_TYPE:0,COMBINATOR_TYPE:1,MEDIA_FEATURE_TYPE:2,MEDIA_QUERY_TYPE:3,PROPERTY_NAME_TYPE:4,PROPERTY_VALUE_TYPE:5,PROPERTY_VALUE_PART_TYPE:6,SELECTOR_TYPE:7,SELECTOR_PART_TYPE:8,SELECTOR_SUB_PART_TYPE:9,_stylesheet:function(){var e=this._tokenStream,t=null,n,r,i;this.fire("startstylesheet"),this._charset(),this._skipCruft();while(e.peek()==Tokens.IMPORT_SYM)this._import(),this._skipCruft();while(e.peek()==Tokens.NAMESPACE_SYM)this._namespace(),this._skipCruft();i=e.peek();while(i>Tokens.EOF){try{switch(i){case Tokens.MEDIA_SYM:this._media(),this._skipCruft();break;case Tokens.PAGE_SYM:this._page(),this._skipCruft();break;case Tokens.FONT_FACE_SYM:this._font_face(),this._skipCruft();break;case Tokens.KEYFRAMES_SYM:this._keyframes(),this._skipCruft();break;case Tokens.VIEWPORT_SYM:this._viewport(),this._skipCruft();break;case Tokens.UNKNOWN_SYM:e.get();if(!!this.options.strict)throw new SyntaxError("Unknown @ rule.",e.LT(0).startLine,e.LT(0).startCol);this.fire({type:"error",error:null,message:"Unknown @ rule: "+e.LT(0).value+".",line:e.LT(0).startLine,col:e.LT(0).startCol}),n=0;while(e.advance([Tokens.LBRACE,Tokens.RBRACE])==Tokens.LBRACE)n++;while(n)e.advance([Tokens.RBRACE]),n--;break;case Tokens.S:this._readWhitespace();break;default:if(!this._ruleset())switch(i){case Tokens.CHARSET_SYM:throw r=e.LT(1),this._charset(!1),new SyntaxError("@charset not allowed here.",r.startLine,r.startCol);case Tokens.IMPORT_SYM:throw r=e.LT(1),this._import(!1),new SyntaxError("@import not allowed here.",r.startLine,r.startCol);case Tokens.NAMESPACE_SYM:throw r=e.LT(1),this._namespace(!1),new SyntaxError("@namespace not allowed here.",r.startLine,r.startCol);default:e.get(),this._unexpectedToken(e.token())}}}catch(s){if(!(s instanceof SyntaxError&&!this.options.strict))throw s;this.fire({type:"error",error:s,message:s.message,line:s.line,col:s.col})}i=e.peek()}i!=Tokens.EOF&&this._unexpectedToken(e.token()),this.fire("endstylesheet")},_charset:function(e){var t=this._tokenStream,n,r,i,s;t.match(Tokens.CHARSET_SYM)&&(i=t.token().startLine,s=t.token().startCol,this._readWhitespace(),t.mustMatch(Tokens.STRING),r=t.token(),n=r.value,this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),e!==!1&&this.fire({type:"charset",charset:n,line:i,col:s}))},_import:function(e){var t=this._tokenStream,n,r,i,s=[];t.mustMatch(Tokens.IMPORT_SYM),i=t.token(),this._readWhitespace(),t.mustMatch([Tokens.STRING,Tokens.URI]),r=t.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/,"$1"),this._readWhitespace(),s=this._media_query_list(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"import",uri:r,media:s,line:i.startLine,col:i.startCol})},_namespace:function(e){var t=this._tokenStream,n,r,i,s;t.mustMatch(Tokens.NAMESPACE_SYM),n=t.token().startLine,r=t.token().startCol,this._readWhitespace(),t.match(Tokens.IDENT)&&(i=t.token().value,this._readWhitespace()),t.mustMatch([Tokens.STRING,Tokens.URI]),s=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"namespace",prefix:i,uri:s,line:n,col:r})},_media:function(){var e=this._tokenStream,t,n,r;e.mustMatch(Tokens.MEDIA_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),r=this._media_query_list(),e.mustMatch(Tokens.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:r,line:t,col:n});for(;;)if(e.peek()==Tokens.PAGE_SYM)this._page();else if(e.peek()==Tokens.FONT_FACE_SYM)this._font_face();else if(e.peek()==Tokens.VIEWPORT_SYM)this._viewport();else if(!this._ruleset())break;e.mustMatch(Tokens.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:r,line:t,col:n})},_media_query_list:function(){var e=this._tokenStream,t=[];this._readWhitespace(),(e.peek()==Tokens.IDENT||e.peek()==Tokens.LPAREN)&&t.push(this._media_query());while(e.match(Tokens.COMMA))this._readWhitespace(),t.push(this._media_query());return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null,i=[];e.match(Tokens.IDENT)&&(n=e.token().value.toLowerCase(),n!="only"&&n!="not"?(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()==Tokens.IDENT?(t=this._media_type(),r===null&&(r=e.token())):e.peek()==Tokens.LPAREN&&(r===null&&(r=e.LT(1)),i.push(this._media_expression()));if(t===null&&i.length===0)return null;this._readWhitespace();while(e.match(Tokens.IDENT))e.token().value.toLowerCase()!="and"&&this._unexpectedToken(e.token()),this._readWhitespace(),i.push(this._media_expression());return new MediaQuery(n,t,i,r.startLine,r.startCol)},_media_type:function(){return this._media_feature()},_media_expression:function(){var e=this._tokenStream,t=null,n,r=null;return e.mustMatch(Tokens.LPAREN),t=this._media_feature(),this._readWhitespace(),e.match(Tokens.COLON)&&(this._readWhitespace(),n=e.LT(1),r=this._expression()),e.mustMatch(Tokens.RPAREN),this._readWhitespace(),new MediaFeature(t,r?new SyntaxUnit(r,n.startLine,n.startCol):null)},_media_feature:function(){var e=this._tokenStream;return e.mustMatch(Tokens.IDENT),SyntaxUnit.fromToken(e.token())},_page:function(){var e=this._tokenStream,t,n,r=null,i=null;e.mustMatch(Tokens.PAGE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),e.match(Tokens.IDENT)&&(r=e.token().value,r.toLowerCase()==="auto"&&this._unexpectedToken(e.token())),e.peek()==Tokens.COLON&&(i=this._pseudo_page()),this._readWhitespace(),this.fire({type:"startpage",id:r,pseudo:i,line:t,col:n}),this._readDeclarations(!0,!0),this.fire({type:"endpage",id:r,pseudo:i,line:t,col:n})},_margin:function(){var e=this._tokenStream,t,n,r=this._margin_sym();return r?(t=e.token().startLine,n=e.token().startCol,this.fire({type:"startpagemargin",margin:r,line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:t,col:n}),!0):!1},_margin_sym:function(){var e=this._tokenStream;return e.match([Tokens.TOPLEFTCORNER_SYM,Tokens.TOPLEFT_SYM,Tokens.TOPCENTER_SYM,Tokens.TOPRIGHT_SYM,Tokens.TOPRIGHTCORNER_SYM,Tokens.BOTTOMLEFTCORNER_SYM,Tokens.BOTTOMLEFT_SYM,Tokens.BOTTOMCENTER_SYM,Tokens.BOTTOMRIGHT_SYM,Tokens.BOTTOMRIGHTCORNER_SYM,Tokens.LEFTTOP_SYM,Tokens.LEFTMIDDLE_SYM,Tokens.LEFTBOTTOM_SYM,Tokens.RIGHTTOP_SYM,Tokens.RIGHTMIDDLE_SYM,Tokens.RIGHTBOTTOM_SYM])?SyntaxUnit.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream;return e.mustMatch(Tokens.COLON),e.mustMatch(Tokens.IDENT),e.token().value},_font_face:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.FONT_FACE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startfontface",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endfontface",line:t,col:n})},_viewport:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.VIEWPORT_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startviewport",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endviewport",line:t,col:n})},_operator:function(e){var t=this._tokenStream,n=null;if(t.match([Tokens.SLASH,Tokens.COMMA])||e&&t.match([Tokens.PLUS,Tokens.STAR,Tokens.MINUS]))n=t.token(),this._readWhitespace();return n?PropertyValuePart.fromToken(n):null},_combinator:function(){var e=this._tokenStream,t=null,n;return e.match([Tokens.PLUS,Tokens.GREATER,Tokens.TILDE])&&(n=e.token(),t=new Combinator(n.value,n.startLine,n.startCol),this._readWhitespace()),t},_unary_operator:function(){var e=this._tokenStream;return e.match([Tokens.MINUS,Tokens.PLUS])?e.token().value:null},_property:function(){var e=this._tokenStream,t=null,n=null,r,i,s,o;return e.peek()==Tokens.STAR&&this.options.starHack&&(e.get(),i=e.token(),n=i.value,s=i.startLine,o=i.startCol),e.match(Tokens.IDENT)&&(i=e.token(),r=i.value,r.charAt(0)=="_"&&this.options.underscoreHack&&(n="_",r=r.substring(1)),t=new PropertyName(r,n,s||i.startLine,o||i.startCol),this._readWhitespace()),t},_ruleset:function(){var e=this._tokenStream,t,n;try{n=this._selectors_group()}catch(r){if(r instanceof SyntaxError&&!this.options.strict){this.fire({type:"error",error:r,message:r.message,line:r.line,col:r.col}),t=e.advance([Tokens.RBRACE]);if(t!=Tokens.RBRACE)throw r;return!0}throw r}return n&&(this.fire({type:"startrule",selectors:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endrule",selectors:n,line:n[0].line,col:n[0].col})),n},_selectors_group:function(){var e=this._tokenStream,t=[],n;n=this._selector();if(n!==null){t.push(n);while(e.match(Tokens.COMMA))this._readWhitespace(),n=this._selector(),n!==null?t.push(n):this._unexpectedToken(e.LT(1))}return t.length?t:null},_selector:function(){var e=this._tokenStream,t=[],n=null,r=null,i=null;n=this._simple_selector_sequence();if(n===null)return null;t.push(n);do{r=this._combinator();if(r!==null)t.push(r),n=this._simple_selector_sequence(),n===null?this._unexpectedToken(e.LT(1)):t.push(n);else{if(!this._readWhitespace())break;i=new Combinator(e.token().value,e.token().startLine,e.token().startCol),r=this._combinator(),n=this._simple_selector_sequence(),n===null?r!==null&&this._unexpectedToken(e.LT(1)):(r!==null?t.push(r):t.push(i),t.push(n))}}while(!0);return new Selector(t,t[0].line,t[0].col)},_simple_selector_sequence:function(){var e=this._tokenStream,t=null,n=[],r="",i=[function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,o=i.length,u=null,a=!1,f,l;f=e.LT(1).startLine,l=e.LT(1).startCol,t=this._type_selector(),t||(t=this._universal()),t!==null&&(r+=t);for(;;){if(e.peek()===Tokens.S)break;while(s1&&e.unget()),null)},_class:function(){var e=this._tokenStream,t;return e.match(Tokens.DOT)?(e.mustMatch(Tokens.IDENT),t=e.token(),new SelectorSubPart("."+t.value,"class",t.startLine,t.startCol-1)):null},_element_name:function(){var e=this._tokenStream,t;return e.match(Tokens.IDENT)?(t=e.token(),new SelectorSubPart(t.value,"elementName",t.startLine,t.startCol)):null},_namespace_prefix:function(){var e=this._tokenStream,t="";if(e.LA(1)===Tokens.PIPE||e.LA(2)===Tokens.PIPE)e.match([Tokens.IDENT,Tokens.STAR])&&(t+=e.token().value),e.mustMatch(Tokens.PIPE),t+="|";return t.length?t:null},_universal:function(){var e=this._tokenStream,t="",n;return n=this._namespace_prefix(),n&&(t+=n),e.match(Tokens.STAR)&&(t+="*"),t.length?t:null},_attrib:function(){var e=this._tokenStream,t=null,n,r;return e.match(Tokens.LBRACKET)?(r=e.token(),t=r.value,t+=this._readWhitespace(),n=this._namespace_prefix(),n&&(t+=n),e.mustMatch(Tokens.IDENT),t+=e.token().value,t+=this._readWhitespace(),e.match([Tokens.PREFIXMATCH,Tokens.SUFFIXMATCH,Tokens.SUBSTRINGMATCH,Tokens.EQUALS,Tokens.INCLUDES,Tokens.DASHMATCH])&&(t+=e.token().value,t+=this._readWhitespace(),e.mustMatch([Tokens.IDENT,Tokens.STRING]),t+=e.token().value,t+=this._readWhitespace()),e.mustMatch(Tokens.RBRACKET),new SelectorSubPart(t+"]","attribute",r.startLine,r.startCol)):null},_pseudo:function(){var e=this._tokenStream,t=null,n=":",r,i;return e.match(Tokens.COLON)&&(e.match(Tokens.COLON)&&(n+=":"),e.match(Tokens.IDENT)?(t=e.token().value,r=e.token().startLine,i=e.token().startCol-n.length):e.peek()==Tokens.FUNCTION&&(r=e.LT(1).startLine,i=e.LT(1).startCol-n.length,t=this._functional_pseudo()),t&&(t=new SelectorSubPart(n+t,"pseudo",r,i))),t},_functional_pseudo:function(){var e=this._tokenStream,t=null;return e.match(Tokens.FUNCTION)&&(t=e.token().value,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(Tokens.RPAREN),t+=")"),t},_expression:function(){var e=this._tokenStream,t="";while(e.match([Tokens.PLUS,Tokens.MINUS,Tokens.DIMENSION,Tokens.NUMBER,Tokens.STRING,Tokens.IDENT,Tokens.LENGTH,Tokens.FREQ,Tokens.ANGLE,Tokens.TIME,Tokens.RESOLUTION,Tokens.SLASH]))t+=e.token().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){var e=this._tokenStream,t,n,r="",i,s=null;return e.match(Tokens.NOT)&&(r=e.token().value,t=e.token().startLine,n=e.token().startCol,r+=this._readWhitespace(),i=this._negation_arg(),r+=i,r+=this._readWhitespace(),e.match(Tokens.RPAREN),r+=e.token().value,s=new SelectorSubPart(r,"not",t,n),s.args.push(i)),s},_negation_arg:function(){var e=this._tokenStream,t=[this._type_selector,this._universal,function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo],n=null,r=0,i=t.length,s,o,u,a;o=e.LT(1).startLine,u=e.LT(1).startCol;while(r0?new PropertyValue(n,n[0].line,n[0].col):null},_term:function(e){var t=this._tokenStream,n=null,r=null,i=null,s,o,u;return n=this._unary_operator(),n!==null&&(o=t.token().startLine,u=t.token().startCol),t.peek()==Tokens.IE_FUNCTION&&this.options.ieFilters?(r=this._ie_function(),n===null&&(o=t.token().startLine,u=t.token().startCol)):e&&t.match([Tokens.LPAREN,Tokens.LBRACE,Tokens.LBRACKET])?(s=t.token(),i=s.endChar,r=s.value+this._expr(e).text,n===null&&(o=t.token().startLine,u=t.token().startCol),t.mustMatch(Tokens.type(i)),r+=i,this._readWhitespace()):t.match([Tokens.NUMBER,Tokens.PERCENTAGE,Tokens.LENGTH,Tokens.ANGLE,Tokens.TIME,Tokens.FREQ,Tokens.STRING,Tokens.IDENT,Tokens.URI,Tokens.UNICODE_RANGE])?(r=t.token().value,n===null&&(o=t.token().startLine,u=t.token().startCol),this._readWhitespace()):(s=this._hexcolor(),s===null?(n===null&&(o=t.LT(1).startLine,u=t.LT(1).startCol),r===null&&(t.LA(3)==Tokens.EQUALS&&this.options.ieFilters?r=this._ie_function():r=this._function())):(r=s.value,n===null&&(o=s.startLine,u=s.startCol))),r!==null?new PropertyValuePart(n!==null?n+r:r,o,u):null},_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match(Tokens.FUNCTION)){t=e.token().value,this._readWhitespace(),n=this._expr(!0),t+=n;if(this.options.ieFilters&&e.peek()==Tokens.EQUALS)do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_ie_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match([Tokens.IE_FUNCTION,Tokens.FUNCTION])){t=e.token().value;do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_hexcolor:function(){var e=this._tokenStream,t=null,n;if(e.match(Tokens.HASH)){t=e.token(),n=t.value;if(!/#[a-f0-9]{3,6}/i.test(n))throw new SyntaxError("Expected a hex color but found '"+n+"' at line "+t.startLine+", col "+t.startCol+".",t.startLine,t.startCol);this._readWhitespace()}return t},_keyframes:function(){var e=this._tokenStream,t,n,r,i="";e.mustMatch(Tokens.KEYFRAMES_SYM),t=e.token(),/^@\-([^\-]+)\-/.test(t.value)&&(i=RegExp.$1),this._readWhitespace(),r=this._keyframe_name(),this._readWhitespace(),e.mustMatch(Tokens.LBRACE),this.fire({type:"startkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),n=e.peek();while(n==Tokens.IDENT||n==Tokens.PERCENTAGE)this._keyframe_rule(),this._readWhitespace(),n=e.peek();this.fire({type:"endkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),e.mustMatch(Tokens.RBRACE)},_keyframe_name:function(){var e=this._tokenStream,t;return e.mustMatch([Tokens.IDENT,Tokens.STRING]),SyntaxUnit.fromToken(e.token())},_keyframe_rule:function(){var e=this._tokenStream,t,n=this._key_list();this.fire({type:"startkeyframerule",keys:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys:n,line:n[0].line,col:n[0].col})},_key_list:function(){var e=this._tokenStream,t,n,r=[];r.push(this._key()),this._readWhitespace();while(e.match(Tokens.COMMA))this._readWhitespace(),r.push(this._key()),this._readWhitespace();return r},_key:function(){var e=this._tokenStream,t;if(e.match(Tokens.PERCENTAGE))return SyntaxUnit.fromToken(e.token());if(e.match(Tokens.IDENT)){t=e.token();if(/from|to/i.test(t.value))return SyntaxUnit.fromToken(t);e.unget()}this._unexpectedToken(e.LT(1))},_skipCruft:function(){while(this._tokenStream.match([Tokens.S,Tokens.CDO,Tokens.CDC]));},_readDeclarations:function(e,t){var n=this._tokenStream,r;this._readWhitespace(),e&&n.mustMatch(Tokens.LBRACE),this._readWhitespace();try{for(;;){if(!(n.match(Tokens.SEMICOLON)||t&&this._margin())){if(!this._declaration())break;if(!n.match(Tokens.SEMICOLON))break}this._readWhitespace()}n.mustMatch(Tokens.RBRACE),this._readWhitespace()}catch(i){if(!(i instanceof SyntaxError&&!this.options.strict))throw i;this.fire({type:"error",error:i,message:i.message,line:i.line,col:i.col}),r=n.advance([Tokens.SEMICOLON,Tokens.RBRACE]);if(r==Tokens.SEMICOLON)this._readDeclarations(!1,t);else if(r!=Tokens.RBRACE)throw i}},_readWhitespace:function(){var e=this._tokenStream,t="";while(e.match(Tokens.S))t+=e.token().value;return t},_unexpectedToken:function(e){throw new SyntaxError("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!=Tokens.EOF&&this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){Validation.validate(e,t)},parse:function(e){this._tokenStream=new TokenStream(e,Tokens),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery:function(e){this._tokenStream=new TokenStream(e,Tokens);var t=this._media_query();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._expr();return this._readWhitespace(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._ruleset();return this._readWhitespace(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._selector();return this._readWhitespace(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new TokenStream(e,Tokens),this._readDeclarations()}};for(t in n)n.hasOwnProperty(t)&&(e[t]=n[t]);return e}();var Properties={"align-items":"flex-start | flex-end | center | baseline | stretch","align-content":"flex-start | flex-end | center | space-between | space-around | stretch","align-self":"auto | flex-start | flex-end | center | baseline | stretch","-webkit-align-items":"flex-start | flex-end | center | baseline | stretch","-webkit-align-content":"flex-start | flex-end | center | space-between | space-around | stretch","-webkit-align-self":"auto | flex-start | flex-end | center | baseline | stretch","alignment-adjust":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ","alignment-baseline":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",animation:1,"animation-delay":{multi:"