iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 21
1
Modern Web

Angular 元件庫 NG-ZORRO 基礎入門系列 第 21

[Angular 元件庫 NG-ZORRO 基礎入門] Day 21 - 國際化 i18n

前言回顧

昨天我們介紹了 實驗性功能 裡的 Resizable 元件,另一個基於 Monaco Editor 開發的 Code Editor 元件,對於開發線上編輯器或者程式碼預覽等功能時很有用處,我們不過多介紹,感興趣的同學可前往官網檢視使用示例。

今天我們介紹一下 NG-ZORRO 的國際化方案,同時也會介紹 Angular i18n 的部分內容。

國際化

Angular i18n

使用過 Angular 的同學都應該瞭解過其國際化相關的知識,其 i18n 模板翻譯流程有四個階段:

  • 在元件模板中標記需要翻譯的靜態文字資訊(即打上i18n標籤)
  • Angular的i18n工具將標記的資訊提取到一個行業標準的翻譯原始檔(如.xlf檔案,使用ng xi18n)
  • 翻譯人員編輯該檔案,翻譯提取出來的文字資訊到目標語言
  • Angular編譯器匯入完成翻譯的檔案,使用翻譯的文字替換原始資訊,並生成新的目標語言版本的應用程式。

Angular 本身簡化了國際化工作的下列幾個方面:

  • 用本地格式顯示日期、數字、百分比以及貨幣
  • 準備元件模板中待翻譯的文字
  • 處理單詞的複數形式
  • 處理候選文字。

而這些工作,我們只要在需要翻譯的元素上打上標籤,執行ng xi18n即可自動創建出xlf檔案,通常為message.xlf,搭配語義化的 ID,可很好地維護,這部分內容在 國際化(i18n) 一章可瞭解到詳細的知識。

一個最簡單的翻譯標籤:

<html>
  <head>
    <meta charset="utf-8">
    <title>Angular i18n</title>
  </head>
  <body>
    <h1 i18n="Site Header|An introduction header for i18n Project@@stTitle">Angular 國際化專案</h1>
      <p>
        <span i18n="@@agDescription">國際化是一項很具有挑戰性,需要多方面的努力、持久的奉獻和決心的任務。</span>
        <span class="delete" i18n-title="@@agDelete" title="刪除"></span>
      </p>
      <p><ng-container i18n=@@agLetGo>讓我們現在開始吧!</ng-container>朋友!</p>
  </body>
</html>

我們最初在專案的 app.module.ts 檔案裡看到過 locale 的設定,這是 Angular 本地化設定地區操作:

import { registerLocaleData } from '@angular/common';
import zh_Hant from '@angular/common/locales/zh-Hant';
// the second parameter 'zh-tw' is optional
registerLocaleData(zh_Hant, 'zh-tw');

關於 Angular 國際化基礎我們不過多展開,我們下面來看一下 NG-ZORRO 是如何設定國際化的。

NG-ZORRO i18n

/** 配置 angular i18n **/
import { registerLocaleData } from '@angular/common';
import en from '@angular/common/locales/en';
registerLocaleData(en);

/** 配置 ng-zorro-antd 國際化 **/
import { NZ_I18N, en_US } from 'ng-zorro-antd/i18n';

@NgModule({
  ...
  imports     : [ NgZorroAntdModule ],
  providers   : [
    { provide: NZ_I18N, useValue: en_US }
  ]
})
export class AppModule { }

可以看到,NG-ZORRO 提供了幾個配置型 token 用於全域性配置國際化文案和日期,NZ_I18N 用於國際化文案。除此之外,NZ_DATE_CONFIG 用於修改日期相關特性,預設使用 Angular 的語言包來進行日期格式化(需要引入相應的Angular語言包)。

之前介紹 Date 元件的專案中,我們也寫過如何使用 NzI18nService 來動態切換語言顯示:

import { en_US, NzI18nService } from 'ng-zorro-antd/i18n';
...
constructor(private i18n: NzI18nService) { }
switchLanguage() {
  this.i18n.setLocale(en_US);
}

另外,它還提供了可選的 NZ_DATE_LOCALE 用於 date-fns 方式來格式化本地日期。

NZ_DATE_CONFIG 日期全域性配置

預設配置如下:

{
  /** 指定哪一天為一週的開始(null表示採用內部預設值,0表示星期日,1表示星期一,以此類推) */
  firstDayOfWeek: null
}

日期配置通常是為了適應不同國家對一週第一天的不同情況,一些操作我們在介紹 Date 元件時也有所涉及。當然,如果有需要使用 date-fns 進行日期格式化的需求,也可以切換至 date-fns 方式日期格式化

NG-ZORRO i18n 原始碼

我們下載 NG-ZORRO 原始碼可以發現,其 components 資料夾下存放著 i18n 資料夾,所有國際化相關的程式碼都在這裡:

components/i18n
├── date-config.ts
├── date-helper.service.spec.ts
├── date-helper.service.ts
├── index.ts
├── languages(all languages files)
├── nz-i18n.interface.ts
├── nz-i18n.module.ts
├── nz-i18n.pipe.ts
├── nz-i18n.service.spec.ts
├── nz-i18n.service.ts
├── nz-i18n.token.ts
├── package.json
└── public-api.ts

我們先看一下 languages 檔案的全域性翻譯結構是什麼 - zh_CN.ts

import Calendar from './calendar/zh_CN';
import DatePicker from './date-picker/zh_CN';
import Pagination from './pagination/zh_CN';
import TimePicker from './time-picker/zh_CN';

export default {
  locale: 'zh-cn',
  Pagination,
  DatePicker,
  TimePicker,
  Calendar,
  // locales for all comoponents
  global: {
    placeholder: '请选择'
  },
  Table: {
    filterTitle: '筛选',
    filterConfirm: '确定',
    filterReset: '重置',
    selectAll: '全选当页',
    selectInvert: '反选当页',
    sortTitle: '排序'
  },
  Modal: {
    okText: '确定',
    cancelText: '取消',
    justOkText: '知道了'
  },
  Popconfirm: {
    cancelText: '取消',
    okText: '确定'
  },
  Transfer: {
    searchPlaceholder: '请输入搜索内容',
    itemUnit: '项',
    itemsUnit: '项'
  },
  Upload: {
    uploading: '文件上传中',
    removeFile: '删除文件',
    uploadError: '上传错误',
    previewFile: '预览文件'
  },
  Empty: {
    description: '暂无数据'
  },
  Icon: {
    icon: '图标'
  },
  Text: {
    edit: '编辑',
    copy: '复制',
    copied: '复制成功',
    expand: '展开'
  },
  PageHeader: {
    back: '返回'
  }
};

所有的語言檔案都遵循這個結構,於是 nz-i18n.service.ts 的核心方法(如下)就可以按照 path 路徑去解析查詢到對應的文字從而渲染預設設定:

// [NOTE] Performance issue: this method may called by every change detections
// TODO: cache more deeply paths for performance
/* tslint:disable-next-line:no-any */
translate(path: string, data?: any): string {
  // this._logger.debug(`[NzI18nService] Translating(${this._locale.locale}): ${path}`);
  let content = this._getObjectPath(this._locale, path) as string;
  if (typeof content === 'string') {
	if (data) {
	  Object.keys(data).forEach(key => (content = content.replace(new RegExp(`%${key}%`, 'g'), data[key])));
	}
	return content;
  }
  return path;
}
// tslint:disable-next-line:no-any
private _getObjectPath(obj: IndexableObject, path: string): string | object | any {
  let res = obj;
  const paths = path.split('.');
  const depth = paths.length;
  let index = 0;
  while (res && index < depth) {
	res = res[paths[index++]];
  }
  return index === depth ? res : null;
}

其餘幾個關於 Date 日期的國際化處理也是差不多的邏輯,如果你在使用中發現部分翻譯並不是正確的或者要提供一個新的地區語言檔案,你也可以按照這些格式修改檔案並提交 Pull Request 要求開源社群組來儘快修復它。

總結 & 預告

我們今天粗略地介紹了 Angular 和 NG-ZORRO 的國際化方案,如果在使用中出現問題也可以去 Github Issue 去查詢或者建立提問,通常來說,你想要知道的答案都能在 Issue 列表中找到,無法解決的按照官方提問連結建立 Issue 也會很快得到解釋。

相關資料

  • Angular i18n:https://angular.tw/guide/i18n
  • NG-ZORRO i18n:https://ng.ant.design/docs/i18n/zh
  • Angular 國際化示例:https://zhuanlan.zhihu.com/p/32665315

上一篇
[Angular 元件庫 NG-ZORRO 基礎入門] Day 20 - 實驗性功能 Resizable
下一篇
[Angular 元件庫 NG-ZORRO 基礎入門] Day 22 - 查漏補缺: 常見問題
系列文
Angular 元件庫 NG-ZORRO 基礎入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言