跳转至主要内容
Angular i18n

Angular i18n 解决方案

为 Angular 应用程序提供独立组件、Signals 和 SSR 支持。

Setup

在 Angular 中实现运行时翻译,只需三步

Angular 内置的 i18n 会为每种语言编译一个包。若希望翻译在不重新构建的情况下更新,ngx-translate 可以在运行时从 Better I18N 读取。

安装 loader 依赖

ngx-translate 提供 pipe、service 和 loader 契约;core 负责获取并缓存文案。

terminalbash
npm install @ngx-translate/core @better-i18n/core

# @better-i18n/core ships zero dependencies —
# it is the same client our React SDKs are built on.

编写一个基于 CDN 的 TranslateLoader

TranslateLoader 要求每种语言返回一个 Observable,因此用 rxjs 的 from() 包一层 getMessages 就是整个适配器。

src/app/better-i18n.loader.tsts
import { Injectable } from '@angular/core'
import { TranslateLoader } from '@ngx-translate/core'
import { createI18nCore } from '@better-i18n/core'
import { from, Observable } from 'rxjs'

// Module scope: the 60s in-memory cache lives on the instance, so one
// client per app — not one per component.
const betterI18n = createI18nCore({
  projectId: 'your-org/your-project', // Settings → General → Project ID
  defaultLocale: 'en',
})

@Injectable({ providedIn: 'root' })
export class BetterI18nLoader implements TranslateLoader {
  // TranslateLoader's contract: one Observable of messages per language.
  getTranslation(lang: string): Observable<Record<string, unknown>> {
    return from(betterI18n.getMessages(lang))
  }
}

export { betterI18n }

注册并在运行时切换

在 bootstrapApplication 中注册一个 provider,之后 use() 即可切换语言,无需刷新页面,也无需按语言构建。

src/main.tsts
import { bootstrapApplication } from '@angular/platform-browser'
import { importProvidersFrom } from '@angular/core'
import { TranslateModule, TranslateLoader } from '@ngx-translate/core'
import { AppComponent } from './app/app.component'
import { BetterI18nLoader } from './app/better-i18n.loader'

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(
      TranslateModule.forRoot({
        defaultLanguage: 'en',
        loader: { provide: TranslateLoader, useClass: BetterI18nLoader },
      })
    ),
  ],
})

How it works

Angular 中的文案从哪里来

不需要按语言分包:loader 在运行时解析语言,由 edge 返回结果。

Read path — every locale load

Your Angular app

The translate pipe reads what TranslateService already loaded.

0 network calls per render

@better-i18n/core

getMessages(lang) inside the TranslateLoader — cached per language.

60s TTL · 0 deps

CDN edge

Cloudflare worker answers from the nearest edge cache.

max-age=60 · always 200

R2 object store

The published translation files the sync worker wrote.

source of truth

Fallback chain — tried in order when a hop fails

1In-memory TTL cache
2CDN fetch, with timeout and one retry
3Persistent storage, if configured
4staticData bundled with the app
5Throw — after everything above missed

Write path — dashboard to app

AI or translator

Proposal reviewed in the dashboard, glossary enforced.

MCP · dashboard · CLI

Publish

Sync worker writes the locale files to R2.

better-i18n publish

CDN purge

Fire-and-forget purge of the affected keys and the manifest.

non-critical by design

Live in the app

The next getMessages() past the TTL returns the new copy.

~60s worst case

0dependencies in core
60scache TTL, client and edge
200CDN status, even on failure
5fallback layers before an error
Switching locale

快速开始

使用管道和服务将 i18n 添加到您的 Angular 应用程序中。

src/app/locale-switcher.component.tsts
import { Component, inject } from '@angular/core'
import { TranslateModule, TranslateService } from '@ngx-translate/core'
import { betterI18n } from './better-i18n.loader'

@Component({
  selector: 'app-locale-switcher',
  standalone: true,
  imports: [TranslateModule],
  template: `
    <select (change)="switchTo($any($event.target).value)">
      <option *ngFor="let l of languages" [value]="l.code">{{ l.name }}</option>
    </select>
  `,
})
export class LocaleSwitcherComponent {
  private translate = inject(TranslateService)
  languages: { code: string; name: string }[] = []

  async ngOnInit() {
    // Locales come from the project manifest, not a hardcoded array.
    this.languages = await betterI18n.getLanguages()
  }

  switchTo(lang: string) {
    // use() calls the loader, which hits the cache or the CDN.
    this.translate.use(lang)
  }
}
In a template

In a template

translate pipe 和 service 都从 loader 读取,因此组件完全不需要知道 CDN 的存在。

src/app/app.component.htmlhtml
<!-- app.component.html -->
<h1>{{ 'home.title' | translate }}</h1>
<p>{{ 'home.greeting' | translate: { name: 'World' } }}</p>

<!-- ICU plurals authored in the Better i18n dashboard -->
<p>{{ 'cart.items' | translate: { count: 3 } }}</p>

<app-locale-switcher />
Capabilities

功能

独立组件支持
Signals 支持
翻译管道
i18n 指令
可注入服务
延迟加载模块
Angular Universal SSR
AOT 编译支持
Angular CLI 集成
Works with

兼容热门 Angular i18n 库

Better I18N 补充你的 Angular i18n 库 — 可视化管理翻译、与翻译人员协作,并通过 CDN 部署。

Better I18N + @ngx-translate/core

使用最广泛的 Angular 翻译库。通过管道、指令和服务注入实现运行时翻译。Better I18N 导出为 ngx-translate JSON 格式。在仪表板中编辑翻译,自动同步到你的仓库。

Better I18N + Angular i18n (built-in)

Angular 官方 i18n 系统,支持 AOT 编译、ICU 表达式和构建时翻译提取。导出为 Angular XLIFF 格式。Better I18N 管理翻译工作流,Angular CLI 构建特定语言环境的包。

Better I18N + Transloco

现代、轻量级的 Angular i18n 库,支持延迟加载、丰富的插件和出色的 TypeScript 支持。通过 Better I18N 的 GitHub 集成将翻译同步到 Transloco JSON 格式。通过 CDN 分发实时更新。

浏览其他框架指南

Get started

开始使用 Angular i18n 构建

提供免费层级。无需信用卡。