Files
bDS/src/main/shared/menuCommands.ts
Georg Bauer b855d61524 Feature/post media translations (#42)
* chore: updated todo with translation ideas

* feat: first take at the implementation of translations

* fix: small addition for the translation feature

* feat: support language switching in the editor and preview

* feat: better handling of long bodies by not running them through a json envelope

* fix: unknown macros have better fallback

* feat: api for python to get translations

* fix: strip dumb prefix of content in translation

* feat: extend meta diff for translations

* feat: hook up translations to rebuild-from-disk

* feat: generation of the website prefers project language, falling back to canonical language

* fix: crashes during rendering

* feat: translation validation report

* fix: made the translation validation actually work

* chore: reorganization of menu

* fix: some topics cleanup

* chore: updated doc

* feat: translations for media

* feat: more aligned in UI/UX

* feat: edit translations possible

* chore: added full multi-language todo

* chore: updated todo for clarity

* feat: implementation of full multi-linguality

* fix: page creation creates pages

* fix: flags on every page

* fix: better prompt

* feat: made MCP server aware of language content

* feat: python tools for translations

* fix: better fill-in-translations

* fix: better prompt for translation. maybe.

* fix: losing posts from search due to translation process

* fix: translation validation handles in-db content and fill-in of missing translations fixed to flush

* fix: faster scanning for infilling of missing translations

* chore: updated agent instructions

* feat: calendar and tag cloud respect current language now

* fix: retries going up

* fix: got metadata-diff and rebuild into sync

* fix: extended meta-diff for timestamps

* fix: made website validation look at translated content, too

* fix: multi-lingual search

* chore: refactor Editor.tsx into two separate editors

* feat: do language detection when no explicit language given

---------

Co-authored-by: hugo <hugoms@me.com>
2026-03-09 14:43:18 +01:00

209 lines
7.9 KiB
TypeScript

export type AppMenuAction =
| 'newPost'
| 'importMedia'
| 'save'
| 'openInBrowser'
| 'openDataFolder'
| 'quit'
| 'undo'
| 'redo'
| 'cut'
| 'copy'
| 'paste'
| 'delete'
| 'selectAll'
| 'find'
| 'replace'
| 'editPreferences'
| 'viewPosts'
| 'viewMedia'
| 'toggleSidebar'
| 'togglePanel'
| 'toggleAssistantSidebar'
| 'toggleDevTools'
| 'reload'
| 'forceReload'
| 'resetZoom'
| 'zoomIn'
| 'zoomOut'
| 'toggleFullScreen'
| 'publishSelected'
| 'previewPost'
| 'rebuildDatabase'
| 'reindexText'
| 'rebuildEmbeddingIndex'
| 'metadataDiff'
| 'editMenu'
| 'generateSitemap'
| 'regenerateCalendar'
| 'validateSite'
| 'validateTranslations'
| 'uploadSite'
| 'openDocumentation'
| 'openApiDocumentation'
| 'fillMissingTranslations'
| 'findDuplicates'
| 'about'
| 'viewOnGitHub'
| 'reportIssue';
export type AppMenuRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'delete' | 'selectAll';
export interface AppMenuItemDefinition {
label: string;
action: AppMenuAction | `${string}-separator-${number}`;
accelerator?: string;
separator?: boolean;
role?: AppMenuRole;
id?: string;
enabled?: boolean;
}
export interface AppMenuGroupDefinition {
label: 'File' | 'Edit' | 'View' | 'Blog' | 'Help';
items: AppMenuItemDefinition[];
}
export const APP_MENU_ITEM_IDS = {
previewPost: 'blog.previewPost',
} as const;
export const APP_MENU_GROUPS: AppMenuGroupDefinition[] = [
{
label: 'File',
items: [
{ label: 'menu.item.newPost', action: 'newPost', accelerator: 'CmdOrCtrl+N' },
{ label: 'menu.item.importMedia', action: 'importMedia', accelerator: 'CmdOrCtrl+I' },
{ label: '', action: 'file-separator-0', separator: true },
{ label: 'menu.item.save', action: 'save', accelerator: 'CmdOrCtrl+S' },
{ label: '', action: 'file-separator-1', separator: true },
{ label: 'menu.item.openInBrowser', action: 'openInBrowser' },
{ label: '', action: 'file-separator-2', separator: true },
{ label: 'menu.item.openDataFolder', action: 'openDataFolder' },
{ label: '', action: 'file-separator-3', separator: true },
{ label: 'menu.item.quit', action: 'quit', accelerator: 'CmdOrCtrl+Q' },
],
},
{
label: 'Edit',
items: [
{ label: 'menu.item.undo', action: 'undo', accelerator: 'CmdOrCtrl+Z', role: 'undo' },
{ label: 'menu.item.redo', action: 'redo', accelerator: 'CmdOrCtrl+Y', role: 'redo' },
{ label: '', action: 'edit-separator-1', separator: true },
{ label: 'menu.item.cut', action: 'cut', accelerator: 'CmdOrCtrl+X', role: 'cut' },
{ label: 'menu.item.copy', action: 'copy', accelerator: 'CmdOrCtrl+C', role: 'copy' },
{ label: 'menu.item.paste', action: 'paste', accelerator: 'CmdOrCtrl+V', role: 'paste' },
{ label: 'menu.item.delete', action: 'delete', role: 'delete' },
{ label: '', action: 'edit-separator-2', separator: true },
{ label: 'menu.item.selectAll', action: 'selectAll', accelerator: 'CmdOrCtrl+A', role: 'selectAll' },
{ label: '', action: 'edit-separator-3', separator: true },
{ label: 'menu.item.find', action: 'find', accelerator: 'CmdOrCtrl+F' },
{ label: 'menu.item.replace', action: 'replace', accelerator: 'CmdOrCtrl+H' },
{ label: 'menu.item.editPreferences', action: 'editPreferences', accelerator: 'CmdOrCtrl+,' },
],
},
{
label: 'View',
items: [
{ label: 'menu.item.viewPosts', action: 'viewPosts', accelerator: 'CmdOrCtrl+1' },
{ label: 'menu.item.viewMedia', action: 'viewMedia', accelerator: 'CmdOrCtrl+2' },
{ label: 'menu.item.toggleSidebar', action: 'toggleSidebar', accelerator: 'CmdOrCtrl+B' },
{ label: 'menu.item.togglePanel', action: 'togglePanel', accelerator: 'CmdOrCtrl+J' },
{ label: 'menu.item.toggleAssistantSidebar', action: 'toggleAssistantSidebar', accelerator: 'CmdOrCtrl+\\' },
{ label: 'menu.item.toggleDevTools', action: 'toggleDevTools', accelerator: 'CmdOrCtrl+Shift+I' },
{ label: '', action: 'view-separator-1', separator: true },
{ label: 'menu.item.reload', action: 'reload' },
{ label: 'menu.item.forceReload', action: 'forceReload' },
{ label: '', action: 'view-separator-2', separator: true },
{ label: 'menu.item.resetZoom', action: 'resetZoom' },
{ label: 'menu.item.zoomIn', action: 'zoomIn' },
{ label: 'menu.item.zoomOut', action: 'zoomOut' },
{ label: '', action: 'view-separator-3', separator: true },
{ label: 'menu.item.toggleFullScreen', action: 'toggleFullScreen' },
],
},
{
label: 'Blog',
items: [
{ label: 'menu.item.publishSelected', action: 'publishSelected', accelerator: 'CmdOrCtrl+Shift+P' },
{ label: '', action: 'blog-separator-1', separator: true },
{ label: 'menu.item.previewPost', action: 'previewPost', id: APP_MENU_ITEM_IDS.previewPost, enabled: false, accelerator: 'CmdOrCtrl+Shift+V' },
{ label: 'menu.item.editMenu', action: 'editMenu' },
{ label: '', action: 'blog-separator-2', separator: true },
{ label: 'menu.item.rebuildDatabase', action: 'rebuildDatabase' },
{ label: 'menu.item.reindexText', action: 'reindexText' },
{ label: 'menu.item.rebuildEmbeddingIndex', action: 'rebuildEmbeddingIndex' },
{ label: '', action: 'blog-separator-3', separator: true },
{ label: 'menu.item.metadataDiff', action: 'metadataDiff' },
{ label: 'menu.item.regenerateCalendar', action: 'regenerateCalendar' },
{ label: 'menu.item.validateTranslations', action: 'validateTranslations' },
{ label: 'menu.item.fillMissingTranslations', action: 'fillMissingTranslations' },
{ label: 'menu.item.findDuplicates', action: 'findDuplicates' },
{ label: '', action: 'blog-separator-4', separator: true },
{ label: 'menu.item.generateSitemap', action: 'generateSitemap', accelerator: 'CmdOrCtrl+R' },
{ label: 'menu.item.validateSite', action: 'validateSite', accelerator: 'CmdOrCtrl+Shift+L' },
{ label: 'menu.item.uploadSite', action: 'uploadSite', accelerator: 'CmdOrCtrl+Shift+U' },
],
},
{
label: 'Help',
items: [
{ label: 'menu.item.about', action: 'about' },
{ label: 'menu.item.openDocumentation', action: 'openDocumentation' },
{ label: 'menu.item.openApiDocumentation', action: 'openApiDocumentation' },
{ label: '', action: 'help-separator-1', separator: true },
{ label: 'menu.item.viewOnGitHub', action: 'viewOnGitHub' },
{ label: 'menu.item.reportIssue', action: 'reportIssue' },
],
},
];
export const APP_MENU_ACTION_EVENT_MAP: Partial<Record<AppMenuAction, string>> = {
newPost: 'menu:newPost',
importMedia: 'menu:importMedia',
save: 'menu:save',
find: 'menu:find',
replace: 'menu:replace',
editPreferences: 'menu:editPreferences',
viewPosts: 'menu:viewPosts',
viewMedia: 'menu:viewMedia',
toggleSidebar: 'menu:toggleSidebar',
togglePanel: 'menu:togglePanel',
toggleAssistantSidebar: 'menu:toggleAssistantSidebar',
toggleDevTools: 'menu:toggleDevTools',
previewPost: 'menu:previewPost',
publishSelected: 'menu:publishSelected',
rebuildDatabase: 'menu:rebuildDatabase',
reindexText: 'menu:reindexText',
rebuildEmbeddingIndex: 'menu:rebuildEmbeddingIndex',
metadataDiff: 'menu:metadataDiff',
editMenu: 'menu:editMenu',
generateSitemap: 'menu:generateSitemap',
regenerateCalendar: 'menu:regenerateCalendar',
validateSite: 'menu:validateSite',
validateTranslations: 'menu:validateTranslations',
fillMissingTranslations: 'menu:fillMissingTranslations',
findDuplicates: 'menu:findDuplicates',
uploadSite: 'menu:uploadSite',
openDocumentation: 'menu:openDocumentation',
openApiDocumentation: 'menu:openApiDocumentation',
about: 'menu:about',
};
export const APP_MENU_WEB_CONTENTS_ACTIONS: ReadonlySet<AppMenuAction> = new Set([
'undo',
'redo',
'cut',
'copy',
'paste',
'delete',
'selectAll',
'toggleDevTools',
'reload',
'forceReload',
'resetZoom',
'zoomIn',
'zoomOut',
'toggleFullScreen',
]);