主题与国际化

统一编辑器外观、深色模式和语言资源,让扩展界面与应用一致。

主题与国际化是共享运行时能力:六个产品使用统一的主题服务、语言资源和区域配置,自定义插件也可以订阅同一套状态。品牌外观与用户偏好可以在运行中更新,内容模型继续保留自己的数据与样式。

当前 SDK 内置 19 个界面语言/地区选项、7 套主题色板,六个产品共用外观、语言与区域配置。自定义主题和业务翻译也接入同一套服务。

一套状态,同时驱动界面与渲染

ThemeService 分别保存完整主题与深色模式状态,并通过 currentTheme$、darkMode$ 发布变化。UI 将主题展开为 --univer-* CSS 变量,并响应 univer-dark 类;渲染器监听同一服务,将相关组件标记为需要重绘。Canvas 颜色服务负责解析颜色 Token,并在深色模式显示时进行映射和缓存。

本章配置与示例以 @univerjs/*、@univerjs-pro/* 1.2.0 为基准;应用中应保持 SDK 依赖版本一致。

配置可选值与范围运行时入口
theme7 套内置色板,或完整自定义 Theme。setTheme()
darkModetrue / false,默认 false;与色板独立。toggleDarkMode()
locale19 个内置 LocaleType;先加载对应资源。setLocale()
locales按语言标识组合产品、功能插件和业务翻译。loadLocales()
region使用同一组 LocaleType;显式设置前跟随界面语言。setRegion()
directionltr / rtl,默认 ltr;仅菜单等界面 UI,Canvas 内容区尚不支持 RTL。setDirection()
100%

从完整色板构建品牌主题

主题由 @univerjs/themes 提供,包含 primary、gray、各功能色阶、loop-color 与 highlight.background。从内置主题复制并覆盖需要的分支,保留完整结构;setTheme() 接收的是完整主题替换,不会为局部对象自动深度补齐。下面使用连续的紫色色阶覆盖品牌色。

内置 7 套色板: blueTheme, darkBlueTheme, greenTheme, orangeTheme, purpleTheme, redTheme, yellowTheme.

defaultTheme 是 blueTheme 的别名。色板与深色模式开关分别设置。可配置范围包括:

主题分支可配置选项
primary品牌色 10 级:50、100 至 900。
gray中性色 12 级:0、50、100 至 900、1000。
blue · red · orange · yellow · green · jiqing · indigo · purple · pink9 组功能色,每组 10 级。
loop-color12 个循环配色位置,引用色阶 Token。
highlight.background16 个背景高亮位置,分别设置 color 与 alpha。
TypeScript
import type { Theme } from '@univerjs/themes';import { defaultTheme } from '@univerjs/themes';export const brandTheme: Theme = {  ...defaultTheme,  primary: {    ...defaultTheme.primary,    50: '#F5F3FF', 100: '#EDE9FE', 200: '#DDD6FE', 300: '#C4B5FD',    400: '#A78BFA', 500: '#8B5CF6', 600: '#7C3AED', 700: '#6D28D9',    800: '#5B21B6', 900: '#4C1D95',  },};

将主题传给已经选择好的产品集成。下面以 Sheet 核心预设为例,同时注册应用自己的语言键;其他产品使用各自的插件组合。

TypeScript
import { LocaleType, mergeLocales } from '@univerjs/core';import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core';import SheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US';import { createUniver } from '@univerjs/presets';import { brandTheme } from './brand-theme';import '@univerjs/preset-sheets-core/lib/index.css';export const { univer, univerAPI } = createUniver({  theme: brandTheme,  darkMode: false,  locale: LocaleType.EN_US,  locales: {    [LocaleType.EN_US]: mergeLocales(SheetsCoreEnUS, {      'sales-report': { generate: 'Generate report', ready: 'Ready for {0}' },    }),  },  presets: [UniverSheetsCorePreset({ container: 'app' })],});

运行中切换,并跟随应用偏好

setTheme() 更换色板,toggleDarkMode() 改变深色模式状态;可以通过 getCurrentTheme()、isDarkMode() 回读。只更换 darkBlueTheme 不会自动开启深色模式标志。外观变化不需要销毁并重建编辑器。

下面的函数跟随系统偏好,返回停止监听的清理函数。若应用提供手动外观选项,也可以在应用的主题处理器中直接调用 toggleDarkMode()。

TypeScript
import type { FUniver } from '@univerjs/core/facade';import { brandTheme } from './brand-theme';export function followSystemAppearance(univerAPI: FUniver): () => void {  univerAPI.setTheme(brandTheme);  const preference = window.matchMedia('(prefers-color-scheme: dark)');  const update = () => univerAPI.toggleDarkMode(preference.matches);  update();  preference.addEventListener('change', update);  return () => preference.removeEventListener('change', update);}

宿主在编辑器就绪后调用此函数,并在组件卸载或停止跟随系统时执行返回的清理函数。React 等集成中保留已有实例,通过 Facade 更新外观。

让自定义插件跟随主题与语言

DOM 扩展使用运行时注入的 CSS 变量,并为深色模式类提供对应状态。CSS 变量保存色板值,深色模式状态仍需由组件自己的样式规则消费。

CSS
.report-panel {  color: var(--univer-gray-900);  background: var(--univer-gray-0);  border: 1px solid var(--univer-gray-200);}.univer-dark .report-panel {  color: var(--univer-gray-100);  background: var(--univer-gray-800);  border-color: var(--univer-gray-700);}

Canvas 扩展通过 ThemeService 读取当前 Token,再通过 ICanvasColorService 获取用于实际绘制的颜色。下面把主题、深色模式与语言变化合并为可订阅状态;文字在更新时翻译,颜色在状态变化时解析,避免每帧重复查找和分配。

TypeScript
import { Disposable, Inject, LocaleService, ThemeService, toDisposable } from '@univerjs/core';import { ICanvasColorService } from '@univerjs/engine-render';import { combineLatest, ReplaySubject } from 'rxjs';export interface IReportAppearance {  label: string;  accent: string;}export class ReportAppearance extends Disposable {  readonly state$ = new ReplaySubject<IReportAppearance>(1);  constructor(    @Inject(ThemeService) theme: ThemeService,    @Inject(LocaleService) locale: LocaleService,    @ICanvasColorService colors: ICanvasColorService,  ) {    super();    this.disposeWithMe(toDisposable(() => this.state$.complete()));    this.disposeWithMe(combineLatest([      theme.currentTheme$, theme.darkMode$, locale.currentLocale$,    ]).subscribe(() => {      this.state$.next({        label: locale.t('sales-report.generate'),        accent: colors.getRenderColor(theme.getColorFromTheme('primary.600')),      });    }));  }}

在业务插件中通过 DI 注册并获取 ReportAppearance,由视图或绘制控制器订阅 state$ 并刷新。订阅由使用方管理,状态服务在拥有者销毁时 dispose()。Node.js 也有主题与语言服务,但不会注入浏览器 CSS。

深色模式(Dark Mode)

Sheet、Doc、Slide、Relational Table、Canvases 和 PDF 共用应用主题,并支持深色模式。下面是本地标准演示的实际截图,界面与内容使用英文。深色显示不会把映射后的显示颜色写回 Snapshot;应用外观与 PDF 页面内容处理分别配置,PDF 的本地验证结果见下方说明。

产品共享主题深色模式界面国际化
Sheet✓✓✓
Doc✓✓✓
Slide✓✓✓
Relational Table✓✓✓
Canvases✓✓✓
PDF✓界面支持;正文存在显示问题✓

语言能力使用各产品和已安装功能提供的资源,目标语言的覆盖范围以对应包为准。应用色板不会代替产品插件注册、语言资源加载或样式表导入。

19 个内置语言/地区选项

以下为 LocaleType 的 19 个内置选项,包含中文的简体、繁体和香港繁体变体。六个产品的主要 UI 包均提供这些语言资源;扩展插件的覆盖范围以所用包为准。语言包标签用于导入路径,初始化与 Facade 配置使用对应枚举值。

RTL 支持范围: 阿拉伯语(ar-SA)等语言包提供菜单、提示等界面翻译;direction: 'rtl' 目前仅用于菜单等界面 UI 的方向适配。Canvas 内容区尚未实现 RTL 排版与编辑。

语言(原文名称)语言包标签配置值
Englishen-USLocaleType.EN_US
简体中文zh-CNLocaleType.ZH_CN
繁體中文zh-TWLocaleType.ZH_TW
繁體中文(香港)zh-HKLocaleType.ZH_HK
日本語ja-JPLocaleType.JA_JP
한국어ko-KRLocaleType.KO_KR
Tiếng Việtvi-VNLocaleType.VI_VN
Bahasa Indonesiaid-IDLocaleType.ID_ID
Françaisfr-FRLocaleType.FR_FR
Deutschde-DELocaleType.DE_DE
Españoles-ESLocaleType.ES_ES
Catalàca-ESLocaleType.CA_ES
Italianoit-ITLocaleType.IT_IT
Português (Brasil)pt-BRLocaleType.PT_BR
Polskipl-PLLocaleType.PL_PL
Slovenčinask-SKLocaleType.SK_SK
Русскийru-RULocaleType.RU_RU
فارسیfa-IRLocaleType.FA_IR
العربيةar-SALocaleType.AR_SA

跨产品的国际化资源: 以当前 1.2.0 源码为例,Web SDK 与 Pro 编辑器的 92 个模块提供 1,751 个语言资源入口文件,覆盖公共 UI、产品编辑器及公式、数字格式、评论等功能。资源按模块维护和发布,应用按启用功能与目标语言组合加载。

统计范围为两套源码 packages/*/src/locale 下的语言入口 .ts 文件,不含测试与生成子目录;文件数量不代表每个模块都完整覆盖 19 个选项。部分模块提供额外语言资源,统一内置选项以 LocaleType 为准。

语言资源按插件组合,按需加载与切换

LocaleService 以语言标识组织资源,按命名空间和键路径查找文字。mergeLocales() 组合产品预设、功能插件和业务翻译,loadLocales() 动态合并资源,setLocale() 才选择当前语言。切换本身不会自动下载语言包。

100%

下面为前面的 Sheet 实例补充中文资源,切换界面语言,并显式保留德国地区习惯。LocaleType.ZH_CN 的值是 zhCN;zh-CN 是语言包文件或文档路由的写法。

TypeScript
import type { FUniver } from '@univerjs/core/facade';import { LocaleType, mergeLocales } from '@univerjs/core';import SheetsCoreZhCN from '@univerjs/preset-sheets-core/locales/zh-CN';export function switchInterface(univerAPI: FUniver): void {  univerAPI.loadLocales(LocaleType.ZH_CN, mergeLocales(SheetsCoreZhCN, {    'sales-report': { generate: '生成报告', ready: '已为 {0} 就绪' },  }));  univerAPI.setLocale(LocaleType.ZH_CN);  univerAPI.setRegion(LocaleType.DE_DE);  univerAPI.setDirection('ltr');}

业务键如 sales-report.generate 随所属插件管理。需要动态参数时使用完整翻译句子与 {0}、{1} 占位符,例如 LocaleService.t('sales-report.ready', 'Alex');不要在模块加载时缓存翻译。资源已经初始化但键缺失时,当前实现返回键名。界面语言切换不会翻译正文或重命名已有 Unit。

区分语言、地区和内容格式

层次实际影响
界面语言 locale菜单、提示、插件文字;部分语言相关行为还使用它,例如文档分词。
地区 region支持该设置的货币操作、评论时间显示和统计数字格式等;不换算金额,也不修改时间戳。
内容数字格式Sheet 已保存的数字/日期格式由单元格格式及相应内容 locale 决定,不会因切换地区统一重写。
布局方向 direction独立控制 UI 的左右方向,切换语言或地区不会自动修改它。

未显式指定地区时使用对应默认值;一旦显式设置 region,可以与界面语言独立选择。region 不是时区配置。当前 RTL 仅用于菜单等界面 UI 的方向适配;Canvas 内容区尚未实现从右到左的排版与编辑。

内容主题与应用主题各有边界

应用主题控制工作台与渲染默认值,不会重写持久化的单元格填充、文字、图形、PDF 标注或显式图表颜色。范围/表格主题、Slide 内容色彩方案、Canvases 内容主题等,通过各自产品的公开能力管理。

Pro 图表还有独立的 IEchartTheme 注册表。它可以被 Sheet、Doc、Slide 和 Canvases 图表共享,不能直接传入应用的 Theme。在已经安装相应图表插件的宿主中,导入图表 Facade 后可注册完整主题:

TypeScript
import type { IEchartTheme } from '@univerjs-pro/engine-chart';import type { FUniver } from '@univerjs/core/facade';import { UniverTheme1 } from '@univerjs-pro/engine-chart';import '@univerjs-pro/engine-chart/facade';export function registerBrandChartTheme(univerAPI: FUniver): void {  const chartTheme: IEchartTheme = {    ...UniverTheme1,    themeName: 'sales-brand',    theme: {      ...UniverTheme1.theme,      color: ['#7C3AED', '#0EA5E9', '#10B981', '#F59E0B'],    },  };  univerAPI.registerTheme('sales-brand', chartTheme);}

图表创建时通过其 builder 的 setTheme('sales-brand') 选择此名称;显式图表调色板也可能覆盖主题中的系列颜色。

同一个浏览器文档中的应用外观还要统一:当前 UI 的 CSS 变量和 univer-dark 类写入文档根节点。多个编辑器实例要使用一致的外观,或通过 iframe 等独立文档隔离;不要把容器不同理解为 CSS 主题已经隔离。

继续阅读:主题与深色模式 · 国际化详细配置 · 插件与 Facade 扩展 · 图表能力

返回功能总览

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.