어떻게 Angular Universal과ngxtranslate를 사용하여 검색엔진의 우호적인 국제화 웹 응용 프로그램을 만듭니까
검색 엔진 최적화(SEO)는 여러 각도의 단일 페이지 응용 프로그램(SPA)에 있어 매우 중요하다.당신은 Angular Universal로 SEO의 우호적인 Angular 사이트를 구축할 수 있지만, 어떻게 하면 당신의 응용 프로그램이 당신의 사이트에서 지원하는 모든 언어에서 SEO에 우호적일 수 있습니까?구글, Yandex, 바이두는 당신의 페이지에 영어, 스페인어, 러시아어 또는 중국어를 사용하도록 요구할 수 있습니다. 당신은 어떻게 당신의 서버에 정확한 언어를 되돌려 줄 수 있습니까?
답은 ngx-translate, Angular의 국제화(i18n와 현지화 라이브러리입니다.이 모듈은 번역 파일을 쉽게 사용하여 클라이언트와 서버 측의 렌더링에 정확한 언어를 제공할 수 있습니다.이 글은 너에게 그것을 어떻게 사용하는지 보여줄 것이다.
이 글에서 우리는 다음과 같이 할 것이다.
Node.js and npm(Node.js 설치도 npm을 설치합니다.
Angular 프로젝트를 설정하고 Hello World를 실행합니다!
각 Angular 항목은 설치 및 초기화 패키지에서 시작됩니다.명령 프롬프트에서 다음을 입력합니다.
ng new angular-universal-i18n --style css --routing false
항목을 초기화한 후 디렉토리로 이동합니다.cd angular-universal-i18n
다음을 입력하여 응용 프로그램을 실행합니다.ng serve -o
콘솔에서 다음 출력을 볼 수 있습니다.** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
Date: 2018-10-29T08:58:37.685Z
Hash: cb54e4608cfb1115882b
Time: 7682mschunk {main} main.js, main.js.map (main) 10.7 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 227 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 5.22 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 15.9 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.29 MB [initial] [rendered]
-o
플래그가 기본 브라우저에서 응용 프로그램을 엽니다.(Chrome 버전 63 이상에서 유효한 보안 인증서가 없는 HTTP 링크와 사이트(예를 들어 localhost)를 열기 위해 로고를 설정해야 합니다.명령 출력에 제공된 URL을 수동으로 탐색할 수 있습니다.브라우저에서 다음 화면을 볼 수 있습니다.
Angular Universal을 사용하여 서버 측 렌더링
현재, 우리는 Angular Universal 서버 측의 렌더링을 응용 프로그램에 추가하려고 합니다. 이것은 서버에서 웹 페이지를 렌더링하는 기술이기 때문에 검색 엔진 파충류는 당신의 웹 페이지를 신속하고 쉽게 읽을 수 있습니다.설치하려면 다음 명령을 수행합니다.
ng add @ng-toolkit/universal
서버 측 렌더링이 제대로 작동하는지 확인
응용 프로그램을 실행하고 볼륨 요청을 실행하여 Angular Universal이 제대로 작동하는지 확인합니다.
npm run build:prod;npm run server
curl http://localhost:8080
curl을 사용하지 않으려면 브라우저에서 URL을 열고 페이지 원본 코드를 검사할 수 있습니다.결과는 다음과 같습니다.<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>angular-universal-i18n</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.3bb2a9d4949b7dc120a9.css">
<style ng-transition="app-root">
/*# sourceMappingURL=data:application/json;
base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzcmMvYXBwL2FwcC5jb21wb25lbnQuY3NzIn0= */
</style></head>
<body>
<app-root _nghost-sc0="" ng-version="7.0.4"><div _ngcontent-sc0="" style="text-align:center"><h1 _ngcontent-sc0=""> Welcome to angular-universal-i18n! </h1>
...
</div>
<h2 _ngcontent-sc0="">Here are some links to help you start: </h2>
<ul _ngcontent-sc0="">
<li _ngcontent-sc0="">
<h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://angular.io/tutorial" rel="noopener" target="_blank">Tour of Heroes</a></h2>
</li>
<li _ngcontent-sc0="">
<h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://github.com/angular/angular-cli/wiki" rel="noopener" target="_blank">CLI Documentation</a></h2>
</li><li _ngcontent-sc0="">
<h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://blog.angular.io/" rel="noopener" target="_blank">Angular blog</a></h2>
</li></ul></app-root>
<script type="text/javascript" src="runtime.ec2944dd8b20ec099bf3.js"></script><script type="text/javascript" src="polyfills.c6871e56cb80756a5498.js"></script>
<script type="text/javascript" src="main.f27bf40180c4a8476e2e.js"></script>
<script id="app-root-state" type="application/json">{}</script>
</body></html>
다음 단계를 따르려면 다음과 같이 하십시오.git clone https://github.com/maciejtreder/angular-universal-i18n.git
cd angular-universal-i18n
git checkout step1
npm install
ng serve -o
ngxtranslate를 사용하여 응용 프로그램에 국제화 추가
우리는 우리의 응용 프로그램이 세계 각지의 사용자에게 더욱 우호적이다.이를 실현하기 위해 우리는 ngx-translate library로 국제화(i18n)를 추가할 것이다.우리는 우리의 사이트 방문자에게 클릭할 수 있는 링크를 제공할 것이다. 그들은 이 링크를 사용하여 서로 다른 번역 사이를 전환할 수 있다.이 번역들은 불러옵니다.각 언어의 json 파일은
ngx-translate
에서 제공합니다.translate
템플릿의 모든 app.component.html
키에 번역 값을 주입합니다.첫 번째 단계는 설치 종속성입니다.
npm install @ngx-translate/core @ngx-translate/http-loader
번역을 위해 다음 파일 구조를 만듭니다.src/assets/i18n/en.json
src/assets/i18n/es.json
src/assets/i18n/ru.json
src/assets/i18n/zh.json
각 파일에 다음 키 값 쌍을 배치합니다.src/assets/i18n/en.json
:{
"Welcome to": "Welcome to",
"Here are some links to help you start": "Here are some links to help you start"
}
src/assets/i18n/es.json
:{
"Welcome to": "Bienvenido a",
"Here are some links to help you start": "Aquí hay algunos enlaces para ayudarte a comenzar"
}
src/assets/i18n/ru.json
:{
"Welcome to": "Добро пожаловать в",
"Here are some links to help you start": "Вот несколько ссылок, которые помогут вам начать"
}
src/assets/i18n/zh.json
:{
"Welcome to": "欢迎来到",
"Here are some links to help you start": "以下是一些可帮助您入门的链接"
}
우리는 네 가지 언어의 번역을 제공했다.현재, 우리는 응용 프로그램에서 번역 메커니즘을 실현할 것이다.다음 코드로 ngx-translate
의 내용을 대체하고 src/app/app.browser.module.ts
모듈 및 번역 로더를 가져옵니다.import { AppComponent } from './app.component';
import { AppModule } from './app.module';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
@NgModule({
bootstrap: [AppComponent],
imports: [
BrowserModule.withServerTransition({appId: 'app-root'}),
AppModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient]}
})
]
})
export class AppBrowserModule {}
우리가 여기서 하는 일은 HttpClientModule
라이브러리에서 가져오는 것이다.HTTP를 사용하여 번역 파일을 로드할 수 있는 공장 접근 방법@angular/common/http
을 제공해야 합니다.export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
마지막으로 TranslateModule을 가져오고 로드를 제공합니다.TranslateModule.forRoot({
loader: {provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient]}
})
HttpClient
파일을 가져와야 합니다.import { NgtUniversalModule } from '@ng-toolkit/universal';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { TranslateModule } from '@ngx-translate/core';
@NgModule({
declarations: [
AppComponent
],
imports: [
CommonModule,
NgtUniversalModule,
TranslateModule.forChild(),
]
})
export class AppModule { }
TranslateModule
템플릿의 코드를 다음 코드로 교체하여 언어 간 전환에 사용할 번역 키와 링크를 제공합니다.<div style="text-align:center">
<h1>
{{'Welcome to' | translate}} {{ title }}!
</h1>
<div>
<span (click)="switchLanguage('en')">English</span>
<span (click)="switchLanguage('es')">Español</span>
<span (click)="switchLanguage('ru')">Pусский язык</span>
<span (click)="switchLanguage('zh')">中文</span>
</div>
</div>
<h2>{{'Here are some links to help you start' | translate}}: </h2>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>
브라우저 사이드 코드에서 국제화를 제공하는 마지막 단계는 우리 구성 요소에서 src/app/app.module.ts
방법을 실현하고 활동 구역에 기본 번역을 제공하는 것이다.src/app/app.component.html
에서 다음과 같이 변경합니다.import { Component, OnInit, Inject, PLATFORM_ID, Optional } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'angular-universal-i18n';
constructor(private translate: TranslateService) {}
public ngOnInit(): void {
this.setDefaultTranslation();
}
private setDefaultTranslation(): void {
if (['en', 'es', 'zh', 'ru'].indexOf(this.translate.getBrowserLang()) > -1) {
this.translate.setDefaultLang(this.translate.getBrowserLang());
} else {
this.translate.setDefaultLang('en');
}
}
public switchLanguage(lang: string): void {
this.translate.setDefaultLang(lang);
}
}
우리 성공했어!브라우저 쪽이 국제화를 실현했다!살펴보겠습니다.ng serve -o
injected로 이동하여 선택한 언어를 스페인어로 변경한 후 다음을 볼 수 있습니다.http://localhost:4200
다음 단계를 따르려면 다음과 같이 하십시오.
git clone https://github.com/maciejtreder/angular-universal-i18n.git
cd angular-universal-i18n
git checkout step2
npm install
ng serve -o
서버 측 국제화 추가
우리 클라이언트가 서버 측의 모든 기능을 파괴했는지 확인하십시오.다음 명령을 실행하여 서버 모드에서 응용 프로그램을 시작합니다.
npm run build:prod
npm run server
로 이동하면 애플리케이션이 더 이상 작동하지 않는 것을 볼 수 있습니다.http://localhost:8080
콘솔에서 더 많은 오류 정보를 볼 수 있습니다.
ERROR { Error: StaticInjectorError(AppServerModule)[TranslateService -> TranslateStore]:
StaticInjectorError(Platform: core)[TranslateService -> TranslateStore]:
NullInjectorError: No provider for TranslateStore!
at NullInjector.module.exports.NullInjector.get (/Users/mtreder/angular-universal-i18n/dist/server.js:1361:19)
at resolveToken (/Users/mtreder/angular-universal-i18n/dist/server.js:1598:24)
at tryResolveToken (/Users/mtreder/angular-universal-i18n/dist/server.js:1542:16)
at StaticInjector.module.exports.StaticInjector.get (/Users/mtreder/angular-universal-i18n/dist/server.js:1439:20)
at resolveToken (/Users/mtreder/angular-universal-i18n/dist/server.js:1598:24)
at tryResolveToken (/Users/mtreder/angular-universal-i18n/dist/server.js:1542:16)
at StaticInjector.module.exports.StaticInjector.get (/Users/mtreder/angular-universal-i18n/dist/server.js:1439:20)
at resolveNgModuleDep (/Users/mtreder/angular-universal-i18n/dist/server.js:18300:29)
at _createClass (/Users/mtreder/angular-universal-i18n/dist/server.js:18353:32)
at _createProviderInstance (/Users/mtreder/angular-universal-i18n/dist/server.js:18317:26)
ngTempTokenPath: null,
ngTokenPath: [ 'TranslateService', [Function: TranslateStore] ] }
이 문제를 해결하기 위해서는 서버 모듈에서 switchLanguage
을 제공해야 합니다.src/app/app.component.ts
에서 다음과 같이 변경합니다.import { AppComponent } from './app.component';
import { AppModule } from './app.module';
import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { BrowserModule } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { Observable, Observer } from 'rxjs';
import { readFileSync } from 'fs';
export function universalLoader(): TranslateLoader {
return {
getTranslation: (lang: string) => {
return Observable.create((observer: Observer<any>) => {
observer.next(JSON.parse(readFileSync(`./dist/browser/assets/i18n/${lang}.json`, 'utf8')));
observer.complete();
});
}
} as TranslateLoader;
}
@NgModule({
bootstrap: [AppComponent],
imports: [
BrowserModule.withServerTransition({appId: 'app-root'}),
AppModule,
ServerModule,
NoopAnimationsModule,
ModuleMapLoaderModule,
ServerTransferStateModule,
TranslateModule.forRoot({
loader: {provide: TranslateLoader, useFactory: universalLoader}
})
]
})
export class AppServerModule {}
서버에서 i18n을 실현하기 위해 TranslateModule
에서 변경해야 합니다.다음 코드로 내용을 대체합니다.import { Component, OnInit, Inject, PLATFORM_ID, Optional } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { isPlatformBrowser } from '@angular/common';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'angular-universal-i18n';
constructor(
private translate: TranslateService,
@Optional()
@Inject(REQUEST) private request: Request,
@Inject(PLATFORM_ID) private platformId: any
) {}
public ngOnInit(): void {
const language = this.getLang();
if (['en', 'es', 'zh', 'ru'].indexOf(language) > -1) {
this.translate.setDefaultLang(language);
} else {
this.translate.setDefaultLang('en');
}
}
public getLang(): string {
let lang: string;
if (isPlatformBrowser(this.platformId)) {
lang = this.translate.getBrowserLang();
} else {
lang = (this.request.headers['accept-language'] || '').substring(0, 2);
}
return lang;
}
public switchLanguage(lang: string): void {
this.translate.setDefaultLang(lang);
}
}
추가 코드는 사용자 에이전트가 지정한 URI에서 페이지를 요청할 때 사용자 에이전트(브라우저 또는 인터넷 파충류)가 보낸 HTTPsrc/app/app.server.module.ts
헤더를 읽어 사용자 에이전트의 현재 언어를 확인합니다.이 헤더를 검색하기 위해서, 우리는 src/app/app.component.ts
에서 제공한 accept-language
을 주입해야 한다.그리고 우리는
@REQUEST
방법과 @nguniversal/express-engine/tokens
영패를 사용하여 브라우저에서 코드를 실행하는지 서버에서 코드를 실행하는지 확인합니다.만약 우리가 브라우저에 있다면, 우리는 번역 서비스에서 언어를 검색하여 이전과 같은 방식으로 언어를 설정할 수 있다.만약 우리가 서버에 있다면, 우리는 제목에서 그것을 읽을 것이다.lang = (this.request.headers['accept-language'] || '').substring(0, 2);
typescript 프로필 isPlatformBrowser
에 대한 작은 변경이 필요합니다.{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": ["node"]
},
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}
@PLATFORM_ID
값을 src/tsconfig.app.json
섹션에 추가합니다.서버 쪽 렌더링을 실행할 때 node
파일 시스템에서 번역 파일을 직접 불러오기 때문에 필요합니다.테스트 서버 측 국제화 렌더링
우리는 이미 서버 측의 번역을 완성했다.프로그램을 실행하고 사용자 정의 헤더를 사용하여curl 요청을 실행합니다.다음과 같이 애플리케이션을 구축하고 실행합니다.
npm run build:prod
npm run server
그리고 curl 요청을 보내서 현재 사용자 프록시 언어로 러시아어(ru_ru)를 지정합니다.curl http://localhost:8080 --header "accept-language: ru_RU"
또는 홈 페이지의 P-Online 을 클릭하면 브라우저의 개발자 도구에서 페이지 원본 코드를 검사할 수 있습니다.단, 페이지 원본 코드 보기를 사용하면 페이지를 다시 불러오고 영어(또는 기본값) 언어 버전을 표시할 수 있습니다.결과는 다음과 같습니다.
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>angular-universal-i18n</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.3bb2a9d4949b7dc120a9.css"><style ng-transition="app-root">
/*# sourceMappingURL=data:application/json;
base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzcmMvYXBwL2FwcC5jb21wb25lbnQuY3NzIn0= */
</style></head>
<body>
<app-root _nghost-sc0="" ng-version="7.0.4"><div _ngcontent-sc0="" style="text-align:center"><h1 _ngcontent-sc0=""> Добро пожаловать в angular-universal-i18n! </h1><div _ngcontent-sc0=""><span _ngcontent-sc0="">English</span> <span _ngcontent-sc0="">Español</span> <span _ngcontent-sc0="">Pусский язык</span> <span _ngcontent-sc0="">中文</span></div></div><h2 _ngcontent-sc0="">Вот несколько ссылок, которые помогут вам начать: </h2><ul _ngcontent-sc0=""><li _ngcontent-sc0=""><h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://angular.io/tutorial" rel="noopener" target="_blank">Tour of Heroes</a></h2></li><li _ngcontent-sc0=""><h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://github.com/angular/angular-cli/wiki" rel="noopener" target="_blank">CLI Documentation</a></h2></li><li _ngcontent-sc0=""><h2 _ngcontent-sc0=""><a _ngcontent-sc0="" href="https://blog.angular.io/" rel="noopener" target="_blank">Angular blog</a></h2></li></ul></app-root>
<script type="text/javascript" src="runtime.ec2944dd8b20ec099bf3.js"></script><script type="text/javascript" src="polyfills.c6871e56cb80756a5498.js"></script><script type="text/javascript" src="main.3d5a73b9ae1f4de7b2c1.js"></script>
<script id="app-root-state" type="application/json">{}</script></body></html>
예!우리가 예상한 바와 같이 우리의 사이트는 서버에서 나타난 것이고 러시아어 번역은 이미 응용되었다!다음 단계를 따르려면 다음과 같이 하십시오.
git clone https://github.com/maciejtreder/angular-universal-i18n.git
cd angular-universal-i18n
git checkout step3
npm install
npm run build:prod
npm run server
총결산
오늘날 우리는 모든 성숙한 응용 프로그램이 직면한 중요한 도전인 국제화에 대해 토론했다.보시다시피서버 쪽 렌더링에 국제화를 도입하여 응용 프로그램 검색 엔진을 지원하는 모든 언어로 최적화할 수 있습니다.
각도 공통 기술에 대한 더 많은 정보를 알고 싶으면 Twilio 블로그에 올린 글을 보십시오 .
이 문서에 사용된 코드의 GitHub 저장소는 다음과 같습니다. Getting Started with Serverless Angular Universal on AWS Lambda.
또한 https://github.com/maciejtreder/angular-universal-i18n, [email protected] 또는
( https://www.maciejtreder.com , , ).
Reference
이 문제에 관하여(어떻게 Angular Universal과ngxtranslate를 사용하여 검색엔진의 우호적인 국제화 웹 응용 프로그램을 만듭니까), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/twilio/how-to-create-search-engine-friendly-internationalized-web-apps-with-angular-universal-and-ngx-translate-50gc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)