Repository Public
1export type Locale = "en" | "fr";2export const LOCALES: Locale[] = ["en", "fr"];3export const isLocale = (x: string): x is Locale => x === "en" || x === "fr";4/** English lives at the root, French under /fr. */5export const href = (l: Locale, path: string) => (l === "fr" ? `/fr${path === "/" ? "" : path}` : path);67const en = {8 brand: "CLIP",9 tagline: "Autonomous AI cinema",10 nav: { home: "Home", feed: "Watch", explore: "Explore", series: "Series", search: "Search", about: "How it's made", saved: "Saved" },11 skip: "Skip to content",12 home: {13 kicker: "Now showing",14 watch: "Watch the film", openFeed: "Open the feed",15 latest: "Latest premieres", latestSub: "The newest films, in release order.",16 series: "Series", seriesSub: "Eight editorial lines. Each one has rules the system must follow.",17 top: "Best rated", topSub: "Ranked by the critic's score, not by engagement.",18 process: "Behind the screen",19 processBody: "Every film here was conceived, written, storyboarded, shot, narrated, edited and reviewed by an orchestrated AI system — then approved by a person before release. Nothing is published on a failed review.",20 processLink: "See the full process",21 stats: { films: "films", minutes: "minutes of cinema", shots: "generated shots" },22 emptyTitle: "The projector is warming up",23 emptyBody: "No film has been released yet. The first premiere will appear here as soon as it passes review.",24 soon: "No film yet",25 },26 film: {27 aiDisclosure: "AI-generated film",28 aiDisclosureLong: "Every image, clip and voice in this film is synthetic. No real person, place or event is depicted.",29 takeaway: "What it leaves you with", synopsis: "Synopsis", provenance: "Provenance", sources: "Sources", related: "More to watch",30 runtime: "Runtime", language: "Language", released: "Released", series: "Series", episode: "Episode", kind: "Form",31 models: "Models", pipeline: "Pipeline", approval: "Release decision", audio: "Sound", narration: "Narration", bed: "Ambience", music: "Music",32 share: "Share", copied: "Link copied", like: "Like", liked: "Liked", save: "Save", saved: "Saved", report: "Report this film", download: "Download",33 factChecked: "Fact-checked", factCheckedBody: "The factual statements in this film were checked against these sources before release.",34 fiction: "Fiction", factual: "Informational", experimental: "Experimental",35 watchInFeed: "Watch in the feed", why: "Why this film",36 },37 player: {38 play: "Play", pause: "Pause", mute: "Mute", unmute: "Unmute", captions: "Captions", captionsOff: "Captions off", replay: "Replay",39 progress: "Playback position", buffering: "Buffering…", error: "This film could not be played.", retry: "Try again", lowData: "Low-data version",40 tapUnmute: "Tap for sound", next: "Next film", previous: "Previous film", details: "Film details", offline: "You are offline.",41 },42 feed: { end: "You have seen everything, for now.", back: "Back to the start", empty: "No film matches yet.", hint: "Swipe, scroll or use ↑ ↓ — Space to pause, M for sound, C for captions" },43 explore: { title: "Explore", sub: "Browse by series, form, mood, topic, style, language and length.", all: "All", any: "Any", length: "Length", under30: "Under 30 s", under45: "Under 45 s", results: "films", none: "No film matches these filters yet.", clear: "Clear filters", sort: "Order", latest: "Latest", top: "Best rated", form: "Form", language: "Language" },44 tagKinds: { genre: "Genre", mood: "Mood", topic: "Topic", technique: "Technique", style: "Style" } as Record<string, string>,45 langs: { en: "English", fr: "French", bilingual: "Bilingual" } as Record<string, string>,46 search: { title: "Search", placeholder: "A theme, a mood, an object…", button: "Search", none: "Nothing matched. Try a broader word.", matched: "Matched by", hint: "Search runs on titles, synopses, narration and tags. Each result says why it matched." },47 seriesPage: { all: "All series", episodes: "films", none: "No film in this series yet.", rules: "Editorial rule", upcoming: "In development" },48 saved: { title: "Saved films", sub: "Kept in this browser only. Nothing is sent to the server.", none: "You have not saved a film yet." },49 about: {50 title: "How CLIP makes a film",51 lead: "CLIP is a small autonomous studio. It makes few films, slowly, and each one has to earn its release.",52 steps: [53 ["Idea", "A Creative Director proposes four different pitches. A critic scores them for originality, feasibility, visual potential, clarity and artifact risk, and compares them with everything already made to avoid repetition."],54 ["Research", "When a film states facts, a Research Editor checks every claim against reliable sources and saves the citations. Unverified claims hold the film."],55 ["Script", "A Screenwriter writes one spoken line per shot, in English, in French, or in both — with a native adaptation for the captions."],56 ["Storyboard", "A style bible fixes the palette, light, lens and recurring objects. Each shot gets a first frame and a single, simple camera move."],57 ["Images, voice, motion", "First frames are generated as stills, the narration is synthesised, and each still is then animated for exactly as long as its line needs."],58 ["Edit", "Shots are conformed and cut, the ambience is ducked under the voice, loudness is normalised, and word-timed captions are produced in both languages."],59 ["Review", "Automated checks look for blank or frozen frames, silence, clipping and missing captions. A critic then watches sampled frames and scores the film."],60 ["Release", "A person approves each film. A failed review cannot be published without a written, recorded override."],61 ] as [string, string][],62 disclosureTitle: "Disclosure", disclosure: "Everything you see and hear on CLIP is AI-generated: images and video by xAI Grok Imagine, narration by a synthetic preset voice, text by a language model. No voice is cloned and no real person is depicted. There is no third-party music.",63 privacyTitle: "Privacy", privacy: "No account, no advertising, no third-party script. Views and likes are counted with an anonymous identifier that changes every day; your IP address is not stored. Saved films stay in your browser.",64 reportTitle: "Report a problem", report: "If a film is inaccurate, harmful, or resembles a real person or protected work, tell us. Reported films are reviewed by a person and can be withdrawn immediately.",65 reportLink: "Open the report form",66 },67 report: { title: "Report a film", film: "Film (title or link)", reason: "Reason", detail: "What is wrong?", contact: "Contact (optional)", send: "Send report", thanks: "Thank you. A person will review this report.", reasons: { inaccurate: "Factual error", harmful: "Harmful or offensive", likeness: "Resembles a real person", copyright: "Copyright or trademark", other: "Other" } as Record<string, string>, error: "Please describe the problem in a few words.", limit: "Too many reports from this connection. Try again later." },68 footer: { disclosure: "All films on CLIP are AI-generated.", by: "A project by Simon-Pierre Boucher", studio: "Studio", language: "Français", api: "API" },69 notFound: { title: "This reel is missing", body: "The page you are looking for does not exist, or the film was withdrawn.", home: "Back to the programme" },70 errorPage: { title: "Something went wrong", body: "The page could not be loaded.", retry: "Try again" },71 sec: "s",72};73type Dict = typeof en;7475const fr: Dict = {76 brand: "CLIP",77 tagline: "Cinéma d'IA autonome",78 nav: { home: "Accueil", feed: "Regarder", explore: "Explorer", series: "Séries", search: "Recherche", about: "Fabrication", saved: "Enregistrés" },79 skip: "Aller au contenu",80 home: {81 kicker: "À l'affiche",82 watch: "Regarder le film", openFeed: "Ouvrir le fil",83 latest: "Dernières premières", latestSub: "Les films les plus récents, par ordre de sortie.",84 series: "Séries", seriesSub: "Huit lignes éditoriales. Chacune impose des règles au système.",85 top: "Les mieux notés", topSub: "Classés selon la note du critique, pas selon l'engagement.",86 process: "Derrière l'écran",87 processBody: "Chaque film a été imaginé, écrit, découpé, tourné, narré, monté et évalué par un système d'IA orchestré — puis approuvé par une personne avant sa sortie. Rien n'est publié après une évaluation négative.",88 processLink: "Voir tout le processus",89 stats: { films: "films", minutes: "minutes de cinéma", shots: "plans générés" },90 emptyTitle: "Le projecteur chauffe",91 emptyBody: "Aucun film n'est encore sorti. La première apparaîtra ici dès qu'elle aura passé l'évaluation.",92 soon: "Aucun film pour l'instant",93 },94 film: {95 aiDisclosure: "Film généré par IA",96 aiDisclosureLong: "Chaque image, chaque plan et chaque voix de ce film est synthétique. Aucune personne, aucun lieu ni aucun événement réel n'est représenté.",97 takeaway: "Ce qu'il vous laisse", synopsis: "Synopsis", provenance: "Provenance", sources: "Sources", related: "À voir aussi",98 runtime: "Durée", language: "Langue", released: "Sortie", series: "Série", episode: "Épisode", kind: "Forme",99 models: "Modèles", pipeline: "Chaîne de production", approval: "Décision de sortie", audio: "Son", narration: "Narration", bed: "Ambiance", music: "Musique",100 share: "Partager", copied: "Lien copié", like: "J'aime", liked: "Aimé", save: "Enregistrer", saved: "Enregistré", report: "Signaler ce film", download: "Télécharger",101 factChecked: "Faits vérifiés", factCheckedBody: "Les affirmations factuelles de ce film ont été vérifiées avec ces sources avant sa sortie.",102 fiction: "Fiction", factual: "Informatif", experimental: "Expérimental",103 watchInFeed: "Regarder dans le fil", why: "Pourquoi ce film",104 },105 player: {106 play: "Lire", pause: "Pause", mute: "Couper le son", unmute: "Activer le son", captions: "Sous-titres", captionsOff: "Sans sous-titres", replay: "Revoir",107 progress: "Position de lecture", buffering: "Chargement…", error: "Ce film n'a pas pu être lu.", retry: "Réessayer", lowData: "Version légère",108 tapUnmute: "Touchez pour le son", next: "Film suivant", previous: "Film précédent", details: "Fiche du film", offline: "Vous êtes hors ligne.",109 },110 feed: { end: "Vous avez tout vu, pour l'instant.", back: "Revenir au début", empty: "Aucun film ne correspond pour l'instant.", hint: "Balayez, défilez ou utilisez ↑ ↓ — Espace pour la pause, M pour le son, C pour les sous-titres" },111 explore: { title: "Explorer", sub: "Parcourez par série, forme, ambiance, sujet, style, langue et durée.", all: "Tout", any: "Toutes", length: "Durée", under30: "Moins de 30 s", under45: "Moins de 45 s", results: "films", none: "Aucun film ne correspond encore à ces filtres.", clear: "Effacer les filtres", sort: "Ordre", latest: "Récents", top: "Mieux notés", form: "Forme", language: "Langue" },112 tagKinds: { genre: "Genre", mood: "Ambiance", topic: "Sujet", technique: "Technique", style: "Style" },113 langs: { en: "Anglais", fr: "Français", bilingual: "Bilingue" },114 search: { title: "Recherche", placeholder: "Un thème, une ambiance, un objet…", button: "Chercher", none: "Aucun résultat. Essayez un mot plus général.", matched: "Trouvé par", hint: "La recherche porte sur les titres, les synopsis, la narration et les étiquettes. Chaque résultat indique pourquoi il correspond." },115 seriesPage: { all: "Toutes les séries", episodes: "films", none: "Aucun film dans cette série pour l'instant.", rules: "Règle éditoriale", upcoming: "En développement" },116 saved: { title: "Films enregistrés", sub: "Conservés dans ce navigateur seulement. Rien n'est envoyé au serveur.", none: "Vous n'avez encore enregistré aucun film." },117 about: {118 title: "Comment CLIP fabrique un film",119 lead: "CLIP est un petit studio autonome. Il fait peu de films, lentement, et chacun doit mériter sa sortie.",120 steps: [121 ["Idée", "Un directeur de création propose quatre projets différents. Un critique les note selon l'originalité, la faisabilité, le potentiel visuel, la clarté et le risque d'artefacts, puis les compare à tout ce qui a déjà été produit pour éviter les redites."],122 ["Recherche", "Quand un film énonce des faits, un rédacteur de recherche vérifie chaque affirmation auprès de sources fiables et conserve les références. Une affirmation non vérifiée retient le film."],123 ["Scénario", "Un scénariste écrit une phrase dite par plan, en anglais, en français ou dans les deux langues — avec une adaptation naturelle pour les sous-titres."],124 ["Découpage", "Une bible de style fixe la palette, la lumière, l'optique et les objets récurrents. Chaque plan reçoit une première image et un seul mouvement de caméra, simple."],125 ["Images, voix, mouvement", "Les premières images sont générées, la narration est synthétisée, puis chaque image est animée exactement le temps que demande sa phrase."],126 ["Montage", "Les plans sont conformés et montés, l'ambiance s'efface sous la voix, le niveau sonore est normalisé, et des sous-titres calés au mot près sont produits dans les deux langues."],127 ["Évaluation", "Des contrôles automatiques détectent les images noires ou figées, les silences, la saturation et les sous-titres manquants. Un critique regarde ensuite des images du film et le note."],128 ["Sortie", "Une personne approuve chaque film. Une évaluation négative ne peut être contournée que par une dérogation écrite et consignée."],129 ],130 disclosureTitle: "Transparence", disclosure: "Tout ce que vous voyez et entendez sur CLIP est généré par IA : images et vidéos par xAI Grok Imagine, narration par une voix synthétique prédéfinie, textes par un modèle de langage. Aucune voix n'est clonée et aucune personne réelle n'est représentée. Il n'y a aucune musique de tiers.",131 privacyTitle: "Vie privée", privacy: "Pas de compte, pas de publicité, aucun script tiers. Les vues et les mentions « J'aime » sont comptées à l'aide d'un identifiant anonyme qui change chaque jour ; votre adresse IP n'est pas conservée. Les films enregistrés restent dans votre navigateur.",132 reportTitle: "Signaler un problème", report: "Si un film est inexact, préjudiciable, ou s'il ressemble à une personne réelle ou à une œuvre protégée, dites-le-nous. Les films signalés sont examinés par une personne et peuvent être retirés immédiatement.",133 reportLink: "Ouvrir le formulaire de signalement",134 },135 report: { title: "Signaler un film", film: "Film (titre ou lien)", reason: "Motif", detail: "Quel est le problème ?", contact: "Contact (facultatif)", send: "Envoyer le signalement", thanks: "Merci. Une personne examinera ce signalement.", reasons: { inaccurate: "Erreur factuelle", harmful: "Préjudiciable ou offensant", likeness: "Ressemble à une personne réelle", copyright: "Droit d'auteur ou marque", other: "Autre" }, error: "Décrivez le problème en quelques mots.", limit: "Trop de signalements depuis cette connexion. Réessayez plus tard." },136 footer: { disclosure: "Tous les films de CLIP sont générés par IA.", by: "Un projet de Simon-Pierre Boucher", studio: "Studio", language: "English", api: "API" },137 notFound: { title: "Cette bobine est introuvable", body: "La page que vous cherchez n'existe pas, ou le film a été retiré.", home: "Retour au programme" },138 errorPage: { title: "Une erreur est survenue", body: "La page n'a pas pu être chargée.", retry: "Réessayer" },139 sec: "s",140};141142export const dict = (l: Locale): Dict => (l === "fr" ? fr : en);143export type { Dict };144145export const fmtDuration = (s: number) => `${Math.floor(s / 60)}:${String(Math.round(s % 60)).padStart(2, "0")}`;146export const fmtDate = (iso: string, l: Locale) => new Intl.DateTimeFormat(l === "fr" ? "fr-CA" : "en-CA", { year: "numeric", month: "long", day: "numeric", timeZone: "America/Toronto" }).format(new Date(iso));147