Access i18next Translation in Function not in App.js - node.js

Im using ExpressJS and i18next.
in app.js
var express = require('express')
, i18n = require('i18next')
, user = require('./routes/user')
...
//internationalization
i18n.init({
lng: 'en-US',
saveMissing: true,
debug: true
});
...
app.use(i18n.handle);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
...
i18n.registerAppHelper(app);
...
app.post('/users/save', user.save);
I can access the translation in jade:
t('app.title')
How can I access the translation in routes.user.js
exports.save = function(req, res){
//t('app.title')
}

t is available in your route handlers as res.locals.t. This should work in Express 3 and 2 as well.

i18next-express-middleware -> the translation function could be accessed through req.i18n.t or just req.t. but obviously it's under res.locals.t too - to be accessible in templates.

Related

Handlebars registerHelper serverside with Expressjs

I am using expressjs with handlebars as templating engine with following code in Webstorm IDE with express generator.There is no visible handlebars require in the code (I guess express generator has it someplace else which is not visible)
var app = express();
.
.
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
How do i use registerHelper on serverside in this situation ?
My other renderings and partials are working.So handlebars is doing its work.Its just that registerHelper seems to be cause of worry.
I have given a thumbs up to #Mukesh Sharma as he very nearly had the syntax that worked for me and really led me to it.
He is doing a bit more to make it work for the front end I believe. All I needed was the following
// index.js
//in the declarations
const exphbs = require('express-handlebars');
//when configuring the app view engine
app.engine('.hbs', exphbs({
extname: '.hbs',
helpers: require('./config/handlebars-helpers') //only need this
}));
app.set('view engine', '.hbs');
Then I have a simple file I include from where I have helper stuff .
// config/handlebars-helpers.js
module.exports = {
ifeq: function(a, b, options){
if (a === b) {
return options.fn(this);
}
return options.inverse(this);
},
bar: function(){
return "BAR!";
}
}
No need to pass or import handlebars-express - including the simple object of helper functions as part of the exhbs options hash under helpers lets express hbs do all of the registering by it's own approach.
(Bonus ifeq is a tiny helper that compares two arguments and will show the block if true .. useful for something like:
class = "{{#ifeq thisUrl '/about'}}active{{/ifeq}}" .. to set a nav pill class as 'active' )
found it here https://gist.github.com/pheuter/3515945
I think express-generator just sets view engine to hbs only. To configure the hbs engine, you have to use express-handlebars.
e.g.
var app = express(),
exphbs = require("express-handlebars");
app.engine("hbs", exphbs({
defaultLayout: "main",
extname: ".hbs",
helpers: require("./public/js/helpers.js").helpers, // same file that gets used on our client
partialsDir: "views/partials/", // same as default, I just like to be explicit
layoutsDir: "views/layouts/" // same as default, I just like to be explicit
}));
app.set("view engine", "hbs");
And, helpers.js
var register = function(Handlebars) {
var helpers = {
// put all of your helpers inside this object
foo: function(){
return "FOO";
},
bar: function(){
return "BAR";
}
};
if (Handlebars && typeof Handlebars.registerHelper === "function") {
// register helpers
for (var prop in helpers) {
Handlebars.registerHelper(prop, helpers[prop]);
}
} else {
// just return helpers object if we can't register helpers here
return helpers;
}
};
module.exports.register = register;
module.exports.helpers = register(null);
Source: http://www.codyrushing.com/using-handlebars-helpers-on-both-client-and-server/
You can register both your own customer helpers and the ones from 'handlebars-helpers' like this:
const hbshelpers = require('handlebars-helpers');
const multihelpers = hbshelpers(['object', 'string']);
const helpersDM = {
hlp: echo => `Echo: ${echo}.`,
STATIC: `/static`,
};
const hbs = exphbs.create({
layoutsDir: join(__dirname, 'views', 'layouts'),
partialsDir: join(__dirname, 'views', 'partials'),
extname: '.hbs',
defaultLayout: 'base',
helpers: {...multihelpers, ...helpersDM},
});
app.engine('.hbs', hbs.engine);
app.setViewEngine('.hbs');
I was able to add partial and register a helper using hbs.
Seems to be it is the same view engine used within express for templating with handlebars.
According to hbs docs, add the following to the entry point of the application: (index.js or app.js) and before setting the view engine in express.
index.js
const hbs = require('hbs');
const express = require('express');
hbs.registerHelper('number_format', function (option) {
// option :
// will contain the arguments passed
// to the helper from the template
// computation can be done here
return `USD ${option}`;
});
hbs.registerPartial('partial', function (options, ...rest) {
// options :
// will contain the arguments passed
// to the partial from the template
// as a object (key value pair)
// ex:
console.log(option.argOne) // 1
console.log(option.argTwo) // 2
// ----------
// Have a look at the other arguments like context data
console.log(...rest)
// computation can be done here by using argument values
return `partial value: ARG1:: ${option.argOne} & ARG2:: ${option.argTwo}`;
});
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
Partial in a hbs template file
<h1>
{{>partial argOne=1 argTwo=2 }}
</h2>
above will generate the following,
<h1>partial value: ARG1:: 1 & ARG2:: 2<h1>
Helper in a hbs template file
<h1>{{number_format 100 }}</h1>
above will generate the following,
<h1>USD 100</h1>
learn more about handlebars partials using their docs on partials

Rendering a view without res.render

Following the documentation:
https://github.com/ericf/express-handlebars
I have a need to compile a template, but not using the documented method of res.render('myView'), because in my context there is not res.
This is what I have so far:
var express = require('express')
, exphbs = require('express-handlebars');
, hbs = exphbs.create({
extname: '.hbs',
defaultLayout: 'default'
});
app.use(express.static('public'));
app.engine('hbs', hbs.engine);
app.set('view engine', 'hbs');
var tplVars = {
id: 12345,
name: 'John Doe'
}
hbs.handlebars.compile( .. path to pdf.hbs ... )(vars);
Now, obviously I need to register the template. What is missing here?
My file structure in /views:
views/
layouts/
default.hbs
partials/
css.hbs
pdf.hbs
Copy paste from the comment above.
I don't think you can compile templates with express-handlebars, but you can do so with handlebars.
Details in a previous answer here.

Parse Cloud Hosting with Express and Handlebars Templates

There is a node package for using handlebars templates in Express.js, express-handlebars, but I'd like to be able to use the same package in a Parse Cloud Hosting project. The only discussion I can find about how to make it work is here, and it's painfully brief: https://parse.com/questions/dynamic-website-handlebars-for-template-engine
The last comment mentions specifying the 'cloud' directory 'to the required command for a lot of dependent modules'. The author does not explain how he did that, and the thread is now closed.
After following the install instructions I have this in my main app.js file:
var express = require('express');
var exphbs = require('express-handlebars');
var parseExpressCookieSession = require('parse-express-cookie-session');
var home = require('cloud/routes/home');
var register = require('cloud/routes/register');
var login = require('cloud/routes/login');
var app = express();
// Configure the app
app.set('views', 'cloud/views');
app.set('view engine', 'hbs');
app.engine('hbs', exphbs({
extname: 'hbs',
defaultLayout: 'layouts/main.hbs'
}));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('ABCDEFG1234567'));
app.use(parseExpressCookieSession({ cookie: { maxAge: 3600000 }}));
app.use(app.router);
// Define all the endpoints
app.get('/', home.index);
app.get('/register', register.new);
app.post('/register', register.create);
app.get('/login', login.new);
app.post('/login', login.create);
app.get('/logout', login.destroy);
app.listen();
My file structure looks like this:
cloud
└──routes
└──views
└──layouts
└──main.hbs
└──home
└──index.hbs
└──register
└──new.hbs
└──login
└──new.hbs
config
node_modules
public
package.json
All route files are a slight variation of this:
exports.index = function(req, res){
res.render('home/index');
};
Running my app results in the following error:
Error: Failed to lookup view "home/index"
With the default 'ejs' templates, the app runs fine. Personally, I'm fine with ejs templates, but it's not up to me. Handlebars are what's required of the project, so that's what I'm out to accomplish. Thanks!

Get request url in server.js file. Node.js

I have server.js file where i define my server and all settings.
And i need to define request url before declaring those settings. Because i need to define them depend on request url.
An example:
var siteDir = ((app.route).lastIndexOf('/admin', 0) === 0) ? '/admin' : '/client';
app.engine('ejs', require('ejs-locals'));
app.set('views', __dirname + ('/template' + siteDir));
app.set('view engine', 'ejs');
So, if request url begins with 'admin' i will load templates from admin folder, otherwise from client.
My current implementation doesn't work, because app.route always returns '/'.
What can i do here. Please give me some advises. Thanks in advanced.
You cannot set the views directory per request with Express, which is what you're trying to do.
But you can use subdirectories in your calls to res.render():
app.get('/admin/', function(req, res) {
res.render('admin/index'); // renders '__dirname + /template/admin/index.ejs'
});
app.get('/', function(req, res) {
res.render('client/index'); // renders '__dirname + /template/client/index.ejs'
});
you can write your own middleware for this.
Something like this:
var siteDir = "/client"; //default case;
app.use(function(req,res,next){
if(req.path == '/admin') siteDir = '/admin';
else siteDir = '/client';
next();
});
app.engine('ejs', require('ejs-locals'));
app.set('views', __dirname + ('/template' + siteDir));
app.set('view engine', 'ejs');

Jade URL Routing in Node Express

I am building a Node Express application using Jade, and I am confused about how to route my views to the specific requests the browser will make. I understand that in order to get URLs to work in the browser, we need to use Node's routes; however, from looking online, I have discovered that Express has its own router.
I used PHPStorm to start up my project, and the index.jade will load... but how do I load the others? Here is my existing code:
var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path');
var app = express();
app.configure(function ()
{
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(require('less-middleware')({ src:__dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function ()
{
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function ()
{
console.log("Express server listening on port " + app.get('port'));
});
What is the most basic way to route my application, and where can I find more extensive documentation on this topic?
Thanks.
I understand that in order to get URLs to work in the browser,
we need to use Node's routes; however, from looking online,
I have discovered that Express has its own router.
Node.js per-se does not provide support for "routes", but Express does. You build your routes in Express using the following syntax:
app.[verb]('[url-path]', [handler]);
So your route app.get('/', routes.index) will process HTTP GET request to URL path / with the routes.index function. Express will automatically pass a request and response objects to your handler.
You can add more routes like this:
app.get('/users', routes.userList);
app.get('/user/:id', routes.userInfoView);
app.post('/user/:id', routes.userInfoSave);
You can find more information about this here http://expressjs.com/api.html#app.param
I am building a Node Express application using Jade, and I
am confused about how to route my views to the specific
requests the browser will make.
Once a route handler is invoked, say (routes.userList) you can call res.render() method inside userList to render the Jade file that you want. For example:
res.render('user_list',
{ users: [{name: "user1", age: 10}, {name: "user2", age: 20}] });
See here for more information: http://expressjs.com/api.html#res.render

Resources