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>
This commit is contained in:
Georg Bauer
2026-03-09 14:43:18 +01:00
committed by GitHub
parent f1c9038803
commit b855d61524
116 changed files with 19954 additions and 2094 deletions

View File

@@ -54,6 +54,33 @@
"siteValidation.error.validate": "Validazione del sito non riuscita",
"siteValidation.error.apply": "Applicazione della validazione non riuscita",
"siteValidation.toast.applySuccess": "Validazione applicata: {rendered} renderizzati, {deleted} eliminati",
"menu.item.validateTranslations": "Valida traduzioni",
"translationValidation.tabTitle": "Validazione traduzioni",
"translationValidation.title": "Valida traduzioni",
"translationValidation.summary": "Righe DB controllate: {dbRows} · File controllati: {files} · Righe DB non valide: {invalidDb} · File non validi: {invalidFiles}",
"translationValidation.loading": "Validazione traduzioni in corso...",
"translationValidation.empty": "Esegui Blog -> Valida traduzioni per controllare lintegrità delle traduzioni.",
"translationValidation.databaseTitle": "Righe di traduzione non valide nel database",
"translationValidation.filesystemTitle": "File di traduzione non validi sul disco",
"translationValidation.noneDatabase": "Nessuna riga di traduzione non valida trovata.",
"translationValidation.noneFilesystem": "Nessun file di traduzione non valido trovato.",
"translationValidation.error.validate": "Validazione traduzioni non riuscita",
"translationValidation.issue.sameLanguage": "La lingua della traduzione coincide con la lingua canonica del post",
"translationValidation.issue.missingSource": "La traduzione punta a un post sorgente mancante",
"translationValidation.issue.doNotTranslate": "Il post è contrassegnato come non-tradurre ma ha traduzioni",
"translationValidation.issue.contentInDatabase": "Traduzione pubblicata con contenuto nel DB invece del filesystem",
"translationValidation.field.translationFor": "Post sorgente",
"translationValidation.field.translationId": "Riga traduzione",
"translationValidation.field.title": "Titolo",
"translationValidation.field.languages": "Lingue",
"translationValidation.field.filePath": "File",
"translationValidation.languagesWithCanonical": "{canonical} = {translation}",
"translationValidation.revalidate": "Rivalidare",
"translationValidation.revalidating": "Rivalidazione…",
"translationValidation.fix": "Correggi problemi",
"translationValidation.fixing": "Correzione…",
"translationValidation.toast.fixSuccess": "{dbRows} righe DB e {files} file eliminati, {flushed} traduzioni scritte su disco",
"translationValidation.error.fix": "Correzione delle traduzioni non valide fallita",
"menuEditor.tabTitle": "Menu blog",
"menuEditor.title": "Editor del menu blog",
"menuEditor.description": "Gestisci la struttura centrale di navigazione del blog e salvala in meta/menu.opml.",
@@ -419,18 +446,18 @@
"metadataDiff.orphanFiles.badge": "File orfano",
"metadataDiff.orphanFiles.slug": "Slug",
"metadataDiff.orphanFiles.path": "Percorso",
"metadataDiff.orphanFiles.importButton": "D \u2192 DB",
"metadataDiff.orphanFiles.importButton": "D DB",
"metadataDiff.orphanFiles.importTitle": "Importa tutti i file orfani nel database",
"metadataDiff.orphanFiles.importing": "Importazione…",
"metadataDiff.orphanFiles.importSuccess": "{success} file orfani importati{failed}",
"metadataDiff.orphanFiles.importError": "Impossibile importare i file orfani",
"metadataDiff.sync.failed": "fallito",
"metadataDiff.sync.dbToFile.title": "Aggiorna i file con i valori del database",
"metadataDiff.sync.dbToFile.short": "DB\u2192F",
"metadataDiff.sync.dbToFile.short": "DBF",
"metadataDiff.sync.dbToFile.success": "Sincronizzati {success} post nei file{fallito}",
"metadataDiff.sync.dbToFile.error": "Impossibile sincronizzare nei file",
"metadataDiff.sync.fileToDb.title": "Aggiorna il database con i valori dei file",
"metadataDiff.sync.fileToDb.short": "F\u2192DB",
"metadataDiff.sync.fileToDb.short": "FDB",
"metadataDiff.sync.fileToDb.success": "Sincronizzati {success} file nel database{fallito}",
"metadataDiff.sync.fileToDb.error": "Impossibile sincronizzare nel database",
"metadataDiff.value.database": "Database locale",
@@ -461,6 +488,7 @@
"sidebar.published": "Pubblicati",
"sidebar.archived": "Archiviati",
"sidebar.untitled": "Senza titolo",
"sidebar.languagesAvailable": "{count} lingue disponibili",
"sidebar.noMatchingPosts": "Nessun post corrispondente",
"sidebar.createFirstPost": "Crea il tuo primo post",
"sidebar.loadMore": "Carica altro ({loaded} di {total})",
@@ -525,6 +553,8 @@
"settings.project.publicUrlPlaceholder": "https://example.com",
"settings.project.mainLanguageLabel": "Lingua principale",
"settings.project.mainLanguageDescription": "Lingua principale dei contenuti del blog. Titoli, alt text e didascalie generate dallIA useranno questa lingua.",
"settings.project.blogLanguagesLabel": "Lingue del blog",
"settings.project.blogLanguagesDescription": "Lingue in cui viene generato il blog. La lingua principale è sempre inclusa. Le lingue aggiuntive generano sottocartelle tradotte.",
"settings.project.defaultAuthorLabel": "Autore predefinito",
"settings.project.defaultAuthorDescription": "Nome autore predefinito per nuovi post e media. Può essere modificato per singolo elemento.",
"settings.project.defaultAuthorPlaceholder": "Nome autore",
@@ -578,6 +608,27 @@
"editor.previewFrameTitle": "Anteprima post",
"editor.previewLoading": "Caricamento anteprima...",
"editor.metadata.toggle": "Metadati",
"editor.translations.title": "Traduzioni",
"editor.translations.currentLanguage": "Lingua corrente: {language}",
"editor.translations.none": "Nessuna traduzione disponibile.",
"editor.translations.selectTarget": "Seleziona lingua di destinazione",
"editor.translations.translateButton": "Traduci in...",
"editor.translations.translateTitle": "Crea o aggiorna una traduzione con l'IA",
"editor.translations.translating": "Traduzione in corso...",
"editor.translations.refresh": "Aggiorna",
"editor.translations.refreshTitle": "Rigenera questa traduzione con l'IA",
"editor.translations.publish": "Pubblica",
"editor.translations.publishTitle": "Pubblica questa traduzione nel suo file Markdown",
"editor.translations.publishing": "Pubblicazione...",
"editor.translations.missing": "Mancanti: {languages}",
"editor.translations.complete": "Tutte le lingue di traduzione supportate sono disponibili.",
"editor.translations.translateSuccess": "Traduzione aggiornata per {language}",
"editor.translations.translateFailed": "Traduzione non riuscita",
"editor.translations.publishSuccess": "Traduzione pubblicata per {language}",
"editor.translations.publishFailed": "Pubblicazione della traduzione non riuscita",
"editor.translations.status.draft": "Bozza",
"editor.translations.status.published": "Pubblicato",
"editor.translations.status.archived": "Archiviato",
"editor.excerpt.toggle": "Estratto",
"editor.footer.created": "Creato",
"editor.footer.updated": "Aggiornato",
@@ -927,6 +978,12 @@
"editor.media.quickActions.button": "✨ Analizza con IA",
"editor.media.quickActions.aiTitle": "Titolo suggerito dallIA",
"editor.media.quickActions.aiDescription": "Genera automaticamente titolo, testo alternativo e didascalia.",
"editor.media.quickActions.detectLanguageTitle": "Rileva lingua",
"editor.media.quickActions.detectLanguageDescription": "Rileva la lingua dai metadati con lIA",
"editor.media.quickActions.translateTitle": "Traduci in…",
"editor.media.quickActions.translateDescription": "Crea o aggiorna una traduzione con lIA",
"editor.media.translations.currentLanguage": "Lingua corrente: {language}",
"editor.media.translations.selectTarget": "Seleziona la lingua di destinazione",
"editor.post.quickActions.title": "Azioni rapide",
"editor.post.quickActions.analyzing": "⏳ Analisi…",
"editor.post.quickActions.button": "⚡ Azioni rapide",
@@ -949,6 +1006,24 @@
"editor.media.field.caption": "Didascalia",
"editor.media.field.tags": "Tag",
"editor.media.field.author": "Autore",
"editor.media.field.language": "Lingua",
"editor.media.field.languageNone": "Non impostata",
"editor.media.translations.title": "Traduzioni",
"editor.media.translations.none": "Nessuna traduzione ancora.",
"editor.media.translations.translateButton": "Traduci in…",
"editor.media.translations.translating": "Traduzione…",
"editor.media.translations.translateSuccess": "Traduzione aggiornata per {language}",
"editor.media.translations.translateFailed": "Traduzione fallita",
"editor.media.translations.refresh": "Aggiorna",
"editor.media.translations.refreshTitle": "Rigenera questa traduzione tramite IA",
"editor.media.translations.deleteTitle": "Elimina questa traduzione",
"editor.media.translations.deleted": "Traduzione eliminata per {language}",
"editor.media.translations.deleteFailed": "Eliminazione della traduzione fallita",
"editor.media.translations.editTitle": "Modifica traduzione — {language}",
"editor.media.translations.saved": "Traduzione salvata per {language}",
"editor.media.translations.saveFailed": "Salvataggio della traduzione fallito",
"editor.media.toast.languageDetected": "Lingua rilevata: {language}",
"editor.media.error.detectLanguage": "Rilevamento della lingua fallito",
"editor.media.placeholder.title": "Inserisci un titolo",
"editor.media.placeholder.altText": "Descrivi limmagine per laccessibilità",
"editor.media.placeholder.caption": "Aggiungi una didascalia",
@@ -1130,5 +1205,9 @@
"duplicatesView.checkAll": "Seleziona tutto",
"duplicatesView.uncheckAll": "Deseleziona tutto",
"duplicatesView.dismissChecked": "Ignora selezionati ({count})",
"duplicatesView.notEnabled": "La similarità semantica non è abilitata. Abilitala in Impostazioni → Tecnologia."
"duplicatesView.notEnabled": "La similarità semantica non è abilitata. Abilitala in Impostazioni → Tecnologia.",
"editor.doNotTranslateLabel": "Non tradurre",
"blog.fillMissing.nothingToDo": "Tutte le traduzioni sono aggiornate.",
"blog.fillMissing.started": "Attività di traduzione avviata. Controlla il pannello attività per il progresso.",
"blog.fillMissing.error": "Impossibile completare le traduzioni mancanti."
}