Files
sm-journal-plugin/assets/src/blogeditor/labels.ts
Jakub Zych df67939251 feat(editor): toggleable preview pane in a sandboxed frame
- A per-element Preview toggle (aria-pressed, off by default) splits the editor 50/50 with an auto-fit grid that wraps the pane below on narrow widths.
- The pane is an iframe with an empty sandbox, content set only through srcdoc, created on first use; it reads only the value getter, so previewing never edits or emits summer-change.
2026-10-10 13:53:48 +02:00

161 lines
4.3 KiB
TypeScript

/** Every label, prompt and error the Blog Editor shows. */
export interface Labels {
tabWysiwyg: string
tabSource: string
toolbar: string
paragraph: string
heading2: string
heading3: string
heading4: string
bold: string
italic: string
bulletList: string
orderedList: string
link: string
blockquote: string
insertTable: string
addRow: string
deleteRow: string
addColumn: string
deleteColumn: string
deleteTable: string
image: string
embed: string
rawHtml: string
undo: string
redo: string
linkUrl: string
linkApply: string
linkRemove: string
linkInvalid: string
embedUrl: string
embedInsert: string
embedInvalid: string
cancel: string
uploading: string
uploadFailed: string
uploadTimeout: string
notAnImage: string
altText: string
caption: string
altRequired: string
insertImage: string
rawHtmlCard: string
editAsHtml: string
embedCard: string
preview: string
previewFrame: string
}
const en: Labels = {
tabWysiwyg: 'WYSIWYG',
tabSource: 'Source',
toolbar: 'Formatting',
paragraph: 'Paragraph',
heading2: 'Heading 2',
heading3: 'Heading 3',
heading4: 'Heading 4',
bold: 'Bold',
italic: 'Italic',
bulletList: 'Bullet list',
orderedList: 'Numbered list',
link: 'Link',
blockquote: 'Quote',
insertTable: 'Insert table',
addRow: 'Add row',
deleteRow: 'Delete row',
addColumn: 'Add column',
deleteColumn: 'Delete column',
deleteTable: 'Delete table',
image: 'Image',
embed: 'Embed video',
rawHtml: 'HTML block',
undo: 'Undo',
redo: 'Redo',
linkUrl: 'Link URL',
linkApply: 'Apply',
linkRemove: 'Remove link',
linkInvalid: 'Links must use http, https, mailto or a relative URL.',
embedUrl: 'YouTube URL',
embedInsert: 'Insert',
embedInvalid: 'This video URL is not supported. Paste a YouTube link.',
cancel: 'Cancel',
uploading: 'Uploading {name}…',
uploadFailed: 'Upload failed: {error}',
uploadTimeout: 'The upload of {name} took too long.',
notAnImage: 'Only JPEG, PNG, GIF and WebP images can be uploaded.',
altText: 'Alt text (required)',
caption: 'Caption (optional)',
altRequired: 'Enter the alt text.',
insertImage: 'Insert image',
rawHtmlCard: 'HTML block',
editAsHtml: 'Edit as HTML',
embedCard: 'Embedded video',
preview: 'Preview',
previewFrame: 'Post preview',
}
const pl: Labels = {
tabWysiwyg: 'WYSIWYG',
tabSource: 'Źródło',
toolbar: 'Formatowanie',
paragraph: 'Akapit',
heading2: 'Nagłówek 2',
heading3: 'Nagłówek 3',
heading4: 'Nagłówek 4',
bold: 'Pogrubienie',
italic: 'Kursywa',
bulletList: 'Lista punktowana',
orderedList: 'Lista numerowana',
link: 'Link',
blockquote: 'Cytat',
insertTable: 'Wstaw tabelę',
addRow: 'Dodaj wiersz',
deleteRow: 'Usuń wiersz',
addColumn: 'Dodaj kolumnę',
deleteColumn: 'Usuń kolumnę',
deleteTable: 'Usuń tabelę',
image: 'Obraz',
embed: 'Osadź wideo',
rawHtml: 'Blok HTML',
undo: 'Cofnij',
redo: 'Ponów',
linkUrl: 'Adres linku',
linkApply: 'Zastosuj',
linkRemove: 'Usuń link',
linkInvalid: 'Link musi używać http, https, mailto albo adresu względnego.',
embedUrl: 'Adres filmu YouTube',
embedInsert: 'Wstaw',
embedInvalid: 'Ten adres filmu nie jest obsługiwany. Wklej link do YouTube.',
cancel: 'Anuluj',
uploading: 'Wysyłanie {name}…',
uploadFailed: 'Wysyłanie nie powiodło się: {error}',
uploadTimeout: 'Wysyłanie {name} trwało zbyt długo.',
notAnImage: 'Można wysłać tylko obrazy JPEG, PNG, GIF i WebP.',
altText: 'Tekst alternatywny (wymagany)',
caption: 'Podpis (opcjonalny)',
altRequired: 'Wpisz tekst alternatywny.',
insertImage: 'Wstaw obraz',
rawHtmlCard: 'Blok HTML',
editAsHtml: 'Edytuj jako HTML',
embedCard: 'Osadzone wideo',
preview: 'Podgląd',
previewFrame: 'Podgląd wpisu',
}
const TABLES: Record<string, Labels> = { en, pl }
/**
* labelsFor returns the labels for the admin UI locale (the element's
* ui-locale attribute): the table for its language subtag, else English.
*/
export function labelsFor(uiLocale: string | null | undefined): Labels {
const language = (uiLocale ?? '').toLowerCase().split(/[-_]/)[0] ?? ''
return TABLES[language] ?? en
}
/** format replaces {name} placeholders in a label. */
export function format(label: string, values: Record<string, string>): string {
return label.replace(/\{(\w+)\}/g, (match, key: string) => values[key] ?? match)
}