1
  1. My frontend - Angular 12. I am using server side rendering and everything was working fine.

  2. Client has requested to add i18n support (en & ko lang). I Followed https://angular.io/guide/i18n-overview. Also added language switcher.

Deployed on apache (Without SSR) everything again is working fine. (mysitename.com/en & mysitename.com/ko)

  1. Now when I try to build / deploy (2 locales sites -en, ko) with SSR the problem starts. I have added below for browser & server targets inside angular.json

    "localize:true" 
    
  2. Modified server.ts to change the views (I was getting node error saying index.html is not found for specified Views)

     const distFolder = join(process.cwd(), 'dist/ecokrypt-uiapp/browser/en');
     server.set('views', distFolder);
    
  3. SSR build gives me below structure inside /dist folder

     /dist/myappname/
    
     .../browser
    
     ....../en
    
     ....../ko
    
    
     .../server
    
     ....../en
    
     ....../ko
    

6)node server starts properly, but browser gives below error and page does not get loaded completely.

Brrowser console

  1. I am bit confused and lost here - how to incorporate SSR + i18n with locales together. Tried to search a lot on google.

I want

mysitename.com OR mysitename.com/en => to redirect to english and

mysitename.com/ko => to redirect to korean

How to achieve SSR + 2 lang support together ?

user2869612
  • 607
  • 2
  • 10
  • 32

1 Answers1

0

Are you using @ngx-translate? I have a project setup like this, which works as expected. The language is in the query parameters.

I did have to split up my AppModule in an AppServerModule and an AppBrowserModule. So you'll need to update your main.ts too:

main.ts:

platformBrowserDynamic(providers).bootstrapModule(AppBrowserModule)

app.server.module.ts

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: () => {
          return new TranslateJsonLoader();
        }
      }
    })
  ],
  bootstrap: [AppComponent]
})
export class AppServerModule {}

app.browser.module.ts

@NgModule({
  imports: [
    AppModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (http: HttpClient) => {
          return new TranslateHttpLoader(http);
        },
        deps: [ HttpClient ]
      }
    })
  ],
  bootstrap: [AppComponent]
})
export class AppBrowserModule {}

Both import the AppModule, which contains everything else of your app.

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    TranslateModule.forChild(),
    AdvancedRouterModule,

    AppRoutingModule,
  ],
  providers: [
    // If you wish to preserve the `lang` query parameter, and drop the `return` query parameter
    {
      provide: QUERY_PARAMS_CONFIG,
      useValue: <QueryParamsConfig>{
        'lang': 'preserve',
        'return': ''
      }
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

translate-json-loader.ts

import { TranslateLoader } from '@ngx-translate/core';
import { of } from 'rxjs';
import * as translationEn from '../../assets/i18n/en.json';
import * as translationNl from '../../assets/i18n/nl.json';

export class TranslateJsonLoader implements TranslateLoader {
  constructor() {
  }

  public getTranslation(lang: string) {
    switch (lang) {
      case 'nl': {
        return of(translationNl);
      } break;
      default: {
        return of(translationEn);
      } break;
  }
}}

Change the language through navigation:

<a [advRouterLink]='[]' [queryParams]="{'lang':'nl'}" class="mx-2" title="Nederlands">
    Nederlands
</a>

The AppComponent keeps an eye on the lang query parameter, and changes the language:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor(
    private route: ActivatedRoute,
    private translateService: TranslateService,
  ) {
    const defaultLang = 'en';
    this.translateService.setDefaultLang(defaultLang);
    this.route.queryParamMap.subscribe((params) => {
      let lang = params.get('lang');
      if (lang === null) {
        this.translateService.use(defaultLang);
      } else {
        this.translateService.use(lang);
      }
    });
  }
}

As far as I remember, that's it.

Pieterjan
  • 2,738
  • 4
  • 28
  • 55