339 lines
11 KiB
TypeScript
339 lines
11 KiB
TypeScript
export const LOCALES = ["it", "en", "es"] as const;
|
|
export type Locale = (typeof LOCALES)[number];
|
|
|
|
export function isLocale(value: string): value is Locale {
|
|
return LOCALES.includes(value as Locale);
|
|
}
|
|
|
|
type Dictionary = {
|
|
home: {
|
|
badge: string;
|
|
title: string;
|
|
subtitle: string;
|
|
requestTitle: string;
|
|
requestText: string;
|
|
structureTitle: string;
|
|
structureText: string;
|
|
structureChips: string[];
|
|
demoTitle: string;
|
|
openDemo: string;
|
|
openConfig: string;
|
|
kpis: {
|
|
words: string;
|
|
intersections: string;
|
|
rows: string;
|
|
cols: string;
|
|
};
|
|
};
|
|
newPage: {
|
|
badge: string;
|
|
title: string;
|
|
subtitle: string;
|
|
};
|
|
form: {
|
|
topic: string;
|
|
difficulty: string;
|
|
initialWords: string;
|
|
themedFillCount: string;
|
|
targetEmptyRatio: string;
|
|
seed: string;
|
|
lexiconFile: string;
|
|
submit: string;
|
|
submitting: string;
|
|
note: string;
|
|
};
|
|
play: {
|
|
badge: string;
|
|
subtitle: string;
|
|
loading: string;
|
|
errorPrefix: string;
|
|
overviewTitle: string;
|
|
boardTitle: string;
|
|
cluesTitle: string;
|
|
instructions: string;
|
|
actions: {
|
|
newCrossword: string;
|
|
viewSolution: string;
|
|
};
|
|
stats: {
|
|
words: string;
|
|
intersections: string;
|
|
filledCells: string;
|
|
topicWords: string;
|
|
};
|
|
};
|
|
solution: {
|
|
badge: string;
|
|
title: string;
|
|
subtitle: string;
|
|
solvedGridTitle: string;
|
|
answersTitle: string;
|
|
backToGame: string;
|
|
answer: string;
|
|
clue: string;
|
|
};
|
|
player: {
|
|
topic: string;
|
|
difficulty: string;
|
|
lexicon: string;
|
|
};
|
|
clues: {
|
|
across: string;
|
|
down: string;
|
|
};
|
|
};
|
|
|
|
const dictionaries: Record<Locale, Dictionary> = {
|
|
it: {
|
|
home: {
|
|
badge: "Alpha 01 Backoffice + Web UI",
|
|
title: "Cruciverba su richiesta, pronti per essere giocati.",
|
|
subtitle:
|
|
"Questa prima interfaccia Next.js separa nettamente il motore Python dal frontend: il sito invia una richiesta JSON, il backend genera il cruciverba e la pagina finale lo rende giocabile in modo interattivo.",
|
|
requestTitle: "Nuova richiesta",
|
|
requestText:
|
|
"Qui l'utente configurerà il cruciverba. Per ora il form prepara già la struttura della richiesta e apre la pagina del gioco reale.",
|
|
structureTitle: "Perche questa struttura",
|
|
structureText:
|
|
"Il frontend non deve conoscere i dettagli dell'algoritmo: riceve solo il JSON finale del cruciverba e lo trasforma in esperienza giocabile, stampabile e riapribile.",
|
|
structureChips: ["Next.js UI", "Backend JSON", "Motore Python separato", "PDF e mobile-ready"],
|
|
demoTitle: "Stato demo",
|
|
openDemo: "Apri demo giocabile",
|
|
openConfig: "Vai alla configurazione",
|
|
kpis: {
|
|
words: "Parole",
|
|
intersections: "Intersezioni",
|
|
rows: "Righe",
|
|
cols: "Colonne",
|
|
},
|
|
},
|
|
newPage: {
|
|
badge: "Configurazione",
|
|
title: "Chiedi al motore un nuovo cruciverba.",
|
|
subtitle:
|
|
"Questa pagina e il punto naturale da cui il sito invierà al backend la request JSON del contratto che abbiamo definito.",
|
|
},
|
|
form: {
|
|
topic: "Topic",
|
|
difficulty: "Difficolta",
|
|
initialWords: "Parole seme",
|
|
themedFillCount: "Parole filler in tema",
|
|
targetEmptyRatio: "Rapporto vuoti",
|
|
seed: "Seed",
|
|
lexiconFile: "Lessico runtime",
|
|
submit: "Genera cruciverba",
|
|
submitting: "Preparazione...",
|
|
note: "La richiesta ora chiama davvero il motore Python e apre il cruciverba generato.",
|
|
},
|
|
play: {
|
|
badge: "Cruciverba interattivo",
|
|
subtitle: "Questa pagina carica il JSON reale generato dal motore Python del backoffice.",
|
|
loading: "Generazione in corso, sto caricando il cruciverba...",
|
|
errorPrefix: "Errore di caricamento",
|
|
overviewTitle: "Schema pronto per essere giocato",
|
|
boardTitle: "Griglia di gioco",
|
|
cluesTitle: "Definizioni",
|
|
instructions:
|
|
"Clicca una casella, poi scrivi da tastiera. Le definizioni restano leggibili nella colonna laterale.",
|
|
actions: {
|
|
newCrossword: "Nuovo cruciverba",
|
|
viewSolution: "Vedi soluzioni",
|
|
},
|
|
stats: {
|
|
words: "Parole",
|
|
intersections: "Intersezioni",
|
|
filledCells: "Caselle piene",
|
|
topicWords: "Parole in tema",
|
|
},
|
|
},
|
|
solution: {
|
|
badge: "Pagina soluzioni",
|
|
title: "Controllo finale del cruciverba",
|
|
subtitle:
|
|
"Qui trovi la griglia compilata e l'elenco completo delle risposte collegate alle definizioni.",
|
|
solvedGridTitle: "Griglia risolta",
|
|
answersTitle: "Elenco soluzioni",
|
|
backToGame: "Torna al gioco",
|
|
answer: "Soluzione",
|
|
clue: "Definizione",
|
|
},
|
|
player: {
|
|
topic: "Topic",
|
|
difficulty: "Difficolta",
|
|
lexicon: "Lessico",
|
|
},
|
|
clues: {
|
|
across: "Orizzontali",
|
|
down: "Verticali",
|
|
},
|
|
},
|
|
en: {
|
|
home: {
|
|
badge: "Alpha 01 Backoffice + Web UI",
|
|
title: "Crosswords on demand, ready to be played.",
|
|
subtitle:
|
|
"This first Next.js interface clearly separates the Python engine from the frontend: the site sends a JSON request, the backend generates the crossword, and the final page turns it into an interactive experience.",
|
|
requestTitle: "New request",
|
|
requestText:
|
|
"This is where the user configures the crossword. The form already prepares the request structure and opens the real game page.",
|
|
structureTitle: "Why this structure",
|
|
structureText:
|
|
"The frontend should not know the details of the algorithm: it only receives the final crossword JSON and turns it into a playable, printable and reusable experience.",
|
|
structureChips: ["Next.js UI", "JSON backend", "Separate Python engine", "PDF and mobile-ready"],
|
|
demoTitle: "Demo status",
|
|
openDemo: "Open playable demo",
|
|
openConfig: "Go to configuration",
|
|
kpis: {
|
|
words: "Words",
|
|
intersections: "Intersections",
|
|
rows: "Rows",
|
|
cols: "Columns",
|
|
},
|
|
},
|
|
newPage: {
|
|
badge: "Configuration",
|
|
title: "Ask the engine for a new crossword.",
|
|
subtitle:
|
|
"This page is the natural place from which the site sends the JSON request defined in our contract to the backend.",
|
|
},
|
|
form: {
|
|
topic: "Topic",
|
|
difficulty: "Difficulty",
|
|
initialWords: "Seed words",
|
|
themedFillCount: "Themed filler words",
|
|
targetEmptyRatio: "Empty ratio",
|
|
seed: "Seed",
|
|
lexiconFile: "Runtime lexicon",
|
|
submit: "Generate crossword",
|
|
submitting: "Preparing...",
|
|
note: "The request now calls the real Python engine and opens the generated crossword.",
|
|
},
|
|
play: {
|
|
badge: "Interactive crossword",
|
|
subtitle: "This page loads the real JSON generated by the Python backoffice engine.",
|
|
loading: "Generation in progress, loading crossword...",
|
|
errorPrefix: "Loading error",
|
|
overviewTitle: "Crossword ready to be played",
|
|
boardTitle: "Game grid",
|
|
cluesTitle: "Clues",
|
|
instructions: "Click a cell, then type from the keyboard. The clues stay readable in the side panel.",
|
|
actions: {
|
|
newCrossword: "New crossword",
|
|
viewSolution: "View solutions",
|
|
},
|
|
stats: {
|
|
words: "Words",
|
|
intersections: "Intersections",
|
|
filledCells: "Filled cells",
|
|
topicWords: "Theme words",
|
|
},
|
|
},
|
|
solution: {
|
|
badge: "Solutions page",
|
|
title: "Final crossword check",
|
|
subtitle: "Here you can inspect the solved grid and the full list of answers tied to each clue.",
|
|
solvedGridTitle: "Solved grid",
|
|
answersTitle: "Answer key",
|
|
backToGame: "Back to game",
|
|
answer: "Answer",
|
|
clue: "Clue",
|
|
},
|
|
player: {
|
|
topic: "Topic",
|
|
difficulty: "Difficulty",
|
|
lexicon: "Lexicon",
|
|
},
|
|
clues: {
|
|
across: "Across",
|
|
down: "Down",
|
|
},
|
|
},
|
|
es: {
|
|
home: {
|
|
badge: "Alpha 01 Backoffice + Web UI",
|
|
title: "Crucigramas a pedido, listos para jugar.",
|
|
subtitle:
|
|
"Esta primera interfaz en Next.js separa claramente el motor Python del frontend: el sitio envia una solicitud JSON, el backend genera el crucigrama y la pagina final lo convierte en una experiencia interactiva.",
|
|
requestTitle: "Nueva solicitud",
|
|
requestText:
|
|
"Aqui el usuario configura el crucigrama. El formulario ya prepara la estructura de la solicitud y abre la pagina del juego real.",
|
|
structureTitle: "Por que esta estructura",
|
|
structureText:
|
|
"El frontend no debe conocer los detalles del algoritmo: solo recibe el JSON final del crucigrama y lo transforma en una experiencia jugable, imprimible y reutilizable.",
|
|
structureChips: ["Next.js UI", "Backend JSON", "Motor Python separado", "PDF y movil listos"],
|
|
demoTitle: "Estado de la demo",
|
|
openDemo: "Abrir demo jugable",
|
|
openConfig: "Ir a configuracion",
|
|
kpis: {
|
|
words: "Palabras",
|
|
intersections: "Intersecciones",
|
|
rows: "Filas",
|
|
cols: "Columnas",
|
|
},
|
|
},
|
|
newPage: {
|
|
badge: "Configuracion",
|
|
title: "Pide al motor un nuevo crucigrama.",
|
|
subtitle:
|
|
"Esta pagina es el punto natural desde el que el sitio enviara al backend la solicitud JSON del contrato que hemos definido.",
|
|
},
|
|
form: {
|
|
topic: "Tema",
|
|
difficulty: "Dificultad",
|
|
initialWords: "Palabras semilla",
|
|
themedFillCount: "Palabras de relleno tematico",
|
|
targetEmptyRatio: "Proporcion de vacios",
|
|
seed: "Semilla",
|
|
lexiconFile: "Lexico activo",
|
|
submit: "Generar crucigrama",
|
|
submitting: "Preparando...",
|
|
note: "La solicitud ahora llama de verdad al motor Python y abre el crucigrama generado.",
|
|
},
|
|
play: {
|
|
badge: "Crucigrama interactivo",
|
|
subtitle: "Esta pagina carga el JSON real generado por el motor Python del backoffice.",
|
|
loading: "Generacion en curso, cargando crucigrama...",
|
|
errorPrefix: "Error de carga",
|
|
overviewTitle: "Crucigrama listo para jugar",
|
|
boardTitle: "Cuadricula de juego",
|
|
cluesTitle: "Definiciones",
|
|
instructions:
|
|
"Haz clic en una casilla y escribe desde el teclado. Las definiciones siguen legibles en la columna lateral.",
|
|
actions: {
|
|
newCrossword: "Nuevo crucigrama",
|
|
viewSolution: "Ver soluciones",
|
|
},
|
|
stats: {
|
|
words: "Palabras",
|
|
intersections: "Intersecciones",
|
|
filledCells: "Casillas llenas",
|
|
topicWords: "Palabras tematicas",
|
|
},
|
|
},
|
|
solution: {
|
|
badge: "Pagina de soluciones",
|
|
title: "Revision final del crucigrama",
|
|
subtitle:
|
|
"Aqui puedes ver la cuadricula completa y la lista de respuestas asociadas a cada definicion.",
|
|
solvedGridTitle: "Cuadricula resuelta",
|
|
answersTitle: "Listado de soluciones",
|
|
backToGame: "Volver al juego",
|
|
answer: "Solucion",
|
|
clue: "Definicion",
|
|
},
|
|
player: {
|
|
topic: "Tema",
|
|
difficulty: "Dificultad",
|
|
lexicon: "Lexico",
|
|
},
|
|
clues: {
|
|
across: "Horizontales",
|
|
down: "Verticales",
|
|
},
|
|
},
|
|
};
|
|
|
|
export function getDictionary(locale: Locale): Dictionary {
|
|
return dictionaries[locale];
|
|
}
|