Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
502 changes: 502 additions & 0 deletions docs/superpowers/plans/2026-04-27-translate-to-english.md

Large diffs are not rendered by default.

114 changes: 114 additions & 0 deletions docs/superpowers/specs/2026-04-27-translate-to-english-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Translate WeCode to English — Design Spec

## Context

WeCode currently has all UI strings in French. The decision is to switch the entire app to English — UI labels, error messages, editor hints, lesson content, changelog, and internal type values. No i18n library; strings stay hardcoded, just in English instead of French.

## Scope

~150 French strings across ~30 files. Grouped by domain:

### 1. Types (internal values)

- `LessonData.difficulty`: `"débutant" | "intermédiaire" | "avancé"` → `"beginner" | "intermediate" | "advanced"` (in `src/lessons/types.ts` + both JSON files)
- `HomeTab`: `"accueil"` → `"home"` (in `src/home/homeStore.ts` + all consumers: `HomeNav.tsx`, `HomeShell.tsx`, `CommandPalette.tsx`, `useCommandPaletteShortcut.ts`)
- `PALETTE_GROUP_LABELS`: French labels → English (in `src/palette/types.ts`)

### 2. Editor hints (`src/ide/editor/hints.ts`)

~50 entries with `kindLabel`, `title`, `body`, and `example` fields. All French bodies/titles to English. `kindLabel` values like `"Élément HTML"` → `"HTML Element"`, `"Propriété CSS"` → `"CSS Property"`.

### 3. Lesson JSON files (`src/lessons/data/`)

- `html-01-structure.json`: title, description, heading, paragraphs, checkpoint labels
- `challenge-01-simple-page.json`: same fields

### 4. Changelog (`src/changelog.md`)

Entire file rewritten in English. Section headings `Ajouté / Amélioré / Corrigé` → `Added / Changed / Fixed`. All bullet points translated.

### 5. Home components (`src/home/`)

| File | French strings |
| --------------------------- | ---------------------------------- |
| `HomeNav.tsx` | "Accueil", "Leçons" labels |
| `HomeRailFoot.tsx` | "Nouveautés de la", "Docs et aide" |
| `HomeSearch.tsx` | placeholder, aria-label |
| `ContinueCard.tsx` | eyebrow, meta text, buttons |
| `ContinueLessonCard.tsx` | eyebrow, subtitle, button |
| `ContinueSection.tsx` | heading, empty state |
| `RecentProjectsSection.tsx` | heading, empty state, context menu |
| `ChangelogModal.tsx` | title, close button |
| `LessonCard.tsx` | status badges, time label |
| `LessonsListView.tsx` | heading |
| `ChallengesListView.tsx` | heading |

### 6. IDE shell components (`src/ide/`)

| File | French strings |
| ---------------------- | ----------------------------------------------------- |
| `Toolbar.tsx` | aria-labels, placeholder, tooltips |
| `StatusBar.tsx` | (reads from statusBarFormat) |
| `statusBarFormat.ts` | "Texte", "Sauvegarde auto", "Sauvegardé il y a..." |
| `ConfirmDialog.tsx` | default confirm/cancel labels |
| `Toasts.tsx` | aria-label |
| `FileTree.tsx` | labels, aria-labels, modal titles, context menu items |
| `LessonDock.tsx` | "Leçon"/"Challenge", "points", hint footer |
| `OpenFilesTabs.tsx` | empty state, aria-label |
| `fileErrorMessages.ts` | all 8 error messages |

### 7. Project modals (`src/projects/ui/`)

| File | French strings |
| ------------------------- | ------------------------------------------------ |
| `CreateProjectModal.tsx` | title, field labels, placeholder, toast, buttons |
| `DeleteProjectDialog.tsx` | title, body, checkbox, warning, toast, buttons |
| `RenameProjectModal.tsx` | title, body, label, toast, buttons |

### 8. Palette (`src/palette/`)

| File | French strings |
| -------------------- | -------------------------------------------------- |
| `CommandPalette.tsx` | aria-label, placeholder, empty state, footer hints |
| `commands.ts` | command title/subtitle |
| `sources.ts` | pill labels, lesson placeholder toast |

### 9. Other

- `src/projects/actions.ts` — error message "Un projet avec ce nom existe déjà"
- `src/projects/paths.ts` — validation messages
- `src/projects/diskAutoSave.ts` — toast message
- `src/lessons/lessonStore.ts` — (no direct French, reads from JSON)

### 10. Tests to update

- `src/ide/shell/fileErrorMessages.test.ts` — French assertions → English
- `src/ide/shell/statusBarFormat.test.ts` — French format strings → English
- `src/home/HomeShell.test.tsx` — French text matchers → English
- `src/palette/CommandPalette.test.tsx` — French text matchers → English

### 11. CLAUDE.md update

- `"UI strings are in French"` → `"UI strings are in English"`
- Changelog convention: mention both files are now in English

## What does NOT change

- `CHANGELOG.md` (root) — already in English
- `README.md` — already in English
- Git conventions (commits, PR bodies, branches) — already in English
- Code identifiers — already in English
- CSS class names — already in English
- Rust backend error messages — already in English

## Verification

```bash
npm run typecheck # type changes (difficulty, HomeTab) compile
npm run lint
npm run test # updated test assertions pass
npm run format:check
npm run build
grep -rn "Sauvegard\|Rechercher\|Nouveau\|Supprimer\|Renommer\|Annuler\|Confirmer\|Leçon\|débutant\|Reprends\|Fichiers\|fichier\|dossier\|Accueil" src/ --include="*.ts" --include="*.tsx" | grep -v node_modules | grep -v ".test."
# Should return 0 hits (no French left in source, excluding test context)
```
120 changes: 60 additions & 60 deletions src/changelog.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,90 @@
# Nouveautés
# What's new

## v0.3.0 — 27 avril 2026
## v0.3.0 — April 27, 2026

### Ajouté
### Added

- **Système de leçons** — des leçons guidées pas à pas avec validation en temps réel. L'app vérifie ton code à chaque modification et coche les objectifs au fur et à mesure.
- **Système de challenges** — des défis libres où tu dois atteindre un objectif sans instructions détaillées. Tu peux créer et supprimer des fichiers.
- **Navigation par onglets dans l'Accueil** — le rail gauche est maintenant un routeur : clique sur Leçons ou Challenges pour voir la liste complète avec ton avancement.
- **Compteur de progression** — le rail affiche combien de leçons tu as terminées (ex : `1 / 2`).
- **Carte « Reprends »** — si tu as une leçon en cours, la carte de reprise la montre en priorité sur les projets.
- **Première leçon** : « La structure d'une page HTML » — apprends `<head>`, `<body>`, `<title>`, `<h1>`, `<p>` avec 5 checkpoints.
- **Premier challenge** : « Crée une page simple » — un titre, un paragraphe et une couleur de fond.
- **Modale changelog** — clique sur « Nouveautés de la vX.Y.Z » dans le rail pour voir l'historique des mises à jour.
- **Lesson system** — step-by-step guided lessons with real-time validation. The app checks your code on every edit and ticks off objectives as you go.
- **Challenge system** — open-ended challenges where you reach a goal without detailed instructions. You can create and delete files.
- **Tab navigation in Home** — the left rail is now a router: click Lessons or Challenges to see the full list with your progress.
- **Progress counter** — the rail shows how many lessons you have completed (e.g. `1 / 2`).
- **"Continue" card** — if you have a lesson in progress, the resume card shows it above your projects.
- **First lesson**: "HTML Page Structure" — learn `<head>`, `<body>`, `<title>`, `<h1>`, `<p>` with 5 checkpoints.
- **First challenge**: "Build a simple page" — a heading, a paragraph, and a background color.
- **Changelog modal** — click "What's new in vX.Y.Z" in the rail to view the update history.

### Amélioré
### Changed

- Les raccourcis clavier (Ctrl+Tab, Ctrl+W) fonctionnent en mode leçon. Ctrl+N est bloqué (pas de création de fichier en leçon).
- Le dock leçon est un vrai `<button>` accessible au clavier (avec `aria-expanded`).
- Le menu « Ouvrir » en clic droit sur un fichier fonctionne en mode leçon.
- La barre de statut affiche la progression des checkpoints au lieu de la version en mode leçon.
- Keyboard shortcuts (Ctrl+Tab, Ctrl+W) work in lesson mode. Ctrl+N is blocked (no file creation during a lesson).
- The lesson dock is a proper accessible `<button>` (with `aria-expanded`).
- The "Open" right-click context menu on a file works in lesson mode.
- The status bar shows checkpoint progress instead of the version in lesson mode.

### Corrigé
### Fixed

- Le dock se replie correctement (le contenu ne déborde plus sous le header).
- Le contour ambre ne s'affiche plus sur les boutons de sélection de template.
- La propriété CSS dans les règles de validation est correctement échappée (pas de faux match avec des caractères spéciaux).
- The dock collapses correctly (content no longer overflows below the header).
- The amber outline no longer appears on template selection buttons.
- The CSS property in validation rules is properly escaped (no false match with special characters).

---

## v0.2.0-2 — 25 avril 2026
## v0.2.0-2 — April 25, 2026

### Ajouté
### Added

- **Palette de commandes** (Ctrl+K / ⌘K) — rechercher un projet, un fichier ou une commande depuis l'Accueil.
- **Menu contextuel** sur la section Projets récentsclic droit pour créer un nouveau projet ou lancer une recherche.
- **Logo pixel-perfect** — le logo WeCode correspond maintenant exactement au design original dans toutes ses variantes.
- Bannière et carte Open Graph pour le repo GitHub.
- **Command palette** (Ctrl+K / ⌘K) — search for a project, a file, or a command from Home.
- **Context menu** on the Recent Projects sectionright-click to create a new project or start a search.
- **Pixel-perfect logo** — the WeCode logo now exactly matches the original design in all its variants.
- Open Graph banner and card for the GitHub repo.

### Amélioré
### Changed

- L'app ne plante plus si le dossier du dernier projet a été supprimé pendant qu'elle était fermée.
- Un toast d'erreur apparaît si la sauvegarde automatique échoue (disque plein, permissions, etc.).
- Renommer un projet avec un nom déjà pris par un autre est maintenant interdit.
- Les onglets de l'ancien projet sont vidés quand tu passes à un autre.
- Le bouton « Ouvrir le dossier » fonctionne sur Windows (utilise `revealItemInDir` au lieu de `openPath`).
- L'animation d'apparition des cartes projets est plus rapide.
- Les items de navigation du rail sont maintenant accessibles au clavier.
- Le focus clavier est visible sur les onglets de l'éditeur.
- The app no longer crashes if the last project's folder was deleted while it was closed.
- An error toast appears if autosave fails (disk full, permissions, etc.).
- Renaming a project to a name already taken by another is now blocked.
- The previous project's tabs are cleared when switching to another project.
- The "Open folder" button works on Windows (uses `revealItemInDir` instead of `openPath`).
- The project card appear animation is faster.
- Rail navigation items are now keyboard-accessible.
- Keyboard focus is visible on editor tabs.

### Corrigé
### Fixed

- Le contour orange parasite ne s'affiche plus sur les boutons de template ni sur le menu contextuel.
- Le menu natif du navigateur (Retour, Actualiser, Inspecter) est bloqué partout dans l'app.
- The stray orange outline no longer appears on template buttons or the context menu.
- The browser's native menu (Back, Refresh, Inspect) is blocked everywhere in the app.

---

## v0.2.0-1 — 23 avril 2026
## v0.2.0-1 — April 23, 2026

### Ajouté
### Added

- **Page d'accueil** — vue par défaut avec la liste des projets récents, la section « Continue le parcours » et les modèles de projet.
- **Projets sur disque** — chaque projet est un vrai dossier sous `~/Documents/WeCode/`.
- Créer un projet depuis un modèle (Dossier vierge ou HTML + CSS) avec un sélecteur de dossier natif.
- Renommer et supprimer un projet (avec option de suppression du dossier sur le disque).
- Menu contextuel sur les cartes projets : Ouvrir, Ouvrir le dossier, Renommer, Supprimer.
- Rechargement automatique quand un éditeur externe modifie les fichiers du projet actif.
- Aperçu mobile / desktop dans le preview.
- Infobulles sur les mots-clés HTML et CSS dans l'éditeur.
- Notifications toast et boîtes de confirmation.
- Raccourcis clavier : `Ctrl+N` (nouveau fichier), `Ctrl+W` (fermer l'onglet), `Ctrl+Tab` / `Ctrl+Shift+Tab` (naviguer entre les onglets).
- Barre de statut avec sauvegarde auto, latence preview, langue, encodage, ligne:colonne.
- Refonte visuelle basée sur un design system oklch (Geist + JetBrains Mono).
- **Home page** — default view with the recent projects list, the "Continue your path" section, and project templates.
- **Disk-backed projects** — each project is a real folder under `~/Documents/WeCode/`.
- Create a project from a template (Blank folder or HTML + CSS) with a native folder picker.
- Rename and delete a project (with an option to remove the folder from disk).
- Context menu on project cards: Open, Open folder, Rename, Delete.
- Automatic reload when an external editor modifies files in the active project.
- Mobile / desktop toggle in the preview panel.
- Hover tooltips on HTML and CSS keywords in the editor.
- Toast notifications and confirmation dialogs.
- Keyboard shortcuts: `Ctrl+N` (new file), `Ctrl+W` (close tab), `Ctrl+Tab` / `Ctrl+Shift+Tab` (navigate between tabs).
- Status bar with autosave, preview latency, language, encoding, line:column.
- Visual redesign based on an oklch design system (Geist + JetBrains Mono).

### Amélioré
### Changed

- Latence preview réduite de ~1 s à ~100 ms.
- Preview latency reduced from ~1 s to ~100 ms.

### Corrigé
### Fixed

- Fuites de listeners lors des recharges HMR.
- Le panneau d'aperçu ne reste plus blanc sans mises à jour.
- Listener leaks on HMR reloads.
- The preview panel no longer stays blank without updates.

---

## v0.1.0 — 20 avril 2026
## v0.1.0 — April 20, 2026

### Ajouté
### Added

- Première version : shell Tauri v2, éditeur trois panneaux (arborescence, éditeur CodeMirror 6, aperçu live) avec un système de fichiers virtuel en mémoire.
- First release: Tauri v2 shell, three-panel editor (file tree, CodeMirror 6 editor, live preview) with an in-memory virtual file system.
6 changes: 3 additions & 3 deletions src/home/HomeShell.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ describe("HomeShell", () => {
});
});

it("renders the welcome headline and the Projets récents section header", () => {
it("renders the welcome headline and the Recent projects section header", () => {
render(<HomeShell />);

expect(screen.getByText(/Bienvenue dans/i)).toBeTruthy();
expect(screen.getByRole("heading", { name: /Projets récents/i })).toBeTruthy();
expect(screen.getByText(/Welcome to/i)).toBeTruthy();
expect(screen.getByRole("heading", { name: /Recent projects/i })).toBeTruthy();
});
});
2 changes: 1 addition & 1 deletion src/home/HomeShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function HomeShell() {
<div className="home-shell">
<HomeRail />
<main className="home-main">
{tab === "accueil" && (
{tab === "home" && (
<>
<HomeSearch />
<ContinueSection />
Expand Down
4 changes: 2 additions & 2 deletions src/home/homeStore.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { create } from "zustand";

export type HomeTab = "accueil" | "lessons" | "challenges";
export type HomeTab = "home" | "lessons" | "challenges";

interface HomeState {
tab: HomeTab;
setTab: (tab: HomeTab) => void;
}

export const useHomeStore = create<HomeState>((set) => ({
tab: "accueil",
tab: "home",
setTab: (tab) => set({ tab }),
}));
4 changes: 2 additions & 2 deletions src/home/rail/HomeGreeting.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function formatDate(now: Date): string {
return new Intl.DateTimeFormat("fr-FR", {
return new Intl.DateTimeFormat("en-US", {
weekday: "long",
day: "numeric",
month: "long",
Expand All @@ -12,7 +12,7 @@ export function HomeGreeting() {
<div className="home-greet">
<div className="home-greet-date">{dateLabel}</div>
<h1 className="home-greet-title">
Bienvenue dans <span className="home-greet-accent">WeCode</span>.
Welcome to <span className="home-greet-accent">WeCode</span>.
</h1>
</div>
);
Expand Down
8 changes: 4 additions & 4 deletions src/home/rail/HomeNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ export function HomeNav() {
<nav className="home-nav" aria-label="Navigation principale">
<HomeNavItem
icon={<IconHome />}
label="Accueil"
active={tab === "accueil"}
onClick={() => setTab("accueil")}
label="Home"
active={tab === "home"}
onClick={() => setTab("home")}
/>
<HomeNavItem
icon={<IconBook />}
label="Leçons"
label="Lessons"
active={tab === "lessons"}
onClick={() => setTab("lessons")}
counter={`${completed} / ${LESSONS.length}`}
Expand Down
4 changes: 2 additions & 2 deletions src/home/rail/HomeRailFoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export function HomeRailFoot() {
<div className="home-rail-sep" aria-hidden="true" />
<button type="button" className="home-rail-link" onClick={() => setShowChangelog(true)}>
<IconShield />
Nouveautés de la {APP_VERSION}
What's new in {APP_VERSION}
</button>
<a className="home-rail-link">
<IconHelp />
Docs et aide
Docs &amp; help
</a>
{showChangelog && <ChangelogModal onClose={() => setShowChangelog(false)} />}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/home/sections/ChallengesListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function ChallengesListView() {
return (
<section className="home-section">
<div className="home-sec-head">
<h3>Tous les challenges</h3>
<h3>All challenges</h3>
<span className="home-sec-count">
{completed} / {CHALLENGES.length}
</span>
Expand Down
4 changes: 2 additions & 2 deletions src/home/sections/ChangelogModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ export function ChangelogModal({ onClose }: Props) {
aria-labelledby="changelog-title"
>
<div id="changelog-title" className="modal__title">
Nouveautés
What's new
</div>
<div
className="cl-body"
dangerouslySetInnerHTML={{ __html: renderMarkdown(changelogRaw) }}
/>
<div className="modal__actions">
<button type="button" onClick={onClose}>
Fermer
Close
</button>
</div>
</div>
Expand Down
Loading