From 253e0c3df3951f4a6e6f4f85e6d2ae0a08dfd309 Mon Sep 17 00:00:00 2001 From: Trevor Brown Date: Sat, 7 Nov 2026 22:49:04 -0500 Subject: [PATCH] Components: Create component set refuses nested layers and is translated (#2095 review) component.createSet now refuses a selection where one layer is inside another, as component.combineVariants does, before changing the document (the nested layer was silently dropped from the set). Adds the component.createSet label to the 22 locale catalogs that list component.createMultiple. Co-Authored-By: Claude Sonnet 5.5 Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium --- crates/engine/src/cmd/component/variants.rs | 3 +++ crates/engine/src/components_behaviour_tests.rs | 14 ++++++++++++++ crates/ui-egui/locales/ar.toml | 1 + crates/ui-egui/locales/bs.toml | 1 + crates/ui-egui/locales/cs.toml | 1 + crates/ui-egui/locales/de.toml | 1 + crates/ui-egui/locales/es.toml | 1 + crates/ui-egui/locales/fi.toml | 1 + crates/ui-egui/locales/fr.toml | 1 + crates/ui-egui/locales/id.toml | 1 + crates/ui-egui/locales/it.toml | 1 + crates/ui-egui/locales/ja.toml | 1 + crates/ui-egui/locales/ka.toml | 1 + crates/ui-egui/locales/ko.toml | 1 + crates/ui-egui/locales/nl.toml | 1 + crates/ui-egui/locales/pl.toml | 1 + crates/ui-egui/locales/pt-BR.toml | 1 + crates/ui-egui/locales/ru.toml | 1 + crates/ui-egui/locales/sv.toml | 1 + crates/ui-egui/locales/th.toml | 1 + crates/ui-egui/locales/tr.toml | 1 + crates/ui-egui/locales/vi.toml | 1 + crates/ui-egui/locales/zh-Hans.toml | 1 + crates/ui-egui/locales/zh-Hant.toml | 1 + 24 files changed, 39 insertions(+) diff --git a/crates/engine/src/cmd/component/variants.rs b/crates/engine/src/cmd/component/variants.rs index 53e00ca6d..cfba5accf 100644 --- a/crates/engine/src/cmd/component/variants.rs +++ b/crates/engine/src/cmd/component/variants.rs @@ -115,6 +115,9 @@ pub(super) fn create_set(s: &mut Session, p: &Value) -> Result { }) { return Err(EngineError::Disabled(cmd.into(), "select layers that aren't components, component sets or instances".into())); } + if roots(doc, &ids).len() != ids.len() { + return Err(EngineError::Disabled(cmd.into(), "a layer can't be in a set with one inside it".into())); + } let mut made = Vec::new(); for i in roots(doc, &ids) { let r = create(s, &json!({"ids": [i]}))?; diff --git a/crates/engine/src/components_behaviour_tests.rs b/crates/engine/src/components_behaviour_tests.rs index f65049de5..510fb2e74 100644 --- a/crates/engine/src/components_behaviour_tests.rs +++ b/crates/engine/src/components_behaviour_tests.rs @@ -1139,3 +1139,17 @@ fn create_set_refuses_instances_and_leaves_the_document_alone() { assert_eq!(undo_len(&s), before); assert!(matches!(s.doc().unwrap().node(frames[1]).unwrap().kind, NodeKind::Frame)); } + +#[test] +fn create_set_refuses_a_target_inside_another_target_and_leaves_the_document_alone() { + let mut s = Session::new(); + let frames = named_frames(&mut s, &["Outer", "Inner"], false); + s.execute("node.reparent", &json!({"ids": [frames[1]], "parent": frames[0]})).unwrap(); + let before = undo_len(&s); + let e = s.execute("component.createSet", &json!({"ids": [frames[0], frames[1]]})).unwrap_err(); + assert!(matches!(e, crate::EngineError::Disabled(..)), "{e:?}"); + assert_eq!(undo_len(&s), before); + let doc = s.doc().unwrap(); + assert!(matches!(doc.node(frames[0]).unwrap().kind, NodeKind::Frame)); + assert!(matches!(doc.node(frames[1]).unwrap().kind, NodeKind::Frame)); +} diff --git a/crates/ui-egui/locales/ar.toml b/crates/ui-egui/locales/ar.toml index da4474e79..cbbe8e07d 100644 --- a/crates/ui-egui/locales/ar.toml +++ b/crates/ui-egui/locales/ar.toml @@ -2009,6 +2009,7 @@ status = "draft — needs native review" "component.combineVariants" = "جمع كتنويعات" "component.create" = "إنشاء مكوّن" "component.createMultiple" = "إنشاء مكونات متعددة" +"component.createSet" = "إنشاء مجموعة مكونات" "component.deleteProperty" = "حذف خاصية المكوّن" "component.detach" = "فصل النسخة المثيلة" "component.editProperty" = "تحرير خاصية المكوّن" diff --git a/crates/ui-egui/locales/bs.toml b/crates/ui-egui/locales/bs.toml index 36d71664c..e39053f08 100644 --- a/crates/ui-egui/locales/bs.toml +++ b/crates/ui-egui/locales/bs.toml @@ -2038,6 +2038,7 @@ status = "draft — needs native review" "component.combineVariants" = "Kombinuj kao varijante" "component.create" = "Kreiraj komponentu" "component.createMultiple" = "Kreiraj više komponenti" +"component.createSet" = "Kreiraj skup komponenti" "component.deleteProperty" = "Izbriši svojstvo komponente" "component.detach" = "Odvoji instancu" "component.editProperty" = "Uredi svojstvo komponente" diff --git a/crates/ui-egui/locales/cs.toml b/crates/ui-egui/locales/cs.toml index d401654ac..de7f9cc89 100644 --- a/crates/ui-egui/locales/cs.toml +++ b/crates/ui-egui/locales/cs.toml @@ -1913,6 +1913,7 @@ status = "draft — needs native review" "component.combineVariants" = "Sloučit jako varianty" "component.create" = "Vytvořit komponentu" "component.createMultiple" = "Vytvořit více komponent" +"component.createSet" = "Vytvořit sadu komponent" "component.deleteProperty" = "Smazat vlastnost komponenty" "component.detach" = "Odpojit instanci" "component.editProperty" = "Upravit vlastnost komponenty" diff --git a/crates/ui-egui/locales/de.toml b/crates/ui-egui/locales/de.toml index 6fd1838d6..6256fc1e0 100644 --- a/crates/ui-egui/locales/de.toml +++ b/crates/ui-egui/locales/de.toml @@ -2079,6 +2079,7 @@ status = "draft — needs native review" "component.combineVariants" = "Als Varianten kombinieren" "component.create" = "Komponente erstellen" "component.createMultiple" = "Mehrere Komponenten erstellen" +"component.createSet" = "Komponentensatz erstellen" "component.deleteProperty" = "Komponenteneigenschaft löschen" "component.detach" = "Instanz lösen" "component.editProperty" = "Komponenteneigenschaft bearbeiten" diff --git a/crates/ui-egui/locales/es.toml b/crates/ui-egui/locales/es.toml index 2baa2b31e..6c2d171c3 100644 --- a/crates/ui-egui/locales/es.toml +++ b/crates/ui-egui/locales/es.toml @@ -2002,6 +2002,7 @@ status = "draft — needs native review" "component.combineVariants" = "Combinar como variantes" "component.create" = "Crear componente" "component.createMultiple" = "Crear varios componentes" +"component.createSet" = "Crear conjunto de componentes" "component.deleteProperty" = "Eliminar propiedad de componente" "component.detach" = "Separar instancia" "component.editProperty" = "Editar propiedad de componente" diff --git a/crates/ui-egui/locales/fi.toml b/crates/ui-egui/locales/fi.toml index 2f5db319a..a1b33417f 100644 --- a/crates/ui-egui/locales/fi.toml +++ b/crates/ui-egui/locales/fi.toml @@ -2086,6 +2086,7 @@ status = "draft — needs native review" "component.combineVariants" = "Yhdistä varianteiksi" "component.create" = "Luo komponentti" "component.createMultiple" = "Luo useita komponentteja" +"component.createSet" = "Luo komponenttijoukko" "component.deleteProperty" = "Poista komponentin ominaisuus" "component.detach" = "Irrota ilmentymä" "component.editProperty" = "Muokkaa komponentin ominaisuutta" diff --git a/crates/ui-egui/locales/fr.toml b/crates/ui-egui/locales/fr.toml index d47ad9597..e5feebc9b 100644 --- a/crates/ui-egui/locales/fr.toml +++ b/crates/ui-egui/locales/fr.toml @@ -1958,6 +1958,7 @@ status = "draft — needs native review" "component.combineVariants" = "Combiner en variantes" "component.create" = "Créer un composant" "component.createMultiple" = "Créer plusieurs composants" +"component.createSet" = "Créer un ensemble de composants" "component.deleteProperty" = "Supprimer la propriété de composant" "component.detach" = "Détacher l’instance" "component.editProperty" = "Modifier la propriété de composant" diff --git a/crates/ui-egui/locales/id.toml b/crates/ui-egui/locales/id.toml index cbebaf1c4..3bb5d027c 100644 --- a/crates/ui-egui/locales/id.toml +++ b/crates/ui-egui/locales/id.toml @@ -1917,6 +1917,7 @@ status = "draft — needs native review" "component.combineVariants" = "Gabungkan sebagai variant" "component.create" = "Buat component" "component.createMultiple" = "Buat beberapa component" +"component.createSet" = "Buat set component" "component.deleteProperty" = "Hapus properti component" "component.detach" = "Lepaskan instance" "component.editProperty" = "Edit properti component" diff --git a/crates/ui-egui/locales/it.toml b/crates/ui-egui/locales/it.toml index 364aeedf8..f6b6dfe0d 100644 --- a/crates/ui-egui/locales/it.toml +++ b/crates/ui-egui/locales/it.toml @@ -1861,6 +1861,7 @@ status = "draft — needs native review" "component.combineVariants" = "Combina come varianti" "component.create" = "Crea componente" "component.createMultiple" = "Crea più componenti" +"component.createSet" = "Crea set di componenti" "component.deleteProperty" = "Elimina proprietà del componente" "component.detach" = "Scollega istanza" "component.editProperty" = "Modifica proprietà del componente" diff --git a/crates/ui-egui/locales/ja.toml b/crates/ui-egui/locales/ja.toml index 5a8918a20..c53b03e25 100644 --- a/crates/ui-egui/locales/ja.toml +++ b/crates/ui-egui/locales/ja.toml @@ -1938,6 +1938,7 @@ status = "draft — needs native review" "component.combineVariants" = "バリアントとして結合" "component.create" = "コンポーネントを作成" "component.createMultiple" = "複数のコンポーネントを作成" +"component.createSet" = "コンポーネントセットを作成" "component.deleteProperty" = "コンポーネントプロパティを削除" "component.detach" = "インスタンスを切り離す" "component.editProperty" = "コンポーネントプロパティを編集" diff --git a/crates/ui-egui/locales/ka.toml b/crates/ui-egui/locales/ka.toml index 2af58f385..fa681b9fd 100644 --- a/crates/ui-egui/locales/ka.toml +++ b/crates/ui-egui/locales/ka.toml @@ -2013,6 +2013,7 @@ status = "draft — reviewed by a native speaker, awaiting a maintainer's approv "component.combineVariants" = "ვარიანტებად გაერთიანება" "component.create" = "კომპონენტის შექმნა" "component.createMultiple" = "რამდენიმე კომპონენტის შექმნა" +"component.createSet" = "კომპონენტების ნაკრების შექმნა" "component.deleteProperty" = "კომპონენტის თვისების წაშლა" "component.detach" = "ინსტანსის გამოყოფა" "component.editProperty" = "კომპონენტის თვისების რედაქტირება" diff --git a/crates/ui-egui/locales/ko.toml b/crates/ui-egui/locales/ko.toml index ebea678d1..6b5a39b60 100644 --- a/crates/ui-egui/locales/ko.toml +++ b/crates/ui-egui/locales/ko.toml @@ -1978,6 +1978,7 @@ status = "draft — needs native review" "component.combineVariants" = "배리언트로 결합" "component.create" = "컴포넌트 만들기" "component.createMultiple" = "여러 컴포넌트 만들기" +"component.createSet" = "컴포넌트 세트 만들기" "component.deleteProperty" = "컴포넌트 속성 삭제" "component.detach" = "인스턴스 분리" "component.editProperty" = "컴포넌트 속성 편집" diff --git a/crates/ui-egui/locales/nl.toml b/crates/ui-egui/locales/nl.toml index e43d40b5e..a1d39c7fd 100644 --- a/crates/ui-egui/locales/nl.toml +++ b/crates/ui-egui/locales/nl.toml @@ -1956,6 +1956,7 @@ status = "draft — needs native review" "component.combineVariants" = "Combineren als varianten" "component.create" = "Component maken" "component.createMultiple" = "Meerdere componenten maken" +"component.createSet" = "Componentenset maken" "component.deleteProperty" = "Componenteigenschap verwijderen" "component.detach" = "Instance loskoppelen" "component.editProperty" = "Componenteigenschap bewerken" diff --git a/crates/ui-egui/locales/pl.toml b/crates/ui-egui/locales/pl.toml index 68fe136d7..c479cd1be 100644 --- a/crates/ui-egui/locales/pl.toml +++ b/crates/ui-egui/locales/pl.toml @@ -1969,6 +1969,7 @@ name = "Polski" "component.combineVariants" = "Połącz jako warianty" "component.create" = "Utwórz komponent" "component.createMultiple" = "Utwórz wiele komponentów" +"component.createSet" = "Utwórz zestaw komponentów" "component.deleteProperty" = "Usuń właściwość komponentu" "component.detach" = "Odłącz instancję" "component.editProperty" = "Edytuj właściwość komponentu" diff --git a/crates/ui-egui/locales/pt-BR.toml b/crates/ui-egui/locales/pt-BR.toml index c2ccba835..efcde47fe 100644 --- a/crates/ui-egui/locales/pt-BR.toml +++ b/crates/ui-egui/locales/pt-BR.toml @@ -1975,6 +1975,7 @@ status = "draft — needs native review" "component.combineVariants" = "Combinar como variantes" "component.create" = "Criar componente" "component.createMultiple" = "Criar vários componentes" +"component.createSet" = "Criar conjunto de componentes" "component.deleteProperty" = "Excluir propriedade de componente" "component.detach" = "Desvincular instância" "component.editProperty" = "Editar propriedade de componente" diff --git a/crates/ui-egui/locales/ru.toml b/crates/ui-egui/locales/ru.toml index 01e1d86ac..97980eaed 100644 --- a/crates/ui-egui/locales/ru.toml +++ b/crates/ui-egui/locales/ru.toml @@ -1969,6 +1969,7 @@ name = "Русский" "component.combineVariants" = "Объединить в варианты" "component.create" = "Создать компонент" "component.createMultiple" = "Создать несколько компонентов" +"component.createSet" = "Создать набор компонентов" "component.deleteProperty" = "Удалить свойство компонента" "component.detach" = "Отсоединить экземпляр" "component.editProperty" = "Изменить свойство компонента" diff --git a/crates/ui-egui/locales/sv.toml b/crates/ui-egui/locales/sv.toml index a94feb2a9..0a97701f8 100644 --- a/crates/ui-egui/locales/sv.toml +++ b/crates/ui-egui/locales/sv.toml @@ -2076,6 +2076,7 @@ name = "Svenska" "component.combineVariants" = "Kombinera som varianter" "component.create" = "Skapa komponent" "component.createMultiple" = "Skapa flera komponenter" +"component.createSet" = "Skapa komponentuppsättning" "component.deleteProperty" = "Radera komponentegenskap" "component.detach" = "Koppla bort instans" "component.editProperty" = "Redigera komponentegenskap" diff --git a/crates/ui-egui/locales/th.toml b/crates/ui-egui/locales/th.toml index 81b581ce0..d5e98915f 100644 --- a/crates/ui-egui/locales/th.toml +++ b/crates/ui-egui/locales/th.toml @@ -1934,6 +1934,7 @@ status = "draft — needs native review" "component.combineVariants" = "รวมเป็นแวเรียนต์" "component.create" = "สร้างคอมโพเนนต์" "component.createMultiple" = "สร้างหลายคอมโพเนนต์" +"component.createSet" = "สร้างชุดคอมโพเนนต์" "component.deleteProperty" = "ลบพร็อพเพอร์ตีของคอมโพเนนต์" "component.detach" = "ถอดอินสแตนซ์" "component.editProperty" = "แก้ไขพร็อพเพอร์ตีของคอมโพเนนต์" diff --git a/crates/ui-egui/locales/tr.toml b/crates/ui-egui/locales/tr.toml index b07d25462..25bf777ce 100644 --- a/crates/ui-egui/locales/tr.toml +++ b/crates/ui-egui/locales/tr.toml @@ -1917,6 +1917,7 @@ name = "Türkçe" "component.combineVariants" = "Varyant olarak birleştir" "component.create" = "Bileşen oluştur" "component.createMultiple" = "Birden çok bileşen oluştur" +"component.createSet" = "Bileşen kümesi oluştur" "component.deleteProperty" = "Bileşen özelliğini sil" "component.detach" = "Örneği ayır" "component.editProperty" = "Bileşen özelliğini düzenle" diff --git a/crates/ui-egui/locales/vi.toml b/crates/ui-egui/locales/vi.toml index 9a4d600fe..98420ba48 100644 --- a/crates/ui-egui/locales/vi.toml +++ b/crates/ui-egui/locales/vi.toml @@ -1862,6 +1862,7 @@ status = "draft — needs native review" "component.combineVariants" = "Kết hợp thành các biến thể" "component.create" = "Tạo thành phần" "component.createMultiple" = "Tạo nhiều thành phần" +"component.createSet" = "Tạo bộ thành phần" "component.deleteProperty" = "Xóa thuộc tính thành phần" "component.detach" = "Tách bản thể" "component.editProperty" = "Chỉnh sửa thuộc tính thành phần" diff --git a/crates/ui-egui/locales/zh-Hans.toml b/crates/ui-egui/locales/zh-Hans.toml index b48345acc..7d6bfb0b7 100644 --- a/crates/ui-egui/locales/zh-Hans.toml +++ b/crates/ui-egui/locales/zh-Hans.toml @@ -1871,6 +1871,7 @@ status = "draft — needs native review" "component.combineVariants" = "合并为变体" "component.create" = "创建组件" "component.createMultiple" = "创建多个组件" +"component.createSet" = "创建组件集" "component.deleteProperty" = "删除组件属性" "component.detach" = "分离实例" "component.editProperty" = "编辑组件属性" diff --git a/crates/ui-egui/locales/zh-Hant.toml b/crates/ui-egui/locales/zh-Hant.toml index f14698b00..59b9064de 100644 --- a/crates/ui-egui/locales/zh-Hant.toml +++ b/crates/ui-egui/locales/zh-Hant.toml @@ -2089,6 +2089,7 @@ status = "draft — needs native review" "component.combineVariants" = "合併為變體" "component.create" = "建立元件" "component.createMultiple" = "建立多個元件" +"component.createSet" = "建立元件集" "component.deleteProperty" = "刪除元件屬性" "component.detach" = "分離實例" "component.editProperty" = "編輯元件屬性"