From 3d3b1f276c0b1de7d9a30b2bf152561c839c5aac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:31:54 +0000 Subject: [PATCH 1/6] Initial plan From a2f3ceb142336aa549d3f3dec328fea665c34138 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:42:40 +0000 Subject: [PATCH 2/6] Replace placeholder syntax for type synonyms to be more DX friendly Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com> --- config/permissions.yaml | 22 +++++++++---------- ...ynonymsAsTranslationParametersListener.php | 18 +++++++++------ ...terSynonymsAsTranslationParametersTest.php | 11 +++++----- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/config/permissions.yaml b/config/permissions.yaml index 5adfb79d6..8c6a145ed 100644 --- a/config/permissions.yaml +++ b/config/permissions.yaml @@ -18,7 +18,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co parts: # e.g. this maps to perms_parts in User/Group database group: "data" - label: "{{part}}" + label: "[[Part]]" operations: # Here are all possible operations are listed => the op name is mapped to bit value read: label: "perm.read" @@ -71,7 +71,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co storelocations: &PART_CONTAINING - label: "{{storage_location}}" + label: "[[Storage_location]]" group: "data" operations: read: @@ -103,39 +103,39 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co footprints: <<: *PART_CONTAINING - label: "{{footprint}}" + label: "[[Footprint]]" categories: <<: *PART_CONTAINING - label: "{{category}}" + label: "[[Category]]" suppliers: <<: *PART_CONTAINING - label: "{{supplier}}" + label: "[[Supplier]]" manufacturers: <<: *PART_CONTAINING - label: "{{manufacturer}}" + label: "[[Manufacturer]]" projects: <<: *PART_CONTAINING - label: "{{project}}" + label: "[[Project]]" attachment_types: <<: *PART_CONTAINING - label: "{{attachment_type}}" + label: "[[Attachment_type]]" currencies: <<: *PART_CONTAINING - label: "{{currency}}" + label: "[[Currency]]" measurement_units: <<: *PART_CONTAINING - label: "{{measurement_unit}}" + label: "[[Measurement_unit]]" part_custom_states: <<: *PART_CONTAINING - label: "{{part_custom_state}}" + label: "[[Part_custom_state]]" tools: label: "perm.part.tools" diff --git a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php index b216aad45..6bc7c9490 100644 --- a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php +++ b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php @@ -60,14 +60,18 @@ public function getSynonymPlaceholders(): array //Generate a placeholder for each element type foreach (ElementTypes::cases() as $elementType) { - //We have a placeholder for singular - $placeholders['{' . $elementType->value . '}'] = $this->typeNameGenerator->typeLabel($elementType); - //We have a placeholder for plural - $placeholders['{{' . $elementType->value . '}}'] = $this->typeNameGenerator->typeLabelPlural($elementType); + // Get the capitalized labels + $capitalizedSingular = $this->typeNameGenerator->typeLabel($elementType); + $capitalizedPlural = $this->typeNameGenerator->typeLabelPlural($elementType); + + // Curly braces for lowercase versions + $placeholders['{' . $elementType->value . '}'] = mb_strtolower($capitalizedSingular); + $placeholders['{{' . $elementType->value . '}}'] = mb_strtolower($capitalizedPlural); - //And we have lowercase versions for both - $placeholders['[' . $elementType->value . ']'] = mb_strtolower($this->typeNameGenerator->typeLabel($elementType)); - $placeholders['[[' . $elementType->value . ']]'] = mb_strtolower($this->typeNameGenerator->typeLabelPlural($elementType)); + // Square brackets for capitalized versions (with capital first letter in placeholder) + $capitalizedKey = ucfirst($elementType->value); + $placeholders['[' . $capitalizedKey . ']'] = $capitalizedSingular; + $placeholders['[[' . $capitalizedKey . ']]'] = $capitalizedPlural; } return $placeholders; diff --git a/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php b/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php index d08edecb8..636b9fe77 100644 --- a/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php +++ b/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php @@ -40,10 +40,11 @@ public function testGetSynonymPlaceholders(): void $placeholders = $this->listener->getSynonymPlaceholders(); $this->assertIsArray($placeholders); - $this->assertSame('Part', $placeholders['{part}']); - $this->assertSame('Parts', $placeholders['{{part}}']); - //Lowercase versions: - $this->assertSame('part', $placeholders['[part]']); - $this->assertSame('parts', $placeholders['[[part]]']); + // Curly braces for lowercase versions + $this->assertSame('part', $placeholders['{part}']); + $this->assertSame('parts', $placeholders['{{part}}']); + // Square brackets for capitalized versions (with capital first letter in placeholder) + $this->assertSame('Part', $placeholders['[Part]']); + $this->assertSame('Parts', $placeholders['[[Part]]']); } } From 97f4d22292ab75d269662aae245a287bbb5ff77b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:44:59 +0000 Subject: [PATCH 3/6] Update translation files to use new placeholder syntax Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com> --- translations/messages.de.xlf | 4 ++-- translations/messages.en.xlf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index d187d4c71..25eeb7530 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -14545,9 +14545,9 @@ Bitte beachten Sie, dass dieses System derzeit experimentell ist und die hier de Mit Typsynonymen können Sie die Bezeichnungen von integrierten Datentypen ersetzen. Zum Beispiel können Sie „Footprint" in etwas anderes umbenennen. - + - {{part}} + [[Part]] Bauteile diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 917d2675f..4cef4f295 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -14394,9 +14394,9 @@ Please note that this system is currently experimental, and the synonyms defined Type synonyms allow you to replace the labels of built-in data types. For example, you can rename "Footprint" to something else. - + - {{part}} + [[Part]] Parts From 9e095ec1c8b738ad5ad0c2d2d5b570bd1ae67bbf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:46:29 +0000 Subject: [PATCH 4/6] Use mb_strtoupper with mb_substr for Unicode consistency Co-authored-by: jbtronics <5410681+jbtronics@users.noreply.github.com> --- .../RegisterSynonymsAsTranslationParametersListener.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php index 6bc7c9490..1495bbaae 100644 --- a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php +++ b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php @@ -69,7 +69,8 @@ public function getSynonymPlaceholders(): array $placeholders['{{' . $elementType->value . '}}'] = mb_strtolower($capitalizedPlural); // Square brackets for capitalized versions (with capital first letter in placeholder) - $capitalizedKey = ucfirst($elementType->value); + // Use mb_strtoupper for the first character to handle multibyte strings consistently + $capitalizedKey = mb_strtoupper(mb_substr($elementType->value, 0, 1)) . mb_substr($elementType->value, 1); $placeholders['[' . $capitalizedKey . ']'] = $capitalizedSingular; $placeholders['[[' . $capitalizedKey . ']]'] = $capitalizedPlural; } From 51547523683a8e032e362365817afc8141ab34d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sat, 6 Dec 2025 23:27:12 +0100 Subject: [PATCH 5/6] Make placeholder generation right --- config/reference.php | 34 +++++++++---------- ...ynonymsAsTranslationParametersListener.php | 19 ++++------- ...terSynonymsAsTranslationParametersTest.php | 4 +-- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/config/reference.php b/config/reference.php index 6ea524192..5d58153f9 100644 --- a/config/reference.php +++ b/config/reference.php @@ -1548,11 +1548,6 @@ * dump_destination?: scalar|null, // A stream URL where dumps should be written to. // Default: null * theme?: "dark"|"light", // Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light". // Default: "dark" * } - * @psalm-type MakerConfig = array{ - * root_namespace?: scalar|null, // Default: "App" - * generate_final_classes?: bool, // Default: true - * generate_final_entities?: bool, // Default: false - * } * @psalm-type WebpackEncoreConfig = array{ * output_path: scalar|null, // The path where Encore is building the assets - i.e. Encore.setOutputPath() * crossorigin?: false|"anonymous"|"use-credentials", // crossorigin value when Encore.enableIntegrityHashes() is used, can be false (default), anonymous or use-credentials // Default: false @@ -1677,6 +1672,12 @@ * post_processors?: array>, * }, * } + * @psalm-type DamaDoctrineTestConfig = array{ + * enable_static_connection?: mixed, // Default: true + * enable_static_meta_data_cache?: bool, // Default: true + * enable_static_query_cache?: bool, // Default: true + * connection_keys?: list, + * } * @psalm-type TwigExtraConfig = array{ * cache?: bool|array{ * enabled?: bool, // Default: false @@ -2372,13 +2373,6 @@ * invalidate_on_env_change?: bool, // Default: true * }, * } - * @psalm-type JbtronicsTranslationEditorConfig = array{ - * translations_path?: scalar|null, // Default: "%translator.default_path%" - * format?: scalar|null, // Default: "xlf" - * xliff_version?: scalar|null, // Default: "2.0" - * use_intl_icu_format?: bool, // Default: false - * writer_options?: list, - * } * @psalm-type ApiPlatformConfig = array{ * title?: scalar|null, // The title of the API. // Default: "" * description?: scalar|null, // The description of the API. // Default: "" @@ -2634,11 +2628,17 @@ * ... * }, * } - * @psalm-type DamaDoctrineTestConfig = array{ - * enable_static_connection?: mixed, // Default: true - * enable_static_meta_data_cache?: bool, // Default: true - * enable_static_query_cache?: bool, // Default: true - * connection_keys?: list, + * @psalm-type MakerConfig = array{ + * root_namespace?: scalar|null, // Default: "App" + * generate_final_classes?: bool, // Default: true + * generate_final_entities?: bool, // Default: false + * } + * @psalm-type JbtronicsTranslationEditorConfig = array{ + * translations_path?: scalar|null, // Default: "%translator.default_path%" + * format?: scalar|null, // Default: "xlf" + * xliff_version?: scalar|null, // Default: "2.0" + * use_intl_icu_format?: bool, // Default: false + * writer_options?: list, * } * @psalm-type ConfigType = array{ * imports?: ImportsConfig, diff --git a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php index 1495bbaae..e7ac73005 100644 --- a/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php +++ b/src/EventListener/RegisterSynonymsAsTranslationParametersListener.php @@ -60,19 +60,14 @@ public function getSynonymPlaceholders(): array //Generate a placeholder for each element type foreach (ElementTypes::cases() as $elementType) { - // Get the capitalized labels - $capitalizedSingular = $this->typeNameGenerator->typeLabel($elementType); - $capitalizedPlural = $this->typeNameGenerator->typeLabelPlural($elementType); - - // Curly braces for lowercase versions - $placeholders['{' . $elementType->value . '}'] = mb_strtolower($capitalizedSingular); - $placeholders['{{' . $elementType->value . '}}'] = mb_strtolower($capitalizedPlural); + //Versions with capitalized first letter + $capitalized = ucfirst($elementType->value); //We have only ASCII element type values, so this is sufficient + $placeholders['[' . $capitalized . ']'] = $this->typeNameGenerator->typeLabel($elementType); + $placeholders['[[' . $capitalized . ']]'] = $this->typeNameGenerator->typeLabelPlural($elementType); - // Square brackets for capitalized versions (with capital first letter in placeholder) - // Use mb_strtoupper for the first character to handle multibyte strings consistently - $capitalizedKey = mb_strtoupper(mb_substr($elementType->value, 0, 1)) . mb_substr($elementType->value, 1); - $placeholders['[' . $capitalizedKey . ']'] = $capitalizedSingular; - $placeholders['[[' . $capitalizedKey . ']]'] = $capitalizedPlural; + //And we have lowercase versions for both + $placeholders['[' . $elementType->value . ']'] = mb_strtolower($this->typeNameGenerator->typeLabel($elementType)); + $placeholders['[[' . $elementType->value . ']]'] = mb_strtolower($this->typeNameGenerator->typeLabelPlural($elementType)); } return $placeholders; diff --git a/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php b/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php index 636b9fe77..4f49284a2 100644 --- a/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php +++ b/tests/EventListener/RegisterSynonymsAsTranslationParametersTest.php @@ -41,8 +41,8 @@ public function testGetSynonymPlaceholders(): void $this->assertIsArray($placeholders); // Curly braces for lowercase versions - $this->assertSame('part', $placeholders['{part}']); - $this->assertSame('parts', $placeholders['{{part}}']); + $this->assertSame('part', $placeholders['[part]']); + $this->assertSame('parts', $placeholders['[[part]]']); // Square brackets for capitalized versions (with capital first letter in placeholder) $this->assertSame('Part', $placeholders['[Part]']); $this->assertSame('Parts', $placeholders['[[Part]]']); From 23086c94bc6047f97d0dbbf97448c4d7d5708ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sat, 6 Dec 2025 23:29:18 +0100 Subject: [PATCH 6/6] Removed obsolete transltions --- config/reference.php | 34 +++++++++++++++++----------------- translations/messages.de.xlf | 6 ------ translations/messages.en.xlf | 6 ------ 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/config/reference.php b/config/reference.php index 5d58153f9..6ea524192 100644 --- a/config/reference.php +++ b/config/reference.php @@ -1548,6 +1548,11 @@ * dump_destination?: scalar|null, // A stream URL where dumps should be written to. // Default: null * theme?: "dark"|"light", // Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light". // Default: "dark" * } + * @psalm-type MakerConfig = array{ + * root_namespace?: scalar|null, // Default: "App" + * generate_final_classes?: bool, // Default: true + * generate_final_entities?: bool, // Default: false + * } * @psalm-type WebpackEncoreConfig = array{ * output_path: scalar|null, // The path where Encore is building the assets - i.e. Encore.setOutputPath() * crossorigin?: false|"anonymous"|"use-credentials", // crossorigin value when Encore.enableIntegrityHashes() is used, can be false (default), anonymous or use-credentials // Default: false @@ -1672,12 +1677,6 @@ * post_processors?: array>, * }, * } - * @psalm-type DamaDoctrineTestConfig = array{ - * enable_static_connection?: mixed, // Default: true - * enable_static_meta_data_cache?: bool, // Default: true - * enable_static_query_cache?: bool, // Default: true - * connection_keys?: list, - * } * @psalm-type TwigExtraConfig = array{ * cache?: bool|array{ * enabled?: bool, // Default: false @@ -2373,6 +2372,13 @@ * invalidate_on_env_change?: bool, // Default: true * }, * } + * @psalm-type JbtronicsTranslationEditorConfig = array{ + * translations_path?: scalar|null, // Default: "%translator.default_path%" + * format?: scalar|null, // Default: "xlf" + * xliff_version?: scalar|null, // Default: "2.0" + * use_intl_icu_format?: bool, // Default: false + * writer_options?: list, + * } * @psalm-type ApiPlatformConfig = array{ * title?: scalar|null, // The title of the API. // Default: "" * description?: scalar|null, // The description of the API. // Default: "" @@ -2628,17 +2634,11 @@ * ... * }, * } - * @psalm-type MakerConfig = array{ - * root_namespace?: scalar|null, // Default: "App" - * generate_final_classes?: bool, // Default: true - * generate_final_entities?: bool, // Default: false - * } - * @psalm-type JbtronicsTranslationEditorConfig = array{ - * translations_path?: scalar|null, // Default: "%translator.default_path%" - * format?: scalar|null, // Default: "xlf" - * xliff_version?: scalar|null, // Default: "2.0" - * use_intl_icu_format?: bool, // Default: false - * writer_options?: list, + * @psalm-type DamaDoctrineTestConfig = array{ + * enable_static_connection?: mixed, // Default: true + * enable_static_meta_data_cache?: bool, // Default: true + * enable_static_query_cache?: bool, // Default: true + * connection_keys?: list, * } * @psalm-type ConfigType = array{ * imports?: ImportsConfig, diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 25eeb7530..7ad25213d 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -14545,12 +14545,6 @@ Bitte beachten Sie, dass dieses System derzeit experimentell ist und die hier de Mit Typsynonymen können Sie die Bezeichnungen von integrierten Datentypen ersetzen. Zum Beispiel können Sie „Footprint" in etwas anderes umbenennen. - - - [[Part]] - Bauteile - - log.element_edited.changed_fields.part_ipn_prefix diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 4cef4f295..349f001fa 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -14394,12 +14394,6 @@ Please note that this system is currently experimental, and the synonyms defined Type synonyms allow you to replace the labels of built-in data types. For example, you can rename "Footprint" to something else. - - - [[Part]] - Parts - - log.element_edited.changed_fields.part_ipn_prefix