localize-router icon indicating copy to clipboard operation
localize-router copied to clipboard

Universal support for latest version of Angular

Open prvn3294 opened this issue 7 years ago • 27 comments

Hi, The example we have with universal is outdated as universal-cli has been deprecated , will it be possible for you to update the example or post a new repository with angular 5 and universal support. :)

Thank you ...!!

prvn3294 avatar Feb 15 '18 11:02 prvn3294

+1 need this

arthurhamon avatar Mar 27 '18 07:03 arthurhamon

+1

MR-MAP avatar Apr 04 '18 10:04 MR-MAP

I did this repo and use it as reference in my company : https://github.com/gilsdav/angular-universal-localize-router

gilsdav avatar Apr 04 '18 19:04 gilsdav

@gilsdav , giving your work a shot. Will update you on the same :)

prvn3294 avatar Apr 09 '18 07:04 prvn3294

@gilsdav David, I tried your repository but its not changing URL while changing the language using button on UI for example I created two buttons of dashboard page and bind it with events like this

`
<button  class="col-1-4" (click)="switchLanguage('en')">English</button>
<button  class="col-1-4" (click)="switchLanguage('fr')">French</button>

<!-- events  -->

switchLanguage(lang) {
      this.localizeService.changeLanguage(lang);
}
`

Any work around or any fixes for this ?

prvn3294 avatar Apr 09 '18 09:04 prvn3294

Please check if #117 solves your problem

meeroslav avatar Apr 10 '18 07:04 meeroslav

Hi @ranavc32, sorry for the inconvenience and thank's for your return. The problem was related to this issue. I downgraded router version to 5.2.6 for now. Check my repo again, I added your switchLang on dashboard page to test if it works.

gilsdav avatar Apr 10 '18 19:04 gilsdav

Thanks @gilsdav . Will give it a try today :) and will update you.

prvn3294 avatar Apr 12 '18 05:04 prvn3294

Hi @gilsdav , So I gave this repository again a shot and everything works fine but only one thing I didn't understand in URL bar its still showing

http://localhost:4200/en/ROUTES.dashboard

So this ROUTES is still there in the URL, how can we just have

http://localhost:4200/en/dashboard

Any help will be appreciated. :)

Though while going through code I saw

export function createTranslateLoader(translate: TranslateService, location: Location, settings: LocalizeRouterSettings,) {
  return new ManualParserLoader(translate, location, settings, ['en', 'fr'], 'ROUTES.');
}

Here you are passing ROUTES to the Manual parser.

prvn3294 avatar Apr 12 '18 12:04 prvn3294

So this problem got resolved when I passed '' to the ManualParser,

export function createTranslateLoader(translate: TranslateService, location: Location, settings: LocalizeRouterSettings,) {
  return new ManualParserLoader(translate, location, settings, ['en', 'fr'], '');
}

Thanks for the solution @gilsdav . Really appreciate your work :)

Happy Coding :)

prvn3294 avatar Apr 12 '18 12:04 prvn3294

Hello @ranavc32 If it put "ROUTES.dashboard" in url this is because it doesn't find this translation in fr.json or en.json files. Take a look at my translation file https://github.com/gilsdav/angular-universal-localize-router/blob/master/src/assets/locales/fr.json . Indeed if you don't need an url translation orther than having the lang like "/fr/", you can remove prefix on ManuelPaserLoader. And thank's for your support :)

gilsdav avatar Apr 12 '18 14:04 gilsdav

Repo updated for Angular 7 : https://github.com/gilsdav/angular-universal-localize-router

gilsdav avatar Nov 16 '18 15:11 gilsdav

Hi @gilsdav I'hve wondering how you managed to make it work the repo https://github.com/gilsdav/angular-universal-localize-router for universal? I've mean, are you setting universal configuration behind the scenes? because I don't see any loader for node server side in that repo, I've tried to set that with my current application and after a lots of error the only that I've got is ERROR [Error] is very annoying.. if you have any idea that was can be happening please let me know. thank you!

BruneXX avatar Sep 14 '19 14:09 BruneXX

Hello @BruneXX ,

Everything related to universal is it these files:

  • package.json all universal dependencies and usage of @gilsdav/ngx-translate-router (that is compatible with angular 8 and SSR). You will find all SSR build scripts too. The entry script is npm run build:ssr.
  • angular.json: need to add a project to point on all server entry files
  • tsconfig.server.json: typescript config for server build and entry module
  • main.server.ts: to avoid some behaviors from main.ts
  • app.server.module.ts: enable server module and lazy-loading feature for ssr
  • app.module.ts: specify that the app will be used with ssr (withServerTransition)
  • environment.ts: set the base URL to find locales (If you don't want to create your own manual loader for SSR (or use UniversalTranslateLoader) you have to use an absolute URL that start with "http://", "https://" and not with "/" because SSR doesn't have the origin to understand relative url).
  • server.ts: my ssr node server
  • webpack.server.config.js: used to package server and all it's dependences to be able to deploy it without package.json and without using npm install command on server.

I think that's all.

I'm currently reviewing a PR that improve Readme for SSR: https://github.com/gilsdav/ngx-translate-router/pull/35/files Do not hesitate if something is not clear before the merge.

Regards

gilsdav avatar Sep 14 '19 18:09 gilsdav

OK, thanks for the quick reply @gilsdav ! I've some things, I saw that:

  1. LazyUniversalModuleLoaderProvider is not longer used in app.server.module.ts, will be needed anyway?
  2. It's mandatory to use webpack.server.config.js in order this to work? because I'm not doing anything of that, I'm just using the default provided in angular.json for deploy.
  3. The server.ts that I'm using is the same as https://github.com/angular/universal-starter/blob/master/server.ts should that work or need to do some changes in order localize routes work?
  4. Also for locales, I'm using relative path, just '/assets/locales' not he environment behavior (anyway I've tried that, but did not solve my problem)

I've tried to integrate in the same you're doing in this repo: https://github.com/gilsdav/angular-universal-localize-router but I can't figured out, what's the difference with my own and why I'm getting that annoying ERROR [Error] in console with nothing else but that...

I've reviewed all those files you mentioned in your previous note, I've practically cloned the repo into mine, I've used meld to compare files and get all things wired up, but with no success yet.

Anyway, thanks for you help, I'll try to do this again from scratch checking each file you mention in the previous note and try to figured out what can be happening.

If you see something else that could be the culprit of that error just let me know, also the documentation here: https://github.com/Greentube/localize-router differs a bit from the: https://github.com/gilsdav/angular-universal-localize-router repo and I had to say that I saw some errors in that last one:

Here is an image with the error and some part of the URI that is not translated from the demo: issue_with_universal_localized_route_demo

Thanks again for the quick response, appreciated!

BruneXX avatar Sep 14 '19 18:09 BruneXX

Also reviewing the PR, something that is not clear to me at all is this code that AFAIK should be in server.ts: (Please correct me if I am worng)

app.get('/', ngApp);
    data.locales.forEach(route => {
      app.get(`/${route}`, ngApp);
      app.get(`/${route}/*`, ngApp);
    });

From where comes ngApp? I saw deeply in some other repo code, I think from this one: https://github.com/meeroslav/universal-localize-example/blob/master/src/server.ts, that is used as an aside function, but is that up to date? or should be reviewed to be included into the documentation? becuase including that funciton in my case was worst.. but I haven't seen some kind of that code in the https://github.com/gilsdav/angular-universal-localize-router repo.

Thanks!

BruneXX avatar Sep 14 '19 18:09 BruneXX

  1. LazyUniversalModuleLoaderProvider is not needed anymore for Angular 8
  2. ng add @nguniversal/express-engine --clientProject ... command creates the webpack file
  3. I don't think there is something particularly for Localize.
  4. relative url will not works on SSR so you have to implement a workaround for it. I prefer to use absolute url instead of other possibilities because we can quickly put our localization files on other assets server accessible by the client.

For errors:

  1. In can not reproduce the "home" path when "fr". How did you access to that ? Did you tried
  2. I didn't have implemented all the application (there is no "localize" pipe on this list)

For the locales.json you can see I didn't implemented it in my project. I really recommend manualLoader. This workaround is if you really need to create "dynamic" languages.

Does your error only append in node console ?

gilsdav avatar Sep 14 '19 19:09 gilsdav

Hi @gilsdav

  1. OK great!
  2. OK, I assume that's needed, right?
  3. OK.
  4. OK, I'll use full path from now

Errors:

  1. I've just cloned the repo, then executed npm install and then ng serve just the usual..
  2. OK

Yes, I've realized that, I'll need to use dynamic languages.

Yes, It finish the compilation and serve the app, but when I go to the browser and just access to localhost:4200 or whatever route related to the app, the browser is hang on and that error appears in console and there's no more info, just that.

BruneXX avatar Sep 14 '19 20:09 BruneXX

@BruneXX 2. This is needed in most cases (example: deployment on cloud provider) because you can only drop files. Without webpack post build you must have npm on the server and include the dev package.json into the package to be able to install dependences. Otherwise the application will not works on server (but will works locally).

Errors:

  1. Try with npm start to use the project instance of Angular-Cli (I personally always do that). I don't know your version but I tried with last version of Angular CLI and can not reproduce :/

Can you try with same version of all universal dependences than in my project into yours ?

gilsdav avatar Sep 14 '19 20:09 gilsdav

@gilsdav About that, I'm using docker to get those things sorted, so may be that's not necessary. (I guess) because I've all dependencies needed inside the container.

Yes, I've also updated angular dependencies in package.json of your project, I'll give a try to discard that the error comes from there, but I'm pretty sure that is something related to the server.ts file I don't know why yet, but I think it comes from there, but as I saw there are no changes needed there, right? I had to apply some change in server.ts to add [domino] and some other globals, did you have some issues with that before?

BruneXX avatar Sep 14 '19 20:09 BruneXX

@BruneXX You can check const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./server/main');. The generated one (in my current CLI version) is const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');

Check your DIST_FOLDER too. I don't have any reference to "dist" in my repos:

  • https://github.com/gilsdav/aa-universal-workshop/blob/done/server.ts
  • https://github.com/gilsdav/angular-universal-localize-router/blob/master/server.ts

As you can see in the PR (new doc) you must set window.navigator.language = 'en'; (for "en" default lang) if you use [domino]

And finally if you add "node_Modules" into your .dockerignore your image will be widely smaller. Its up to you to choose.

gilsdav avatar Sep 14 '19 20:09 gilsdav

@gilsdav yep, I've realized about that too, but for me only works as is in: https://github.com/angular/universal-starter/blob/master/server.ts

const DIST_FOLDER = join(process.cwd(), 'dist');
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');

I'll try to use that in your repo and check what happens.

PS: also another difference that I've found is that I'm not using import 'reflect-metadata'; in my repo. But I think that will not affect at the current behavior.

BruneXX avatar Sep 14 '19 21:09 BruneXX

@gilsdav well well.. I've got the error :) something more explainatory I guess:

ERROR HttpErrorResponse { headers: HttpHeaders { normalizedNames: Map {}, lazyUpdate: null, headers: Map {} }, status: 0, statusText: 'Unknown Error', url: 'http://localhost:4200/assets/locales/en.json', ok: false, name: 'HttpErrorResponse', message: 'Http failure response for http://localhost:4200/assets/locales/en.json: 0 Unknown Error',

Now regarding this new issue is totally related with docker.. I need a way to map the container ip with the full path for routes, but I'm glad to say that it works!! thanks for all your help @gilsdav I've spent a lot of time trying to make this work and finally I've get it!

Best regards!

BruneXX avatar Sep 15 '19 05:09 BruneXX

Hi @gilsdav I've a question regarding the languages that are set in the url, so for example: Is there a way in your package to set the language without add it in the url like this?

https://{domain}.com/es
https://{domain}.com/en
https://{domain}.com/fr

So I can set the route language at level component for example?

Thanks!

BruneXX avatar Sep 16 '19 17:09 BruneXX

Hi @BruneXX, I'm not sure I clearly see your goal but I will try to be the more complete.

Default lang

As you can see in the documentation, the default lang will be automaticaly set with this logic: languageFromUrl || cachedLanguage || languageOfBrowser || firstLanguageFromConfig. So if you go to https://{domain}.com the application will automatically redirect to https://{domain}.com/fr using the previous logic.

Translate paths

You don't have to put the language into your paths because this.localize.translateRoute(...) and | localize will do it for you.

Do not translate url

You can use skipRouteLocalization route option if you don't want to translate some urls.

Don't use prefix

You can use alwaysSetPrefix: false option but I give no guarantee on it because I don't test it. Keep in mind that if you change lang, the lang will be added to the URL. Only default lang can be removed from urls.

For me the main behavior of this library is to add the lang into URL (like Microsoft do https://docs.microsoft.com), and the second behavior is to translate each segments of the URL.

gilsdav avatar Sep 16 '19 18:09 gilsdav

Hi @gilsdav Great explanation! My main concern is to not use the prefix, but there's no way to totally remove the /{lang} from url, right?

I was wondering to do that, in order to use a subdomain instead of an url "/{lang}" something like:

en.{domain}.com/my-route
es.{domain}.com/mi-ruta

but currently that's not possible since you told me in previous comment.

So may be we can report that as a new feature to improve (and may be add) the non-prefix behavior?

Thanks for all your help on this! :)

BruneXX avatar Sep 16 '19 19:09 BruneXX

@BruneXX That's the deference between Angular I18n and ngx-translate.

  • i18n: generate a dist by language to allow you to deploy it on deferent domains.
  • ngx-translate: dynamic language loading to keep same domain.

localize-router and ngx-translate-router are only compatible with ngx-translate.

gilsdav avatar Sep 17 '19 05:09 gilsdav