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.
// 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:
- The internal locale updates immediately.
- A
sciflow-locale-changeCustomEvent fires ondocument. - All mounted components re-render with the new strings.
- 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¶
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¶
- OJS determines the active locale as usual (user preference, journal default).
- The plugin reads OJS locale strings with
__()and passes them to JavaScript. registerTranslations()merges them into the editor's dictionary.- The
localeattribute on<sciflow-editor>(or asetLocale()call) activates the matching language. - 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.
Sub-path Import¶
The i18n module is also available as a dedicated sub-path export:
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.