当前位置: 首页 > news >正文

General Translation:基于组件翻译的React国际化新范式

1. 项目概述:一个颠覆传统思维的国际化方案

如果你正在开发一个需要面向全球用户的 React 或 Next.js 应用,那么“国际化”这个词对你来说,可能意味着无尽的麻烦。传统的 i18n 方案,比如 react-i18next 或 next-intl,通常要求你把所有 UI 文本都抽离到一个独立的 JSON 或 YAML 字典文件里。这个过程有多痛苦?你需要遍历整个代码库,找出每一个字符串,给它们起一个唯一的 key,然后小心翼翼地维护这个日益庞大的字典文件。更头疼的是,当设计稿更新或者产品逻辑变动时,你不仅要改代码,还得同步更新字典,稍有不慎就会导致 key 找不到或者翻译缺失,页面上直接给你显示一个冷冰冰的t(‘some.key’)

今天要聊的General Translation,简称 GT,就是来终结这种痛苦的。它的核心思想极其简单,却又非常大胆:直接翻译整个 React 组件,而不是翻译零散的字符串。你不再需要把“Hello, world!”改成t(‘greeting’),你只需要用它的<T>组件把你的按钮、段落、标题包裹起来,GT 就会在背后自动帮你处理多语言。你写代码的方式几乎和开发单语言应用时一模一样,只是多了一层“翻译包装”。我第一次看到这个思路时,感觉就像有人告诉我“不用学游泳也能过河”一样不可思议,但实际用下来,它确实在相当多的场景下,让 i18n 这件事变得前所未有的轻松。

GT 不是一个单一的库,而是一个完整的工具套件。它包含了从开发时的 React 组件包装、构建时的代码编译,到持续集成中的自动翻译管理,甚至还有与 CMS 集成的插件。你可以把它理解为一套“全栈式”的国际化解决方案。它的目标很明确:让开发者能像写单语言应用一样自然地开发多语言应用,把国际化的复杂度从开发者肩上卸下来,交给工具链去自动化处理。

2. 核心设计思路:为什么是“翻译组件”?

要理解 GT 的价值,我们得先看看传统 i18n 方案到底卡在哪里。传统方案的核心是“字典映射”。你有一个源语言(比如英语)的字典,里面是一堆key: value对。在代码里,你通过t(key)来获取当前语言下的value。这个模型在理论上很清晰,但在实践中会引发一系列连锁问题。

首先,它破坏了开发的心流和代码的可读性。你正在写一个漂亮的 React 组件,逻辑清晰,结构明了。突然,你需要把“Submit”这个按钮文字国际化。于是你停下来,去字典文件里找一个合适的 key,比如button.submit,然后回到代码里写成t(‘button.submit’)。这个过程打断了你的思路,而且让代码变得抽象——光看代码,你并不知道这个按钮最终显示什么文字,必须去查字典。当组件复杂,包含多个动态插值和条件渲染时,字典 key 的管理会变成一场噩梦。

其次,它带来了巨大的同步和维护成本。UI 改了,字典得改;新功能加了,字典得加;旧的 key 没用了,你敢删吗?会不会有哪个角落还在引用它?这种代码和内容的强耦合,使得重构和迭代变得小心翼翼。更不用说,当团队里有设计师、产品经理、翻译人员共同参与时,如何确保字典的更新能及时、准确地同步到代码中,又是一个沟通上的挑战。

GT 的解决方案是釜底抽薪:既然字典映射这么麻烦,那我们干脆不要字典了。当然,不是真的不要翻译,而是换一种组织形式。GT 的思路是,把“翻译”这个动作,从“开发时提取字符串”推迟到“构建时或运行时处理组件”。

具体来说,当你用<T>组件包裹一段 JSX 时,GT 的编译器(比如它的 Vite 或 Webpack 插件)会分析这段 JSX。它会识别出里面所有的静态文本、动态表达式、甚至是属性值。然后,在构建过程中,它为每一种支持的语言生成一个对应的、翻译好的组件版本。在运行时,根据用户选择的语言,GT 的运行时库会动态加载并渲染对应语言的组件版本。

这样做有几个革命性的好处:

  1. 开发体验无缝:你写的代码就是最终 UI 的直观反映。<button>Submit</button>包裹后就是<T><button>Submit</button></T>,一目了然。没有抽象的 key,没有上下文切换。
  2. 内容与代码天然同步:因为翻译的对象就是 JSX 本身,所以只要 UI 变了,需要翻译的内容就自动变了。不存在漏掉某个 key 的情况。
  3. 支持复杂内容结构:传统字典对包含 HTML 标签(如加粗、链接)的富文本翻译很不友好,通常需要用危险的dangerouslySetInnerHTML。而 GT 直接翻译 JSX,可以完美保留原有的 DOM 结构,只是替换其中的文本内容,既安全又强大。
  4. 便于与设计工具和 CMS 对接:组件本身就是设计的载体。这种“翻译组件”的模型,更容易与 Figma 这类设计工具或 Sanity 这类无头 CMS 打通,实现从设计到多语言代码的自动化流程。

当然,这个模型并非没有代价。它意味着你的代码包体积可能会因为包含多份组件“模板”而增大,虽然 GT 声称通过巧妙的代码分割和按需加载来优化。同时,它要求翻译人员可能需要接触类似 JSX 的结构(虽然 GT 提供了更友好的翻译管理界面)。但对于中大型、UI 复杂的 React 应用来说,GT 带来的开发效率提升和维护成本的降低,很可能是值得的。

3. 快速上手指南:从零到一的多语言应用

理论说得再多,不如动手试试。GT 的入门流程设计得非常顺畅,我们以最流行的 Next.js 应用为例,走一遍完整的配置过程。

3.1 环境准备与初始化

首先,确保你有一个现成的 Next.js 项目(App Router 或 Pages Router 均可)。如果没有,可以用以下命令快速创建一个:

npx create-next-app@latest my-gt-app --typescript --tailwind --app cd my-gt-app

接下来,运行 GT 的初始化向导。这是最推荐的方式,它会以交互式问答引导你完成所有配置。

npx gt@latest

运行这个命令后,你会看到一个命令行向导。它会问你几个问题:

  1. 项目类型:选择Next.js
  2. 源语言:通常是你编写代码时使用的语言,比如en(英语)。
  3. 目标语言:你想要翻译成的语言,比如zh-CN(简体中文)、ja(日语)等,可以多选。
  4. General Translation API 密钥:这里需要你前往 generaltranslation.com 注册一个免费账户,并在控制台创建一个项目以获取 API 密钥。免费额度对于个人项目或早期产品通常足够。

向导运行完毕后,它会自动完成以下几件事:

  • 在项目根目录创建gt.config.json配置文件。
  • 安装必要的 npm 包:gt-next(Next.js 集成库)和@generaltranslation/compiler(构建插件)。
  • 修改你的next.config.js,引入 GT 的编译器插件。
  • 在项目中创建初始的语言文件目录结构。

你的gt.config.json可能看起来像这样:

{ “sourceLocale”: “en”, “targetLocales”: [“zh-CN”, “ja”], “apiKey”: “gt_xxxx_your_api_key_xxxx” }

next.config.js会被更新,加入 GT 插件:

const { withGT } = require(‘@generaltranslation/compiler/with-gt’); /** @type {import(‘next’).NextConfig} */ const nextConfig = { // ... 你原有的配置 }; module.exports = withGT(nextConfig);

注意:务必确保你的gt.config.json文件被添加到.gitignore中,尤其是当它包含 API 密钥时。你应该通过环境变量GT_API_KEY来传递密钥,并在配置文件中引用:“apiKey”: process.env.GT_API_KEY。这是保护密钥安全的标准做法。

3.2 核心组件<T>的基本用法

配置完成后,你就可以在组件中开始使用 GT 了。首先,在需要使用国际化的组件中引入T组件。

// app/page.tsx import { T } from ‘gt-next’; // 如果是 Pages Router,则从 ‘gt-react’ 导入 export default function HomePage() { return ( <div> <h1><T>Welcome to My App</T></h1> <p> <T> This is a demonstration of seamless internationalization. You can write your UI naturally. </T> </p> <button> <T>Click Me</T> </button> </div> ); }

就是这么简单。把需要翻译的文本用<T>标签包起来。在开发服务器运行时,你看到的仍然是英文。当你运行构建命令时,魔法就发生了。

3.3 执行构建与翻译获取

运行构建命令,GT 编译器开始工作:

npm run build

在构建过程中,GT 编译器会扫描所有被<T>包裹的 JSX 块,提取出文本内容,并通过 General Translation 的 API 将其发送到云端进行翻译(使用你配置的目标语言)。翻译完成后,它会为每种语言生成优化后的组件代码。

构建完成后,你可以像往常一样启动生产服务器:

npm start

现在,打开浏览器访问你的应用。GT 默认会尝试根据用户浏览器的语言首选项自动匹配语言。你也可以通过查询参数?locale=zh-CN或编程方式(后面会讲)来切换语言。刷新页面,你会发现标题、段落和按钮都变成了中文。

这里有一个非常重要的实操细节:首次构建时,因为需要调用翻译 API 并等待结果,构建时间会显著变长。GT 会将翻译结果缓存到本地的.gt目录下。后续构建如果没有新的或修改过的<T>块,就会直接使用缓存,速度飞快。你可以把.gt目录也加入.gitignore,因为翻译缓存可以在每次构建时重新生成。

4. 进阶功能与深度配置解析

仅仅包裹静态文本只是开始。真实的 UI 充满动态内容、插值和条件逻辑。GT 为此提供了丰富的功能。

4.1 处理动态内容与插值

你的文本中经常需要插入变量,比如用户名、数量、日期。GT 的<T>组件支持插值,语法非常直观。

function UserGreeting({ userName, orderCount }) { return ( <p> <T> Hello, {userName}! You have {orderCount} unread messages. </T> </p> ); }

GT 的编译器足够智能,它能识别出{userName}{orderCount}是动态插值槽位。当它提取文本发送翻译时,会生成一个带占位符的句子,比如“Hello, {0}! You have {1} unread messages.”。翻译人员只需要翻译这个带占位符的句子即可。在运行时,GT 会正确地将对应的变量值填充到翻译后的文本的相应位置。

注意事项:翻译带有插值的句子时,不同语言的语序可能完全不同。例如,中文可能说“{userName},你好!你有 {orderCount} 条未读消息。”。专业的翻译平台会处理好这种占位符的重新排序,但作为开发者,你需要确保插值变量名本身是语义化的(如userName),而不是{0}{1},这样在翻译管理后台查看时会清晰得多。GT 的管理界面通常能很好地展示这些上下文。

4.2 切换语言与语言状态管理

GT 提供了useLocaleuseSetLocale钩子,让你能在组件内轻松获取和修改当前语言。

// app/components/LanguageSwitcher.tsx ‘use client’; // Next.js App Router 中需要在客户端组件中使用钩子 import { useLocale, useSetLocale } from ‘gt-next’; export function LanguageSwitcher() { const locale = useLocale(); // 例如 ‘en’ const setLocale = useSetLocale(); return ( <div> <button onClick={() => setLocale(‘en’)} style={{ fontWeight: locale === ‘en’ ? ‘bold’ : ‘normal’ }} > English </button> <button onClick={() => setLocale(‘zh-CN’)} style={{ fontWeight: locale === ‘zh-CN’ ? ‘bold’ : ‘normal’ }} > 中文 </button> </div> ); }

LanguageSwitcher组件放在你的布局或导航栏中,用户就可以点击切换语言了。setLocale函数会更新语言上下文,并触发所有<T>组件重新渲染其对应语言的版本。

语言持久化:你通常希望记住用户的选择。GT 可以与你的状态管理或存储方案结合。一个常见的做法是,在setLocale的同时,将选择保存到localStoragecookie中,然后在应用初始化时(例如在根布局或自定义Provider中)读取这个值并设置回去。

// 一个增强版的 setLocale import { useSetLocale } from ‘gt-next’; export function usePersistentLocale() { const setLocale = useSetLocale(); const setLocaleAndSave = (newLocale: string) => { setLocale(newLocale); // 保存到 localStorage localStorage.setItem(‘preferred-locale’, newLocale); // 如果你需要服务端感知(用于SSR),也可以设置一个cookie document.cookie = `NEXT_LOCALE=${newLocale}; path=/; max-age=31536000`; // 一年有效期 }; return setLocaleAndSave; }

4.3 翻译覆盖与手动校对

自动翻译虽然强大,但难免有不准确或不符合产品语境的地方。GT 允许你对自动翻译的结果进行覆盖和手动校对。

方法一:通过本地翻译文件覆盖在构建和首次翻译后,GT 会在项目内生成翻译文件(通常在locales/目录下)。你可以直接编辑这些文件中的翻译字符串。下次构建时,GT 会优先使用你手动修改的版本,而不会用 API 的自动翻译覆盖它。

方法二:通过 General Translation 仪表盘更推荐的方式是使用其云服务仪表盘。登录 generaltranslation.com ,进入你的项目,你可以看到所有被提取的字符串及其在不同语言下的翻译。在这里,你可以邀请专业的翻译人员协作,对机器翻译的结果进行审核、编辑和定稿。所有修改会与你的项目同步。

4.4 与 Tailwind CSS 或样式化组件的协作

一个常见的顾虑是:翻译后文本长度变化,会不会破坏 UI 布局?比如,一个按钮的英文是“Submit”(6个字符),中文是“提交”(2个字符),德文可能是“Absenden”(8个字符)。GT 本身不解决这个问题,但可以很好地与现有方案配合。

对于 Tailwind CSS,确保你的按钮使用padding而不是固定width,让宽度根据内容自适应。

<button className=“px-4 py-2 bg-blue-500 text-white rounded”> <T>Submit</T> </button>

对于更复杂的情况,可以考虑为特定语言设置特定样式。你可以结合useLocale钩子:

const locale = useLocale(); return ( <button className={`px-4 py-2 rounded ${locale === ‘de’ ? ‘text-sm’ : ‘text-base’}`}> <T>Submit</T> </button> );

4.5 性能考量:代码分割与按需加载

有人可能会担心,为每种语言都生成组件副本,会不会导致打包体积爆炸?GT 在这方面做了优化。它默认会利用 Next.js 或 React 的代码分割功能,为不同语言生成独立的 chunk(代码块)。只有当用户切换到某种语言时,对应语言的翻译 chunk 才会被加载。这意味着初始加载的包大小只包含源语言(或一种默认语言)的代码。

你可以在gt.config.json中配置loading策略,甚至自定义加载中的占位符组件,以提升切换语言时的用户体验。

5. 实战场景与避坑经验

在实际项目中大规模使用 GT 几个月后,我积累了一些宝贵的经验,也踩过一些坑。这里分享出来,希望能帮你绕开弯路。

5.1 场景一:处理富文本与内嵌组件

有时,一段文本中间包含一个链接、一个强调的加粗,或者一个自定义组件。GT 能处理吗?完全可以。

<p> <T> Please read our <a href=“/terms”>Terms of Service</a> and <strong>Privacy Policy</strong> before proceeding. </T> </p>

GT 会完整地保留astrong标签及其属性,只翻译它们包裹的文本内容。这对于法律条款、产品说明等场景至关重要。你不再需要把 HTML 标签转换成标记语言字符串再交给翻译人员。

避坑点:确保内嵌的组件或标签是自闭合有闭合标签的简单元素。过于复杂的嵌套结构可能会让翻译解析变得困难。如果遇到问题,可以尝试将特别复杂的部分拆分成独立的<T>块。

5.2 场景二:翻译复数与性别等复杂语言规则

不同语言对于复数、性别、格的变化规则千差万别。GT 通过“消息语法”来支持这些高级特性。它允许你在<T>组件中使用类似 ICU MessageFormat 的语法。

<T> {userCount, plural, =0 {No users online} =1 {One user online} other {# users online} } </T>

在构建时,GT 会识别这种语法,并将其转换为目标语言正确的复数形式。中文可能不需要复数变化,但俄语、阿拉伯语等语言会有复杂的规则,GT 的翻译后端会正确处理。

实操心得:对于简单的复数(如英文的itemvsitems),你可以依赖 GT 的自动处理。但对于涉及性别(如法语connectévsconnectée)或更复杂格式(如货币、日期),明确使用消息语法是更可靠的做法。虽然学习曲线稍陡,但它保证了翻译的准确性。

5.3 场景三:服务端渲染与静态生成

对于 Next.js 应用,SSR 和 SSG 是核心特性。GT 对此有很好的支持。

  • 服务端渲染:在getServerSideProps或 App Router 的 Server Component 中,你可以根据请求头或 cookie 确定用户的语言偏好,并确保<T>组件在服务端就渲染出正确的语言版本。这有利于 SEO 和首屏性能。GT 的 Next.js 集成包 (gt-next) 已经帮你处理好了这部分逻辑,你只需要确保语言状态能从服务端传递到客户端。
  • 静态生成:如果你使用getStaticProps生成静态页面,你需要为每一种支持的语言生成一个页面版本。Next.js 本身支持国际化路由(/en/page,/zh-CN/page)。GT 可以与这个功能协同工作。你可以在next.config.js中配置i18n选项,然后 GT 会在构建时为每种语言生成对应的静态 HTML。关键在于,你需要运行一次构建过程,让 GT 完成所有语言的翻译和静态生成。

一个常见的坑:在静态生成站点时,如果你在构建后才通过仪表盘修改了翻译,静态页面不会自动更新。你需要重新触发构建(或使用增量静态再生成 ISR)来获取最新的翻译内容。因此,对于内容频繁更新的营销页面,可能更适合使用 SSR 或客户端渲染。

5.4 场景四:与测试框架集成

如何测试包含<T>组件的 UI?你不需要一个真实的翻译服务来运行测试。GT 提供了测试工具。

在 Jest 或 Vitest 的配置中,你可以设置一个测试环境,让<T>组件在测试中直接渲染其子内容(即源语言文本),或者渲染一个模拟的翻译结果。这可以避免测试依赖于外部 API,并让测试断言更稳定。

// 在你的测试设置文件中 import { setTestLocale } from ‘gt-react’; // 在所有测试之前,设置一个固定的测试语言环境 beforeAll(() => { setTestLocale(‘en’); });

这样,在你的单元测试或组件测试中,<T>Hello</T>就会直接渲染出“Hello”,你可以像测试普通组件一样进行断言。

6. 生态工具与高级工作流

GT 的强大不仅在于核心库,更在于其围绕“组件翻译”理念构建的一整套工具链。

6.1 CLI 工具:自动化翻译工作流

gtCLI 工具(即你最初运行的npx gt@latest)不仅用于初始化。在持续集成中,你可以用它来:

  • 提取字符串:运行gt extract命令,扫描代码并提取所有新的或修改过的待翻译内容。
  • 推送翻译gt push将提取的内容推送到 General Translation 云端项目。
  • 拉取翻译gt pull将云端已完成的翻译拉取到本地,更新本地缓存。 你可以将这些命令集成到 CI/CD 流水线中,实现“代码合并请求 -> 自动提取新字符串 -> 通知翻译人员 -> 翻译完成 -> 自动拉取并部署”的自动化流程。

6.2 Sanity Studio 插件:内容与翻译一体化

如果你使用 Sanity 作为内容管理系统,gt-sanity插件将是无价之宝。安装后,它会在你的 Sanity Studio 中为可翻译字段添加一个侧边栏或内联界面,编辑人员可以直接在 Sanity 中查看和编辑不同语言的版本。当内容在 Sanity 中更新时,可以触发 webhook 通知你的应用重新构建或更新翻译缓存,实现内容与多语言 UI 的实时同步。

6.3 Locadex:AI 驱动的复杂代码库迁移

对于已有的大型、未做国际化的代码库,手动添加成千上万个<T>标签是一项浩大的工程。这就是locadex工具的用武之地。它是一个 AI 智能体,能够分析你的代码库,智能地识别出需要国际化的用户界面字符串,并尝试自动为你包裹上<T>组件。虽然不能做到 100% 准确,但它能完成大部分机械性的工作,极大提升老项目迁移到 GT 的效率。

6.4 自定义编译器与打包集成

@generaltranslation/compiler是 GT 的引擎。它提供了与 Webpack、Vite、Rollup、esbuild 等打包器的集成接口。这意味着你不仅能在 Next.js 中使用 GT,理论上可以在任何使用这些打包器的 React 项目中使用。配置方式类似,你需要找到对应打包器的插件入口并配置。这为 GT 在更广泛的 JavaScript 生态中的应用打开了大门。

7. 决策指南:何时选择 GT,何时选择传统方案?

GT 并非银弹,理解它的适用场景至关重要。

选择 GT,如果你的项目:

  • 是 React/Next.js 技术栈:这是 GT 的主场,集成度最高。
  • UI 复杂,动态内容多:富文本、条件渲染、插值频繁的界面。
  • 开发迭代速度快:GT 能极大减少因国际化带来的开发摩擦和重构成本。
  • 团队希望设计、开发、翻译流程更紧密:GT 的组件模型更容易与设计系统、CMS 对接。
  • 你愿意接受一种新的、可能有一定供应商锁定的范式:虽然核心是开源的,但自动翻译和部分高级功能依赖其云服务。

考虑传统 i18n 库,如果:

  • 你的项目技术栈多样:需要支持 Vue、Svelte、纯 JavaScript 等。
  • 翻译内容极度稳定,且已有成熟的翻译管理流程:比如使用专业的 TMS,传统字典模型与这些系统对接可能更成熟。
  • 你对 bundle 大小有极其苛刻的要求:虽然 GT 做了代码分割,但为每种语言生成组件模板的模型,在支持语言非常多(比如 50+)时,其总体积可能仍大于一个精心优化的字典文件。
  • 你需要完全离线的翻译能力:GT 的自动翻译和部分管理功能需要网络,虽然翻译结果可以缓存。

我个人在多个中型 SaaS 产品中使用了 GT,最大的感受是它真正把国际化从一项“专项任务”变成了一个“基础设施功能”。开发者不再需要时刻惦记着 i18n,可以更专注于业务逻辑本身。对于初创公司和快速迭代的产品,这种效率提升是巨大的。当然,在引入任何新技术栈时,充分的评估和在小范围模块的试点都是明智之举。

http://www.jsqmd.com/news/779927/

相关文章:

  • 2026年现阶段,丰台区市政工程检查井盖板优质供应商深度解析 - 2026年企业推荐榜
  • Archlinux微信中文输入法问题
  • Alfred集成Ollama:打造macOS本地AI无缝工作流
  • Git Worktree管理器:提升多分支并行开发效率的Rust工具
  • Random Forest 涨点改进|全网独家复现|特征增强 + 可解释性优化,助力血细胞异常检测临床级精准识别
  • Jmeter 分布式压测常见坑以及解决方案
  • 2026绍兴GEO优化公司实测对比:服务与效果验证亲历分享
  • 2026年郑州薄膜开关面板供应商深度解析:如何选择一体化解决方案伙伴? - 2026年企业推荐榜
  • 【2026年5月渠道认证】卖家精灵折扣码:SZYM72 / SZYM78 / SZYM90 - 易派
  • ESP32物联网入门:用MicroPython和MicroDot做个能网页控制的智能灯(附完整代码)
  • 对话智能分析引擎:从聊天记录到知识库的NLP与向量搜索实践
  • 2026现阶段青岛高端旅游包车服务深度观察:云尚景国际旅行社如何定义专业标准 - 2026年企业推荐榜
  • 2026年至今,如何选择手机维修培训机构?指南舟案例深度剖析 - 2026年企业推荐榜
  • 大模型未来趋势展望——从技术突破到生态共赢
  • 商业应用(15)合规发票管理系统—东方仙盟练气期
  • AI 盲人导航眼镜系统|全网独家复现|YOLO + 光流 + 状态机联合涨点,盲道 / 红绿灯 / 障碍物全场景精准感知
  • Cortex-A75性能监控架构与调试实践
  • 2026年当下,云南PC耐力板选购指南:为何高玛阳光板备受青睐? - 2026年企业推荐榜
  • 金融研究AI智能体:文献综述技能部署与高效使用指南
  • R语言本地大模型应用指南:ollamar包集成Ollama实战
  • 2026年5月正规的黄岛区上门修空调中心哪家靠谱厂家推荐榜,[变频空调维修、中央空调维修、定频空调加氟、空调电路检修、空调移机服务]厂家选择指南 - 海棠依旧大
  • 初识 Kubernetes 后如何快速安装?
  • Hugging Face Datasets库实战:高效数据处理与多模态支持
  • 构建可编程.NET内存分析工具:从原理到实战
  • C++高性能AI智能体SDK开发指南:从架构设计到生产部署
  • 2026年5月靠谱的深圳旅游租车服务商哪家好厂家推荐榜,自驾/代驾/商务接待/婚庆用车/机场接送厂家选择指南 - 海棠依旧大
  • AI智能体开发框架解析:从模块化架构到实战应用
  • 2026年5月新发布:上海办公室装修可靠之选,荷悦装饰全方位解析 - 2026年企业推荐榜
  • 2026年Q2湖北高位自卸式垃圾站制造厂综合评估:湖北中昱领衔推荐 - 2026年企业推荐榜
  • Science丨TranscriptFormer大模型跨越15亿年进化史,利用1.12亿单细胞数据构建通用生成式细胞图谱