Steps to reproduce:
Login to https://jhipster-4-demo.herokuapp.com/ with user/user.
Click on Entities > Blog and notice how the page title is translation-not-found[blogApp.blog.home.title].

Refresh your browser and it renders properly.

Click on Entities > Entry and see the same behavior.

This looks like an asynchronous issue, maybe related to Observable in TranslatePartialLoader when it combines partial translations for newly visited entity page with already loaded transaltions.
I replaced ng-jhipster MissingTranslationHandler by mine which logs on console.
I get many missing translations logged (twice per menu item) when I go from an entity page to home page even though the page displays correctly.
Also in the log below, you can see the request to get the json translation.
Console output
XHR finished loading: GET "http://localhost:9000/i18n/en/home.json". missing-i18n.ts:5 missing translation footer missing-i18n.ts:5 missing translation footer missing-i18n.ts:5 missing translation global.menu.account.main missing-i18n.ts:5 missing translation global.menu.account.main missing-i18n.ts:5 missing translation global.title missing-i18n.ts:5 missing translation global.title missing-i18n.ts:5 missing translation global.menu.home missing-i18n.ts:5 missing translation global.menu.home missing-i18n.ts:5 missing translation global.menu.language missing-i18n.ts:5 missing translation global.menu.language missing-i18n.ts:5 missing translation global.ribbon.dev missing-i18n.ts:5 missing translation global.ribbon.dev missing-i18n.ts:5 missing translation global.menu.entities.main missing-i18n.ts:5 missing translation global.menu.entities.main missing-i18n.ts:5 missing translation global.menu.entities.rankingList missing-i18n.ts:5 missing translation global.menu.entities.rankingList missing-i18n.ts:5 missing translation global.menu.entities.tournamentType missing-i18n.ts:5 missing translation global.menu.entities.tournamentType missing-i18n.ts:5 missing translation global.menu.entities.tournament missing-i18n.ts:5 missing translation global.menu.entities.tournament missing-i18n.ts:5 missing translation global.menu.entities.countryMedal missing-i18n.ts:5 missing translation global.menu.entities.countryMedal missing-i18n.ts:5 missing translation global.menu.entities.medal missing-i18n.ts:5 missing translation global.menu.entities.medal missing-i18n.ts:5 missing translation global.menu.entities.doubleMatch missing-i18n.ts:5 missing translation global.menu.entities.doubleMatch missing-i18n.ts:5 missing translation global.menu.entities.singleMatch missing-i18n.ts:5 missing translation global.menu.entities.singleMatch missing-i18n.ts:5 missing translation global.menu.entities.player missing-i18n.ts:5 missing translation global.menu.entities.player missing-i18n.ts:5 missing translation global.menu.entities.ratingMovement missing-i18n.ts:5 missing translation global.menu.entities.ratingMovement missing-i18n.ts:5 missing translation global.menu.entities.tournamentPlayer missing-i18n.ts:5 missing translation global.menu.entities.tournamentPlayer missing-i18n.ts:5 missing translation global.menu.entities.rating missing-i18n.ts:5 missing translation global.menu.entities.rating missing-i18n.ts:5 missing translation global.menu.admin.database missing-i18n.ts:5 missing translation global.menu.admin.database missing-i18n.ts:5 missing translation global.menu.admin.main missing-i18n.ts:5 missing translation global.menu.admin.main missing-i18n.ts:5 missing translation global.menu.admin.userManagement missing-i18n.ts:5 missing translation global.menu.admin.userManagement missing-i18n.ts:5 missing translation global.menu.admin.metrics missing-i18n.ts:5 missing translation global.menu.admin.metrics missing-i18n.ts:5 missing translation global.menu.admin.health missing-i18n.ts:5 missing translation global.menu.admin.health missing-i18n.ts:5 missing translation global.menu.admin.configuration missing-i18n.ts:5 missing translation global.menu.admin.configuration missing-i18n.ts:5 missing translation global.menu.admin.audits missing-i18n.ts:5 missing translation global.menu.admin.audits missing-i18n.ts:5 missing translation global.menu.admin.logs missing-i18n.ts:5 missing translation global.menu.admin.logs missing-i18n.ts:5 missing translation global.menu.account.settings missing-i18n.ts:5 missing translation global.menu.account.settings missing-i18n.ts:5 missing translation global.menu.account.password missing-i18n.ts:5 missing translation global.menu.account.password missing-i18n.ts:5 missing translation global.menu.account.logout missing-i18n.ts:5 missing translation global.menu.account.logout missing-i18n.ts:5 missing translation global.menu.admin.apidocs missing-i18n.ts:5 missing translation global.menu.admin.apidocs XHR finished loading: GET "http://localhost:9000/i18n/en/global.json".
One way to simplify our TranslateLoader and to avoid partial async loading would be to merge all our i18n JSON files per language, this way we would load all translations at once.
I have been able to do it using webpack core json-loader and a plugin: merge-jsons-webpack-plugin
~~~js
const MergeJsonWebpackPlugin = require("merge-jsons-webpack-plugin");
...
{
// Load i18n files
test: /\.json$/,
loader: 'json-loader',
include: path.resolve('./src/main/webapp/i18n')
},
...
// Merge i18n files per language
new MergeJsonWebpackPlugin({
'output': {
'groupBy':[
{
'pattern': './src/main/webapp/i18n/en/*.json',
'fileName' : './target/www/i18n/en.json'
},
{
'pattern': './src/main/webapp/i18n/fr/*.json',
'fileName' : './target/www/i18n/fr.json'
},
]
}
}),
~~~
I am also investigating an alternative with #5072.
I think I found why pageTitle is not translated first time.
pageTitle is set on NavigationEnd event so before reaching the entity component, the location for translations related to this entity is added in the constructor of the component using jhiLanguageService.setLocations() so it's too late.
A solution for this would be to call jhiLanguageService.setLocations() in a CanActivate guard but I prefer to go with my proposition to use webpack merging json files because it will simplify things and be more performant too.
@deepu105 as you coded the TranslatePartialLoader, what's your opinion?
Yes another caveat of ng router as we used to do it in ui router resolve b4
and worked well.
Also ok to serve a merged json if possible but it would be nice to keep the
files separated for dev else it will endup becoming a single huge file
Thanks & regards,
Deepu
I tried to define a componentless parent route where to add the resolve. It worked fine except for popup routes where I could not remove the auxilliary route from url upon closing the modal. This looks like a bug of the router in ApplyRedirects, I may try to add a unit test to report the issue.
One way to simplify our TranslateLoader and to avoid partial async loading would be to merge all >our i18n JSON files per language, this way we would load all translations at once.
This should probably solve one problem I had. From entity A dialog (non modal page) open a modal dialog for (a new) entity B - that causes the non modal page texts (under the popup) to change to "translation not found"...
I solved it by adding locations for both entities, ie:
jhiLanguageService.setLocations(['A', 'B']);
Good point, we already had to add more locations for social signin for same reason: a view aggregates messages from several i18n files (different entities or different features).
While your case could probably easily be addressed at generation time because we know all entities related to the current entity and so could call setLocations() with correct list, it's very likely that we cannot guess what kind of aggregations our users will build so we could make their life simpler by having a full i18n bundle per language.
@mraible This is not happening in the current build. I believe this can be closed.
Tested with JHipster v4.0.8 via https://github.com/mraible/jhipster4-demo and it appears to be fixed.
@gmarziou Is it possible to implement this solution in the existing JHipster project? I have successfully combined JSON files using configuration you provided, but it still searches for the translation files by component name..
I also removed from the webpack.common.js under CopyWebpackPlugin line { from: './src/main/webapp/i18n', to: 'i18n' }.
I get: http://localhost:9000/i18n/en/global.json 404 (Not Found) error, and like that for every translation file..
It is really annoying because I am using nested components and translation only loads for the last imported component.. For parent component I get translation-not-found error.. So, I have to use combined file..
Have you checked #5689 ?
@gmarziou Didn't see that.. :) It took me a few hours to solve conflicts but after upgrade everything works fine.. Thanks..! :+1: