i18next is not loading the translation file - backbone.js

I am working on some Backbone based project where i am using i18next for locales.
Following is my app.js code:
/*
This file is used to initialize your application.
*/
require(['i18n','application','handlebars_Helpers'], function(i18n, Application) {
i18n.init({
lng: 'en',
debug: true,
fallbackLng: false,
load:'unspecific',
resGetPath: "locales/__lng__/__ns__.json",
ns: {
namespaces: ['translation']
}
});
(new Application()).initialize();
});
Translation file:
{
"loginModule": {
"signin": "Sign In"
}
}
Following is my helper file:
/**
* Set of generic handlebars helpers
*/
define(['i18n'], function(i18n) {
/**
* This helper provides i18Next in templates
*
*
* Usage: span {{t "my.key" }}
*/
Handlebars.registerHelper('t', function(i18n_key) {
var result = i18n.t(i18n_key);
return new Handlebars.SafeString(result);
});
return Handlebars;
});
When i am loading my page through localhost it shows me following message in console:
currentLng set to: en i18n.js:490
GET http://localhost:8000/locales/en/translation.json?_=1374495189376 404 (Not Found) i18n.js:376
failed loading: locales/en/translation.json
Don't understand what i am missing? or why this error is show?

In which folder do you store translations file? Default behavior for i18n is, that it tries to find localization file in specific path: /locales/{lang-code}/{namespace}.json
If you keep file in root, try to change initialization code to following:
i18n.init({
lang: 'en',
debug: true,
fallbackLng: false,
load:'unspecific',
resGetPath: "__ns__-__lng__.json",
ns: {
namespaces: ['translation'],
defaultNs: 'translation'
}
});
This will try to load file from following url: http://localhost:8000/translation-en.json
Basically, try to check location of translations file, name of translation file and construct 'regGenPath' accordingly, more info can be found in i18n documentation http://i18next.com/node/pages/doc_init.html

Related

Can I put the locales folder containing JSON files for each language in a custom directory outside public folder while using react-i18next? How to do?

Can I put the locales folder containing JSON files for each language in a custom directory outside public folder while using react-i18next? How to configure the same?
I am also using lazy loading and caching.
Things work when the locales folder is inside public folder like this:
But does not work as soon as I move it outside public folder like this:
No luck after changing loadPath also.
My i18n.js looks like this:
`
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import ChainedBackend from "i18next-chained-backend";
import HttpBackend from "i18next-http-backend";
import LocalStorageBackend from "i18next-localstorage-backend";
i18n
.use(initReactI18next)
.use(ChainedBackend)
.init({
lng: 'hi_IN',
interpolation: {
escapeValue: false,
},
react: {
useSuspense: true,
},
saveMissing: true,
backend: {
backends: [
LocalStorageBackend,
HttpBackend
],
backendOptions: [{
expirationTime: 7 * 24 * 60 * 60 * 1000
}, {
loadPath: '../src/locales/{{lng}}/{{ns}}.json',
}]
}
});
export default i18n;
`
Thank you.
I tried changing loadPath and addPath, I searched through StackOverflow and Google. Went through the docs, but no luck.

lazy loading on i18n react questions

I am working in a project where we are using modules with lazy loading to separate it, now we would like to separate also the translations into the different modules, so only the translations that belogn to that module get loaded.
currently we have the translations as it follows:
translations
--en
--de
--it
--sp
we would like to have sth like this now:
translations
--en
|--moduleA
|--moduleB
|--moduleC
--it
|--moduleA
|--moduleB
|--moduleC
etc,
I have been throug the documentation and tried the 'useTranslation (hook)' and 'withTranslation', both dont seem to work since they load all the translations in the specified ns anyway and after take what is received when calling i18n, I also hada look at the i18next-http-backend but the documentation do not specify how to use it very clearly.
basically I am missing some information about how to use it, but as per my findings seems the only posible solution, am I wrong?.
after installing the dependancy I have my i18n as followns:
import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import moment from 'moment'
import HttpApi from 'i18next-http-backend'
import request from 'superagent'
import {EN} from './translations/eng'
import {test} from './translations/test'
i18n
.use(LanguageDetector)
.use(HttpApi)
.init({
backend: options,
resources: {
en: {
translations: EN,
translations2: test,
},
},
fallbackLng: 'en',
ns: ['translations', 'translations2'],
defaultNS: 'translations',
keySeparator: false,
interpolation: {
escapeValue: false,
formatSeparator: ',',
format: function(value, formatting) {
if (value instanceof Date) return moment(value).format(formatting)
return value.toString()
},
},
react: {
wait: true,
},
})
the backend key is expecting some options information:
const options = {
loadPath: 'path to file',
addPath: 'path to file',
allowMultiLoading: false,
parse: function(data) {
return data.replace(/a/g, '')
},
parsePayload: function(namespace, key, fallbackValue) {
return {key}
},
request: function(options, url, payload, callback) {},
}
But I am not really sure about the way how to use it,I wanted to know if someone has experience with this and if someone can recomend any guide or documentation that might help me.
thanks
I think you may be looking for Namespaces:
Namespaces are a feature in i18next internationalization framework which allows you to separate translations that get loaded into multiple files.
While in a smaller project it might be reasonable to just put everything in one file you might get at a point where you want to break translations into multiple files. Reasons might be:
You start losing the overview having more than 300 segments in a file
Not every translation needs to be loaded on the first page, speed up load time

Unable to use JSON from S3 buck in i18next

This is how my i18n file looks like -
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import HttpApi from 'i18next-http-backend';
i18n
.use(HttpApi)
.use(initReactI18next)
.init({
// resources: resourcesObj,
initImmediate: false,
backend: {
loadPath: 'https://bucketlink.amazonaws.com/locales/{{lng}}/{{ns}}.json',
crossDomain: true,
allowMultiLoading: true,
},
lng: "en",
fallbackLng: "en",
debug: false,
ns: ["translations"],
defaultNS: "translations",
keySeparator: false,
interpolation: {
escapeValue: true
}
});
export default i18n;
When I change the language I see i my Network tab that the JSON is coming from S3 properly. Though, the key is being displayed instead of values in all my screen. Can someone let me know why my translation values are not displaying.
Note -- If I use resources and put my json object inside of it, it works as expected.
From the demo that you've posted, the problem is that your json files (the ones that are stored in s3) are not in the right format.
You need to split the json file by lang & namespace (translations in your case), and the json files must contain only the keys that are relevant to the lang & namespace.
For example, your folder should look like:
└── locales
├── en
│   └── translations.json
└── he
└── translations.json
and each translation.json file should contain:
{
"Overview": "Overview",
"TaskList": "Task List"
}
PS, your translation files can be a nested object, then you will need to specify the key with a dot notation (something like a.b.c)

React i18next Backend-Path different in local and production environment

I'm using a react app with react-i18next and loading the translation with i18next-xhr-backend
i18n
.use(Backend)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: "de",
backend: {
loadPath: '/static/locales/{{lng}}/{{ns}}.json'
}
});
If I run it locally my app is served over http://localhost:3000/
and the translation file is also loading nicely (src is located in public/statuc/locales/ ) http://localhost:3000/static/locales/de/translation.json
I'm now facing the issue that in production the app is not served from root, instead the builded files are served over a subfolder. Because of that I changed my packages.json and added homepage
{
"name": "myapp",
"version": "0.1.0",
"homepage": "/static/app/",
...
}
After building the application and deploying it on prod, it still loads correctly, but the translation files are not found.
http://production.tld/static/app/index.html
react app files are loaded correctly http://production.tld/static/app/static/js/main*.js
but the translation file is still fetched by http://production.tld/static/locales/de/translation.json which is not available anymore (instead http://production.tld/static/app/static/locales/de/translation.json would be correct)
I could fix it by changing the i18n config
backend: {
loadPath: '/static/app/static(locales/{{lng}}/{{ns}}.json'
}
then it works in production, but not locally anymore :-/
I'm not sure how to avoid this situation ?
You can pass loadPath as function.
backend: {
loadPath: () => {
// check the domain
const host = window.location.host;
return (host === 'production.ltd' ? '/static/app':'') + '/static/app/static/locales/{{lng}}/{{ns}}.json';
},
},
Another solution would be to work with environment variables. Only the condition would be different and without a function, the idea is like #felixmosh's solution.
An example with create-react-app, here you can use the environment variable 'NODE_ENV' for the condition.
i18n.use(XHR)
.use(initReactI18next)
.init({
backend: {
loadPath:
process.env.NODE_ENV !== "production"
? `./locales/{{lng}}/{{ns}}.json`
: ` /static/app/static/locales/{{lng}}/{{ns}}.json`,
},
lng: "de",
fallbackLng: "de",
load: "languageOnly",
debug: true,
react: {
transSupportBasicHtmlNodes: true,
transKeepBasicHtmlNodesFor: ["br", "strong", "i", "sub", "sup", "li"],
},
});
Here the documentation of create-react-app
https://create-react-app.dev/docs/adding-custom-environment-variables
Here's a follow-along question that may deserve its own top-level question:
it appears that if your locales directories have dashes in the name (e.g. locales/en-us/translation.json), then things don't work. How are we supposed to get around that? I stumbled on this answer because I thought perhaps I could do something along the lines of:
loadPath: (lng, ns) => { return `/locales/{{lng.replace(/-/g,'')/{{ns}}.json` }
But during my initial testing, that didn't work.

i18next always returning missing key

Every time I try to translate I get i18next::translator: missingKey es-AR
This is my pug
component.pug
.headersGroup
h2(ng-i18next="{{$ctrl.getFilterTitle()}}")
h3(ng-i18next="landing.name")
I tried to translate in two ways. From the pug file and from the controller.
component.js
getFilterTitle () {
return this.$i18next.t('landing.title')
}
I not even interpolating or anything. Just a basic translation.
es-AR.json
{
"landing": {
"title" : "Filtros",
"name" : "Principales"
}
}
This is my init
window.i18next
.use(window.i18nextXHRBackend);
window.i18next.use(window.i18nextLocalStorageCache);
window.i18next.init({
debug: '!{env}' !== 'production',
lng: config.locale, // If not given, i18n will detect the browser language.
fallbackLng: false,
backend: {
loadPath: '/
myApp/build/i18n/{{lng}}/{{ns}}.json'
},
cache: {
enabled: true,
prefix: 'i18next_experts_',
expirationTime: 7 * 24 * 60 * 60 * 1000,
versions: {}
},
useCookie: false,
useLocalStorage: false
}, function (err, t) {
console.log(err, t);
});
Rather sure you render (call t function) before i18next loaded the translations.
Check the console output...do you get those missing log entries before there is the backend loaded message?

Resources