feat: entry editor at /content/:key/new and /content/:key/:id

This commit is contained in:
Florian Sylvain committed 2026-10-21 00:12:34 +02:00
1 parent 91d916fb74
commit fba20f83c5
94 files changed
+7116 -423

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ const SOURCES = [
'components/SortSelect.vue',
'lib/entryCells.ts',
'lib/entryListQuery.ts',
'views/ContentListView.vue',
'views/ContentListPage.vue',
]
const SAME_IN_FRENCH = new Set(['ID'])
+58
View File
@@ -0,0 +1,58 @@
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
import { messages } from './messages'
const SOURCES = [
'components/ContentState.vue',
'components/EntryActions.vue',
'components/EntryControl.vue',
'components/EntryDateField.vue',
'components/EntryDeleteDialog.vue',
'components/EntryEditor.vue',
'components/EntryEditorSkeleton.vue',
'components/EntryForm.vue',
'components/EntryNotices.vue',
'components/MarkdownField.vue',
'composables/useEntryEditorPage.ts',
'composables/useEntryRemoval.ts',
'lib/entryForm.ts',
'lib/entryMessages.ts',
'lib/entryEditors.ts',
'views/EntryEditorPage.vue',
]
const SAME_IN_FRENCH = new Set<string>([])
const LITERAL = /\bt\(\s*(?:'((?:\\.|[^'\\])*)'|"((?:\\.|[^"\\])*)")/g
function keysIn(source: string) {
return [...source.matchAll(LITERAL)].map((match) =>
(match[1] ?? match[2] ?? '').replace(/\\u0022/g, '"').replace(/\\(['"\\])/g, '$1'),
)
}
describe('Entry editor messages', () => {
const keys = SOURCES.flatMap((file) =>
keysIn(readFileSync(join(import.meta.dirname, '..', file), 'utf8')).map((key) => ({
file,
key,
})),
)
it('finds the strings of the screen', () => {
expect(keys.length).toBeGreaterThan(60)
})
it.each(keys.map(({ file, key }) => [file, key]))(
'%s: "%s" has its own French entry',
(_file, key) => {
const french = (messages as Record<string, string>)[key as string]
expect(french).toMatch(/\S/)
if (!SAME_IN_FRENCH.has(key as string)) {
expect(french).not.toBe(key)
}
},
)
})
+78
View File
@@ -2530,6 +2530,84 @@ export const messages = {
'{0}, sorted by last updated, newest first':
'{0}, trié par dernière modification, plus récent en premier',
'{0}, sorted by {1}, {2}': '{0}, trié par {1}, {2}',
'Entry saved': 'Entrée enregistrée',
'\u0022{0}\u0022 is up to date.': '« {0} » est à jour.',
'Entry deleted': 'Entrée supprimée',
'\u0022{0}\u0022 was deleted from {1}.': '« {0} » a été supprimée de {1}.',
'Delete this entry?': 'Supprimer cette entrée ?',
"\u0022{0}\u0022 will be deleted from {1}. This can't be undone.":
'« {0} » sera supprimée de {1}. Cette action est irréversible.',
'Delete entry': 'Supprimer l’entrée',
"Couldn't delete the entry": 'Impossible de supprimer l’entrée',
'Something went wrong on our side. Nothing was deleted. Try again in a moment.':
'Un problème est survenu de notre côté. Rien n’a été supprimé. Réessayez dans un instant.',
"Couldn't save the entry": 'Impossible d’enregistrer l’entrée',
"Couldn't load the entry": 'Impossible de charger l’entrée',
'GET {0} failed. Check your connection and try again.':
'GET {0} a échoué. Vérifiez votre connexion et réessayez.',
'Not saved': 'Non enregistrée',
'Not saved yet': 'Pas encore enregistrée',
Entry: 'Entrée',
'Entry {0}': 'Entrée {0}',
'Entry not found': 'Entrée introuvable',
'It may have been deleted by someone else.':
'Elle a peut-être été supprimée par quelqu’un d’autre.',
'Back to {0}': 'Retour à {0}',
'The fields of {0} changed': 'Les champs de {0} ont changé',
"A field was removed and a new required field, {0}, was added after you opened this form. Reload the form to continue. What you typed here can't be saved against the old fields.":
'Un champ a été supprimé et un nouveau champ obligatoire, {0}, a été ajouté après l’ouverture de ce formulaire. Rechargez le formulaire pour continuer. Ce que vous avez saisi ici ne peut pas être enregistré avec les anciens champs.',
'Reload form': 'Recharger le formulaire',
'Another entry already uses this {0}. Change it and save again.':
'Une autre entrée utilise déjà ce champ ({0}). Modifiez-le et enregistrez à nouveau.',
'Another entry already uses this choice. Change it and save again.':
'Une autre entrée utilise déjà ce choix. Modifiez-le et enregistrez à nouveau.',
'Another entry already uses this date. Change it and save again.':
'Une autre entrée utilise déjà cette date. Modifiez-la et enregistrez à nouveau.',
'Another entry already uses this {0}. Enter a different one.':
'Une autre entrée utilise déjà ce champ ({0}). Saisissez une autre valeur.',
'Another entry already uses this choice for {0}.':
'Une autre entrée utilise déjà ce choix pour {0}.',
'Another entry already uses this date for {0}.':
'Une autre entrée utilise déjà cette date pour {0}.',
'Each entry needs a different {0}.': 'Chaque entrée doit avoir une valeur différente ({0}).',
'{0} · Fields marked * are required.': '{0} · Les champs marqués * sont obligatoires.',
'{0} · Entry {1}': '{0} · Entrée {1}',
'Fill in {0}.': 'Renseignez {0}.',
'Pick a date for {0}.': 'Choisissez une date pour {0}.',
'Choose an option for {0}.': 'Choisissez une option pour {0}.',
'Choose yes or no for {0}.': 'Choisissez oui ou non pour {0}.',
'{0} must be text.': '{0} doit être du texte.',
'{0} must be a number.': '{0} doit être un nombre.',
'{0} must be yes or no.': '{0} doit être oui ou non.',
'{0} must be a date, like 2026-11-21.': '{0} doit être une date, par exemple 2026-11-21.',
'{0} must be one of the choices.': '{0} doit être l’un des choix.',
'{0} must be at least {1}.': '{0} doit être au moins {1}.',
'{0} must be at most {1}.': '{0} doit être au plus {1}.',
"{0} can't be before {1}.": '{0} ne peut pas être avant le {1}.',
"{0} can't be after {1}.": '{0} ne peut pas être après le {1}.',
'{0} needs at least {1} characters.': '{0} doit contenir au moins {1} caractères.',
'{0} can be up to {1} characters.': '{0} peut contenir jusqu’à {1} caractères.',
'Choose one of: {0}.': 'Choisissez parmi : {0}.',
'{0} or {1}': '{0} ou {1}',
'From {0} until {1}.': 'Du {0} au {1}.',
'From {0}.': 'À partir du {0}.',
'Until {0}.': 'Jusqu’au {0}.',
'Between {0} and {1}.': 'Entre {0} et {1}.',
'At least {0}.': 'Au moins {0}.',
'At most {0}.': 'Au plus {0}.',
'Markdown. Switch to Preview to check the result.':
'Markdown. Passez à l’aperçu pour vérifier le résultat.',
'Write in Markdown': 'Écrivez en Markdown',
'Nothing to preview yet.': 'Rien à prévisualiser pour l’instant.',
Write: 'Écrire',
'Pick a date': 'Choisir une date',
'Open calendar': 'Ouvrir le calendrier',
'Enter a number': 'Saisissez un nombre',
'Choose an option': 'Choisissez une option',
On: 'Activé',
Off: 'Désactivé',
Heading: 'Titre',
List: 'Liste',
id: 'identifiant',
} as const