Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular recognize only the default lang in SSR. #163

Open
bcentdev opened this issue May 9, 2019 · 4 comments
Open

Angular recognize only the default lang in SSR. #163

bcentdev opened this issue May 9, 2019 · 4 comments

Comments

@bcentdev
Copy link

bcentdev commented May 9, 2019

I'm submitting a ... (check one with "x")

[x] bug report => Search github for a similar issue or PR before submitting
[ ] feature request => Please check if similar feature request does not exist
[ ] support request => Suggested place for help and support is [stackoverflow](https://stackoverflow.com/), search for similar question before posting

Description

Hello, I have an Angular application with Angular Universal, localize-router and ngx-translate installed. When I navigate in the client side of the website, the languages are working well. I have the default language (es) configured to be hidden in the url and english as secondary language. For example:

es => http://localhost:4000/quotation
en => http://localhost:4000/en/quotation

The problem is that if I deactivate Javascript and force to load the server side of the website, only It works the default language.

es => http://localhost:4000/quotation
en => http://localhost:4000/en/quotation

Even If I try to put the default language in the url, It works too:

es => http://localhost:4000/es/quotation

Node returns me this error in console:

Error: Cannot match any routes. URL Segment: 'en/quotation'

It's like the localize is not well configured but I think that I configured similar to the client side.

🔬 My files

Dependencies of package.json


{
  "dependencies": {
    "@angular/animations": "^7.2.10",
    "@angular/common": "^7.2.12",
    "@angular/compiler": "^7.2.12",
    "@angular/core": "^7.2.12",
    "@angular/forms": "^7.2.12",
    "@angular/http": "^7.2.12",
    "@angular/platform-browser": "^7.2.12",
    "@angular/platform-browser-dynamic": "^7.2.12",
    "@angular/platform-server": "^7.2.12",
    "@angular/router": "^7.2.12",
    "@bugsnag/js": "^6.0.0",
    "@bugsnag/plugin-angular": "^6.0.0",
    "@ng-bootstrap/ng-bootstrap": "^4.1.1",
    "@nguniversal/express-engine": "^7.1.1",
    "@nguniversal/module-map-ngfactory-loader": "^7.1.1",
    "@ngx-translate/core": "^11.0.1",
    "@ngx-translate/http-loader": "^4.0.0",
    "bootstrap": "^4.3.1",
    "classlist.js": "^1.1.20150312",
    "compression": "^1.7.4",
    "cookie-parser": "^1.4.4",
    "core-js": "^2.6.5",
    "express": "^4.16.4",
    "font-awesome": "^4.7.0",
    "jquery": "^3.3.1",
    "localize-router": "^2.0.0-RC.2",
    "localize-router-lazy-universal-module-loader": "^1.0.1",
    "material-design-icons": "^3.0.1",
    "ngx-cacheable": "^1.1.6",
    "ngx-cookie-service": "^2.1.0",
    "ngx-device-detector": "^1.3.5",
    "ngx-owl-carousel-o": "^1.1.1",
    "rxjs": "^6.4.0",
    "rxjs-compat": "^6.4.0",
    "standard-version": "^4.4.0",
    "tslib": "^1.9.0",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.29"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^0.13.8",
    "@angular/cli": "^7.3.8",
    "@angular/compiler-cli": "^7.2.12",
    "@angular/language-service": "^7.2.12",
    "@types/jasmine": "^2.8.16",
    "@types/jasminewd2": "~2.0.3",
    "@types/jquery": "^3.3.29",
    "@types/node": "^8.10.45",
    "angular-router-loader": "^0.8.5",
    "awesome-typescript-loader": "^5.2.1",
    "codelyzer": "~4.5.0",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~3.1.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^2.0.5",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2",
    "nucleus-styleguide": "^1.1.1",
    "protractor": "~5.4.0",
    "ts-loader": "^5.3.3",
    "ts-node": "~7.0.0",
    "tsconfig-paths-webpack-plugin": "^3.2.0",
    "tslint": "~5.11.0",
    "typescript": "~3.1.6",
    "webpack-cli": "^3.3.0"
  }
}

NgModule of app.module.ts


@NgModule({
	declarations: [
		AppComponent,
		CalendarModalComponent,
		TimeSlotModalComponent,
		DiscountModalComponent
	],
	imports: [
		BrowserModule.withServerTransition({ appId: 'frontend' }),
		AppRoutingModule,
		BrowserAnimationsModule,
		CoreModule,
		NgbModule.forRoot(),
		SharedModule,
		TranslateModule.forRoot({
			loader: {
				provide: TranslateLoader,
				useFactory: (http: HttpClient) => {
					return new TranslateHttpLoader(http);
				},
				deps: [HttpClient]
			}
		}),
		LocalizeRouterModule.forRoot(routes,{
			parser: {
				provide: LocalizeParser,
				useFactory: (translate, location, settings) =>
					new ManualParserLoader(translate, location, 
						new LocalizeRouterSettings(false, false, 'LocalStorage', 'LOCALIZE_DEFAULT_LANGUAGE', function(languages, cachedLang, browserLang) {
							return languages[0];
						}), config.languages, ''),
				deps: [TranslateService, Location, LocalizeRouterSettings]
			}
		})
	],
	providers: [
		CookieService,
		{ provide: ErrorHandler, useFactory: errorHandlerFactory },
	],
	bootstrap: [AppComponent],
	entryComponents: [
		CalendarModalComponent,
		TimeSlotModalComponent,
		DiscountModalComponent
	]
})

app.server.module.ts


import { Observable } from 'rxjs';
import { Location } from '@angular/common';
import { Routes } from '@angular/router';
import { LocalizeRouterSettings, LocalizeRouterModule, ManualParserLoader } from 'localize-router';
import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { LazyUniversalModuleLoaderProvider } from 'localize-router-lazy-universal-module-loader';

import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { TranslateService, TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { routes, AppRoutingModule } from './app-routing.module';
import { config } from '@config/config';

let fs = require('fs');

export class TranslateUniversalLoader implements TranslateLoader {
	/**
	 * Gets the translations from the server
	 * @param lang
	 * @returns {any}
	 */
	public getTranslation(lang: string): Observable {
		return Observable.create(observer => {
			observer.next(JSON.parse(fs.readFileSync(`../src/assets/i18n/${lang}.json`, 'utf8')));
			observer.complete();
		});
	}
}

export function translateLoaderFactory() {
	return new TranslateUniversalLoader();
}

export class LocalizeUniversalLoader extends ManualParserLoader {
	/**
	 * Gets config from the server
	 * @param routes
	 */
	public load(routes: Routes): Promise {
		return new Promise((resolve: any) => {
			let data: any = JSON.parse(fs.readFileSync('../src/assets/locales.json', 'utf8'));
			this.locales = data.locales;
			this.prefix = '';
			this.init(routes).then(resolve);
		});
	}
}

export function localizeLoaderFactory(translate: TranslateService, location: Location, settings: LocalizeRouterSettings) {
	return new LocalizeUniversalLoader(translate, location, 
		new LocalizeRouterSettings(false, false, 'LocalStorage', 'LOCALIZE_DEFAULT_LANGUAGE', function(languages, cachedLang, browserLang) {
			return languages[0];
	}), config.languages, '');
}

@NgModule({
	imports: [
		AppModule,
		ServerModule,
		AppRoutingModule,
		ServerTransferStateModule,
		ModuleMapLoaderModule,
		TranslateModule.forRoot({
			loader: {
				provide: TranslateLoader,
				useFactory: translateLoaderFactory
			}
		}),
		LocalizeRouterModule.forRoot(routes,{
			parser: {
				provide: ManualParserLoader,
				useFactory: localizeLoaderFactory,
				deps: [TranslateService, Location, LocalizeRouterSettings]
			}
		})
	],
	providers: [
		LazyUniversalModuleLoaderProvider
	],
	bootstrap: [AppComponent],
})
export class AppServerModule { }

locales.json


{
    "locales": [
        "es",
        "en"
    ]
}

'config.languages' returns...


export const languages = [
	'es', 'en'
];

🌍 Your Environment

Angular Version:


Angular CLI: 7.3.8
Node: 11.13.0
OS: darwin x64
Angular: 7.2.14
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.13.8
@angular-devkit/build-angular     0.13.8
@angular-devkit/build-optimizer   0.13.8
@angular-devkit/build-webpack     0.13.8
@angular-devkit/core              7.3.8
@angular-devkit/schematics        7.3.8
@angular/cli                      7.3.8
@ngtools/webpack                  7.3.8
@schematics/angular               7.3.8
@schematics/update                0.13.8
rxjs                              6.5.1
typescript                        3.1.6
webpack                           4.29.0

Localize Router Version:


"localize-router": "^2.0.0-RC.2"

Anything else relevant?
I have tried to do changes in LocalizeRouterSettings, change ManualParserLoader by ** LocalizeParser**... But nothing.

I have asked to Melisandre, Geralt de Rivia and Gandalf... But nothing...

Who could be my Superman?

Thank you so much!

@gilsdav
Copy link

gilsdav commented May 10, 2019

Hello,

Can you check if it works as expected when you enable alwaysSetPrefix ?

Only these urls have to works :
es => http://localhost:4000/es/quotation
en => http://localhost:4000/en/quotation

Thank's

@bcentdev
Copy link
Author

bcentdev commented May 14, 2019

It doesn't work. Anyway I need to configure it without prefix in the default language.

Thank you.

@gilsdav
Copy link

gilsdav commented May 17, 2019

Hello, Can you check files app-routing.module.ts, app.module.ts and app.server.module.ts from https://github.com/gilsdav/angular-universal-localize-router/tree/master/src/app and unsure you have imports and providers at the same place and with the same order ?

For example LocalizeRouterModule on app-routing.modules.ts and imported after RouterModule

@martinvano
Copy link

any update on this issue? We are experiencing similar symptoms, very often CSR & SSR behavior is not consistent so I am trying to figure what's up before I open a new issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants