이 가이드에서는 Angular 애플리케이션에서 ngx-translate를 사용하여 다국어 처리를 구현하는 방법을 다룹니다. NgModule 방식과 Standalone 방식을 모두 지원하며, 엔터프라이즈급 애플리케이션을 위한 고급 설정 옵션과 모범 사례를 설명합니다.
필요한 의존성 패키지 설치:
npm install @ngx-translate/core @ngx-translate/http-loader --save
// app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, 'assets/i18n/', '.json');
}
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
defaultLanguage: 'ko-KR',
useDefaultLang: true
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { importProvidersFrom } from '@angular/core';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, 'assets/i18n/', '.json');
}
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(),
importProvidersFrom(
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
defaultLanguage: 'ko-KR',
useDefaultLang: true
})
)
]
}).catch(err => console.error(err));
// app.component.ts
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { LanguageService } from './services/language.service';
@Component({
selector: 'app-root',
standalone: true,
imports: [
CommonModule,
TranslateModule
],
providers: [LanguageService],
template: `
<div [innerHTML]="'common.welcome' | translate"></div>
`
})
export class AppComponent {
// standalone은 이 코드를 사용
languageService = inject(LanguageService);
// module은 이 코드를 사용
constructor(private languageService: LanguageService) {
this.languageService.initialize();
}
}
// interfaces/language.interface.ts
export enum LanguageCode {
'en-US' = 'English',
'ko-KR' = '한국어',
'zh-CN' = '简体中文',
'ja-JP' = '日本語'
}
export interface TranslationKeys {
common: {
welcome: string;
login: string;
logout: string;
};
errors: {
required: string;
invalid: string;
};
}
// services/language.service.ts
import { Injectable, inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LanguageCode } from '../interfaces/language.interface';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class LanguageService {
// standalone은 이 코드를 사용
languageService = inject(LanguageService);
private currentLang = new BehaviorSubject<string>(null);
currentLang$ = this.currentLang.asObservable();
// module은 이 코드를 사용
constructor(private translateService: TranslateService) {}
initialize(): void {
const languages = Object.keys(LanguageCode);
this.translateService.addLangs(languages);
const browserLang = this.translateService.getBrowserLang();
const defaultLang = languages.find(lang =>
browserLang.toLowerCase() === lang.toLowerCase()
) || 'ko-KR';
this.translateService.setDefaultLang(defaultLang);
this.setLanguage(defaultLang);
}
setLanguage(lang: keyof typeof LanguageCode): void {
this.translateService.use(lang);
this.currentLang.next(lang);
}
getCurrentLang(): Observable<string> {
return this.currentLang$;
}
}
// assets/i18n/ko-KR.json
{
"common": {
"welcome": "애플리케이션에 오신 것을 환영합니다",
"login": "로그인",
"logout": "로그아웃"
},
"errors": {
"required": "필수 입력 항목입니다",
"invalid": "잘못된 입력값입니다"
}
}
// 템플릿 사용 예시
@Component({
template: `
<div [innerHTML]="'notifications.welcome' | translate:{ username: currentUser.name }"></div>
`
})
// 번역 파일
{
"notifications": {
"welcome": "{{username}}님, 환영합니다!"
}
}
@Component({
selector: 'app-language-switcher',
standalone: true,
imports: [CommonModule, TranslateModule],
template: `
<select (change)="onLanguageChange($event)" [value]="currentLang$ | async">
<option *ngFor="let lang of languageCodes" [value]="lang">
{{ LanguageCode[lang] }}
</option>
</select>
`
})
export class LanguageSwitcherComponent {
// standalone은 이 코드를 사용
languageService = inject(LanguageService);
protected readonly LanguageCode = LanguageCode;
protected readonly languageCodes = Object.keys(LanguageCode);
protected currentLang$ = this.languageService.getCurrentLang();
// module은 이 코드를 사용
constructor(private languageService: LanguageService) {}
onLanguageChange(event: Event): void {
const lang = (event.target as HTMLSelectElement).value as keyof typeof LanguageCode;
this.languageService.setLanguage(lang);
}
}
성능 최적화
타입 안전성
유지보수
HTML 콘텐츠 처리
중첩된 HTML 요소
// 잘못된 방법
<div>{{ 'key.with.html' | translate }}<span>추가 내용</span></div>
// 올바른 방법
<div [innerHTML]="'key.with.html' | translate"></div>
<span>추가 내용</span>
비동기 번역 로딩
// 번역 로딩 상태 처리
this.translateService.get('key').subscribe({
next: (translation: string) => {
// 번역 성공 처리
},
error: (err) => {
console.error('번역 오류:', err);
// 대체 처리
}
});
라우트 가드
@Injectable({ providedIn: 'root' })
export class TranslationLoadGuard implements CanActivate {
// standalone은 이 코드를 사용
translateService = inject(TranslateService);
// module은 이 코드를 사용
constructor(private translateService: TranslateService) {}
canActivate(): Observable<boolean> {
return this.translateService.get('common.welcome')
.pipe(map(() => true));
}
}
에러 처리
@Injectable({ providedIn: 'root' })
export class GlobalErrorHandler implements ErrorHandler {
// standalone은 이 코드를 사용
translateService = inject(TranslateService);
// 모듈은 이 코드를 사용
constructor(private translateService: TranslateService) {}
handleError(error: Error): void {
this.translateService.get('errors.unexpected')
.subscribe(message => {
// 번역된 메시지로 에러 처리
});
}
}