nodejs i18next is not translating string - node.js

I have this err:authentication:invalid_token in json file. folder is setup as locales/vi_VN/mynamespace-vi_VN.json. However, it's not translating in the console.log below.
Any idea why?
i18n.init({
debug: true,
preload: ['vi_VN'],
resGetPath: 'locales/__lng__/__ns__-__lng__.json',
lng: 'en_GB',
ns: 'mynamespace',
sendMissingTo: 'fallback',
fallbackLng: 'en_GB'
}, function(err, t) {
console.log('i18n is initialized.')
console.log('Translation on:', t('err:authentication:invalid_token', {
lng: 'vi_VN'
}))
})

My bad, i was using colon : in identifier. I need to change it to something else or put it in appropriate namespace

Related

i18next - Loading translations from a JSON file

I'm trying to load translations from a JSON file using i18next library on Node. The path of the JSON file points to the correct location.
I'm getting the following error:
i18next::translator: missingKey en translation test test
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
const instance = i18next.use(Backend).createInstance({
lng: config.language,
debug: true,
fallbackLng: 'en',
initImmediate: false,
backend: {
loadPath: join(__dirname, `${config.language}.json`),
},
}, (error, t) => {
console.log(t('foo'));
});
JSON file:
{
"foo": "bar"
}
Specifying the translations directly in createInstance using resources property works perfectly.
I tried everything I could think of, with no success.
Found the solution!
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
const instance = i18next.use(Backend).createInstance();
instance.init({
lng: config.language,
debug: true,
fallbackLng: 'en',
initImmediate: false,
backend: {
loadPath: join(__dirname, `${config.language}.json`),
},
}, (error, t) => {
console.log(t('foo'));
});

Structure of object is being modified during POST request

So I send a post request using needle with the following object as body:
{ time: 1533725993910,
rconPort: 52940,
rconPassword: 'muqrxllv',
serverPort: 38950,
unique: 795571399,
publicIP: 'localhost',
mods:
[ { modName: 'clusterio_1.0.0.zip',
hash: '341feb6c60918c83f7f3a6a14a4a308aef18dda6' },
{ modName: 'clusterio_1.13.1.zip',
hash: '6124bb9d3896b030fafbef07c971314f4640759f' },
{ modName: 'clusterio_1.13.0.zip',
hash: '3dde5199f63d87e3e6ea6ef7f522e0df5842dee4' },
{ modName: 'hotpatch-multimod_1.1.4.zip',
hash: '0a780e23c42452bd51ecc5ce808b65842e77dc85' },
{ modName: 'creative-mode_0.0.1.zip',
hash: '9af437c10d3f39f1f3ffb57c942c3a51d3786f0f' },
{ modName: 'clusterio_1.12.0.zip',
hash: '959c82380cad1a6f039de401a98dd70e13ca2224' } ],
instanceName: 'test',
playerCount: '0' }
When I console.log(req.body) in the Express handler I get
{ time: '1533722833600',
rconPort: '52940',
rconPassword: 'muqrxllv',
serverPort: '38950',
unique: '795571399',
publicIP: 'localhost',
mods: [ { modName: [Array], hash: [Array] } ],
instanceName: 'test',
playerCount: '0',
mac: '00-FF-8C-0F-21-F0' }
Upon closer inspection it turns out that the "mods" field now looks like this:
"mods":[{
"modName":[
"clusterio_1.0.0.zip",
"clusterio_1.13.0.zip",
"clusterio_1.13.1.zip",
"hotpatch-multimod_1.1.4.zip",
"creative-mode_0.0.1.zip",
"clusterio_1.12.0.zip"
],"hash":[
"341feb6c60918c83f7f3a6a14a4a308aef18dda6",
"3dde5199f63d87e3e6ea6ef7f522e0df5842dee4",
"6124bb9d3896b030fafbef07c971314f4640759f",
"0a780e23c42452bd51ecc5ce808b65842e77dc85",
"9af437c10d3f39f1f3ffb57c942c3a51d3786f0f",
"959c82380cad1a6f039de401a98dd70e13ca2224"
]}]
For logging the data on the server side I use
var app = express();
app.use(bodyParser.json());
app.use((req,res,next) => {
if(req.originalUrl == "/api/getID"){
console.log(req.body)
}
next()
});
On the client side I do
console.log(payload);
needle.post('localhost:8080/api/getID', payload, needleOptionsWithTokenAuthHeader, function (err, response, body) {
At first I suspected this was an issue with middleware, but as I am logging before all the middleware gets loaded I am not too sure about that anymore.
I have never experienced anything like this, and any help would be appreciated.
Have you tried to use the function JSON.stringify (doc) ?
Formating POST request with tables can be tricky.
To send an object like {a:1, b:{c:2, d:[3, 4]}, e:[5,6]} you have to format your parameters to fit an array associative, so the parameters will be like this:
a=1
b[c]=2
b[d][0]=3
b[d][1]=4
e[0]=5
e[1]=6
To fill a non-associative array you can try the e[]=7 notation.

Console.log(err) is crashing my website

I'm currently a student studying Web Development with Node. I recently was reviewing RESTful routes. I was building a blog site to do so. I was setting up a route to show a specific blog "/blogs/:id" which lets you see all the contents of a blog. Here's the route:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
When I access the route using the browser, it loads forever and I get the following error in the terminal:
{ CastError: Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"
at MongooseError.CastError (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/error/cast.js:29:11)
at ObjectId.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schema/objectid.js:158:13)
at ObjectId.SchemaType.applySetters (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:724:12)
at ObjectId.SchemaType._castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1113:15)
at ObjectId.SchemaType.castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1103:15)
at ObjectId.SchemaType.castForQueryWrapper (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1082:15)
at cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/cast.js:303:32)
at Query.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:3355:12)
at Query._castConditions (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1327:10)
at Query._findOne (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1552:8)
at process.nextTick (/home/ubuntu/workspace/RESTful/node_modules/kareem/index.js:333:33)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
message: 'Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"',
name: 'CastError',
stringValue: '"app.css"',
kind: 'ObjectId',
value: 'app.css',
path: '_id',
reason: undefined,
model:
{ [Function: model]
hooks: Kareem { _pres: [Object], _posts: [Object] },
base:
Mongoose {
connections: [Object],
models: [Object],
modelSchemas: [Object],
options: [Object],
_pluralize: [Function: pluralize],
plugins: [Object] },
modelName: 'blog',
model: [Function: model],
db:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
options: null,
otherDbs: [],
relatedDbs: {},
states: [Object],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
_connectionOptions: [Object],
client: [Object],
name: 'restful_routing_revision',
'$initialConnection': [Object],
db: [Object] },
discriminators: undefined,
'$appliedMethods': true,
'$appliedHooks': true,
schema:
Schema {
obj: [Object],
paths: [Object],
aliases: {},
subpaths: {},
virtuals: [Object],
singleNestedPaths: {},
nested: {},
inherits: {},
callQueue: [],
_indexes: [],
methods: {},
methodOptions: {},
statics: {},
tree: [Object],
query: {},
childSchemas: [],
plugins: [Object],
s: [Object],
_userProvidedOptions: {},
options: [Object],
'$globalPluginsApplied': true,
_requiredpaths: [] },
collection:
NativeCollection {
collection: [Object],
opts: [Object],
name: 'blogs',
collectionName: 'blogs',
conn: [Object],
queue: [],
buffer: false,
emitter: [Object] },
Query: { [Function] base: [Object] },
'$__insertMany': [Function],
'$init': Promise { [Object], catch: [Function] } } }
But for some reason, when I change the callback to be the following:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
res.redirect("/")
} else{
res.render("show", {body: blog});
}
})
})
The website works perfectly fine. I also tried removing the header from the show.ejs(the file being rendered when accessing the route) while keeping the console.log(err) and it also solved the problem. I tried removing the header because the header contains the tag that links the app.css file which I saw mentioned in the error. I would like to know what's wrong in console.log(err) with the css file.
p.s. I am using Expres for the routes and mongoose to access the MongoDB database. "blog" is the array of blogs. Incase you want to take a look at my show.ejs file, here it is:
<% include partials/header %>
<h1><%= body.title%></h1>
<img src="<%=body.image%>">
<p><%=body.body%></p>
<div><%=body.created%></div>
<% include partials/footer %>
And if you want to take a look at the app.css file, here it is:
img{
max-width: 600px;
width: 600px;
}
And if you want to take a look at the header.ejs file, here it si:
<!DOCTYPE html>
<html>
<head>
<title>Blogs Website</title>
<link rel="stylesheet" type="text/css" href="app.css">
</head>
<body>
Here is the full app.js file (the file containing the routes):
var express = require("express"),
app = express(),
mongo = require("mongoose"),
bodyParser = require("body-parser"),
expressSanitizer = require("express-sanitizer"),
methodOverride = require("method-override");
mongo.connect("mongodb://localhost/restful_routing_revision");
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(methodOverride('_method'));
var blogSchema = new mongo.Schema({
title: String,
body: String,
image: String,
created: {type: Date, default: Date.now}
});
var blog = mongo.model("blog", blogSchema);
app.get("/", function(req, res){
res.render("landing");
});
app.get("/blogs", function(req, res){
blog.find({}, function(err, body){
if(err){
console.log(err)
}else{
res.render("index", {blogs: body})
}
})
})
app.get("/dogs/new", function(req, res){
res.render("new");
})
app.post("/dogs", function(req, res){
var blogBody = req.body.blog;
blog.create(blogBody, function(err, body){
if(err){
console.log(err)
}else{
res.redirect("/blogs")
}
})
})
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
// res.redirect("/")
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
// blog.findById(req.params.id, function(err, blog){
// if(err){
// res.redirect("/");
// } else {
// res.render("show", {body: blog});
// }
// });
// });
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server has Started!!!!");
})
There are alot of npm packages on top that I'm planning to use later. And I know that the blog Schema isn't well formatted. I also tried doing console.log(err) and res.redirect("/") at the same time, I arrive to the show page but still get the same error.
Just use absolute path /style.css instead of relative path style.css.
Explanation:
You are using app.use(express.static("public")); which will make the route app.get("/blogs/:id", function(req, res){...}); when triggered it tries to render style.css in your html link tag because it meets the route path as /blogs/style.css since your public folder is in the same level with blogs, so by putting / in front of style.css makes it an absolute path, so execution will start the path from the seed, and not continue down from blogs.
Another solution is to just handle triggering the route blogs/style.css by actually creating a route for it as follows:
app.get('/campgrounds/app.css', function(req, res) {
break;
});
Make sure to put it before the route app.get("/blogs/:id", function(req, res){...}); to be executed first, if triggered.
I hope this helps.
Regarding the CastError, I don't know what is going on in the underlying ejs code that causes it to try to run a Mongo query with the css filename, but this post explains how to fix your syntax (read the answer's comments about using a relative path for the css name):
NodeJS error when rendering page:Cast to ObjectId failed for value "styles.css" at path "_id"
I think that will get rid of the error in your endpoint.
For the headline question about crashing the server and the observation that:
When I access the route using the browser, it loads forever
is because the endpoint does not ever issue a response to the client when you get an error. All endpoints need to respond to the client in some way. In your case, the documented1 recommendation is to call the Express middleware function next:
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err);
next(err);
} else{
The next function will return an error result to the client browser. You need to use next because the .find function of your Mongoose model is asynchronous and Expresses next function is designed to deal with this correctly.
A separate detail, from what you posted, your Express server is most likely not crashing. It is logging the console message with an error just like you asked then continuing on waiting for new requests (logging an error to the console is perfectly ok!). If it crashed, you would likely get a 500 error page in the browser and the node process would terminate. I mention this in hopes to help future debugging. I think if you had searched on the client issue of the endpoint not returning, you would likely have found an existing answer about endpoints that never return to the client (this is a common issue to run into when getting started). I hope that helps!
Express Error Handling Doc
You have to put this line at the end
In app.js file
cut this line and paste it at the end:
app.use(express.static("public"));

Accessing Loopback config data from middleware

Say we are in Loopback middleware, such as
app.use(function(req,res,next){
// I am not sure what key to use here in the getter...
const config = app.get('?');
});
I want to access the overall config that Loopback is using.
I tried:
const config = app.get('config');
const config = app.get('env');
const config = app.get('datasources');
nothing gives me quite what I want.
Interestingly, this gives me:
console.log(app.get('restApiRoot'));
=> '/api'
so that's a clue to what's going on, but I want to get the parent object(s) for the above data.
how can we access the configuration that Loopback has loaded. The configuration of course varies by environment variables etc.
I want to log what datasources.x.js file was loaded and what config.x.js file was loaded, and any other server configuration info I can capture.
Having a lot of trouble figuring out how to do this.
This seems to be the same question I have:
https://github.com/strongloop/loopback/issues/1526
but they point me to the void that is Google Groups and I searched through there and couldn't find what the answer to this question.
This behavior is actually inherited from Express.
The entire config is stored in the app.settings object, with app.get(key) and app.set(key,value) just acting as getter/setter.
Doing console.log(app.settings); (in server/server.js for instance) it on a fresh loopback install returns the following:
{ 'x-powered-by': true,
etag: 'weak',
'etag fn': [Function: wetag],
env: 'development',
'query parser': 'extended',
'query parser fn': [Function: parseExtendedQueryString],
'subdomain offset': 2,
'trust proxy': false,
'trust proxy fn': [Function: trustNone],
view: [Function: View],
views: 'C:\\Users\\*******\\Documents\\GitHub\\lbtest\\views',
'jsonp callback name': 'callback',
host: '0.0.0.0',
port: 3000,
restApiRoot: '/api',
remoting:
{ context: { enableHttpContext: false },
rest: { normalizeHttpPath: false, xml: false },
json: { strict: false, limit: '100kb' },
urlencoded: { extended: true, limit: '100kb' },
cors: false,
errorHandler: { disableStackTrace: false } },
legacyExplorer: false,
'loopback-component-explorer': { mountPath: '/explorer' },
url: 'http://localhost:3000/' }

u18next node setLng seems that doesn´t work

I am getting a problem with the module i18next for node.js (using express). I initialize (on the app.js file) the module in this way:
i18n.init({
ns: { namespaces: ['text'], defaultNs: 'text'},
resSetPath: 'locales/__lng__/new.__ns__.json',
preload: ['es', 'uk', 'fr', 'ge', 'ru', 'it'],
saveMissing: true,
debug: true,
lng:"es",
sendMissingTo: 'fallback',
useCookie: false,
detectLngFromHeaders: false,
detectLngFromPath: false
});
and on the routes files I make something like this:
router.get('/not_registered', function(req, res) {
console.log("users.js-> user.get-> init lang: " + req.session.lang);
req.i18n.setLng(req.session.lang, function(t)
{
console.log("users.js-> user.get-> inside function");
res.render('users/user');
});
});
The first console.log works, but not the second... What am I doing wrong?? Any help??
Thank you.
SOLUTION I FOUND
Finally, I saw that the i18n.setLng function doesn´t use a callback... the only I needed to do was:
req.i18n.setLng(req.session.lang);
res.render('users/user');
Thanks #Alexandr

Resources