기존 코드에 ngx-translate을 설치합니다. 다국어 파일을 httploader를 통해 불러오므로 함께 설치합니다.
npm i @ngx-translate/core @ngx-translate/http-loader
app.config에서 ngx-translate 사용을 설정합니다. 이 때, defaultLanguage를 localstorage에서 가져온 값으로 설정합니다.
...
// src/app/app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { routes } from './app.routes';
// ngx-translate의 HttpLoader를 위한 팩토리 함수
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
// LocalStorage 접근은 브라우저 환경에서만 가능하도록 처리
const defaultLanguage = (typeof window !== 'undefined' && window.localStorage.getItem('lang')) || 'ko';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(), // HttpClientModule 대신 사용
importProvidersFrom(
TranslateModule.forRoot({
defaultLanguage: defaultLanguage,
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
},
})
),
],
};
assets/i18n에 다국어를 위해 ko.json과 en.json을 만들고 값을 넣습니다. (한국어를 길게 넣은 이유는 테스트 결과 확인 시 잘 보이도록 하기 위함입니다.)
// ko.json
{
"lang": "한국어한국어한국어한국어한국어한국어"
}
// en.json
{
"lang": "eng"
}
template에 언어 변경 버튼 및 텍스트를 배치합니다.
// src/app/app.component.ts
import { Component, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, TranslateModule], // TranslateModule과 TranslatePipe를 위해 필요
template: `
<button (click)="changeLanguage('ko')">KO</button>
<button (click)="changeLanguage('en')">EN</button>
<p>{{ 'lang' | translate }}</p>
<router-outlet></router-outlet>
`,
})
export class AppComponent {
private translateService = inject(TranslateService);
constructor() {
// 컴포넌트 초기화 시점에 기본 언어 설정
const lang = localStorage.getItem('lang') ?? 'ko';
this.translateService.setDefaultLang(lang);
this.translateService.use(lang);
}
changeLanguage(lang: string): void {
localStorage.setItem('lang', lang);
this.translateService.use(lang);
}
}
이 상태로 scully를 실행하여 영문으로 변경한 뒤 새로고침을 해보면, static으로 생성된 국문 html 파일이 먼저 생성된 후 변경된 언어가 적용됨을 확인할 수 있습니다. 즉, 목적에서 짚은 현상이 발견 되는 것을 확인할 수 있습니다.
위의 목적을 달성해줄 라이브러리를 설치합니다.
npm i @gilsdav/ngx-translate-router
app.config.ts에 LocalizeRouterModule을 선언합니다. 이 때, 반드시 TranslateService와 RouterModule 이 먼저 선언 되어야 합니다.
// src/app/app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { LocalizeRouterModule, LocalizeRouterSettings, LocalizeParser } from '@gilsdav/ngx-translate-router';
import { routes } from './app.routes';
// ... createTranslateLoader 함수 및 defaultLanguage 정의 (이전과 동일) ...
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
importProvidersFrom(
TranslateModule.forRoot({
defaultLanguage: defaultLanguage,
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
},
}),
// LocalizeRouterModule을 routes와 함께 설정
LocalizeRouterModule.forRoot(routes, {
parser: {
provide: LocalizeParser,
useFactory: (translate: TranslateService, location: Location, settings: LocalizeRouterSettings) =>
new ManualParserLoader(translate, location, settings, ['en', 'ko']), // 지원하는 언어 목록
deps: [TranslateService, Location, LocalizeRouterSettings],
},
initialNavigation: true,
})
),
],
};
이제 scully를 실행하여 영문으로 변경한 뒤 새로고침을 해보면 static 파일이 영문 html이 생성되어 즉시 로딩 된 것을 확인할 수 있습니다. (국문도 동일합니다.)
// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
export const routes: Routes = [
// localized를 적용합니다.
{ path: 'home', component: HomeComponent },
// 적용하지 않습니다.
{
path: 'login',
component: LoginComponent,
data: { skipRouteLocalization: true }
},
// route에는 적용하지 않으나 redirect에만 적용합니다.
{
path: 'logout',
redirectTo: 'login',
data: { skipRouteLocalization: { localizeRedirectTo: true } }
},
// 기본 경로 설정
{ path: '', redirectTo: 'home', pathMatch: 'full' }
];
@ gilsdav/ngx-translate-router는 localized 방식으로 동작합니다. 즉, 모든 언어의 라우터를 생성한 뒤 해당 라우터만 사용하는 방식입니다.
접근하는 시점에서 라우터를 가로 채고 localized된 route를 redirectTo 경로로 변환합니다. 예를 들어 /home은 /ko/home, /en/home 중 ngx-translate이 선택한 경로로 변환합니다.
라우터 변환을 일반 애플리케이션 변환과 분리하기 위해 접두사를 사용합니다. escapePrefix를 사용하여 접두사가 제거되고 세그먼트가 번역되지 않도록 할 수 있습니다.
이 라이브러리는 ngx-translate이 선택한 locales를 자동으로 인식하여 동작합니다.
this.translate.setDefaultLang();
this.translate.use();