@ ccssmnn/ intl (英语)
一个不需要取出/编码的国际性效用,是超级型号安全的,与编码剂有很大作用. 基本上只是输入和反应在官方 Unicode Message Format 2.0 上建的公用设备.
特征
- QQ 没有代码生成/ 信件提取: 作者信件并立即使用.
- {}通过 Unicode Message Format 2 语法
messageformat(唯一的依赖). - * 用于供应商、钩子和带有标记渲染的组件的响应公用事业.
- 由于熟悉的语法和友好类型错误,与编码代理无缝对等——消息.
- QQ在服务器上同样有效,例如通知和电子邮件.
支持的信件格式语法
运行时间支持 : 图书馆代表向 messageformat@4 用于完整消息格式2.0支持.
类型级别支持 : TypeScript 类型目前验证规格的焦点子集 :
参数:
{$param}- 字符串参数{$param :number}- 数量参数{$param :datetime}- 日期/时间参数{$param :date}- 日期参数{$param :time}- 时间参数
马克:
{#tag}content{/tag}- 简单的标记跨度(无属性)- 嵌入标记标记
- React 中的类型安全组件映射
选取/拼接:
.input {$var} .match $var模式one编号 :*复数规则- 自定义选择分支
QQ 没有类型验证( 但运行时工作) :
- 参数选项如
style=currency - 标记标签属性
- 复杂函数调用
- 其他信件格式 2. 0 特性
类型系统注重最常见的i18n模式,同时允许您在需要时使用高级特性.
安装
pnpm add @ccssmnn/intl
同伴依赖关系 :
- React 17+(仅在使用 React 集成时需要)
所需经费:
- 有ES2020支持的节点.js 16+或现代浏览器
快速启动
import { messages, createIntl } from "@ccssmnn/intl"
// 1. Define your messages
const copy = messages({
greeting: "Hello {$name}!",
count: "You have {$num :number} items",
})
// 2. Create translator
const t = createIntl(copy, "en")
// 3. Use it
t("greeting", { name: "World" }) // "Hello World!"
t("count", { num: 42 }) // "You have 42 items"
使用量
信件格式 2.0 实例
类型验证的常见模式 :
const messages = messages({
// Basic interpolation
greeting: "Hello {$name}!",
// Typed parameters (type-validated)
price: "Price: {$amount :number}",
date: "Today is {$today :datetime}",
time: "Meeting at {$when :time}",
// Pluralization
items:
".input {$count :number} .match $count one {{one item}} * {{{$count} items}}",
// Selection
status:
".input {$role} .match $role admin {{Welcome admin}} user {{Hello user}} * {{Hi there}}",
// Markup tags
welcome:
"Welcome {#bold}{$name}{/bold}! Click {#link}here{/link} to continue",
// Complex nested structure
cart: `.input {$count :number} {$hasDiscount}
.match $count $hasDiscount
0 true {{Your cart is empty, but you have a discount!}}
0 * {{Your cart is empty}}
one true {{You have one item with discount applied}}
one * {{You have one item}}
* true {{You have {$count} items with discount applied}}
* * {{You have {$count} items}}`,
})
核心 API
import { messages, createIntl, translate } from "@ccssmnn/intl"
// annotates `base` with the messages types
let base = messages({
greeting: "Hello {$name}!",
count: "You have {$num :number} items",
})
// guarantees on a type level that `german` has the same message signature as `base`
let german = translate(base, {
greeting: "Hallo {$name}!",
count: "Du hast {$num :number} Elemente",
})
// create typesafe message consumption utility!
let t = createIntl(german, "de")
t("greeting", { name: "Carl" })
// → "Hallo Carl!"
所有帮助者都被打出强烈的字. 譬如说, t 没有电话就拒绝 name 参数,以及 translate 强制要求翻译保留与底稿相同的参数/标记.
处理错误
库为错误消息提供优雅的错误处理:
const problematic = messages({
valid: "Hello {$name}!",
broken: "Invalid syntax {{{", // Malformed message
})
const t = createIntl(problematic, "en")
t("valid", { name: "Carl" }) // "Hello Carl!"
t("broken") // "❌: broken" (fallback with key name)
// Console shows table with error details
当信件格式汇编失败时, 库 :
- 日志详细错误信息到控制台
- 创建显示有问题的密钥的倒置消息
- 继续执行而不丢弃
反应整合
import { createIntlForReact, messages } from "@ccssmnn/intl"
const copy = messages({
signIn: "Hey {$name}! {#link}Sign in here{/link}",
})
const { IntlProvider, useIntl, T } = createIntlForReact(copy, "en")
function Toolbar() {
const t = useIntl()
return <p>{t("signIn", { name: "Carl" })}</p>
}
function Entry() {
return (
<IntlProvider>
<Toolbar />
<T
k="signIn"
params={{ name: "Carl" }}
components={{ link: ({ children }) => <a href="/login">{children}</a> }}
/>
</IntlProvider>
)
}
钩子暴露了相同的类型 t 函数为核心 API,所以 TypeScript 将在 React 组件中标记缺失的参数/标记右侧。 这个 <T> 组件用途 formatToParts 让您为标记标记提供 React 组件.
API 参考
核心职能
messages(obj)- 从对象文字创建已键入的信件目录createIntl(messages, locale)- 创建用于提供字符串的翻译功能createIntlToParts(messages, locale)- 创建手动渲染的论坛(用于构建UI框架适配器)translate(base, translation)- 创建保护结构的型号安全翻译merge(...catalogs)- 合并多个信息目录(防止关键冲突)check(base, ...parts)- 核查翻译覆盖面并合并部分
反应集成
createIntlForReact(messages, locale)- 回归{ IntlProvider, useIntl, T, useLocale }IntlProvider- 消息和语言的背景提供者useIntl()- Hook 返回翻译功能t(key, params?, components?)T- 发送带有标记的信息的组件:<T k="key" params={{}} components={{}} />useLocale()- Hook 返回当前区域字符串
使用指南
组织工作流程
- 每个特性组织信件目录(例如:.
~/intl/messages.todos.ts(e) 保持相关信息在同一地点,使其更容易工作. - 将全球目录集成到
~/intl/messages.ts通过将特性切片与merge(...),并通过check(...)。 。 。 . - 一次在
shared/intl/setup.ts使用createIntlForReact(messagesEn, "en");导出结果IntlProvider, (中文(简体) ),useIntl, (中文(简体) ),T,以及useLocale。 。 。 . - 重新使用框架不可知性帮助( E)
createIntl, (中文(简体) ),createIntlToParts)用于服务器任务,如本地化的推取通知.
这种办法的好处:
- 更小、重点更突出的信息模块更容易导航和修改
- 相关消息要贴近其使用特性
- 更好地使用能够理解和修改特定特征背景的编码代理
- 当多个特性同时添加信件时, 防止冲突合并
典型布局
shared/
intl/
setup.ts # configured React exports
messages.ts # merges base + locale slices
messages.todos.ts # per-feature catalogue (base + translate)
messages.*.ts # additional slices
server/
notifications/
send-push.ts # imports createIntl() for localized payloads
特性信件切片
// ~/intl/messages.todos.ts
import { messages, translate } from "@ccssmnn/intl"
export { baseTodoMessages, deTodoMessages }
let baseTodoMessages = messages({
"todos.header": "Tasks for {$name}",
"todos.remaining": "You have {#strong}{$count :number}{/strong} remaining",
})
let deTodoMessages = translate(baseTodoMessages, {
"todos.header": "Aufgaben für {$name}",
"todos.remaining": "Du hast noch {#strong}{$count :number}{/strong} übrig",
})
汇总全球目录
// ~/intl/messages.ts
import { merge, check } from "@ccssmnn/intl"
import { baseTodoMessages, deTodoMessages } from "./messages.todos"
// import other feature slices...
export { messagesEn, messagesDe }
let messagesEn = merge(
baseTodoMessages
/* other base slices */
)
let messagesDe = check(
messagesEn,
deTodoMessages
/* other locale slices */
)
反应消耗
// ~/intl/setup.ts
import { createIntlForReact } from "@ccssmnn/intl/react"
import { messagesEn } from "./messages"
// create the provider with the default messages and locale
export const { IntlProvider, useIntl, T, useLocale } = createIntlForReact(
messagesEn,
"en"
)
// ui/components/todo-header.tsx
import { useIntl, T } from "~/intl/setup"
export function TodoHeader({
username,
remaining,
}: {
username: string
remaining: number
}) {
const t = useIntl()
return (
<header>
<h1>{t("todos.header", { name: username })}</h1>
<T
k="todos.remaining"
params={{ count: remaining }}
components={{
strong({ children }) {
return <strong>{children}</strong>
},
}}
/>
</header>
)
}
语言切换
// app/root.tsx
import { IntlProvider } from "~/intl/setup"
import { messagesEn, messagesDe } from "~/intl/messages"
const catalogs = {
en: messagesEn,
de: messagesDe,
}
export function App({ locale }: { locale: keyof typeof catalogs }) {
return (
<IntlProvider messages={catalogs[locale]} locale={locale}>
{/* ... */}
</IntlProvider>
)
}
服务器侧
// server/notifications/send-push.ts
import { createIntl } from "@ccssmnn/intl"
import { messagesEn, messagesDe } from "~/intl/messages"
const catalogs = {
en: messagesEn,
de: messagesDe,
}
export function buildTodoNotification(
locale: keyof typeof catalogs,
taskTitle: string,
dueAt: Date
) {
const t = createIntl(catalogs[locale], locale)
return {
title: t("notifications.todo.title", { title: taskTitle }),
body: t("notifications.todo.body", { dueAt }),
}
}
工作流程提示
- 首先为底片添加新信件密钥; 编译失败, 直至翻译匹配, 保持本地同步 .
- 使用
<T>只有在需要标记时;useIntl()足够简单的弦. - 运行
pnpm test(启用了类型检查)在修改目录后立即捕捉ICU或标记错配. - 提取到共享库时,导出相同的原始文献(
messages, (中文(简体) ),merge, (中文(简体) ),translate, (中文(简体) ),check, (中文(简体) ),createIntl, (中文(简体) ),createIntlForReact),所以客户端和服务器消费者都保留了ergonomics.
发展
pnpm installpnpm test- 运行Vitest套房(Core and React).pnpm build- 将无害环境管理+d.ts产出放入dist/。 。 。 .