Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
993f983
i18n: string-extraction codemod, literal ratchet and en-XA pseudo-loc…
cursoragent Oct 27, 2026
54ffbe8
i18n codemod: drop a path segment that repeats the package namespace
cursoragent Oct 27, 2026
a9350e5
i18n codemod: lazy descriptors for module data; scan detail copy
cursoragent Oct 27, 2026
12752d8
i18n audit: scope findings, full-viewport screenshots, label-based su…
cursoragent Oct 27, 2026
b4cc700
Remove a file that belongs to the navbar migration
cursoragent Oct 27, 2026
562f425
i18n: migrate navbar and top bar
cursoragent Oct 27, 2026
a165e1a
i18n:check: reviewed translations cannot regress; releases require re…
cursoragent Oct 27, 2026
184a2ae
Literal guard: per-text baseline that may only shrink, stricter scanner
cursoragent Oct 27, 2026
2e08651
Pseudo-locale: dev/test builds only; audit allowlist matches whole wo…
cursoragent Oct 27, 2026
5fa76da
i18n: migrate the viewer toolbar so the literal baseline only shrinks
cursoragent Oct 27, 2026
9c31599
i18n tooling: fast fixture tests; document the release review gate
cursoragent Oct 27, 2026
14facd0
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
2ba90c0
i18n extract: never approve a newly filled translation
cursoragent Oct 27, 2026
13b6052
i18n: normalize draft comment order as extract writes it
cursoragent Oct 27, 2026
0134222
Merge main
cursoragent Oct 27, 2026
c1e3a73
Baseline the floor plan panel copy that main changed
cursoragent Oct 27, 2026
8a8eece
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
8d8742f
Keep AppHeader server-safe: translated home link moves to a client leaf
cursoragent Oct 27, 2026
abbf51f
i18n codemod: leave app modules without 'use client' for a person
cursoragent Oct 27, 2026
00cf690
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
0a80256
Literal guard: resolve rendered constants through lexical scope
cursoragent Oct 27, 2026
72317fd
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
e37b746
i18n: releases ship drafts as English; gate on regressions and pack l…
cursoragent Oct 27, 2026
4613317
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
fee4995
Literal guard: measure baseline growth repo-wide; scan rendered text
cursoragent Oct 27, 2026
9ae7763
i18n codemod: ICU-exact encoding, entry-module and callback guards, i…
cursoragent Oct 27, 2026
acea493
i18n:check: catch renamed reviewed IDs; compare pushes with github.ev…
cursoragent Oct 27, 2026
444267a
i18n audit: report controls without an accessible name; tests and doc…
cursoragent Oct 27, 2026
6fbe590
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
c04270d
Navbar: name Preview and Share at mobile widths
cursoragent Oct 27, 2026
285ce3c
i18n:check: a stale draft after a wording change is a draft, not an e…
cursoragent Oct 27, 2026
c804232
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
1032c0f
release-check: compare with the latest @pascal-app/editor release tag
cursoragent Oct 27, 2026
f30dc30
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
8776a6d
i18n: renames warn unless declared; codemod and scanner fidelity fixes
cursoragent Oct 27, 2026
76e6098
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
53abaae
Literal guard: a trailing i18n-ignore exempts only its own line
cursoragent Oct 27, 2026
70f7702
Merge i18n tooling updates from #1167
cursoragent Oct 27, 2026
1ab6538
i18n: translate node definition copy at display time
cursoragent Oct 27, 2026
9f7df64
i18n: migrate the build tab
cursoragent Oct 27, 2026
17bd203
i18n: migrate the bottom tool dock and cursor tooltips
cursoragent Oct 27, 2026
becffda
i18n: migrate the tool HUD and camera hint
cursoragent Oct 27, 2026
14bba89
i18n: catalogs and audit surfaces for tools and toolbar
cursoragent Oct 27, 2026
4176867
i18n: load node definitions from source for the sidecar check
cursoragent Oct 27, 2026
96ca6c7
Merge origin/main (squashed #1167) into the navbar branch
cursoragent Oct 27, 2026
f57aa4b
Merge the navbar branch (with main's squashed #1167) into the tools b…
cursoragent Oct 27, 2026
f3fff6d
Merge origin/main (squashed #1169) into the tools branch
cursoragent Oct 27, 2026
104b9c7
Cut opening HUD: swap the mezzanine drag hint by descriptor ID
cursoragent Oct 27, 2026
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
171 changes: 126 additions & 45 deletions apps/editor/components/build-tab.tsx

Large diffs are not rendered by default.

58 changes: 46 additions & 12 deletions apps/editor/components/kitchen-browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
type CabinetNode,
emitter,
resolveLevelId,
usePascalI18n,
useScene,
} from '@pascal-app/core'
import { useCommandPalette, useCommandRegistry, useEditor } from '@pascal-app/editor'
Expand Down Expand Up @@ -39,6 +40,7 @@ function focusKitchenItem(id: AnyNodeId) {
}

export function KitchenBrowser({ query = '' }: { query?: string }) {
const i18n = usePascalI18n()
const defaults = useEditor((state) => state.toolDefaults.cabinet)
const mode = useEditor((state) => state.mode)
// Read the scene only while a query asks for placed items.
Expand All @@ -49,9 +51,14 @@ export function KitchenBrowser({ query = '' }: { query?: string }) {
return (
<div className="space-y-4">
<div>
<h3 className="text-sm font-medium">Add to kitchen</h3>
<h3 className="text-sm font-medium">
{i18n._({ id: 'app.kitchenBrowser.addToKitchen', message: 'Add to kitchen' })}
</h3>
<p className="mt-1 text-xs text-muted-foreground">
Choose an item, then click to place it. Appliances include their cabinetry.
{i18n._({
id: 'app.kitchenBrowser.chooseAnItemThenClickTo',
message: 'Choose an item, then click to place it. Appliances include their cabinetry.',
})}
</p>
</div>
<KitchenCollection
Expand All @@ -61,22 +68,37 @@ export function KitchenBrowser({ query = '' }: { query?: string }) {
/>
{query.trim() && (
<div className="space-y-2 border-t border-border pt-3">
<h3 className="text-xs font-medium">Find in this project · {matches.length}</h3>
<h3 className="text-xs font-medium">
{i18n._({
id: 'app.kitchenBrowser.findInThisProjectLength',
message: 'Find in this project · {length}',
values: { length: matches.length },
})}
</h3>
{matches.map((node) => (
<button
key={node.id}
type="button"
onClick={() => focusKitchenItem(node.id)}
className="block w-full rounded-lg border border-border/60 px-3 py-2 text-left text-xs hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring"
>
{node.name || 'Kitchen cabinet'}
{node.name ||
i18n._({ id: 'app.kitchenBrowser.kitchenCabinet', message: 'Kitchen cabinet' })}
<span className="block text-[10px] text-muted-foreground">
Select and show in scene
{i18n._({
id: 'app.kitchenBrowser.selectAndShowInScene',
message: 'Select and show in scene',
})}
</span>
</button>
))}
{!matches.length && (
<p className="text-xs text-muted-foreground">No matching kitchen items placed yet.</p>
<p className="text-xs text-muted-foreground">
{i18n._({
id: 'app.kitchenBrowser.noMatchingKitchenItemsPlacedYet',
message: 'No matching kitchen items placed yet.',
})}
</p>
)}
</div>
)}
Expand All @@ -85,6 +107,7 @@ export function KitchenBrowser({ query = '' }: { query?: string }) {
}

export function KitchenCommands() {
const i18n = usePascalI18n()
const register = useCommandRegistry((state) => state.register)
// Always mounted: the placed items are read only while the palette is open to list them.
const paletteOpen = useCommandPalette((state) => state.open)
Expand All @@ -96,13 +119,17 @@ export function KitchenCommands() {
register(
KITCHEN_ITEMS.map((item) => ({
id: `kitchen.add.${item.id}`,
label: `Add ${item.label}`,
group: 'Kitchen · Add',
label: i18n._({
id: 'app.kitchenBrowser.addLabel',
message: 'Add {label}',
values: { label: item.label },
}),
group: i18n._({ id: 'app.kitchenBrowser.groupAdd', message: 'Kitchen · Add' }),
keywords: item.keywords.split(' '),
execute: () => beginKitchenPlacement(item.id),
})),
),
[register],
[register, i18n],
)
useEffect(
() =>
Expand All @@ -120,14 +147,21 @@ export function KitchenCommands() {
const item = KITCHEN_ITEMS.find((entry) => entry.id === preset)!
return {
id: `kitchen.find.${node.id}`,
label: `Find ${node.name || item.label}`,
group: 'Kitchen · In this project',
label: i18n._({
id: 'app.kitchenBrowser.findName',
message: 'Find {name}',
values: { name: node.name || item.label },
}),
group: i18n._({
id: 'app.kitchenBrowser.groupInThisProject',
message: 'Kitchen · In this project',
}),
keywords: item.keywords.split(' '),
execute: () => focusKitchenItem(node.id),
}
}),
),
[register, modules],
[register, modules, i18n],
)
return null
}
22 changes: 17 additions & 5 deletions apps/editor/components/webxr-wand-bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import {
import { useBuildPanelModel, useBuildToolOptions } from '@/lib/build-panel-model'
import { getRoofFootprintSources, ROOF_TYPE_OPTIONS } from '@/lib/build-tab-state'

// The XR plugin takes plain labels and renders them itself, so it receives the English source.
const english = <T extends { label: { message?: string; id: string } }>(
entry: T,
): Omit<T, 'label'> & { label: string } => ({
...entry,
label: entry.label.message ?? entry.label.id,
})

export const webXRWandBindings: PascalXRWandBindings = {
useBuildPalette: useBuildPanelModel,
useToolOptions: useBuildToolOptions,
Expand All @@ -32,9 +40,13 @@ export const webXRWandBindings: PascalXRWandBindings = {
useEditor.getState().setTool(null)
},
activateTerrainSculptMode,
collectBuildTypes,
collectRoofFeatures,
getRoofFootprintSources,
roofTypeOptions: ROOF_TYPE_OPTIONS,
xrMepItems: MEP_ITEMS,
collectBuildTypes: (floorplanMode) => collectBuildTypes(floorplanMode).map(english),
collectRoofFeatures: () => collectRoofFeatures().map(english),
getRoofFootprintSources: (roofType) =>
getRoofFootprintSources(roofType).map((source) => ({
value: source.value,
label: source.label.message,
})),
roofTypeOptions: ROOF_TYPE_OPTIONS.map(english),
xrMepItems: MEP_ITEMS.map(english),
}
Loading
Loading