如何在 Angular 中使用国际化 (i18n)

介绍

国际化是在您的应用程序中支持多种语言的过程。

这可以通过第三方库在 Angular 应用程序中完成,例如ngx-translate,或者您可以使用内置的 i18n 功能。

注: “i18n”是一个数字符号,其中“18”表示“国际化”一词中第一个字母(“I”)和最后一个字母(“N”)之间的字母数。在开发应用程序时,您可能还会遇到“a11y”,它是可访问性的数字名词。

在本教程中,您将学习在 Angular 应用程序中使用内置的 i18n 功能。

先决条件

要完成本教程,您需要:

本教程已通过 Node v14.13.1、npmv6.14.8、angularv10.1.6 和@angular/localizev10.1.6 验证。

步骤 1 — 设置项目

您可以使用它@angular/cli来创建一个新的 Angular 项目。

在终端窗口中,使用以下命令:

  • npx @angular/cli new angular-internationalization-example --style=css --routing=false --skip-tests

这将配置一个新的 Angular 项目,其样式设置为“CSS”(与“Sass”、Less 或“Stylus”相反),没有路由,并跳过测试。

导航到新创建的项目目录:

  • cd angular-internationalization-example

要为翻译项目创建基础,请app.component.html在代码编辑器中打开并将代码替换为以下几行:

src/app/app.component.html
<section>
  <article>
    <h1>Under Construction!</h1>
    <p>This page is under construction.</p>
  </article>
</section>

此代码将显示"Under Construction!""This page is under construction"消息。

接下来,打开app.component.css并用以下几行替换代码:

秒/app/app.component.css
section {
  background: #8e2de2; /* fallback for old browsers */
  background: -webkit-linear-gradient(to right, #4a00e0, #8e2de2); /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(to right, #4a00e0, #8e2de2);
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

article {
  border: 1px solid white;
  box-shadow: 1px 1px 100px 10px rgba(0, 0, 0, 0.8);
  color: white;
  padding: 40px;
  text-align: center;
}

此代码使用 flexbox、视口高度值、线性渐变背景和框阴影将"Under Construction!"消息放在屏幕上居中

然后,打开styles.css并用以下几行替换代码:

源代码/样式.css
html,
body {
  padding: 0;
  margin: 0;
}

这将删除浏览器用户样式默认情况下倾向于放置的任何填充和边距。通过使用这些样式,您可以在具有不同默认值的所有浏览器之间创建一致的基线。

在终端窗口中,启动您的应用程序:

  • npm start

localhost:4200在您的网络浏览器中访问

显示 Under Construction 消息的应用程序当前状态的屏幕截图

一旦您能够验证应用程序是否按预期运行,您就可以开始提取要翻译的消息。

第 2 步 – 使用xi18n提取messages.xlf

让我们首先标记您要在应用程序中翻译的文本。在本教程中,您将使用 Google Translate 提供的翻译将应用程序翻译成法语 ( fr) 和德语 ( de)。

i18n指令添加到您要翻译的所有文本中:

src/app/app.component.html
<section>
  <article>
    <h1 i18n>Under Construction!</h1>
    <p i18n>This page is under construction.</p>
  </article>
</section>

然后,你将不得不作出的NPM脚本中package.json使用的角度CLI从提取标记的项目app.component.htmlmessages.xlf文件:

包.json
{
  // ...
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "i18n:extract": "ng xi18n"
  },
  // ...
}

添加后,在终端窗口中运行新脚本:

  • npm run i18n:extract

然后,打开messages.xlf,你会看到类似的东西:

消息.xlf
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="48a16ab522feaff81571155668deb1a4304291f4" datatype="html">
        <source>Under Construction!</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
      </trans-unit>
      <trans-unit id="84c778d7a95cb5dc26c9cc9feb5b7abb4d295792" datatype="html">
        <source>This page is under construction.</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
      </trans-unit>
    </body>
  </file>
</xliff>

对于每个需要翻译的项目(即有i18n指令),trans-unit将创建一个。

您还可以使用此结构来提供有关翻译的更多信息。如果您要让第三方翻译每条消息并希望提供更多信息,这将非常有用。

在 里面app.component.htmli18n描述更新项目

src/app/app.component.html
<article>
  <h1 i18n="Title for the under construction card">Under Construction!</h1>
  <p i18n="A description for the under construction card.">This page is under construction.</p>
</article>

您可以使用管道字符 ( |)进一步向其添加上下文这给出了一个项目的含义,每个具有相同含义的项目将具有相同的翻译:

src/app/app.component.html
<article>
  <h1 i18n="Card Header|Title for the under construction card">Under Construction!</h1>
  <p i18n="Card Descritpion|A description for the under construction card.">This page is under construction.</p>
</article>

您还可以通过使用两个 at 符号字符 ( ) 来为每个i18n项目指定一个id,以在@@生成翻译时强制持久化:

src/app/app.component.html
<article>
  <h1 i18n="Card Header|Title for the under construction card@@constructionHeader">Under Construction!</h1>
  <p i18n="Card Descritpion|A description for the under construction card.@@constructionDescription">This page is under construction.</p>
</article>

让我们再次构建翻译:

  • npm run int:extract

这些项目现在将使用id含义描述进行更新

消息.xlf
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="constructionHeader" datatype="html">
        <source>Under Construction!</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
        <note priority="1" from="description">Title for the under construction card</note>
        <note priority="1" from="meaning">Card Header</note>
      </trans-unit>
      <trans-unit id="constructionDescription" datatype="html">
        <source>This page is under construction.</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
        <note priority="1" from="description">A description for the under construction card.</note>
        <note priority="1" from="meaning">Card Descritpion</note>
      </trans-unit>
    </body>
  </file>
</xliff>

一旦您拥有一个messages.xlf包含多个trans-units、描述、含义和 id 的文件,您就可以开始创建法语和德语翻译。

第 3 步 — 创建法语和德语翻译

默认情况下,Angular 将所有内容都视为“美式英语” ( en-US) 语言环境。您必须添加其他语言环境并更新配置以支持它们。

这些语言环境由语言环境标识符 (ID) 引用。例如,“美式英语”使用 ID en-US前两个字符 – en– 为“英语”分配区域设置标识符。最后两个字符 – US– 为“美国”分配区域设置扩展名。这些标识符源自 BCP47 建立的规则

为避免项目目录混乱,将翻译文件存储在新目录中可能会有所帮助。您可以为脚本提供一个output-path选项以i18n:extract将它们放置在locales目录中:

包.json
{
  // ...
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "i18n:extract": "ng xi18n --output-path src/locale"
  },
  // ...
}

删除现有messages.xlf文件:

  • rm messages.xlf

并重新运行i18n:extract命令;

  • npm run i18n:extract

一旦您确认脚本更改按预期工作并且目录中有一个messages.xlf文件locales,您就可以开始添加targets 进行翻译。

法语

首先,复制messages.xlfmessages.fr.xlf

  • cp src/locale/messages.xlf src/locale/messages.fr.xlf

然后,target为每个项目添加一个

src/locale/messages.fr.xlf
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="constructionHeader" datatype="html">
        <source>Under Construction!</source>
        <target>En construction</target>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
        <note priority="1" from="description">Title for the under construction card</note>
        <note priority="1" from="meaning">Card Header</note>
      </trans-unit>
      <trans-unit id="constructionDescription" datatype="html">
        <source>This page is under construction.</source>
        <target>Cette page est en construction</target>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
        <note priority="1" from="description">A description for the under construction card.</note>
        <note priority="1" from="meaning">Card Descritpion</note>
      </trans-unit>
    </body>
  </file>
</xliff>

每个trans-unit现在都有一条source英文target消息和一条法文消息。

德语

接下来,复制messages.xlfmessages.de.xlf

  • cp src/locale/messages.xlf src/locale/messages.de.xlf

然后,target为每个项目添加一个

src/locale/messages.de.xlf
<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
  <file source-language="en-US" datatype="plaintext" original="ng2.template">
    <body>
      <trans-unit id="constructionHeader" datatype="html">
        <source>Under Construction!</source>
        <target>Im Bau</target>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">3</context>
        </context-group>
        <note priority="1" from="description">Title for the under construction card</note>
        <note priority="1" from="meaning">Card Header</note>
      </trans-unit>
      <trans-unit id="constructionDescription" datatype="html">
        <source>This page is under construction.</source>
        <target>Diese Seite befindet sich im Aufbau</target>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/app.component.html</context>
          <context context-type="linenumber">4</context>
        </context-group>
        <note priority="1" from="description">A description for the under construction card.</note>
        <note priority="1" from="meaning">Card Descritpion</note>
      </trans-unit>
    </body>
  </file>
</xliff>

每个trans-unit现在都有一条source英语target消息和一条德语消息。

第 4 步 – 创建法语和德语版本

您拥有基于locale.

您可以使用 Angular CLI 为您想要支持的每个语言环境生成特定的构建。

首先,您需要安装@angular/localize

  • ./node_modules/@angular/cli/bin/ng add @angular/localize

angular.json在您的代码编辑器中打开并添加frde语言环境:

angular.json
{
  "projects": {
    "angular-internationalization-example": {
      // ...
      "i18n": {
        "sourceLocale": "en-US",
        "locales": {
          "fr": {
            "translation": "src/locale/messages.fr.xlf",
            "baseHref": ""
          },
          "de": {
            "translation": "src/locale/messages.de.xlf",
            "baseHref": "" 
          }
        }
      },
      "architect": {
        // ...
      }
    }},
  // ...
}

而对于创建配置设置frdebuild

angular.json
{
  "projects": {
    "angular-internationalization-example": {
      // ...
      "architect": {
        "build": {
          // ...
          "configurations": {
            "production": {
              // ...
            },
            "fr": {
              "localize": ["fr"],
              "outputPath": "dist/under-construction-fr/",
              "i18nMissingTranslation": "error"
            },
            "de": {
              "localize": ["de"],
              "outputPath": "dist/under-construction-de/",
              "i18nMissingTranslation": "error"
            }
          }
        },
        // ...
      }
    }},
  // ...
}

注:以前,本教程中使用单独的值"i18nFile""i18nFormat"和` "i18nLocale"这些已被弃用,localize是首选方法。

您还可以更新下的配置设置serve

angular.json
{
  "projects": {
    "angular-internationalization-example": {
      // ...
      "architect": {
        "serve": {
          // ...
          "configurations": {
            "production": {
              "browserTarget": "angular-internationalization-example:build:production"
            },
            "fr": {
              "browserTarget": "angular-internationalization-example:build:fr"
            },
            "de": {
              "browserTarget": "angular-internationalization-example:build:de"
            }
          }
        },
        // ...
      }
    }},
  // ...
}

您现在可以制作更多脚本,package.json其中包括构建和服务新语言环境的能力:

包.json
{
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "start:fr": "ng serve --configuration=fr",
    "start:de": "ng serve --configuration=de",
    "build": "ng build",
    "build:fr": "ng build --configuration=fr",
    "build:de": "ng build --configuration=de",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "i18n:extract": "ng xi18n --output-path src/locale"
  }
}

您可以通过在终端中运行以下命令来启动我们所有的项目:

  • npm start

在另一个终端窗口中,启动法语版本:

  • npm run start:fr -- --port=4201

在另一个终端窗口中,启动德语版本:

  • npm run start:de -- --port=4202

这将在默认端口上运行英语应用程序,在端口 4201 上运行法语,在端口 4202 上运行德语:

已完成演示的英语、法语和德语屏幕截图

您已经构建了应用程序的翻译版本。

结论

在本教程中,您使用了 Angular 可用的内置 i18n 工具来生成法语和德语的翻译版本。

要了解有关使用内置 i18n 工具的更多信息,请参阅官方文档

如果您想了解有关 Angular 的更多信息,请查看我们的 Angular 主题页面,了解练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁