tolgee / tolgee-js

Tolgee JavaScript libraries monorepo
https://tolgee.io
MIT License
218 stars 24 forks source link

Angular 17 SSR - Vite bundler throws error because document is not available on Server. #3331

Open CaspianVahagn opened 4 weeks ago

CaspianVahagn commented 4 weeks ago

Angular 17 can utilized Tolgee only on client site. Alone the import of tolgee within SSR context, results in an error:

11:54:41 [vite] Internal server error: document is not defined

Minimal example here: https://stackblitz.com/edit/fuck-yeah-angular-ssr-1e3ut7?file=src%2Fapp%2Fapp.config.ts,angular.json

+-- @angular-devkit/build-angular@17.3.5
+-- @angular/animations@17.3.5
+-- @angular/cli@17.3.5
+-- @angular/common@17.3.5
+-- @angular/compiler-cli@17.3.5
+-- @angular/compiler@17.3.5
+-- @angular/core@17.3.5
+-- @angular/elements@17.3.5
+-- @angular/forms@17.3.5
+-- @angular/platform-browser-dynamic@17.3.5
+-- @angular/platform-browser@17.3.5
+-- @angular/platform-server@17.3.5
+-- @angular/router@17.3.5
+-- @angular/ssr@17.3.5
+-- @tolgee/ngx@5.24.1
+-- @types/express@4.17.21
+-- @types/jasmine@5.1.4
+-- @types/node@18.19.14
+-- jasmine-core@5.1.1
+-- karma-chrome-launcher@3.2.0
+-- karma-coverage@2.2.1
+-- karma-jasmine-html-reporter@2.1.0
+-- karma-jasmine@5.1.0
+-- karma@6.4.2
+-- rxjs@7.8.1
+-- tslib@2.6.2
+-- typescript@5.3.3
`-- zone.js@0.14.3

Since Angular bundler is not extendable via Viteconfig (for now) workarounds with the SDK do not work.

But I could offer an workaround without the SDK, by using @ngx-translate/core and writing a own translation loader that fetches the data from the service / static files.

The custom Translation Loader with a http request to the tolgee api.

import { TranslateLoader } from '@ngx-translate/core';
import { Location } from '@angular/common';
import {  Observable} from 'rxjs';
import { environment } from '../../environments/environment';
import { HttpClient } from '@angular/common/http';

export class TolgeeLoader extends TranslateLoader {
  constructor(
    private location: Location,
    private http: HttpClient,
  ) {
    super();
  }
  getTranslation(lang = "de-DE" ): Observable<any> {
    if (environment.env === 'dev') {
      return this.http.get(
        environment.config.apiHosts.tolgee.url + '/v2/projects/export',
        {
          params: {
            languages: lang,
            format: 'JSON',
            filterNamespace: 'DEFAULT_NS',
            zip: false,
          },
          // ?languages=de-DE&format=JSON&filterNamespace=DEFAULT_NS&zip=false
          headers: {
            accept: '*/*',
            'X-API-Key': environment.config.apiHosts.tolgee.key,
          },
        },
      );
    }

    return this.http.get('/assets/de-DE.json', {
      headers: {
        'x-assets': 'true',
      },
    });
  }
}

in the app.config.ts

import {
  TranslateLoader,
  TranslateModule,
  TranslateService,
} from '@ngx-translate/core';

import { TolgeeLoader } from '../global/translation/TolgeeLoader';

export const appConfig: ApplicationConfig = {
  providers: [
    ...
    TranslateService,
    importProvidersFrom(
      TranslateModule.forRoot({
        loader: {
          provide: TranslateLoader,
          useFactory: (location: Location, http: HttpClient) => {
            return new TolgeeLoader(location, http);
          },
          deps: [Location, HttpClient],
        },
        useDefaultLang: true,
        defaultLanguage: 'de',
      }),
    ),
   ...
  ],
};
JanCizmar commented 3 weeks ago

I will look into this this week hopefully.

JanCizmar commented 1 week ago

I have assigned this to @stepan662, as it seems like an issue with @tolgee/web and dev tools.