Using i18n with hbs and express - node.js

I am trying to properly use i18n with hbs, but haven't had any success.
Here is my server.js code:
var express = require('express');
var server = express();
var hbs = require('hbs');
var i18n = require('i18n');
var cookieParser = require('cookie-parser');
i18n.configure({
locales: ['en', 'fr'],
cookie: 'locale',
directory: __dirname + "/locales"
});
hbs.registerPartials(__dirname + '/views');
server.set('view engine', 'hbs');
server.engine('hbs', hbs.__express);
server.use(cookieParser());
server.use(i18n.init);
hbs.registerHelper('__', function () {
return i18n.__.apply(this, arguments);
});
hbs.registerHelper('__n', function () {
return i18n.__n.apply(this, arguments);
});
server.get('/', function(req, res) {
res.render('index');
});
And my HTML code :
<ul class="nav navbar-nav navbar-right">
<li>{{__ 'HOME'}}</li>
<li>{{__ 'TEAM'}}</li>
<li>{{__ 'SERVICES'}}</li>
<li>{{{__ 'LEL'}}}</li>
</ul>
And one of my Json files :
{
"HOME": "HOME",
"TEAM": "TEAM",
"SERVICES": "SERVICES",
"LEL": "CONTACT"
}
I can't see what I am doing wrong, if someone could help me bit it would be really helpful! Thank you!
Edit : It seems that my helpers are recognized, but i18n is not translating words..
Édit : Ok I changed my template engine and it worked !

I did it like this
const express = require('express');
const path = require('path');
const handlebars = require('handlebars');
const app = express();
const i18n = require('i18n');
// Language
i18n.configure({
locales: ['es', 'en'],
directory: path.join(__dirname, 'locales'),
defaultLocale: 'es',
queryParameter: 'lang',
});
app.engine('.hbs', exphbs({
defaultLayout: 'index',
layoutsDir: path.join(app.get('views'), 'layouts'),
partialsDir: path.join(app.get('views'), 'partials'),
extname: '.hbs',
handlebars: allowInsecurePrototypeAccess(handlebars),
helpers: {
i18n: function(){
return i18n.__.apply(this,arguments);
},
__n: function(){
return i18n.__n.apply(this, arguments);
},
}
}));
app.set('view engine', 'hbs');
app.use(i18n.init);
and in any .hbs file
<h1>{{i18n 'Hello'}}<h1>

Related

Am I looking for help about i118 express node.js?

When i choose some language, i get error message . that err msg is .translation is not defined.
example :
http://localhost:5000/?clang=en
Can I achieve my goal with just these 23 files or do I have to use other methods as well?
my app.js code is
// Imports
const express = require('express')
const expressLayouts = require('express-ejs-layouts')
const app = express()
const port = 5000
// import Router file
var session = require('express-session');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var i18n=require("i18n-express"); // <-- require the module
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
app.use(i18n({
translationsPath: path.join(__dirname, 'i18n'), // <--- use here. Specify translations files path.
siteLangs: ["es", "en", "de", "ru", "it"],
textsVarName: 'translation'
}));
// Static Files
app.use(express.static('public'))
app.use('/css', express.static(__dirname + 'public/css'))
app.use('/images', express.static(__dirname + 'public/images'))
// Set Templating Engine
app.use(expressLayouts)
app.set('layout', './layouts/full-width')
app.set('view engine', 'ejs')
// Routes
app.get('', (req, res) => {
res.render('index', { title: 'Home Page'})
})
app.get('/about', (req, res) => {
res.render('about', { title: 'About Page', layout: './layouts/sidebar' })
})
// Listen on Port 5000
app.listen(port, () => console.info(`App listening on port ${port}`))
and my i have follow json file
look at my codes
import i18nMiddleware from "i18next-express-middleware";
import { default as i18n } from "i18next";
import Backend from "i18next-node-fs-backend";
i18n
.use(Backend)
.use(LanguageDetector)
.init({
lng: "en",
whitelist: ["en", "fa"],
fallbackLng: "en",
// have a common namespace used around the full app
ns: ["translation"],
debug: false,
backend: {
loadPath: path.join(__dirname + "/locales/{{lng}}/{{ns}}.json")
// jsonIndent: 2
},
preload: ["en", "fa"]
});
this.app.use(i18nMiddleware.handle(i18n));
path locals/en/translate.js
{
"api": {
"events": {
"email": "email",
"fileMimiType": "File mimi type is not allowed",
"fileSize": "File size Can not greater then "
}
}
call it
i18n.t('api.events.email')

An error with __dirname variable in nodejs using express

I have an error with directories and paths.
Look, this is my server config file:
const path = require("path");
const exphbs = require("express-handlebars");
const morgan = require("morgan");
const multer = require("multer");
const express = require("express");
const erroHandler = require("errorhandler");
const routes = require("../routes/index");
module.exports = app => {
app.set("port", process.env.PORT || 3000);
console.log("0. " + __dirname);
let parent = path.normalize(__dirname + "/src/");
console.log("1. " + parent);
app.set('views', path.join(__dirname, '../views'));
let d = app.get("views");
console.log("2. " + d);
app.engine(
".hbs",
exphbs({
extName: ".hbs",
defaultLayout: "main",
partialsDir: [ path.join(__dirname, '../views') ],
layoutDir: path.join(__dirname, '../views', 'layouts'),
helpers: require("../helpers")
})
);
app.set("view engine", ".hbs");
// middlewares
app.use(morgan("dev"));
app.use(
multer({ dest: path.join(__dirname, "../public/upload/temp") }).single(
"image"
)
);
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
//routes
routes(app);
// static files
app.use("/public", express.static(path.join(__dirname, "../public")));
// errorhandlers
if ("development" === app.get("env")) {
app.use(erroHandler);
}
return app;
};
And I get some error like this:
I know it's not the extension but the route. I will show you my directories:
I am getting this error:
Error: ENOENT: no such file or directory, open 'C:\Users\Diesan
Romero\Desktop\redsocial\views\layouts\main.handlebars'
Your path to your layout is incorrect this is what the error message is telling you
looking at your folder structure \Users\Diesan Romero\Desktop\redsocial\views\layouts\main.handlebars should be this: \Users\Diesan Romero\Desktop\redsocial\src\views\layouts\main.handlebars. You are missing the src directory between your redsocial and views directories.
Just declare views folder like this
app.set('views', path.join(__dirname, '../views'));
And change the app.engine like this
app.engine(
".hbs",
exphbs({
extName: ".hbs",
defaultLayout: "main",
partialsDir: [ path.join(__dirname, '../views') ]
layoutDir: path.join(__dirname, '../views', 'layouts'),
helpers: require("../helpers")
})
);
I produced the same error on my side and then fixed it hopefully 90 percent it will do the trick

Why is app.engine not defaulting to layout.hbs as a default

I created a style format with the layout.hbs and notice that all of the pages are not sharing the same consistency in style. I have noticed that I did not declare an app. engine within the app.js. Next, I implemented the app.engine code to set the default layout that is implemented within the layout.hbs
app.engine('hbs', hbs ({extname: 'hbs',defaultLayout: 'layout'}));
An error occurred stating that the layout.hbs cannot be located. I implemented the code again as I noticed I did not direct the folders directories to the layout .hbs. So I implemented the code to
app.engine('hbs', hbs ({extname: 'hbs',defaultLayout: 'layout', layoutsDir:__dirname + '/app_server/views'}));
And the error has disappeared and the default layout structure that has been set to layout.hbs is only showing on the local server index and not the same throughout all of the controllers. I am not too sure what else I am missing
controller and routes code
var express = require('express');
var exphbs = require('express-handlebars');
var router = express.Router();
var ctrlCaribbeanIslands = require('../controllers/CaribbeanIslands')
/* GET home page. */
router.get('/', ctrlCaribbeanIslands.login);
router.get('/blog/add',ctrlCaribbeanIslands.addPost);
router.get('/chat/add',ctrlCaribbeanIslands.addChat);
router.get('/review/add',ctrlCaribbeanIslands.addReview);
router.get('/traceYourTravel', ctrlCaribbeanIslands.tracetravel);
**module.exports = router;**
//controller
module.exports.login = function (req, res) {
res.render('index', { title: 'login'});
};
module.exports.addPost = function(req, res){
res.render('index', { title: 'Add Post' });
};
module.exports.addChat = function(req, res){
res.render('index', { title: 'Add Chat' });
};
module.exports.addReview = function(req, res){
res.render('index', { title: 'Add Review' });
};
module.exports.tracetravel = function(req, res){
res.render('index', { title: 'Trace travel' });
};
app.js
var createError = require('http-errors');
var express = require('express');
var handlebars = require('hbs');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var hbs = require ('express-handlebars');
var indexRouter = require('./app_server/routes/index');
var usersRouter = require('./app_server/routes/users');
var app = express();
app.engine('hbs', hbs ({extname: 'hbs',defaultLayout: 'layout', layoutsDir:__dirname + '/app_server/views'}));
app.set('views', path.join(__dirname, 'app_server','views'));
app.set('view engine', 'hbs');
app.use(express.static(path.join(__dirname, 'public')));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// error handler
app.use(function (err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
#Zrushb Sorry, my bad, it's with app.set, not use. The code should look like this:
const express = require("express"),
hbs = require("hbs"),
mongoose = require("mongoose")
bodyParser = require("body-[arser")
var app = express()
//In ** your database if you need any
mongoose.connect("mongodb:localhost:27017/**")
app.set("view engine", "hbs")
//To get or post
app.set("view engine", "hbs") //Engine HBS
app.set("views", __dirname +"/views") //Folder views (templates)
app.use(express.static("public")) //Public is static (to get .js, images and .css)
app.use('/css',express.static(path.join(__dirname, 'public/stylesheets'))); //Css folder specified (NOT WORKING)
app.use(bodyParser.urlencoded({extended: false})) //Post Body Parser
app.use(bodyParser.json()) //Parser for JSON files
app.use(cookieParser())
hbs.registerPartials(__dirname+ "views/partials")
app.get("/" //etc)
app.post(//etc)
I think express no longer contains handlebars in it, I'd reccomend to download HBS with npm and then require it var hbs = require('hbs')
Then set the view engine to hbs like this -> app.use("view engine", "hbs")
Try that instead of requiring it from express-handlebars, it has worked for me so far.
app.engine('hbs', hbs({
extname: 'hbs',
defaultLayout: 'layout',
layoutsDir:__dirname + '/app_server/views'
}));
change hbs to hbs.engine like this:
app.engine('hbs', hbs.engine({
extname: 'hbs',
defaultLayout: 'layout',
layoutsDir:__dirname + '/app_server/views'
}));
// view engine setup
(01)app.engine('hbs',hbs({extname:'hbs',defaultLayout:'layout',layoutDir:__dirname+'/views/layouts/'}));
(02) app.set('views', path.join(__dirname, 'views'));
(03) app.set('view engine', 'hbs');
change (01) line like this (hbs to hbs.engine):
app.engine('hbs',hbs.engine({extname:'hbs',defaultLayout:'layout',layoutDir:__dirname+'/views/layouts/'}));

can't register handlebar helpers

I'm having trouble registering a custom helper in handlebars.
I've tried anything I could find but nothing works.
here is what I have in app.js
const express= require('express');
const exphbs = require('express-handlebars');
var socket = require('socket.io')
const app=express();
const querystring = require('querystring');
var hbs = exphbs.create({
extname: '.hbs',
defaultLayout: 'default',
layoutsDir: './lib/templates/layouts',
partialsDir: './lib/templates/partials',
helpers: require("./helpers/handlebars.js").helpers
});
app.engine('hbs', hbs.engine);
//Handlebars Middleware
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.use(express.static('public'));
and I have in helpers/handlebars.js this code:
var register = function (Handlebars) {
var helpers = {
formatCurrency: function (currency) {
return currency.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
},
format_date: function (date, format) {
return moment(date).format(format);
}
};
if (Handlebars && typeof Handlebars.registerHelper === "function") {
for (var prop in helpers) {
Handlebars.registerHelper(prop, helpers[prop]);
}
} else {
return helpers;
}
};
module.exports.register = register;
module.exports.helpers = register(null);
(which is an example I found online)
But when I go to my view and try to call this helper:
{{formatCurrency settings.Ngames}}
I get this error:
Error: Missing helper: "formatCurrency"
I've tried also use in Handlebars.register in app.js but it doesn't recognize Handlebars.
What am I doing wrong? How can I register helpers?
Thank you!
You should register the Handlebar helpers.
Posting my full code:
const express = require('express');
const exphbs = require('express-handlebars');
const app = express();
var hbs = exphbs.create({
extname: '.hbs',
defaultLayout: 'default',
layoutsDir: './lib/templates/layouts',
partialsDir: './lib/templates/partials'
});
require("./helpers/handlebars").register(hbs.handlebars);
app.engine('hbs', hbs.engine);
//Handlebars Middleware
app.engine('handlebars', exphbs({ defaultLayout: 'main' }));
app.set('view engine', 'handlebars');
app.use(express.static('public'));
const router = express.Router();
router.get("/hello", function (req, res) {
res.render("index", { layout: false });
});
app.use(router);
app.listen(8080);
The helpers file:
var register = function (Handlebars) {
var helpers = {
formatCurrency: function (currency) {
return currency.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
},
format_date: function (date, format) {
return moment(date).format(format);
}
};
if (Handlebars && typeof Handlebars.registerHelper === "function") {
for (var prop in helpers) {
Handlebars.registerHelper(prop, helpers[prop]);
}
} else {
return helpers;
}
};
module.exports.register = register;

Register assemble handlebars-helpers with Express handlebars

I had a look at this post but it does not come up with a solution: Register Assemble Handlebars Helpers
I want to register all the helpers in https://github.com/assemble/handlebars-helpers to my Express 4 application running express-handlebars.
So far I've tried this but the helpers are not getting registered:
var express = require('express')
, app = express()
, exphbs = require('express-handlebars');
var hbs = exphbs.create({
extname: '.hbs',
defaultLayout: 'default',
layoutsDir: './lib/templates/layouts',
partialsDir: './lib/templates/partials'
helpers: require('handlebars-helpers') // Not registering correctly
});
How does this library work? I'm probably doing it wrong.
Are you supposed to register one at a time or can you load the all helpers?
This working for me:
In app.js:
var exphbs = require('express-handlebars');
var hbs = exphbs.create({
extname: '.hbs',
defaultLayout: 'default',
layoutsDir: './lib/templates/layouts',
partialsDir: './lib/templates/partials'
helpers: require('handlebars-helpers').helpers
});
app.engine('hbs', hbs.engine);
In handlebars-helpers.js:
var register = function (Handlebars) {
var helpers = {
formatCurrency: function (currency) {
return currency.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
},
format_date: function (date, format) {
return moment(date).format(format);
},
...
};
if (Handlebars && typeof Handlebars.registerHelper === "function") {
for (var prop in helpers) {
Handlebars.registerHelper(prop, helpers[prop]);
}
} else {
return helpers;
}
};
module.exports.register = register;
module.exports.helpers = register(null);
In views:
{{formatCurrency settings.phoneNumber}}
Try this:
var express = require('express')
, app = express()
, exphbs = require('express-handlebars')
, hbsHelpers = require('handlebars-helpers');
var hbs = exphbs.create({
//code...
});
hbsHelpers.register(hbs.handlebars, {});
Just want to add a few ideas since this question is already 3 years. I'm using Express 4 as well with express-handlebars (Also nodejs 8.11 LTS). In the app.js (created by express generator).
const exphbs = require('express-handlebars');
const hbsHelpers = require('handlebars-helpers')();
const hbs = exphbs.create({
// Specify helpers which are only registered on this instance.
defaultLayout: 'main',
extname: '.hbs',
helpers: hbsHelpers,
});
app.engine('hbs', hbs.engine);
app.set('view engine', 'hbs');
Tried both above answers but couldn't get them working. But noticed that in the Usage section of handlebars-helpers documentation It says: The main export returns a function that needs to be called to expose the object of helpers.
The express-handlebars create function also support the helpers parameter as an object, such as:
const hbs = exphbs.create({
// Specify helpers which are only registered on this instance.
defaultLayout: 'main',
extname: '.hbs',
helpers: {
tsnumber: () => { return Math.round((new Date()).getTime() / 1000); },
},
});
As you can see in this example, I defined one helper called tsnumber (returns Unix style timestamp), and what helpers get is just an object.
To further extend this functionality by combining the helper I defined (tsnumber) and the express-handlebars, we can use Object.assign.
The new structure will be:
config/hbsHelper.js
node_modules/
app.js
The config directory is a folder I created to combine two libraries.
The content of config/hbsHelper.js is:
const hbsDefaultHelpers = require('handlebars-helpers')();
const extra = {
tsnumber: () => { return Math.round((new Date()).getTime() / 1000); },
};
const merged = Object.assign(extra, hbsDefaultHelpers);
module.exports = merged;
Then in the app.js
const exphbs = require('express-handlebars');
const hbsHelpers = require('./config/hbsHelpers');
const hbs = exphbs.create({
defaultLayout: 'main',
extname: '.hbs',
helpers: hbsHelpers,
});
Solution for hbs:
const hbs = require('hbs');
const app = express();
app.set('view engine', 'hbs');
hbs.registerHelper(require('handlebars-helpers')()); // register extra helpers

Resources