Темы и локализация

Настройте внешний вид, тёмный режим и языковые ресурсы под приложение.

Темы и интернационализация — общие возможности runtime. Шесть продуктов и пользовательские плагины используют одинаковые сервисы темы, языковые ресурсы и региональные настройки. Внешний вид можно менять во время работы, сохраняя собственные данные и стили контента.

SDK предлагает 19 встроенных языковых и региональных вариантов интерфейса и 7 палитр темы. Все шесть продуктов используют общие настройки оформления, языка и региона; пользовательские темы и переводы приложения подключаются к тем же сервисам.

Общее состояние для интерфейса и рендеринга

ThemeService отдельно хранит полную палитру и тёмный режим, публикуя изменения через currentTheme$ и darkMode$. UI создаёт CSS-переменные --univer-* и реагирует на класс univer-dark. Рендереры наблюдают тот же сервис и помечают компоненты для перерисовки. Сервис цветов Canvas разрешает токены, преобразует цвета для тёмного отображения и кеширует результат.

Настройки и примеры этой главы рассчитаны на @univerjs/* и @univerjs-pro/* 1.2.0. Используйте согласованные версии зависимостей SDK в приложении.

НастройкаВарианты и область действияAPI во время работы
theme7 встроенных палитр или полная пользовательская Theme.setTheme()
darkModetrue / false, по умолчанию false; независимо от палитры.toggleDarkMode()
locale19 встроенных значений LocaleType; сначала загрузите ресурсы.setLocale()
localesОбъединение ресурсов продуктов, функций и приложения по идентификатору локали.loadLocales()
regionТе же значения LocaleType; следует языку UI до явной настройки.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. Палитра и тёмный режим задаются отдельно. Настраиваемые разделы:

Раздел темыНастраиваемые варианты
primary10 фирменных оттенков: 50, затем от 100 до 900.
gray12 нейтральных оттенков: 0, 50, от 100 до 900 и 1000.
blue · red · orange · yellow · green · jiqing · indigo · purple · pink9 функциональных шкал, по 10 оттенков в каждой.
loop-color12 позиций циклических цветов со ссылками на токены палитры.
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
.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, затем получают цвет рисования через 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')),      });    }));  }}

Зарегистрируйте и получите ReportAppearance через DI. Представление или контроллер рисования подписывается на state$ и обновляется. Подпиской управляет потребитель, а владелец сервиса вызывает dispose(). В Node.js эти сервисы тоже есть, но CSS браузера не внедряется.

Тёмный режим

Sheet, Doc, Slide, Relational Table, Canvases и PDF используют общую тему и поддерживают тёмный режим. Ниже реальные снимки локальных стандартных демо с английскими интерфейсом и контентом. Преобразованные экранные цвета не записываются обратно в Snapshot; внешний вид и обработка PDF-страниц разделены; результат локальной проверки приведён ниже.

ПродуктОбщая темаТёмный режимЛокализация UI
Sheet✓✓✓
Doc✓✓✓
Slide✓✓✓
Relational Table✓✓✓
Canvases✓✓✓
PDF✓UI поддержан; проблема отображения текста✓

Доступные языки зависят от ресурсов установленных продуктов и функций. Палитра не заменяет регистрацию продуктов, загрузку языков и импорт стилей.

19 встроенных языковых и региональных вариантов

LocaleType предоставляет следующие 19 вариантов, включая упрощённый, традиционный и гонконгский традиционный китайский. Основные UI-пакеты всех шести продуктов содержат эти ресурсы; покрытие расширений зависит от выбранного пакета. В путях импорта используйте теги языковых пакетов, а при инициализации и настройке Facade — соответствующие значения перечисления.

Область поддержки RTL: Арабский (ar-SA) и другие языковые пакеты переводят тексты интерфейса, включая меню и сообщения. direction: 'rtl' пока адаптирует только меню и подобные элементы UI. Размещение и редактирование RTL в области содержимого Canvas ещё не реализованы.

Язык (родное название)Тег пакетаЗначение настройки
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 92 модуля Web SDK и редакторов Pro содержат 1 751 файл входа языковых ресурсов для общего UI, редакторов, формул, числовых форматов и комментариев. Ресурсы поддерживаются и публикуются по модулям; приложение объединяет включённые функции и нужные языки.

Подсчитаны языковые входные .ts-файлы непосредственно в packages/*/src/locale обоих деревьев исходного кода, без тестов и генерируемых подкаталогов. Число файлов не означает полное покрытие всех 19 вариантов в каждом модуле. Некоторые модули содержат дополнительные языки; общие встроенные варианты определяет LocaleType.

Сборка ресурсов плагинов, загрузка и выбор языка

LocaleService группирует ресурсы по языку и ищет строки по пространствам имён и путям ключей. mergeLocales() объединяет пресеты, функции и бизнес-переводы. loadLocales() добавляет ресурсы во время работы, а setLocale() выбирает язык. Выбор не загружает пакет автоматически.

100%

Пример добавляет китайский язык к предыдущему Sheet, выбирает китайский UI и явно задаёт немецкие региональные правила. Значение LocaleType.ZH_CN — zhCN, а zh-CN используется в имени языкового файла и URL документации.

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'), не кешируя перевод при инициализации модуля. После инициализации ресурсов отсутствующий ключ сейчас возвращается как имя ключа. Смена языка UI не переводит контент и не переименовывает Unit.

Разделяйте язык, регион и форматы контента

УровеньРеальное влияние
locale интерфейсаМеню, сообщения, подписи и часть языковых функций, например сегментация документа.
regionПоддерживаемые денежные операции, даты комментариев и формат статистики; без конвертации сумм или изменения временных меток.
Числовые форматы контентаСохранённые форматы Sheet следуют настройкам ячеек и соответствующей locale контента; регион не переписывает их все.
directionНезависимое направление UI, без автоматической смены при выборе языка или региона.

Без явного региона действует соответствующее значение по умолчанию. После явного выбора region можно задать независимо от языка. Это не часовой пояс. RTL пока адаптирует только меню и подобные элементы UI. Размещение и редактирование справа налево в области содержимого Canvas ещё не реализованы.

Границы тем контента и приложения

Тема приложения управляет рабочей средой и стандартными цветами рендеринга, не переписывая сохранённые заливки, текст, фигуры, PDF-аннотации и явные цвета диаграмм. Темы диапазонов/таблиц, схемы Slide и темы Canvases управляются публичными возможностями соответствующего продукта.

Pro Charts использует отдельный реестр 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-переменные и univer-dark сейчас записываются в корень документа. Несколько редакторов должны использовать общую тему либо изолироваться в отдельных документах, например iframe. Разные контейнеры сами по себе не изолируют CSS-темы.

Подробнее: Темы и тёмный режим · Настройка i18n · Плагины и Facade · Диаграммы

Вернуться к обзору функций

Насколько полезно это руководство?

© 2026 DreamNum Co., Ltd.