gt-next@6.3.0
概览
在 gt-next 6.3.0 中,我们正进一步迈向一个同时适用于人类开发者和 AI 开发者的库。本次版本的指导原则是:在尽量减少对现有代码影响的前提下,引入实现 i18n 所必需的核心功能。
为此,我们引入了全新的 msg() 函数,用于在代码库中的任意位置对字符串进行翻译。此前,开发者必须沿调用栈向上传递来自 useGT() 或 getGT() 的 t() 函数,才能对字符串进行翻译。借助 msg(),你只需先对字符串做一次包裹,然后在渲染时通过 m() 传入即可。
对比
以前,字符串必须在多层组件间传递 t() 函数来进行包装:
export const greeting1 = '你好,世界!'
export const getGreeting2 = (t: any) => t('你好,世界!')import { greeting1, getGreeting2 } from './constants'
export default function Page() {
const t = useGT()
return (
<div>
{greeting1}
{getGreeting2(t)}
</div>
)
}现在,借助 msg(),可以直接将字符串声明为常量。唯一的要求是,在显示时需通过 m()(来自 useMessages() 或 getMessages())进行处理。
export const greeting1 = '你好,世界!'
export const greeting2 = msg('你好,世界!')import { greeting1, greeting2 } from './constants'
export default function Page() {
const m = useMessages()
return (
<div>
{greeting1}
{m(greeting2)}
</div>
)
}编码与解码
为了支持插值,msg() 函数返回的是已编码的消息,而不是普通字符串。其格式如下:
<插值内容>:<base64 编码字符串>base64 编码的部分包含一个 JSON 对象,其中包括:
$_hash: 原始字符串的哈希值$_source: 插入到消息中的参数$id: 自定义唯一标识符(如果提供)$context: 消息的上下文(如果指定)- 插值中包含的任意变量
这种设计会略微改变字符串的直接比较方式,但能确保对类型和代码结构的影响降到最低。要访问插值后的内容,请使用 decodeMsg()。
为什么要使用编码字符串?
如果不使用编码字符串,msg() 就必须返回一种包含额外元数据的自定义对象类型。虽然这在编码/解码范式下是可行的,但在处理严格类型时会引入问题。
我们认为,在这种场景下将 i18n 的影响降到最低的最佳方式,就是改为返回一个包含元数据的字符串。
示例
未集成 i18n 的原始代码:
const name = 'John'
const message = `Hello, ${name}!`
if (message.length > 10) {
console.log('消息过长')
} else {
console.log('消息长度合适')
}使用 msg() 和 decodeMsg():
import { msg, decodeMsg } from 'gt-next'
const name = 'John'
const message = msg('你好,{name}!', { name })
if (decodeMsg(message).length > 10) {
console.log('消息过长')
} else {
console.log('消息长度合适')
}其他
你也可以在 t() 函数中覆盖参数,即使它们在调用 msg() 时已经被插值过。
import { msg, useMessages } from 'gt-next'
const message = msg('你好,{name}!', { name: 'John' })
export default function Page() {
const m = useMessages()
return <div>{m(message, { name: 'Jane' })}</div> // 这将返回"你好,Jane!"
}摘要
此版本重点在于让 gt-next 更符合开发者使用习惯,同时将 i18n 的额外成本降到最低。通过免去在调用栈中层层传递 t() 函数的需求,全新的 msg() 函数为翻译字符串提供了一种更简洁、更直观的方式,并大幅简化了 i18n 流程。