跳转至主要内容
JavaScript i18n

JavaScript 国际化:利用 Intl API 实现浏览器原生国际化

JavaScript 将 Intl API 作为内置标准,用于格式化数字、日期和列表,以及处理不同语言环境下的复数规则。无需外部库。该 API 受到所有现代浏览器和 Node.js 的支持,开箱即用即可提供基于语言环境的字符串比较、分段和相对时间格式化功能。

Setup

Add i18n to plain JavaScript in three steps

There is no JavaScript-specific package to install: @better-i18n/core is the plain-JavaScript client every other SDK here wraps.

Install the client

One dependency-free package. It runs in browsers, Node, Deno, Bun and Cloudflare Workers.

terminalbash
npm install @better-i18n/core

# Zero dependencies. Runs in browsers, Node, Deno,
# Bun and Cloudflare Workers.

Create the client once

Instantiate at module scope so the 60-second in-memory cache is shared instead of rebuilt on every call.

i18n.jsjs
import { createI18nCore } from '@better-i18n/core'

export const i18n = createI18nCore({
  projectId: 'your-org/your-project', // Settings → General → Project ID
  defaultLocale: 'en',
})

Read a message

getMessages returns a plain nested object, so a four-line lookup helper is the whole runtime you need.

main.jsjs
import { i18n } from './i18n.js'

const messages = await i18n.getMessages('en')

// getMessages resolves to { namespace: { key: value } }
const t = (path) =>
  path.split('.').reduce((node, part) => node?.[part], messages) ?? path

document.querySelector('h1').textContent = t('home.title')

// Locales come from the project manifest, not a hardcoded array
const languages = await i18n.getLanguages()

How it works

Where a JavaScript string comes from

No build step and no bundled locale files: the client resolves a locale at runtime and the edge answers it.

Read path — every locale load

Your JavaScript app

Reads from the plain object getMessages() already returned.

0 network calls per render

@better-i18n/core

getMessages(locale) — served from the in-memory cache if it is warm.

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
Two ways

With the client, or with fetch

The client adds caching, retries and the fallback chain. If you would rather own that yourself, the CDN is a plain JSON endpoint.

locale.js
import { i18n } from './i18n.js'
import { normalizeLocale } from '@better-i18n/core'

let current = 'en'
let messages = await i18n.getMessages(current)

export async function setLocale(next) {
  // The CDN stores locales lowercased: pt-BR → pt-br
  current = normalizeLocale(next)
  messages = await i18n.getMessages(current)
  document.documentElement.lang = current
  render()
}
Formatting

JavaScript Intl API 实践

在任意现代浏览器或 Node.js 运行时中,使用内置 Intl 构造函数对货币、日期和序数进行格式化,输出符合区域设置的内容。

format.jsjs
// Using the built-in Intl API
const formatter = new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR',
});
console.log(formatter.format(1234.56)); // "1.234,56 €"

// Date formatting
const date = new Intl.DateTimeFormat('ja-JP', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
});
console.log(date.format(new Date())); // "2026年3月2日"

// Pluralization
const plural = new Intl.PluralRules('en');
const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
function ordinal(n) {
  return `${n}${suffixes[plural.select(n)]}`;
}
Capabilities

JavaScript Intl API 功能

内置的 Intl API,无需外部依赖即可完成核心国际化操作
Intl.NumberFormat,用于感知区域设置的货币、百分比和单位格式化
Intl.DateTimeFormat:用于特定区域设置的日期和时间显示格式
适用于100多个地区序数词和基数词复数形式的国际复数规则
ICU MessageFormat 语法:适用于包含复数形式、选择项和嵌套结构的复杂消息
Intl.RelativeTimeFormat,用于生成人类可读的相对日期(例如“3 天前”)
Intl.ListFormat:用于支持区域设置的联结与析取列表
Intl.Collator,用于区分语言的字符串排序和比较
用于单词、句子和字母边界检测的国际分词器

浏览其他框架指南

Get started

立即开始 JavaScript 国际化

借助人工智能驱动的工作流、命令行同步以及低于 50 毫秒的 CDN 交付,管理您的 JavaScript 翻译。