어떻게 Angular Universal과ngxtranslate를 사용하여 검색엔진의 우호적인 국제화 웹 응용 프로그램을 만듭니까

53395 단어 i18nangular
최초 발표 Twilio Blog
검색 엔진 최적화(SEO)는 여러 각도의 단일 페이지 응용 프로그램(SPA)에 있어 매우 중요하다.당신은 Angular Universal로 SEO의 우호적인 Angular 사이트를 구축할 수 있지만, 어떻게 하면 당신의 응용 프로그램이 당신의 사이트에서 지원하는 모든 언어에서 SEO에 우호적일 수 있습니까?구글, Yandex, 바이두는 당신의 페이지에 영어, 스페인어, 러시아어 또는 중국어를 사용하도록 요구할 수 있습니다. 당신은 어떻게 당신의 서버에 정확한 언어를 되돌려 줄 수 있습니까?
답은 ngx-translate, Angular의 국제화(i18n와 현지화 라이브러리입니다.이 모듈은 번역 파일을 쉽게 사용하여 클라이언트와 서버 측의 렌더링에 정확한 언어를 제공할 수 있습니다.이 글은 너에게 그것을 어떻게 사용하는지 보여줄 것이다.
이 글에서 우리는 다음과 같이 할 것이다.
  • 구성 요소를 포함하는 각도 응용 프로그램, 즉 홈 페이지
  • 만들기
  • 사용Angular Universal SEO 목적으로 서버 측 렌더링 추가
  • ngx-translate로 네 가지 언어의 국제화 구축
  • 본문의 작업을 완료하려면 다음 소프트웨어를 설치해야 합니다.

  • Node.js and npm(Node.js 설치도 npm을 설치합니다.
  • Angular CLI
  • 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>&nbsp;
            <span (click)="switchLanguage('es')">Español</span>&nbsp;
            <span (click)="switchLanguage('ru')">Pусский язык</span>&nbsp;
            <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>&nbsp; <span _ngcontent-sc0="">Español</span>&nbsp; <span _ngcontent-sc0="">Pусский язык</span>&nbsp; <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 , , ).

    좋은 웹페이지 즐겨찾기