From d3abc37cb08e540f068af3e3d98d34aaf01d30ee Mon Sep 17 00:00:00 2001 From: Andrea Di Mario Date: Wed, 6 Nov 2019 09:31:25 +0100 Subject: [PATCH] Initialize multiple language and start translations (#91) * Initialize multiple language and start translations * continue with translation * end translations for en and it * fix json syntax en translation, otherwise i18n reset the file * add language info in config * fix json format invalid * solve review comments --- app.js | 100 +++++---- config/baseSchema.json | 6 + config/settings.json | 4 +- locales/en.json | 164 +++++++++++++++ locales/it.json | 165 +++++++++++++++ package-lock.json | 79 +++++++ package.json | 2 + routes/admin.js | 4 +- routes/index.js | 228 +++++++++++---------- views/customer.hbs | 16 +- views/customers.hbs | 16 +- views/forgotten.hbs | 4 +- views/layouts/layout.hbs | 14 +- views/login.hbs | 4 +- views/order.hbs | 49 +++-- views/orders.hbs | 30 +-- views/partials/menu.hbs | 18 +- views/product_edit.hbs | 64 +++--- views/product_new.hbs | 40 ++-- views/products.hbs | 10 +- views/reset.hbs | 4 +- views/settings.hbs | 73 +++---- views/settings_menu.hbs | 5 +- views/settings_page_edit.hbs | 16 +- views/settings_pages.hbs | 15 +- views/setup.hbs | 14 +- views/themes/Cloth/cart.hbs | 13 +- views/themes/Cloth/front-menu.hbs | 2 +- views/themes/Cloth/index.hbs | 8 +- views/themes/Cloth/pay.hbs | 14 +- views/themes/Cloth/payment_complete.hbs | 12 +- views/themes/Cloth/product.hbs | 8 +- views/themes/Material/cart.hbs | 12 +- views/themes/Material/front-menu.hbs | 2 +- views/themes/Material/index.hbs | 8 +- views/themes/Material/pay.hbs | 12 +- views/themes/Material/payment_complete.hbs | 12 +- views/themes/Material/product.hbs | 8 +- views/themes/Mono/cart.hbs | 12 +- views/themes/Mono/front-menu.hbs | 2 +- views/themes/Mono/index.hbs | 8 +- views/themes/Mono/pay.hbs | 12 +- views/themes/Mono/payment_complete.hbs | 12 +- views/themes/Mono/product.hbs | 8 +- views/user_edit.hbs | 14 +- views/user_new.hbs | 12 +- views/users.hbs | 8 +- 47 files changed, 898 insertions(+), 445 deletions(-) create mode 100644 locales/en.json create mode 100644 locales/it.json diff --git a/app.js b/app.js index 29a4fd6..e202769 100644 --- a/app.js +++ b/app.js @@ -17,6 +17,7 @@ const { runIndexing } = require('./lib/indexing'); const { addSchemas } = require('./lib/schema'); const { initDb } = require('./lib/db'); let handlebars = require('express-handlebars'); +const i18n = require('i18n'); // Validate our settings schema const Ajv = require('ajv'); @@ -68,6 +69,20 @@ const authorizenet = require('./routes/payments/authorizenet'); const app = express(); +// Language initialize +i18n.configure({ + locales: config.availableLanguages, + defaultLocale: config.defaultLocale, + cookie: 'locale', + queryParameter: 'lang', + directory: `${__dirname}/locales`, + directoryPermissions: '755', + api: { + __: '__', // now req.__ becomes req.__ + __n: '__n' // and req.__n can be called as req.__n + } +}); + // view engine setup app.set('views', path.join(__dirname, '/views')); app.engine('hbs', handlebars({ @@ -81,6 +96,16 @@ app.set('view engine', 'hbs'); // helpers for the handlebar templating platform handlebars = handlebars.create({ helpers: { + // Language helper + __: () => { return i18n.__(this, arguments); }, + __n: () => { return i18n.__n(this, arguments); }, + availableLanguages: (block) => { + let total = '' + for(const lang of i18n.getLocales()){ + total += block.fn(lang); + } + return total; + }, perRowClass: (numProducts) => { if(parseInt(numProducts) === 1){ return'col-md-12 col-xl-12 col m12 xl12 product-item'; @@ -123,22 +148,22 @@ handlebars = handlebars.create({ }, getStatusColor: (status) => { switch(status){ - case'Paid': - return'success'; - case'Approved': - return'success'; - case'Approved - Processing': - return'success'; - case'Failed': - return'danger'; - case'Completed': - return'success'; - case'Shipped': - return'success'; - case'Pending': - return'warning'; - default: - return'danger'; + case'Paid': + return'success'; + case'Approved': + return'success'; + case'Approved - Processing': + return'success'; + case'Failed': + return'danger'; + case'Completed': + return'success'; + case'Shipped': + return'success'; + case'Pending': + return'warning'; + default: + return'danger'; } }, checkProductOptions: (opts) => { @@ -194,26 +219,26 @@ handlebars = handlebars.create({ }, ifCond: (v1, operator, v2, options) => { switch(operator){ - case'==': - return(v1 === v2) ? options.fn(this) : options.inverse(this); - case'!=': - return(v1 !== v2) ? options.fn(this) : options.inverse(this); - case'===': - return(v1 === v2) ? options.fn(this) : options.inverse(this); - case'<': - return(v1 < v2) ? options.fn(this) : options.inverse(this); - case'<=': - return(v1 <= v2) ? options.fn(this) : options.inverse(this); - case'>': - return(v1 > v2) ? options.fn(this) : options.inverse(this); - case'>=': - return(v1 >= v2) ? options.fn(this) : options.inverse(this); - case'&&': - return(v1 && v2) ? options.fn(this) : options.inverse(this); - case'||': - return(v1 || v2) ? options.fn(this) : options.inverse(this); - default: - return options.inverse(this); + case'==': + return(v1 === v2) ? options.fn(this) : options.inverse(this); + case'!=': + return(v1 !== v2) ? options.fn(this) : options.inverse(this); + case'===': + return(v1 === v2) ? options.fn(this) : options.inverse(this); + case'<': + return(v1 < v2) ? options.fn(this) : options.inverse(this); + case'<=': + return(v1 <= v2) ? options.fn(this) : options.inverse(this); + case'>': + return(v1 > v2) ? options.fn(this) : options.inverse(this); + case'>=': + return(v1 >= v2) ? options.fn(this) : options.inverse(this); + case'&&': + return(v1 && v2) ? options.fn(this) : options.inverse(this); + case'||': + return(v1 || v2) ? options.fn(this) : options.inverse(this); + default: + return options.inverse(this); } }, isAnAdmin: (value, options) => { @@ -262,6 +287,9 @@ app.use(session({ store: store })); +// Set locales from session +app.use(i18n.init); + // serving static content app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'views', 'themes'))); diff --git a/config/baseSchema.json b/config/baseSchema.json index cf14472..3a2aced 100644 --- a/config/baseSchema.json +++ b/config/baseSchema.json @@ -109,6 +109,12 @@ }, "secretSession": { "type": "string" + }, + "availableLanguages": { + "type": "array" + }, + "defaultLocale": { + "type": "string" } }, "required": [ diff --git a/config/settings.json b/config/settings.json index b0c47a4..ad8fcf3 100644 --- a/config/settings.json +++ b/config/settings.json @@ -24,5 +24,7 @@ "databaseConnectionString": "mongodb://127.0.0.1:27017/expresscart", "theme": "Cloth", "trackStock": false, - "orderHook": "" + "orderHook": "", + "availableLanguages": ["en", "it"], + "defaultLocale": "en" } diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 0000000..bb307e1 --- /dev/null +++ b/locales/en.json @@ -0,0 +1,164 @@ +{ + "Languages": "Languages", + "en": "English", + "it": "Italiano", + "Cart": "Cart", + "Name": "Name", + "New": "New", + "Settings": "Settings", + "General settings": "General settings", + "Address 1": "Address 1", + "Address 2": "Address 2", + "Country": "Country", + "State": "State", + "Postcode": "Postcode", + "Phone number": "Phone number", + "Creation date": "Creation date", + "Customers can be filtered by: email, name or phone number": "Customers can be filtered by: email, name or phone number", + "Customers": "Customers", + "Filtered term": "Filtered term", + "No orders found": "No orders found", + "Email address": "Email address", + "Please enter your email address": "Please enter your email address", + "Reset": "Reset", + "Please sign in": "Please sign in", + "Sign in": "Sign in", + "Update status": "Update status", + "Go Back": "Go Back", + "Order date": "Order date", + "Order ID": "Order ID", + "Payment Gateway ref": "Payment Gateway ref", + "Payment Gateway": "Payment Gateway", + "Order total amount": "Order total amount", + "First name": "First name", + "Last name": "Last name", + "Order comment": "Order comment", + "Products ordered": "Products ordered", + "Options": "Options", + "Filter": "Filter", + "By status": "By status", + "Orders can be filtered by: surname, email address or postcode/zipcode": "Orders can be filtered by: surname, email address or postcode/zipcode", + "Completed": "Completed", + "Paid": "Paid", + "Created": "Created", + "Cancelled": "Cancelled", + "Declined": "Declined", + "Shipped": "Shipped", + "Pending": "Pending", + "Orders": "Orders", + "Recent orders": "Recent orders", + "Status": "Status", + "Upload image": "Upload image", + "Save product": "Save product", + "Edit product": "Edit product", + "Product title": "Product title", + "Product price": "Product price", + "Published": "Published", + "Draft": "Draft", + "Stock level": "Stock level", + "Product description": "Product description", + "Validate": "Validate", + "This sets a readable URL for the product": "This sets a readable URL for the product", + "Product options": "Product options", + "Label": "Label", + "Type": "Type", + "Add": "Add", + "Remove": "Remove", + "Here you can set options for your product. Eg: Size, color, style": "Here you can set options for your product. Eg: Size, color, style", + "Allow comment": "Allow comment", + "Allow free form comments when adding products to cart": "Allow free form comments when adding products to cart", + "Product tag words": "Product tag words", + "Tag words used to indexed products, making them easier to find and filter.": "Tag words used to indexed products, making them easier to find and filter.", + "Product images": "Product images", + "Delete": "Delete", + "main image": "main image", + "Set as main image": "Set as main image", + "No images have been uploaded for this product": "No images have been uploaded for this product", + "Product image upload": "Product image upload", + "Select file": "Select file", + "Upload": "Upload", + "New product": "New product", + "Products can be filtered by: product title or product description keywords": "Products can be filtered by: product title or product description keywords", + "Products": "Products", + "Recent products": "Recent products", + "Confirm": "Confirm", + "Update": "Update", + "Setting_menu_explain": "Here you can setup a menu to displayed on your shopping cart. You can use this menu to filter your products by specifying a keyword in the \"link\" field. Eg: To show products with a keyword (or tag) of boots you would set the menu field to \"Backpacks\" and a link value \"backpack\". You can also use this menu to link to static pages, Eg: shipping, returns, help, about, contact etc.", + "Static page": "Static page", + "Page name": "Page name", + "A friendly name to manage the static page.": "A friendly name to manage the static page.", + "Page slug": "Page slug", + "Page_Slug_Description": "This is the relative URL of the page. Eg: A setting of \"about\" would make the page available at: mydomain.com/about", + "Page Enabled": "Page Enabled", + "Page content": "Page content", + "Here you can enter the content you wish to be displayed on your static page.": "Here you can enter the content you wish to be displayed on your static page.", + "New page": "New page", + "Static pages": "Static pages", + "Static_Pages_Info": "Here you can setup and manage static pages for your shopping cart. You may want to setup a page with a little bit about your business called \"About\" or \"Contact Us\" etc.", + "Edit": "Edit", + "There are currently no static pages setup. Please setup a static page.": "There are currently no static pages setup. Please setup a static page.", + "Create new": "Create new", + "Search": "Search", + "Cart name": "Cart name", + "This element is critical for search engine optimisation. Cart title is displayed if your logo is hidden.": "This element is critical for search engine optimisation. Cart title is displayed if your logo is hidden.", + "Cart description": "Cart description", + "This description shows when your website is listed in search engine results.": "This description shows when your website is listed in search engine results.", + "Cart image/logo": "Cart image/logo", + "Cart URL": "Cart URL", + "This URL is used in sitemaps and when your customer returns from completing their payment.": "This URL is used in sitemaps and when your customer returns from completing their payment.", + "This is used as the \"from\" email when sending receipts to your customers.": "This is used as the \"from\" email when sending receipts to your customers.", + "Flat shipping rate": "Flat shipping rate", + "A flat shipping rate applied to all orders.": "A flat shipping rate applied to all orders.", + "Free shipping threshold": "Free shipping threshold", + "Orders over this value will mean the shipped will the FREE. Set to high value if you always want to charge shipping.": "Orders over this value will mean the shipped will the FREE. Set to high value if you always want to charge shipping.", + "Payment gateway": "Payment gateway", + "Payment_Gateway_Info": "You will also need to configure your payment gateway credentials in the `/config/<gateway_name>.json` file.", + "Currency symbol": "Currency symbol", + "Set this to your currency symbol. Eg: $, £, €": "Set this to your currency symbol. Eg: $, £, €", + "Theme": "Theme", + "Theme_Info": "Themes are loaded from `/public/themes/`", + "Products per row": "Products per row", + "The number of products to be displayed across the page.": "The number of products to be displayed across the page.", + "Products per page": "Products per page", + "The number of products to be displayed on each page.": "The number of products to be displayed on each page.", + "Menu Enabled": "Menu Enabled", + "Menu_Enabled_Info": "If a menu is set you can set it up here.", + "Menu header": "Menu header", + "The heading text for your menu.": "The heading text for your menu.", + "Menu location": "Menu location", + "The location of your menu.": "The location of your menu.", + "Google_Analytics_Info": "Your Google Analytics code. Please also inlude the \"script\" tags - Help", + "Custom CSS": "Custom CSS", + "Send test email": "Send test email", + "Users name": "Users name", + "User email": "User email", + "Password confirm": "Password confirm", + "User password": "User password", + "Complete setup": "Complete setup", + "User is admin?": "User is admin?", + "Generate": "Generate", + "New User": "New User", + "Create": "Create", + "Role": "Role", + "User": "User", + "No products found": "No products found", + "Category": "Category", + "Search results": "Search results", + "Add to cart": "Add to cart", + "Pay now": "Pay now", + "Customer details": "Customer details", + "Existing customer": "Existing customer", + "Forgotten": "Forgotten", + "Change customer": "Change customer", + "Enter a password to create an account for next time": "Enter a password to create an account for next time", + "Create account": "Create account", + "Your payment has been successfully processed": "Your payment has been successfully processed", + "Your payment has failed. Please try again or contact us.": "Your payment has failed. Please try again or contact us.", + "Please retain the details above as a reference of payment.": "Please retain the details above as a reference of payment.", + "Quantity": "Quantity", + "Leave a comment?": "Leave a comment?", + "Cart contents": "Cart contents", + "Shipping": "Shipping:", + "Empty cart": "Empty cart", + "List": "List" +} diff --git a/locales/it.json b/locales/it.json new file mode 100644 index 0000000..1ead5f5 --- /dev/null +++ b/locales/it.json @@ -0,0 +1,165 @@ +{ + "Languages": "Lingue", + "en": "English", + "it": "Italiano", + "Cart": "Carrello", + "Name": "Nome", + "New": "Nuovo", + "List": "Lista", + "Settings": "Impostazioni", + "General settings": "Impostazioni generali", + "Address 1": "Indirizzo 1", + "Address 2": "Indirizzo 2", + "Country": "Paese", + "State": "Stato", + "Postcode": "Codice postale", + "Phone number": "Numero di telefono", + "Creation date": "Data di creazione", + "Customers can be filtered by: email, name or phone numnber": "I clienti sono filtrati per: email, nome o numero di telefono", + "Customers": "Clienti", + "Filtered term": "Filtri", + "No orders found": "Nessun ordine trovato", + "Email address": "Indirizzo email", + "Please enter your email address": "Inserisci il tuo indirizzo email", + "Reset": "Reimposta", + "Please sign in": "Per favore collegati", + "Sign in": "Collegati", + "Update status": "Aggiornamento stato", + "Go Back": "Indietro", + "Order date": "Data ordine", + "Order ID": "ID Ordine", + "Payment Gateway ref": "Ref gateway pagamento", + "Payment Gateway": "Gateway Pagamento", + "Order total amount": "Totale ordine", + "First name": "Nome", + "Last name": "Cognome", + "Order comment": "Commento ordine", + "Products ordered": "Prodotti ordinati", + "Options": "Opzioni", + "Filter": "Filtra", + "By status": "Per stato", + "Orders can be filtered by: surname, email address or postcode/zipcode": "Gli ordini possono essere filtrati per: cognome, email o CAP", + "Completed": "Completo", + "Paid": "Pagato", + "Created": "Creato", + "Cancelled": "Cancellato", + "Declined": "Rifiutato", + "Shipped": "Consegnato", + "Pending": "In sospeso", + "Orders": "Ordini", + "Recent orders": "Ordini recenti", + "Status": "Stato", + "Upload image": "Carica immagine", + "Save product": "Salva prodotto", + "Edit product": "Modifica prodotto", + "Product title": "Titolo prodotto", + "Product price": "Prezzo prodotto", + "Published": "Pubblicato", + "Draft": "Bozza", + "Stock level": "Livello stock", + "Product description": "Descrizione prodotto", + "Validate": "Valida", + "This sets a readable URL for the product": "Configura un URL leggibile per il prodotto", + "Product options": "Opzioni prodotto", + "Label": "Etichetta", + "Type": "Tipo", + "Add": "Aggiungi", + "Remove": "Rimuovi", + "Here you can set options for your product. Eg: Size, color, style": "Qui puoi conifigurare le opzioni per il prodotto. Es: taglia, colore, stile", + "Allow comment": "Permetti commenti", + "Allow free form comments when adding products to cart": "Permetti commenti quando si aggiunge un prodotto al carrello", + "Product tag words": "Tag prodotto", + "Tag words used to indexed products, making them easier to find and filter.": "Parole usate per l'indice prodotti, rende più facile le ricerche ed il filtraggio", + "Product images": "Immagini prodotto", + "Delete": "Elimina", + "main image": "immagine principale", + "Set as main image": "Seleziona come immagine principale", + "No images have been uploaded for this product": "Non è stata caricata nessuna immagine per questo prodotto", + "Product image upload": "Upload immagine prodotto", + "Select file": "Seleziona file", + "Upload": "Carica", + "New product": "Nuovo prodotto", + "Products can be filtered by: product title or product description keywords": "I prodotti possono essere filtrati per: titolo o parole chiavi nella descrizione", + "Products": "Prodotti", + "Recent products": "Prodotti recenti", + "Confirm": "Conferma", + "Update": "Aggiorna", + "Setting_menu_explain": "Qui poi configurare un menu per visualizzarlo nel carrello. Puoi usare questo menu per filtrare prodotti tramite specifiche parole chiave nel campo \"link\". Es: Per visualizzare prodotti con parola chiave (o tag) di stivali, vorrai mettere nel campo menu a \"Backpacks\" ed un valore di link \"backpack\". YSi può usare questo menu anche per pagine statiche, Es: shipping, returns, help, about, contact etc.", + "Static page": "Pagine statiche", + "Page name": "Nome pagina", + "A friendly name to manage the static page.": "Un nome semplice per gestire la pagina statica", + "Page slug": "Slug pagina", + "Page_Slug_Description": "Questo è l'url relativo della pagina. Es: Configurando \"about\" la pagina sarà disponibile a: mydomain.com/about", + "Page Enabled": "Pagina abilitata", + "Page content": "Contenuto pagina", + "Here you can enter the content you wish to be displayed on your static page.": "Qui puoi inserire il contenuto che vuoi sia visualizzato nella tua pagina", + "New page": "Nuova pagina", + "Static pages": "Pagine statiche", + "Static_Pages_Info": "Qui puoi configurare e gestire le tue pagine statiche. Vuoi configurare una pagina con informazioni sul tuo business chiamata \"About\" o \"Contattaci\" ecc.", + "Edit": "Modifica", + "There are currently no static pages setup. Please setup a static page.": "Non ci sono attualmente pagine configurate. Configurane una.", + "Create new": "Create new", + "Search": "Cerca", + "Cart name": "Nome carrello", + "This element is critical for search engine optimisation. Cart title is displayed if your logo is hidden.": "Questo elemento è importante per l'ottimizzazione dei motori di ricerca. Il titolo è visualizzato se il tuo logo è nascosto", + "Cart description": "Descrizione carrello", + "This description shows when your website is listed in search engine results.": "Questa descrizione è visualizzata quando il tuo sito appare nei risultati dei motori di ricerca", + "Cart image/logo": "Immagine/logo carrello", + "Cart URL": "URL Carrello", + "This URL is used in sitemaps and when your customer returns from completing their payment.": "Questo URL è usato nelle sitemaps e quando il tuo cliente ritorna per completare il suo pagamento", + "This is used as the \"from\" email when sending receipts to your customers.": "Questo è usato come \"from\" nelle email inviate ai clienti", + "Cart Email": "Cart Email", + "Flat shipping rate": "Tariffa di spedizione fissa", + "A flat shipping rate applied to all orders.": "Una tariffa di spedizione fissa da applicare a tutti gli ordini", + "Free shipping threshold": "Soglia di spedizione gratuita", + "Orders over this value will mean the shipped will the FREE. Set to high value if you always want to charge shipping.": "Ordini oltre questo valore avranno la spedizione GRATUITA. Configura un alto valore se vuoi sempre addebitare la spedizione.", + "Payment gateway": "Gateway pagamento", + "Payment_Gateway_Info": "Dovrai configurare anche le tue credenziali per il gateway di pagamento nel file `/config/<gateway_name>.json`.", + "Currency symbol": "Simbolo valuta", + "Set this to your currency symbol. Eg: $, £, €": "Configura il simbolo della tua valuta. Es: $, £, €", + "Theme": "Tema", + "Theme_Info": "I temi sono caricati da `/public/themes/`", + "Products per row": "Prodotti per riga", + "The number of products to be displayed across the page.": "Il numero di prodotti visualizzati per riga nella pagina", + "Products per page": "Prodotti per pagina", + "The number of products to be displayed on each page.": "Il numero di prodotti visualizzati per ogni pagina", + "Menu Enabled": "Menu abilitato", + "Menu_Enabled_Info": "Se è abilitato, puoi configuralo qui.", + "Menu header": "Testa del menu", + "The heading text for your menu.": "Il testo di testa del tuo menu", + "Menu location": "Posizione del menu", + "The location of your menu.": "La posizione del tuo menu", + "Google_Analytics_Info": "Il tuo codice Google Analytics . Includi anche i tags \"script\" - Aiuto", + "Custom CSS": "Stile personalizzato", + "Send test email": "Invia email di test", + "Users name": "Nome utenti", + "User email": "Email utente", + "Password confirm": "Conferma password", + "User password": "Password utente", + "Complete setup": "Completa il setup", + "User is admin?": "L'utente è un admin?", + "Generate": "Genera", + "New User": "Nuovo utente", + "Create": "Create", + "Role": "Ruolo", + "User": "Utente", + "No products found": "Nessun prodotto trovato", + "Category": "Categoria", + "Search results": "Risultati ricerca", + "Add to cart": "Aggiungi al carrello", + "Pay now": "Paga ora", + "Customer details": "Dettagli cliente", + "Existing customer": "Cliente esistente", + "Forgotten": "Dimenticato", + "Change customer": "Cambia cliente", + "Enter a password to create an account for next time": "Inserisci una password per creare un account per la prossima volta", + "Create account": "Crea account", + "Your payment has been successfully processed": "Il tuo pagamento è stato processato correttamente", + "Your payment has failed. Please try again or contact us.": "Il tuo pagamento è fallito. Prova ancora, o contattaci", + "Please retain the details above as a reference of payment.": "Conserva i dettagli sopra come riferimento del pagamento", + "Quantity": "Quantità", + "Leave a comment?": "Lascia un commento?", + "Cart contents": "Contenuto del carrello", + "Shipping": "Spedizione:", + "Empty cart": "Svuota carrello" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9830d13..b2b0acf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5236,6 +5236,26 @@ "toidentifier": "1.0.0" } }, + "i18n": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.8.4.tgz", + "integrity": "sha512-PvMcG+yqYWXrwgdmCpL+APCGa8lRY0tdlo2cXp9UeR3u4h1bJGqFsgybfmG/MqtL1iDmdaPPPLJebXGrZ1XoMQ==", + "requires": { + "debug": "*", + "make-plural": "^6.0.1", + "math-interval-parser": "^2.0.1", + "messageformat": "^2.3.0", + "mustache": "*", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6141,6 +6161,11 @@ } } }, + "make-plural": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-6.0.1.tgz", + "integrity": "sha512-h0uBNi4tpDkiWUyYKrJNj8Kif6q3Ba5zp/8jnfPy3pQE+4XcTj6h3eZM5SYVUyDNX9Zk69Isr/dx0I+78aJUaQ==" + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -6214,6 +6239,11 @@ } } }, + "math-interval-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", + "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==" + }, "md5-hex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", @@ -6295,6 +6325,42 @@ "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", "dev": true }, + "messageformat": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-2.3.0.tgz", + "integrity": "sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==", + "requires": { + "make-plural": "^4.3.0", + "messageformat-formatters": "^2.0.1", + "messageformat-parser": "^4.1.2" + }, + "dependencies": { + "make-plural": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz", + "integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==", + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, + "messageformat-formatters": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz", + "integrity": "sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==" + }, + "messageformat-parser": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.2.tgz", + "integrity": "sha512-7dWuifeyldz7vhEuL96Kwq1fhZXBW+TUfbnHN4UCrCxoXQTYjHnR78eI66Gk9LaLLsAvzPNVJBaa66DRfFNaiA==" + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -6453,6 +6519,14 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, + "moment-recur": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/moment-recur/-/moment-recur-1.0.7.tgz", + "integrity": "sha1-TVCSr2SK7e1q/lwT7zjFKQHJlBk=", + "requires": { + "moment": "<3.0.0" + } + }, "mongodb": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.3.tgz", @@ -6543,6 +6617,11 @@ "xtend": "^4.0.0" } }, + "mustache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.1.0.tgz", + "integrity": "sha512-3Bxq1R5LBZp7fbFPZzFe5WN4s0q3+gxZaZuZVY+QctYJiCiVgXHOTIC0/HgZuOPFt/6BQcx5u0H2CUOxT/RoGQ==" + }, "mute-stdout": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", diff --git a/package.json b/package.json index 47a63cc..82d4b09 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "deploy": "gulp deploy", "testdata": "node lib/testdata.js", "test": "NODE_ENV=test ava --verbose", + "dev": "nodemon app.js", "lint": "eslint ./" }, "engines": { @@ -29,6 +30,7 @@ "glob": "^7.1.5", "helmet": "^3.21.2", "html-entities": "^1.2.0", + "i18n": "^0.8.4", "jsonschema": "^1.2.4", "lodash": "^4.17.15", "lunr": "^2.3.8", diff --git a/routes/admin.js b/routes/admin.js index 80267e1..54f3c6b 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -84,7 +84,7 @@ router.get('/admin/setup', async (req, res) => { // dont allow the user to "re-setup" if a user exists. // set needsSetup to false as a user exists req.session.needsSetup = false; - if(userCount && userCount === 0){ + if(userCount === 0){ req.session.needsSetup = true; res.render('setup', { title: 'Setup', @@ -112,7 +112,7 @@ router.post('/admin/setup_action', async (req, res) => { // check for users const userCount = await db.users.countDocuments({}); - if(userCount && userCount === 0){ + if(userCount === 0){ // email is ok to be used. try{ await db.users.insertOne(doc); diff --git a/routes/index.js b/routes/index.js index 0f05597..ec5bae5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -15,7 +15,7 @@ const { updateTotalCartAmount, getData, addSitemapProducts - } = require('../lib/common'); +} = require('../lib/common'); // These is the customer facing routes router.get('/payment/:orderId', async (req, res, next) => { @@ -421,36 +421,36 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => { getData(req, pageNum, { _id: { $in: lunrIdArray } }), getMenu(db) ]) - .then(([results, menu]) => { - // If JSON query param return json instead - if(req.query.json === 'true'){ - res.status(200).json(results.data); - return; - } + .then(([results, menu]) => { + // If JSON query param return json instead + if(req.query.json === 'true'){ + res.status(200).json(results.data); + return; + } - res.render(`${config.themeViews}index`, { - title: 'Results', - results: results.data, - filtered: true, - session: req.session, - metaDescription: req.app.config.cartTitle + ' - Search term: ' + searchTerm, - searchTerm: searchTerm, - pageCloseBtn: showCartCloseBtn('search'), - message: clearSessionValue(req.session, 'message'), - messageType: clearSessionValue(req.session, 'messageType'), - productsPerPage: numberProducts, - totalProductCount: results.totalProducts, - pageNum: pageNum, - paginateUrl: 'search', - config: config, - menu: sortMenu(menu), - helpers: req.handlebars.helpers, - showFooter: 'showFooter' + res.render(`${config.themeViews}index`, { + title: 'Results', + results: results.data, + filtered: true, + session: req.session, + metaDescription: req.app.config.cartTitle + ' - Search term: ' + searchTerm, + searchTerm: searchTerm, + pageCloseBtn: showCartCloseBtn('search'), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + productsPerPage: numberProducts, + totalProductCount: results.totalProducts, + pageNum: pageNum, + paginateUrl: 'search', + config: config, + menu: sortMenu(menu), + helpers: req.handlebars.helpers, + showFooter: 'showFooter' + }); + }) + .catch((err) => { + console.error(colors.red('Error searching for products', err)); }); - }) - .catch((err) => { - console.error(colors.red('Error searching for products', err)); - }); }); // search products @@ -475,39 +475,45 @@ router.get('/category/:cat/:pageNum?', (req, res) => { getData(req, pageNum, { _id: { $in: lunrIdArray } }), getMenu(db) ]) - .then(([results, menu]) => { - const sortedMenu = sortMenu(menu); + .then(([results, menu]) => { + const sortedMenu = sortMenu(menu); - // If JSON query param return json instead - if(req.query.json === 'true'){ - res.status(200).json(results.data); - return; - } + // If JSON query param return json instead + if(req.query.json === 'true'){ + res.status(200).json(results.data); + return; + } - res.render(`${config.themeViews}index`, { - title: 'Category', - results: results.data, - filtered: true, - session: req.session, - searchTerm: searchTerm, - metaDescription: req.app.config.cartTitle + ' - Category: ' + searchTerm, - pageCloseBtn: showCartCloseBtn('category'), - message: clearSessionValue(req.session, 'message'), - messageType: clearSessionValue(req.session, 'messageType'), - productsPerPage: numberProducts, - totalProductCount: results.totalProducts, - pageNum: pageNum, - menuLink: _.find(sortedMenu.items, (obj) => { return obj.link === searchTerm; }), - paginateUrl: 'category', - config: config, - menu: sortedMenu, - helpers: req.handlebars.helpers, - showFooter: 'showFooter' + res.render(`${config.themeViews}index`, { + title: 'Category', + results: results.data, + filtered: true, + session: req.session, + searchTerm: searchTerm, + metaDescription: req.app.config.cartTitle + ' - Category: ' + searchTerm, + pageCloseBtn: showCartCloseBtn('category'), + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + productsPerPage: numberProducts, + totalProductCount: results.totalProducts, + pageNum: pageNum, + menuLink: _.find(sortedMenu.items, (obj) => { return obj.link === searchTerm; }), + paginateUrl: 'category', + config: config, + menu: sortedMenu, + helpers: req.handlebars.helpers, + showFooter: 'showFooter' + }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for category', err)); }); - }) - .catch((err) => { - console.error(colors.red('Error getting products for category', err)); - }); +}); + +// Language setup in cookie +router.get('/lang/:locale', (req, res) => { + res.cookie('locale', req.params.locale, { maxAge: 900000, httpOnly: true }); + res.redirect('back'); }); // return sitemap @@ -552,34 +558,34 @@ router.get('/page/:pageNum', (req, res, next) => { getData(req, req.params.pageNum), getMenu(db) ]) - .then(([results, menu]) => { - // If JSON query param return json instead - if(req.query.json === 'true'){ - res.status(200).json(results.data); - return; - } + .then(([results, menu]) => { + // If JSON query param return json instead + if(req.query.json === 'true'){ + res.status(200).json(results.data); + return; + } - res.render(`${config.themeViews}index`, { - title: 'Shop', - results: results.data, - session: req.session, - message: clearSessionValue(req.session, 'message'), - messageType: clearSessionValue(req.session, 'messageType'), - metaDescription: req.app.config.cartTitle + ' - Products page: ' + req.params.pageNum, - pageCloseBtn: showCartCloseBtn('page'), - config: req.app.config, - productsPerPage: numberProducts, - totalProductCount: results.totalProducts, - pageNum: req.params.pageNum, - paginateUrl: 'page', - helpers: req.handlebars.helpers, - showFooter: 'showFooter', - menu: sortMenu(menu) + res.render(`${config.themeViews}index`, { + title: 'Shop', + results: results.data, + session: req.session, + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + metaDescription: req.app.config.cartTitle + ' - Products page: ' + req.params.pageNum, + pageCloseBtn: showCartCloseBtn('page'), + config: req.app.config, + productsPerPage: numberProducts, + totalProductCount: results.totalProducts, + pageNum: req.params.pageNum, + paginateUrl: 'page', + helpers: req.handlebars.helpers, + showFooter: 'showFooter', + menu: sortMenu(menu) + }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for page', err)); }); - }) - .catch((err) => { - console.error(colors.red('Error getting products for page', err)); - }); }); // The main entry point of the shop @@ -594,34 +600,34 @@ router.get('/:page?', async (req, res, next) => { getData(req, 1, {}), getMenu(db) ]) - .then(([results, menu]) => { - // If JSON query param return json instead - if(req.query.json === 'true'){ - res.status(200).json(results.data); - return; - } + .then(([results, menu]) => { + // If JSON query param return json instead + if(req.query.json === 'true'){ + res.status(200).json(results.data); + return; + } - res.render(`${config.themeViews}index`, { - title: `${config.cartTitle} - Shop`, - theme: config.theme, - results: results.data, - session: req.session, - message: clearSessionValue(req.session, 'message'), - messageType: clearSessionValue(req.session, 'messageType'), - pageCloseBtn: showCartCloseBtn('page'), - config: req.app.config, - productsPerPage: numberProducts, - totalProductCount: results.totalProducts, - pageNum: 1, - paginateUrl: 'page', - helpers: req.handlebars.helpers, - showFooter: 'showFooter', - menu: sortMenu(menu) + res.render(`${config.themeViews}index`, { + title: `${config.cartTitle} - Shop`, + theme: config.theme, + results: results.data, + session: req.session, + message: clearSessionValue(req.session, 'message'), + messageType: clearSessionValue(req.session, 'messageType'), + pageCloseBtn: showCartCloseBtn('page'), + config: req.app.config, + productsPerPage: numberProducts, + totalProductCount: results.totalProducts, + pageNum: 1, + paginateUrl: 'page', + helpers: req.handlebars.helpers, + showFooter: 'showFooter', + menu: sortMenu(menu) + }); + }) + .catch((err) => { + console.error(colors.red('Error getting products for page', err)); }); - }) - .catch((err) => { - console.error(colors.red('Error getting products for page', err)); - }); }else{ if(req.params.page === 'admin'){ next(); diff --git a/views/customer.hbs b/views/customer.hbs index 47f31db..3d0a68d 100644 --- a/views/customer.hbs +++ b/views/customer.hbs @@ -11,35 +11,35 @@ {{result.email}} - Name: + {{ @root.__ "Name" }}: {{result.firstName}} {{result.lastName}} - Address 1: + {{ @root.__ "Address 1" }}: {{result.address1}} - Address 2: + {{ @root.__ "Address 2" }}: {{result.address2}} - Country: + {{ @root.__ "Country" }}: {{result.country}} - State: + {{ @root.__ "State" }}: {{result.state}} - Postcode: + {{ @root.__ "Postcode" }}: {{result.postcode}} - Phone number: + {{ @root.__ "Phone number" }}: {{result.phone}} - Creation date: + {{ @root.__ "Creation date" }}: {{formatDate result.created "DD/MM/YYYY hh:mmA"}} diff --git a/views/customers.hbs b/views/customers.hbs index b564f33..49f3cc5 100644 --- a/views/customers.hbs +++ b/views/customers.hbs @@ -11,29 +11,29 @@ -

Customers can be filtered by: email, name or phone numnber

+

{{ @root.__ "Customers can be filtered by: email, name or phone number" }}

{{#if customers}}
{{else}}

- No orders found + {{ @root.__ "No orders found" }}

{{/if}} - \ No newline at end of file + diff --git a/views/forgotten.hbs b/views/forgotten.hbs index dc6d462..73fe2d7 100644 --- a/views/forgotten.hbs +++ b/views/forgotten.hbs @@ -1,9 +1,9 @@
diff --git a/views/layouts/layout.hbs b/views/layouts/layout.hbs index 613586e..08cdfd0 100644 --- a/views/layouts/layout.hbs +++ b/views/layouts/layout.hbs @@ -103,13 +103,21 @@
- +
-

Allow free form comments when adding products to cart

+

{{ @root.__ "Allow free form comments when adding products to cart" }}

- +
-

Tag words used to indexed products, making them easier to find and filter.

+

{{ @root.__ "Tag words used to indexed products, making them easier to find and filter." }}

-

Product images

+

{{ @root.__ "Product images" }}

{{#if images}}
{{#each images}}

- Delete + {{ @root.__ "Delete" }} {{#ifCond this.productImage '==' true}} - main image + {{ @root.__ "main image" }} {{else}} - Set as main image + {{ @root.__ "Set as main image" }} {{/ifCond}}

@@ -147,7 +147,7 @@
{{else}} -

No images have been uploaded for this product

+

{{ @root.__ "No images have been uploaded for this product" }}

{{/if}}
@@ -162,17 +162,17 @@
diff --git a/views/product_new.hbs b/views/product_new.hbs index 7d338bc..46baa43 100644 --- a/views/product_new.hbs +++ b/views/product_new.hbs @@ -6,16 +6,16 @@
-

New product

+

{{ @root.__ "New product" }}

- +
- +
$ @@ -24,24 +24,24 @@
- +
{{#if config.trackStock}}
- +
{{/if}}
- +
@@ -55,26 +55,26 @@
-

This sets a readable URL for the product

+

{{ @root.__ "This sets a readable URL for the product" }}

- +
  • - Name: + {{ @root.__ "Name" }}:
    - Label: + {{ @root.__ "Label" }}:
    - Type: + {{ @root.__ "Type" }}:
    - Options: + {{ @root.__ "Options" }}:

    - +
  • {{#each options}} @@ -97,17 +97,17 @@
    {{this.optType}}
    {{{this.optOptions}}}
    - +
{{/each}} -

Here you can set options for your product. Eg: Size, color, style

+

{{ @root.__ "Here you can set options for your product. Eg: Size, color, style" }}

- +
-

Allow free form comments when adding products to cart

+

{{ @root.__ "Allow free form comments when adding products to cart" }}

-

Tag words used to indexed products, making them easier to find and filter.

+

{{ @root.__ "Tag words used to indexed products, making them easier to find and filter." }}

diff --git a/views/products.hbs b/views/products.hbs index 4a59e5a..c0bc53e 100644 --- a/views/products.hbs +++ b/views/products.hbs @@ -11,14 +11,14 @@ -

Products can be filtered by: product title or product description keywords

+

{{ @root.__ "Products can be filtered by: product title or product description keywords" }}

{{#if results}}
diff --git a/views/settings.hbs b/views/settings.hbs index 3c10e72..cca6f8e 100644 --- a/views/settings.hbs +++ b/views/settings.hbs @@ -3,72 +3,70 @@
-

General Settings +

{{ @root.__ "General settings" }}
- +

- +

- This element is critical for search engine optimisation. Cart title is displayed if your logo is hidden. + {{ @root.__ "This element is critical for search engine optimisation. Cart title is displayed if your logo is hidden." }}

- + -

This description shows when your website is listed in search engine results.

+

{{ @root.__ "This description shows when your website is listed in search engine results." }}

- +
- + -

This URL is used in sitemaps and when your customer returns from completing their payment.

+

{{ @root.__ "This URL is used in sitemaps and when your customer returns from completing their payment." }}

- + -

This is used as the "from" email when sending receipts to your customers.

+

{{ @root.__ "This is used as the \"from\" email when sending receipts to your customers." }}

- + -

A flat shipping rate applied to all orders.

+

{{ @root.__ "A flat shipping rate applied to all orders." }}

- + -

Orders over this value will mean the shipped will the FREE. Set to high value if you always want to charge - shipping.

+

{{ @root.__ "Orders over this value will mean the shipped will the FREE. Set to high value if you always want to charge shipping." }}

- + -

You will also need to configure your payment gateway credentials in the `/config/<gateway_name>.json` - file.

+

{{ @root.__ "Payment_Gateway_Info" }}

- + -

Set this to your currency symbol. Eg: $, £, €

+

{{ @root.__ "Set this to your currency symbol. Eg: $, £, €" }}

- + -

Themes are loaded from `/public/themes/`

+

{{ @root.__ "Theme_Info" }}

- + -

The number of products to be displayed across the page.

+

{{ @root.__ "The number of products to be displayed across the page." }}

- + -

The number of products to be displayed on each page.

+

{{ @root.__ "The number of products to be displayed on each page." }}

- +
-

If a menu is set you can set it up - here.

+

{{{ @root.__ "Menu_Enabled_Info" }}}

- + -

The heading text for your menu.

+

{{ @root.__ "The heading text for your menu." }}

- + -

The location of your menu.

+

{{ @root.__ "The location of your menu." }}

@@ -116,13 +113,11 @@ -

Your Google Analytics code. Please also inlude the "script" tags - - Help +

{{{ @root.__ "Google_Analytics_Info" }}}

- +
@@ -151,7 +146,7 @@
- +
diff --git a/views/settings_menu.hbs b/views/settings_menu.hbs index 476a0c5..b07c753 100644 --- a/views/settings_menu.hbs +++ b/views/settings_menu.hbs @@ -51,9 +51,8 @@

- Here you can setup a menu to displayed on your shopping cart. You can use this menu to filter your products by specifying a keyword in the - "link" field. Eg: To show products with a keyword (or tag) of boots you would set the menu field to "Backpacks" and a link value "backpack". - You can also use this menu to link to static pages, Eg: shipping, returns, help, about, contact etc. + + {{ @root.__ "Setting_menu_explain" }}

diff --git a/views/settings_page_edit.hbs b/views/settings_page_edit.hbs index 0a55052..6039368 100644 --- a/views/settings_page_edit.hbs +++ b/views/settings_page_edit.hbs @@ -3,28 +3,28 @@
-

Static page

+

{{ @root.__ "Static page" }}

- + -

A friendly name to manage the static page.

+

{{ @root.__ "A friendly name to manage the static page." }}

- + -

This is the relative URL of the page. Eg: A setting of "about" would make the page available at: mydomain.com/about

+

{{ @root.__ "Page_Slug_Description" }}

- +
- + -

Here you can enter the content you wish to be displayed on your static page.

+

{{ @root.__ "Here you can enter the content you wish to be displayed on your static page." }}

diff --git a/views/settings_pages.hbs b/views/settings_pages.hbs index 47de8f9..ff19332 100644 --- a/views/settings_pages.hbs +++ b/views/settings_pages.hbs @@ -2,10 +2,9 @@
-

Static pages

+

{{ @root.__ "Static pages" }}

- Here you can setup and manage static pages for your shopping cart. - You may want to setup a page with a little bit about your business called "About" or "Contact Us" etc. + {{ @root.__ "Static_Pages_Info" }}

{{#if pages}} {{else}} -

There are currently no static pages setup. Please setup a static page.

+

{{ @root.__ "There are currently no static pages setup. Please setup a static page." }}

- Create new + {{ @root.__ "Create new" }}

{{/if}}
diff --git a/views/setup.hbs b/views/setup.hbs index e5cdb83..0c4a987 100644 --- a/views/setup.hbs +++ b/views/setup.hbs @@ -2,21 +2,21 @@
diff --git a/views/themes/Cloth/cart.hbs b/views/themes/Cloth/cart.hbs index b441d5f..e8b031e 100644 --- a/views/themes/Cloth/cart.hbs +++ b/views/themes/Cloth/cart.hbs @@ -8,7 +8,7 @@
{{/if}}
-
Cart contents
+
{{ @root.__ "Cart contents" }}
{{#each @root.session.cart}} @@ -64,12 +64,13 @@
{{#ifCond @root.session.shippingCostApplied '===' true}}
- Shipping: + {{currencySymbol config.currencySymbol}}{{formatAmount config.flatShipping}} + {{ @root.__ "Shipping" }} {{currencySymbol @root.config.currencySymbol}}{{formatAmount @root.config.flatShipping}}
{{else}}
- Shipping: + {{ @root.__ "Shipping" }} FREE
{{/ifCond}} @@ -92,12 +93,12 @@
{{#if @root.session.cart}}
- +
{{#ifCond page '!=' 'pay'}}
{{#ifCond @root.page '==' 'checkout'}} - Pay now + {{ @root.__ "Pay now" }} {{else}} Checkout {{/ifCond}} @@ -105,4 +106,4 @@ {{/ifCond}} {{/if}}
-
\ No newline at end of file +
diff --git a/views/themes/Cloth/front-menu.hbs b/views/themes/Cloth/front-menu.hbs index 88a99d5..1fdb539 100644 --- a/views/themes/Cloth/front-menu.hbs +++ b/views/themes/Cloth/front-menu.hbs @@ -15,7 +15,7 @@
- +
diff --git a/views/themes/Cloth/index.hbs b/views/themes/Cloth/index.hbs index 199a1a4..cb9abb0 100644 --- a/views/themes/Cloth/index.hbs +++ b/views/themes/Cloth/index.hbs @@ -3,16 +3,16 @@ {{#if filtered}}
{{#if menuLink}} -

Category: {{menuLink.title}}

+

{{ @root.__ "Category" }}: {{menuLink.title}}

{{else}} -

Search results: {{searchTerm}}

+

{{ @root.__ "Search results" }}: {{searchTerm}}

{{/if}}
{{/if}}
{{#ifCond results.length '==' 0}}
-

No products found

+

{{ @root.__ "No products found" }}

{{/ifCond}} {{#each results}} @@ -51,7 +51,7 @@ {{currencySymbol ../config.currencySymbol}}{{formatAmount productPrice}}

- Add to cart + {{ @root.__ "Add to cart" }}

diff --git a/views/themes/Cloth/pay.hbs b/views/themes/Cloth/pay.hbs index 0aac7e1..0b105e7 100644 --- a/views/themes/Cloth/pay.hbs +++ b/views/themes/Cloth/pay.hbs @@ -3,7 +3,7 @@
@@ -12,10 +12,10 @@ {{/if}}
-
Customer details
+
{{ @root.__ "Customer details" }}
{{#unless session.customer}}
@@ -33,7 +33,7 @@
{{#if session.customer}}
- +
{{/if}}
@@ -45,11 +45,11 @@ {{/if}} {{#unless session.customer}}
-

Enter a password to create an account for next time

+

{{ @root.__ "Enter a password to create an account for next time" }}

- Create account + {{ @root.__ "Create account" }}
{{/unless}}
diff --git a/views/themes/Cloth/payment_complete.hbs b/views/themes/Cloth/payment_complete.hbs index a5a511b..2b93958 100644 --- a/views/themes/Cloth/payment_complete.hbs +++ b/views/themes/Cloth/payment_complete.hbs @@ -2,20 +2,20 @@
{{#ifCond result.orderStatus '==' 'Paid'}} -

Your payment has been successfully processed

+

{{ @root.__ "Your payment has been successfully processed" }}

{{else}} -

Your payment has failed. Please try again or contact us.

+

{{ @root.__ "Your payment has failed. Please try again or contact us." }}

{{/ifCond}} {{#if result}}
-

Order ID: {{result._id}}

-

Payment ID: {{result.orderPaymentId}}

+

{{ @root.__ "Order ID" }}: {{result._id}}

+

{{ @root.__ "Payment ID" }}: {{result.orderPaymentId}}

{{/if}} {{#ifCond result.orderStatus '==' 'Paid'}} -

Please retain the details above as a reference of payment.

+

{{ @root.__ "Please retain the details above as a reference of payment." }}

{{/ifCond}} Home
-
\ No newline at end of file +
diff --git a/views/themes/Cloth/product.hbs b/views/themes/Cloth/product.hbs index ed51e0d..2c3e834 100644 --- a/views/themes/Cloth/product.hbs +++ b/views/themes/Cloth/product.hbs @@ -6,7 +6,7 @@

{{result.productTitle}}

{{currencySymbol config.currencySymbol}}{{result.productPrice}}

{{#if productOptions}} -

Options

+

{{ @root.__ "Options" }}

{{#each productOptions}} {{#ifCond this.optType '==' "select"}} @@ -48,7 +48,7 @@ {{/ifCond}} {{/if}}
-

Quantity

+

{{ @root.__ "Quantity" }}

@@ -61,12 +61,12 @@
{{#if result.productComment}}
- Leave a comment? + {{ @root.__ "Leave a comment?" }}
{{/if}}
- +
{{{productDescription}}} diff --git a/views/themes/Material/cart.hbs b/views/themes/Material/cart.hbs index 7b38560..3802fc6 100644 --- a/views/themes/Material/cart.hbs +++ b/views/themes/Material/cart.hbs @@ -9,7 +9,7 @@ {{/if}}
- Cart contents + {{ @root.__ "Cart contents" }} {{#each @root.session.cart}}
@@ -58,12 +58,12 @@
{{#ifCond @root.session.shippingCostApplied '===' true}}
- Shipping: + {{ @root.__ "Shipping" }} {{currencySymbol config.currencySymbol}}{{formatAmount @root.config.flatShipping}}
{{else}}
- Shipping: + {{ @root.__ "Shipping" }} FREE
{{/ifCond}} @@ -85,12 +85,12 @@
{{#if @root.session.cart}}
- +
{{#ifCond page '!=' 'pay'}}
{{#ifCond @root.page '==' 'checkout'}} - Pay now + {{ @root.__ "Pay now" }} {{else}} Checkout {{/ifCond}} @@ -98,4 +98,4 @@ {{/ifCond}} {{/if}}
-
\ No newline at end of file +
diff --git a/views/themes/Material/front-menu.hbs b/views/themes/Material/front-menu.hbs index 6c02787..46843d2 100644 --- a/views/themes/Material/front-menu.hbs +++ b/views/themes/Material/front-menu.hbs @@ -15,7 +15,7 @@
  • - +
  • diff --git a/views/themes/Material/index.hbs b/views/themes/Material/index.hbs index 0f79424..61fa9f3 100644 --- a/views/themes/Material/index.hbs +++ b/views/themes/Material/index.hbs @@ -3,16 +3,16 @@ {{#if filtered}}
    {{#if menuLink}} -

    Category: {{menuLink.title}}

    +

    {{ @root.__ "Category" }}: {{menuLink.title}}

    {{else}} -

    Search results: {{searchTerm}}

    +

    {{ @root.__ "Search results" }}: {{searchTerm}}

    {{/if}}
    {{/if}}
    {{#ifCond results.length '==' 0}}
    -

    No products found

    +

    {{ @root.__ "No products found" }}

    {{/ifCond}} {{#each results}} @@ -51,7 +51,7 @@ {{currencySymbol ../config.currencySymbol}}{{formatAmount productPrice}}

    - Add to cart + {{ @root.__ "Add to cart" }}

    diff --git a/views/themes/Material/pay.hbs b/views/themes/Material/pay.hbs index b797ed2..eef128c 100644 --- a/views/themes/Material/pay.hbs +++ b/views/themes/Material/pay.hbs @@ -7,9 +7,9 @@
    - Customer details + {{ @root.__ "Customer details" }} {{#unless session.customer}} -

    Existing customer

    +

    {{ @root.__ "Existing customer" }}

    @@ -17,7 +17,7 @@
    @@ -25,7 +25,7 @@ {{/unless}} {{#if session.customer}}
    - +
    {{/if}}
    @@ -37,13 +37,13 @@ {{/if}} {{#unless session.customer}}
    -

    Enter a password to create an account for next time

    +

    {{ @root.__ "Enter a password to create an account for next time" }}

    {{/unless}}
    diff --git a/views/themes/Material/payment_complete.hbs b/views/themes/Material/payment_complete.hbs index f05980c..dbffd91 100644 --- a/views/themes/Material/payment_complete.hbs +++ b/views/themes/Material/payment_complete.hbs @@ -2,20 +2,20 @@
    {{#ifCond result.orderStatus '==' 'Paid'}} -

    Your payment has been successfully processed

    +

    {{ @root.__ "Your payment has been successfully processed" }}

    {{else}} -

    Your payment has failed. Please try again or contact us.

    +

    {{ @root.__ "Your payment has failed. Please try again or contact us." }}

    {{/ifCond}} {{#if result}}
    -

    Order ID: {{result._id}}

    -

    Payment ID: {{result.orderPaymentId}}

    +

    {{ @root.__ "Order ID" }}: {{result._id}}

    +

    {{ @root.__ "Payment ID" }}: {{result.orderPaymentId}}

    {{/if}} {{#ifCond result.orderStatus '==' 'Paid'}} -

    Please retain the details above as a reference of payment.

    +

    {{ @root.__ "Please retain the details above as a reference of payment." }}

    {{/ifCond}} Home
    -
    \ No newline at end of file +
    diff --git a/views/themes/Material/product.hbs b/views/themes/Material/product.hbs index 20572e2..77e10cc 100644 --- a/views/themes/Material/product.hbs +++ b/views/themes/Material/product.hbs @@ -6,7 +6,7 @@

    {{result.productTitle}}

    {{currencySymbol config.currencySymbol}}{{result.productPrice}}

    {{#if productOptions}} -

    Options

    +

    {{ @root.__ "Options" }}

    {{#each productOptions}} {{#ifCond this.optType '==' "select"}} @@ -48,7 +48,7 @@ {{/ifCond}} {{/if}}
    -

    Quantity

    +

    {{ @root.__ "Quantity" }}

    @@ -63,12 +63,12 @@
    {{#if result.productComment}}
    - Leave a comment? + {{ @root.__ "Leave a comment?" }}
    {{/if}}
    - +
    {{{productDescription}}} diff --git a/views/themes/Mono/cart.hbs b/views/themes/Mono/cart.hbs index 0d1cc8f..b0c2854 100644 --- a/views/themes/Mono/cart.hbs +++ b/views/themes/Mono/cart.hbs @@ -9,7 +9,7 @@ {{/if}}
    - Cart contents + {{ @root.__ "Cart contents" }} {{#each @root.session.cart}}
    @@ -58,12 +58,12 @@
    {{#ifCond @root.session.shippingCostApplied '===' true}}
    - Shipping: + {{ @root.__ "Shipping" }} {{currencySymbol config.currencySymbol}}{{formatAmount @root.config.flatShipping}}
    {{else}}
    - Shipping: + {{ @root.__ "Shipping" }} FREE
    {{/ifCond}} @@ -85,12 +85,12 @@
    {{#if @root.session.cart}}
    - +
    {{#ifCond page '!=' 'pay'}}
    {{#ifCond @root.page '==' 'checkout'}} - Pay now + {{ @root.__ "Pay now" }} {{else}} Checkout {{/ifCond}} @@ -98,4 +98,4 @@ {{/ifCond}} {{/if}}
    -
    \ No newline at end of file +
    diff --git a/views/themes/Mono/front-menu.hbs b/views/themes/Mono/front-menu.hbs index 6bdc989..fdd7679 100644 --- a/views/themes/Mono/front-menu.hbs +++ b/views/themes/Mono/front-menu.hbs @@ -7,7 +7,7 @@
  • Home
  • diff --git a/views/themes/Mono/index.hbs b/views/themes/Mono/index.hbs index 0c8d6bd..0af6998 100644 --- a/views/themes/Mono/index.hbs +++ b/views/themes/Mono/index.hbs @@ -3,16 +3,16 @@ {{#if filtered}}
    {{#if menuLink}} -

    Category: {{menuLink.title}}

    +

    {{ @root.__ "Category" }}: {{menuLink.title}}

    {{else}} -

    Search results: {{searchTerm}}

    +

    {{ @root.__ "Search results" }}: {{searchTerm}}

    {{/if}}
    {{/if}}
    {{#ifCond results.length '==' 0}}
    -

    No products found

    +

    {{ @root.__ "No products found" }}

    {{/ifCond}} {{#each results}} @@ -51,7 +51,7 @@ {{currencySymbol ../config.currencySymbol}}{{formatAmount productPrice}}

    - Add to cart + {{ @root.__ "Add to cart" }}

    diff --git a/views/themes/Mono/pay.hbs b/views/themes/Mono/pay.hbs index bcbb2dd..ff0131b 100644 --- a/views/themes/Mono/pay.hbs +++ b/views/themes/Mono/pay.hbs @@ -7,9 +7,9 @@
    - Customer details + {{ @root.__ "Customer details" }} {{#unless session.customer}} -

    Existing customer

    +

    {{ @root.__ "Existing customer" }}

    @@ -17,7 +17,7 @@
    @@ -25,7 +25,7 @@ {{/unless}} {{#if session.customer}}
    - +
    {{/if}}
    @@ -37,13 +37,13 @@ {{/if}} {{#unless session.customer}}
    -

    Enter a password to create an account for next time

    +

    {{ @root.__ "Enter a password to create an account for next time" }}

    {{/unless}}
    diff --git a/views/themes/Mono/payment_complete.hbs b/views/themes/Mono/payment_complete.hbs index 6ab53e4..2ee7e7d 100644 --- a/views/themes/Mono/payment_complete.hbs +++ b/views/themes/Mono/payment_complete.hbs @@ -2,20 +2,20 @@
    {{#ifCond result.orderStatus '==' 'Paid'}} -

    Your payment has been successfully processed

    +

    {{ @root.__ "Your payment has been successfully processed" }}

    {{else}} -

    Your payment has failed. Please try again or contact us.

    +

    {{ @root.__ "Your payment has failed. Please try again or contact us." }}

    {{/ifCond}} {{#if result}}
    -

    Order ID: {{result._id}}

    -

    Payment ID: {{result.orderPaymentId}}

    +

    {{ @root.__ "Order ID" }}: {{result._id}}

    +

    {{ @root.__ "Payment ID" }}: {{result.orderPaymentId}}

    {{/if}} {{#ifCond result.orderStatus '==' 'Paid'}} -

    Please retain the details above as a reference of payment.

    +

    {{ @root.__ "Please retain the details above as a reference of payment." }}

    {{/ifCond}} Home
    -
    \ No newline at end of file +
    diff --git a/views/themes/Mono/product.hbs b/views/themes/Mono/product.hbs index a15b531..97a63f4 100644 --- a/views/themes/Mono/product.hbs +++ b/views/themes/Mono/product.hbs @@ -6,7 +6,7 @@

    {{result.productTitle}}

    {{currencySymbol config.currencySymbol}}{{result.productPrice}}

    {{#if productOptions}} -

    Options

    +

    {{ @root.__ "Options" }}

    {{#each productOptions}} {{#ifCond this.optType '==' "select"}} @@ -48,7 +48,7 @@ {{/ifCond}} {{/if}}
    -

    Quantity

    +

    {{ @root.__ "Quantity" }}

    @@ -63,12 +63,12 @@
    {{#if result.productComment}}
    - Leave a comment? + {{ @root.__ "Leave a comment?" }}
    {{/if}}
    - +
    {{{productDescription}}} diff --git a/views/user_edit.hbs b/views/user_edit.hbs index a87f5f0..b726d95 100644 --- a/views/user_edit.hbs +++ b/views/user_edit.hbs @@ -6,26 +6,26 @@
    - +
    - +
    - +
    - +
    {{#isAnAdmin session.isAdmin}} {{#ifCond session.user '!=' user.userEmail}}
    {{/ifCond}} @@ -35,13 +35,13 @@
    - +

    - +
    diff --git a/views/user_new.hbs b/views/user_new.hbs index 1ea343d..3ff4650 100644 --- a/views/user_new.hbs +++ b/views/user_new.hbs @@ -2,27 +2,27 @@
    -

    New User

    +

    {{ @root.__ "New User" }}

    - +
    - +
    - +
    - +
    - +
    diff --git a/views/users.hbs b/views/users.hbs index 069c979..a39c24b 100644 --- a/views/users.hbs +++ b/views/users.hbs @@ -2,17 +2,17 @@
    -

    Users New user

    +

    Users {{ @root.__ "New user" }}

      {{#each users}}
    • - User: {{this.usersName}} - ({{this.userEmail}}) + {{ @root.__ "User" }}: {{this.usersName}} - ({{this.userEmail}}) - Role: + {{ @root.__ "Role" }}: {{#isAnAdmin this.isAdmin}} Admin {{else}} - User + {{ @root.__ "User" }} {{/isAnAdmin}} {{#isAnAdmin ../session.isAdmin}}