Skip to content

Localization (i18n)

The editor ships with built-in English and German translations for all UI strings — toolbar labels, command descriptions, outline placeholders, and accessibility text.

Switching the Language

Via HTML attribute

The <sciflow-editor> element accepts a locale attribute. Set it declaratively or update it at runtime — the editor and all connected components switch immediately.

<!-- Set the initial locale declaratively -->
<sciflow-editor locale="de"></sciflow-editor>
// Or change it at runtime via the DOM property
document.querySelector('sciflow-editor').locale = 'en';

Via JavaScript

import { setLocale } from '@sciflow/editor-start';
// or: import { setLocale } from '@sciflow/editor-core';

// Switch to German
setLocale('de');

// Switch back to English
setLocale('en');

When setLocale() is called:

  1. The internal locale updates immediately.
  2. A sciflow-locale-change CustomEvent fires on document.
  3. All mounted components re-render with the new strings.
  4. Command metadata (tooltips, aria-labels) resolves to the new locale on next read.

No editor restart or feature re-initialization is needed.

Reading the Current Locale

import { getLocale } from '@sciflow/editor-start';

console.log(getLocale()); // 'en' | 'de'

Available Locales

Code Language
en English (default)
de German

Using the Translation Function Directly

If you build custom UI around the editor, you can use t() to access any translation key:

import { t } from '@sciflow/editor-start';

const label = t('cmd.insertNativeTableFigure.label');
// English: "Insert table"
// German:  "Tabelle einfügen"

Listening for Locale Changes

Custom components can react to locale switches by listening for the event:

import { LOCALE_CHANGE_EVENT } from '@sciflow/editor-start';

document.addEventListener(LOCALE_CHANGE_EVENT, (event) => {
  const { locale } = event.detail;
  console.log(`Locale changed to: ${locale}`);
});

Adding Custom Translations

If you build custom UI components around the editor, use registerTranslations() to add your own keys to the shared dictionary. This way your components use the same t() function and react to the same setLocale() calls — no separate i18n system needed.

import { registerTranslations, t } from '@sciflow/editor-start';

// Register translations for each locale you support
registerTranslations('en', {
  'myApp.sidebar.title': 'My Sidebar',
  'myApp.exportButton': 'Export PDF',
});

registerTranslations('de', {
  'myApp.sidebar.title': 'Meine Seitenleiste',
  'myApp.exportButton': 'PDF exportieren',
});

// Use the same t() everywhere
const label = t('myApp.sidebar.title');

Custom keys are resolved before built-in keys, so you can also override any built-in string if needed. Subsequent calls for the same locale merge into the existing entries.

Namespace your keys

Use a prefix like myApp. or acme. to avoid collisions with current or future built-in keys.

Lit Component Example

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { t, LOCALE_CHANGE_EVENT, registerTranslations } from '@sciflow/editor-start';

registerTranslations('en', { 'myWidget.heading': 'Dashboard' });
registerTranslations('de', { 'myWidget.heading': 'Übersicht' });

@customElement('my-widget')
class MyWidget extends LitElement {
  private localeListener?: EventListener;

  connectedCallback(): void {
    super.connectedCallback();
    this.localeListener = () => this.requestUpdate();
    document.addEventListener(LOCALE_CHANGE_EVENT, this.localeListener);
  }

  disconnectedCallback(): void {
    if (this.localeListener) {
      document.removeEventListener(LOCALE_CHANGE_EVENT, this.localeListener);
    }
    super.disconnectedCallback();
  }

  render() {
    return html`<h2>${t('myWidget.heading')}</h2>`;
  }
}

React Component Example

import { useEffect, useState } from 'react';
import { t, registerTranslations, LOCALE_CHANGE_EVENT, getLocale } from '@sciflow/editor-start';

registerTranslations('en', { 'myPanel.title': 'Analytics' });
registerTranslations('de', { 'myPanel.title': 'Auswertungen' });

function MyPanel() {
  const [, setLocale] = useState(getLocale());

  useEffect(() => {
    const handler = (e: Event) => setLocale((e as CustomEvent).detail.locale);
    document.addEventListener(LOCALE_CHANGE_EVENT, handler);
    return () => document.removeEventListener(LOCALE_CHANGE_EVENT, handler);
  }, []);

  return <h2>{t('myPanel.title')}</h2>;
}

Integration with PKP OJS

PKP OJS has its own XML-based locale system (locale/<code>/locale.xml). An OJS plugin can bridge the two systems so the editor inherits whatever language OJS is currently using.

Mapping OJS locale strings to the editor

In your plugin's page or template handler, read the OJS locale and pass the editor's built-in keys through registerTranslations():

// In your OJS plugin (PHP side)
// Pass the current OJS locale and any custom strings to the frontend
$templateMgr->assign('ojsLocale', AppLocale::getLocale());        // e.g. "de_DE"
$templateMgr->assign('editorStrings', json_encode([
    'myPlugin.submitManuscript' => __('plugins.generic.sciflow.submitManuscript'),
    'myPlugin.saveProgress'     => __('plugins.generic.sciflow.saveProgress'),
]));
<!-- In your Smarty template -->
<sciflow-editor id="editor" locale="{$ojsLocale|substr:0:2}"></sciflow-editor>

<script type="module">
  import { registerTranslations, setLocale } from '@sciflow/editor-start';

  // Register plugin-specific strings translated via OJS's locale XML
  const strings = {$editorStrings|json_encode};
  const locale = '{$ojsLocale|substr:0:2}'; // "de_DE" → "de"

  registerTranslations(locale, strings);
  setLocale(locale);
</script>

OJS locale XML example

Add your plugin's editor strings to the standard OJS locale file:

<!-- plugins/generic/sciflow/locale/en/locale.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<locale name="en" full_name="English">
  <message key="plugins.generic.sciflow.submitManuscript">Submit Manuscript</message>
  <message key="plugins.generic.sciflow.saveProgress">Save Progress</message>
</locale>
<!-- plugins/generic/sciflow/locale/de/locale.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<locale name="de" full_name="Deutsch">
  <message key="plugins.generic.sciflow.submitManuscript">Manuskript einreichen</message>
  <message key="plugins.generic.sciflow.saveProgress">Fortschritt speichern</message>
</locale>

How it works

  1. OJS determines the active locale as usual (user preference, journal default).
  2. The plugin reads OJS locale strings with __() and passes them to JavaScript.
  3. registerTranslations() merges them into the editor's dictionary.
  4. The locale attribute on <sciflow-editor> (or a setLocale() call) activates the matching language.
  5. Built-in editor strings (toolbar, commands, accessibility labels) switch automatically. Plugin-specific strings resolve through the same t() function.

The editor ships with English and German built-in. For other OJS-supported languages, use registerTranslations() to provide translations for the editor's built-in keys as well — they are listed in the translation key reference below.

OJS locale codes

OJS uses codes like de_DE, fr_FR, es_ES. The editor expects the two-letter language prefix (de, fr, es). Extract it with substr(0, 2) or equivalent.

Adding a New Language

The editor ships with English and German. To add a new language (e.g. for an OJS journal in French, Spanish, or Portuguese), provide translations for all built-in keys via registerTranslations().

Step 1: Extract the key template

Use the built-in extraction script to dump all keys with their English defaults:

# JSON (default) — use as a translation template
npx @sciflow/editor-start extract-translations > en.json

# CSV — handy for spreadsheet-based translation workflows
npx @sciflow/editor-start extract-translations --csv > en.csv

The JSON output looks like:

{
  "cmd.insertNativeTableFigure.label": "Insert table",
  "cmd.toggleBold.label": "Bold",
  "formatBar.undo": "Undo",
  "selectionEditor.noElement": "No element selected. Click or select an element in the editor.",
  ...
}

Copy the JSON file, translate the values, and save it as your locale file (e.g. fr.json).

For compile-time safety, use the TranslationDictionary type (exported from @sciflow/editor-core) — your IDE will flag missing keys:

import type { TranslationDictionary } from '@sciflow/editor-start';

const fr: TranslationDictionary = {
  'cmd.insertNativeTableFigure.label': 'Insérer un tableau',
  // ... IDE will error on any missing key
};

The complete key list is also available in the translation key reference below.

Step 2: Register and activate

import { registerTranslations, setLocale } from '@sciflow/editor-start';

registerTranslations('fr', fr);
setLocale('fr');

All built-in components (format bar, selection editor, outline, reference list) will immediately render in French.

Step 3 (optional): Type-safe locale codes

If you want TypeScript to accept your new locale code, augment the Locale type:

declare module '@sciflow/editor-core' {
  export type Locale = 'en' | 'de' | 'fr';
}

Partial translations

registerTranslations() merges keys — you don't have to provide all keys at once. Missing keys fall back to English. This is useful for incremental translation or for overriding only a few labels.

Sub-path Import

The i18n module is also available as a dedicated sub-path export:

import { setLocale, t } from '@sciflow/editor-core/i18n';

Server-Side / Node.js

setLocale() and t() work in Node.js. The CustomEvent dispatch is skipped when document is unavailable, so the runtime is safe for SSR.

Translation Key Reference

Every built-in key, its English default, and where it appears. Use this as a checklist when translating to a new language.

Commands (cmd.*)

Key English Context
cmd.insertNativeTableFigure.label Insert table Format bar insert menu
cmd.insertNativeTableFigure.description Insert a native table with caption Tooltip
cmd.addColumnBefore.label Add column before Table toolbar
cmd.addColumnBefore.description Add column before Tooltip
cmd.addColumnAfter.label Add column after Table toolbar
cmd.addColumnAfter.description Add column after Tooltip
cmd.deleteColumn.label Delete column Table toolbar
cmd.deleteColumn.description Delete column Tooltip
cmd.addRowBefore.label Add row above Table toolbar
cmd.addRowBefore.description Add row above Tooltip
cmd.addRowAfter.label Add row below Table toolbar
cmd.addRowAfter.description Add row below Tooltip
cmd.deleteRow.label Delete row Table toolbar
cmd.deleteRow.description Delete row Tooltip
cmd.mergeCells.label Merge cells Table toolbar
cmd.mergeCells.description Merge cells Tooltip
cmd.splitCell.label Split cell Table toolbar
cmd.splitCell.description Split cell Tooltip
cmd.toggleHeaderRow.label Toggle header row Table toolbar
cmd.toggleHeaderRow.description Toggle header row Tooltip
cmd.toggleHeaderColumn.label Toggle header column Table toolbar
cmd.toggleHeaderColumn.description Toggle header column Tooltip
cmd.goToNextCell.label Next cell Table toolbar
cmd.goToNextCell.description Move to next cell Tooltip
cmd.deleteTable.label Delete table Table toolbar
cmd.deleteTable.description Delete table Tooltip
cmd.alignLeft.label Align left Table toolbar
cmd.alignCenter.label Align center Table toolbar
cmd.alignRight.label Align right Table toolbar
cmd.alignJustify.label Justify Table toolbar
cmd.toggleBulletList.label Bullet list Format bar
cmd.toggleBulletList.description Toggle bullet list formatting Tooltip
cmd.toggleOrderedList.label Ordered list Format bar
cmd.toggleOrderedList.description Toggle ordered list formatting Tooltip
cmd.sinkListItem.label Increase indent Format bar
cmd.sinkListItem.description Indent the current list item Tooltip
cmd.liftListItem.label Decrease indent Format bar
cmd.liftListItem.description Outdent the current list item Tooltip
cmd.insertFigureInteractive.label Insert figure Format bar insert menu
cmd.insertFigureInteractive.description Upload and insert a figure Tooltip
cmd.insertMath.label Insert equation Format bar insert menu
cmd.insertMath.description Insert a math equation (Mod-m to wrap selection) Tooltip
cmd.insertFootnote.label Insert footnote Format bar insert menu
cmd.insertFootnote.description Insert a footnote at the cursor Tooltip
cmd.toggleBold.label Bold Format bar
cmd.toggleBold.description Toggle bold Tooltip
cmd.toggleItalic.label Italic Format bar
cmd.toggleItalic.description Toggle italic Tooltip
cmd.toggleSuperscript.label Superscript Format bar
cmd.toggleSuperscript.description Toggle superscript Tooltip
cmd.toggleSubscript.label Subscript Format bar
cmd.toggleSubscript.description Toggle subscript Tooltip
cmd.insertHyperlink.label Link Format bar
cmd.insertHyperlink.description Insert or remove a hyperlink Tooltip
cmd.toggleBlockquote.label Blockquote Format bar
cmd.toggleBlockquote.description Toggle blockquote formatting Tooltip

Format bar (formatBar.*)

Key English Context
formatBar.styleParagraph Paragraph Block style dropdown
formatBar.styleHeading1 Heading 1 Block style dropdown
formatBar.styleHeading2 Heading 2 Block style dropdown
formatBar.styleHeading3 Heading 3 Block style dropdown
formatBar.undo Undo Toolbar button
formatBar.undoDescription Undo last change Tooltip
formatBar.redo Redo Toolbar button
formatBar.redoDescription Redo last change Tooltip
formatBar.textStyleAriaLabel Text style ARIA label for style dropdown
formatBar.historyAriaLabel History commands ARIA label for undo/redo group
formatBar.insert Insert Insert menu trigger
formatBar.toolbarAriaLabel Formatting toolbar ARIA label for toolbar
formatBar.tableLabel Table Table menu trigger
formatBar.tableAriaLabel Table commands ARIA label for table group

Outline (outline.*)

Key English Context
outline.noHeadings No headings yet. Empty state
outline.untitledSection Untitled section Heading without text
outline.figure Figure Figure entry label
outline.headingIdAriaLabel Heading id ARIA label
outline.figureIdAriaLabel Figure id ARIA label
outline.insertCrossReference Insert ref Button label
outline.insertCrossReferenceAriaLabel Insert cross-reference ARIA label

Reference list (referenceList.*)

Key English Context
referenceList.noReferences No references yet. Empty state
referenceList.cslIdAriaLabel CSL id ARIA label
referenceList.insertCitation Cite Button label

Math (math.*)

Key English Context
math.styleInline Inline Style toggle
math.styleDisplay Display Style toggle

Selection editor (selectionEditor.*)

Key English Context
selectionEditor.noElement No element selected. Click or select an element in the editor. Empty state
selectionEditor.type Type: Property label
selectionEditor.id ID: Property label
selectionEditor.attributes Attributes: Section label
selectionEditor.moreAttributes More attributes Expandable section
selectionEditor.altText Alt text Figure field label
selectionEditor.altTextPlaceholder Describe the image for accessibility Placeholder
selectionEditor.tex TeX Math field label
selectionEditor.texPlaceholder e.g. x^2 + y^2 = z^2 Placeholder
selectionEditor.style Style Math style label
selectionEditor.inline Inline Style option
selectionEditor.display Display Style option
selectionEditor.labelOptional Label (optional) Math label field
selectionEditor.labelPlaceholder eq:mylabel Placeholder
selectionEditor.preview Preview Math preview heading
selectionEditor.equationPreview Equation preview ARIA label
selectionEditor.apply Apply Button
selectionEditor.mathHint Ctrl+Enter to apply, Escape to cancel Hint text
selectionEditor.mathDocsLink MathJax 4 docs Link text
selectionEditor.inTextCitation In-text citation Citation field label
selectionEditor.inTextCitationAriaLabel In-text citation (supports bold and italic) ARIA label
selectionEditor.semanticReference Semantic reference: Citation field label
selectionEditor.update Update Button
selectionEditor.updateHint Ctrl+Enter to apply Hint text
selectionEditor.crossReference cross-reference Node type label
selectionEditor.displayText Display text Cross-ref field label
selectionEditor.displayTextPlaceholder e.g. Chapter 1, Figure 1, Abstract Placeholder
selectionEditor.target Target Cross-ref field label
selectionEditor.revert Revert Button
selectionEditor.draftHint Ctrl+Enter to apply, Escape to revert Hint text
selectionEditor.pinSelection Pin selection Toggle button
selectionEditor.unpinSelection Unpin selection Toggle button
selectionEditor.editFigure Edit figure ARIA label
selectionEditor.editEquation Edit equation ARIA label
selectionEditor.editCitation Edit citation ARIA label
selectionEditor.editCrossReference Edit cross-reference ARIA label
selectionEditor.figure figure Node type label
selectionEditor.math math Node type label
selectionEditor.citation citation Node type label
selectionEditor.heading heading Node type label
selectionEditor.paragraph paragraph Node type label
selectionEditor.expandAttributes Show technical attributes Toggle button
selectionEditor.collapseAttributes Hide technical attributes Toggle button
selectionEditor.hyperlink hyperlink Node type label
selectionEditor.editHyperlink Edit hyperlink ARIA label
selectionEditor.url URL Field label
selectionEditor.urlPlaceholder https://... Placeholder
selectionEditor.removeLink Remove link Button
selectionEditor.sectionElement Element Panel section
selectionEditor.sectionStructure Structure Panel section
selectionEditor.sectionFormatting Formatting Panel section
selectionEditor.sectionAttributes Attributes Panel section
selectionEditor.elementId Element ID Field label
selectionEditor.defaultValue Default Fallback label
selectionEditor.copied Copied! Toast message
selectionEditor.insert Insert… Button