Revert "Füge Unterstützung für Datenquellen-Synonyme hinzu."

This commit is contained in:
Marcel Diegelmann 2025-09-26 12:24:30 +02:00
parent dc4461d0e9
commit 3d3d655b54
27 changed files with 37 additions and 277 deletions

View file

@ -16,20 +16,6 @@ parameters:
partdb.create_assembly_use_ipn_placeholder_in_name: '%env(bool:CREATE_ASSEMBLY_USE_IPN_PLACEHOLDER_IN_NAME)%' # Use an %%ipn%% placeholder in the name of an assembly. Placeholder is replaced with the ipn input while saving.
partdb.data_sources.synonyms: # Define your own synonyms for the given data sources
# Possible datasources: category, storagelocation, footprint, manufacturer, supplier, project, assembly
# Possible locales like the ones in 'partdb.locale_menu': en, de, it, fr, ru, ja, cs, da, zh, pl
#category:
#de: 'Bauteil Kategorien'
#en: 'Part categories'
#project:
#de: 'Geräte'
#en: 'Devices'
#assembly:
#de: 'Zusammengestellte Baugruppe'
#en: 'Combined assembly'
######################################################################################################################
# Users and Privacy
######################################################################################################################

View file

@ -191,25 +191,6 @@ services:
$fontDirectory: '%kernel.project_dir%/var/dompdf/fonts/'
$tmpDirectory: '%kernel.project_dir%/var/dompdf/tmp/'
####################################################################################################################
# Trees
####################################################################################################################
App\Services\Trees\TreeViewGenerator:
arguments:
$dataSourceSynonyms: '%partdb.data_sources.synonyms%'
App\Services\Trees\ToolsTreeBuilder:
arguments:
$dataSourceSynonyms: '%partdb.data_sources.synonyms%'
####################################################################################################################
# Twig Extensions
####################################################################################################################
App\Twig\DataSourceNameExtension:
arguments:
$dataSourceSynonyms: '%partdb.data_sources.synonyms%'
tags: [ 'twig.extension' ]
####################################################################################################################
# Part info provider system
####################################################################################################################

View file

@ -50,15 +50,8 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/
class ToolsTreeBuilder
{
public function __construct(
protected TranslatorInterface $translator,
protected UrlGeneratorInterface $urlGenerator,
protected TagAwareCacheInterface $cache,
protected UserCacheKeyGenerator $keyGenerator,
protected Security $security,
protected ?array $dataSourceSynonyms = [],
) {
$this->dataSourceSynonyms = $dataSourceSynonyms ?? [];
public function __construct(protected TranslatorInterface $translator, protected UrlGeneratorInterface $urlGenerator, protected TagAwareCacheInterface $cache, protected UserCacheKeyGenerator $keyGenerator, protected Security $security)
{
}
/**
@ -173,43 +166,43 @@ class ToolsTreeBuilder
}
if ($this->security->isGranted('read', new Category())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('category', 'tree.tools.edit.categories', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.categories'),
$this->urlGenerator->generate('category_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-tags');
}
if ($this->security->isGranted('read', new Project())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('project', 'tree.tools.edit.projects', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.projects'),
$this->urlGenerator->generate('project_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-archive');
}
if ($this->security->isGranted('read', new Assembly())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('assembly', 'tree.tools.edit.assemblies', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.assemblies'),
$this->urlGenerator->generate('assembly_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-list');
}
if ($this->security->isGranted('read', new Supplier())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('supplier', 'tree.tools.edit.suppliers', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.suppliers'),
$this->urlGenerator->generate('supplier_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-truck');
}
if ($this->security->isGranted('read', new Manufacturer())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('manufacturer', 'tree.tools.edit.manufacturer', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.manufacturer'),
$this->urlGenerator->generate('manufacturer_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-industry');
}
if ($this->security->isGranted('read', new StorageLocation())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('storagelocation', 'tree.tools.edit.storelocation', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.storelocation'),
$this->urlGenerator->generate('store_location_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-cube');
}
if ($this->security->isGranted('read', new Footprint())) {
$nodes[] = (new TreeViewNode(
$this->getTranslatedDataSourceOrSynonym('footprint', 'tree.tools.edit.footprint', $this->translator->getLocale()),
$this->translator->trans('tree.tools.edit.footprint'),
$this->urlGenerator->generate('footprint_new')
))->setIcon('fa-fw fa-treeview fa-solid fa-microchip');
}
@ -317,22 +310,4 @@ class ToolsTreeBuilder
return $nodes;
}
protected function getTranslatedDataSourceOrSynonym(string $dataSource, string $translationKey, string $locale): string
{
$currentTranslation = $this->translator->trans($translationKey);
// Call alternatives from DataSourcesynonyms (if available)
if (!empty($this->dataSourceSynonyms[$dataSource][$locale])) {
$alternativeTranslation = $this->dataSourceSynonyms[$dataSource][$locale];
// Use alternative translation when it deviates from the standard translation
if ($alternativeTranslation !== $currentTranslation) {
return $alternativeTranslation;
}
}
// Otherwise return the standard translation
return $currentTranslation;
}
}

View file

@ -68,11 +68,9 @@ class TreeViewGenerator
protected TranslatorInterface $translator,
private readonly UrlGeneratorInterface $router,
private readonly SidebarSettings $sidebarSettings,
protected ?array $dataSourceSynonyms = [],
) {
$this->rootNodeEnabled = $this->sidebarSettings->rootNodeEnabled;
$this->rootNodeExpandedByDefault = $this->sidebarSettings->rootNodeExpanded;
$this->dataSourceSynonyms = $dataSourceSynonyms ?? [];
}
/**
@ -228,16 +226,14 @@ class TreeViewGenerator
protected function entityClassToRootNodeString(string $class): string
{
$locale = $this->translator->getLocale();
return match ($class) {
Category::class => $this->getTranslatedOrSynonym('category', $locale),
StorageLocation::class => $this->getTranslatedOrSynonym('storelocation', $locale),
Footprint::class => $this->getTranslatedOrSynonym('footprint', $locale),
Manufacturer::class => $this->getTranslatedOrSynonym('manufacturer', $locale),
Supplier::class => $this->getTranslatedOrSynonym('supplier', $locale),
Project::class => $this->getTranslatedOrSynonym('project', $locale),
Assembly::class => $this->getTranslatedOrSynonym('assembly', $locale),
Category::class => $this->translator->trans('category.labelp'),
StorageLocation::class => $this->translator->trans('storelocation.labelp'),
Footprint::class => $this->translator->trans('footprint.labelp'),
Manufacturer::class => $this->translator->trans('manufacturer.labelp'),
Supplier::class => $this->translator->trans('supplier.labelp'),
Project::class => $this->translator->trans('project.labelp'),
Assembly::class => $this->translator->trans('assembly.labelp'),
default => $this->translator->trans('tree.root_node.text'),
};
}
@ -294,22 +290,4 @@ class TreeViewGenerator
return $repo->getGenericNodeTree($parent); //@phpstan-ignore-line
});
}
protected function getTranslatedOrSynonym(string $key, string $locale): string
{
$currentTranslation = $this->translator->trans($key . '.labelp');
// Call alternatives from DataSourcesynonyms (if available)
if (!empty($this->dataSourceSynonyms[$key][$locale])) {
$alternativeTranslation = $this->dataSourceSynonyms[$key][$locale];
// Use alternative translation when it deviates from the standard translation
if ($alternativeTranslation !== $currentTranslation) {
return $alternativeTranslation;
}
}
// Otherwise return the standard translation
return $currentTranslation;
}
}

View file

@ -1,42 +0,0 @@
<?php
namespace App\Twig;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class DataSourceNameExtension extends AbstractExtension
{
private TranslatorInterface $translator;
private array $dataSourceSynonyms;
public function __construct(TranslatorInterface $translator, ?array $dataSourceSynonyms)
{
$this->translator = $translator;
$this->dataSourceSynonyms = $dataSourceSynonyms ?? [];
}
public function getFunctions(): array
{
return [
new TwigFunction('get_data_source_name', [$this, 'getDataSourceName']),
];
}
/**
* Based on the locale and data source names, gives the right synonym value back or the default translator value.
*/
public function getDataSourceName(string $dataSourceName, string $defaultKey): string
{
$locale = $this->translator->getLocale();
// Use alternative dataSource synonym (if available)
if (isset($this->dataSourceSynonyms[$dataSourceName][$locale])) {
return $this->dataSourceSynonyms[$dataSourceName][$locale];
}
// Otherwise return the standard translation
return $this->translator->trans($defaultKey);
}
}

View file

@ -3,9 +3,7 @@
{# @var entity App\Entity\AssemblySystem\Assembly #}
{% block card_title %}
{% set dataSourceName = get_data_source_name('assembly', 'assembly.caption') %}
{% set translatedSource = 'assembly.caption'|trans %}
<i class="fas fa-archive fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-archive fa-fw"></i> {% trans %}assembly.caption{% endtrans %}
{% endblock %}
{% block edit_title %}

View file

@ -1,9 +1,7 @@
{% extends "admin/base_admin.html.twig" %}
{% block card_title %}
{% set dataSourceName = get_data_source_name('category', 'category.labelp') %}
{% set translatedSource = 'category.labelp'|trans %}
<i class="fas fa-tags fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-tags fa-fw"></i> {% trans %}category.labelp{% endtrans %}
{% endblock %}
{% block additional_pills %}

View file

@ -1,9 +1,7 @@
{% extends "admin/base_admin.html.twig" %}
{% block card_title %}
{% set dataSourceName = get_data_source_name('footprint', 'footprint.labelp') %}
{% set translatedSource = 'footprint.labelp'|trans %}
<i class="fas fa-microchip fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-microchip fa-fw"></i> {% trans %}footprint.labelp{% endtrans %}
{% endblock %}
{% block master_picture_block %}

View file

@ -1,9 +1,7 @@
{% extends "admin/base_company_admin.html.twig" %}
{% block card_title %}
{% set dataSourceName = get_data_source_name('manufacturer', 'manufacturer.caption') %}
{% set translatedSource = 'manufacturer.caption'|trans %}
<i class="fas fa-industry fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-industry fa-fw"></i> {% trans %}manufacturer.caption{% endtrans %}
{% endblock %}
{% block edit_title %}

View file

@ -3,9 +3,7 @@
{# @var entity App\Entity\ProjectSystem\Project #}
{% block card_title %}
{% set dataSourceName = get_data_source_name('project', 'project.caption') %}
{% set translatedSource = 'project.caption'|trans %}
<i class="fas fa-archive fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-archive fa-fw"></i> {% trans %}project.caption{% endtrans %}
{% endblock %}
{% block edit_title %}

View file

@ -2,9 +2,7 @@
{% import "label_system/dropdown_macro.html.twig" as dropdown %}
{% block card_title %}
{% set dataSourceName = get_data_source_name('storagelocation', 'storelocation.labelp') %}
{% set translatedSource = 'storelocation.labelp'|trans %}
<i class="fas fa-cube fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-cube fa-fw"></i> {% trans %}storelocation.labelp{% endtrans %}
{% endblock %}
{% block additional_controls %}

View file

@ -1,9 +1,7 @@
{% extends "admin/base_company_admin.html.twig" %}
{% block card_title %}
{% set dataSourceName = get_data_source_name('supplier', 'supplier.caption') %}
{% set translatedSource = 'supplier.caption'|trans %}
<i class="fas fa-truck fa-fw"></i> {% if dataSourceName != translatedSource %}{{ 'datasource.synonym'|trans({'%name%': translatedSource, '%synonym%': dataSourceName}) }}{% else %}{{ translatedSource }}{% endif %}
<i class="fas fa-truck fa-fw"></i> {% trans %}supplier.caption{% endtrans %}
{% endblock %}
{% block additional_panes %}

View file

@ -1,16 +1,14 @@
{% macro sidebar_dropdown() %}
{% set currentLocale = app.request.locale %}
{# Format is [mode, route, label, show_condition] #}
{% set data_sources = [
['categories', path('tree_category_root'), 'category.labelp', is_granted('@categories.read') and is_granted('@parts.read'), 'category'],
['locations', path('tree_location_root'), 'storelocation.labelp', is_granted('@storelocations.read') and is_granted('@parts.read'), 'storagelocation'],
['footprints', path('tree_footprint_root'), 'footprint.labelp', is_granted('@footprints.read') and is_granted('@parts.read'), 'footprint'],
['manufacturers', path('tree_manufacturer_root'), 'manufacturer.labelp', is_granted('@manufacturers.read') and is_granted('@parts.read'), 'manufacturer'],
['suppliers', path('tree_supplier_root'), 'supplier.labelp', is_granted('@suppliers.read') and is_granted('@parts.read'), 'supplier'],
['projects', path('tree_device_root'), 'project.labelp', is_granted('@projects.read'), 'project'],
['assembly', path('tree_assembly_root'), 'assembly.labelp', is_granted('@assemblies.read'), 'assembly'],
['tools', path('tree_tools'), 'tools.label', true, 'tool'],
['categories', path('tree_category_root'), 'category.labelp', is_granted('@categories.read') and is_granted('@parts.read')],
['locations', path('tree_location_root'), 'storelocation.labelp', is_granted('@storelocations.read') and is_granted('@parts.read')],
['footprints', path('tree_footprint_root'), 'footprint.labelp', is_granted('@footprints.read') and is_granted('@parts.read')],
['manufacturers', path('tree_manufacturer_root'), 'manufacturer.labelp', is_granted('@manufacturers.read') and is_granted('@parts.read')],
['suppliers', path('tree_supplier_root'), 'supplier.labelp', is_granted('@suppliers.read') and is_granted('@parts.read')],
['projects', path('tree_device_root'), 'project.labelp', is_granted('@projects.read')],
['assembly', path('tree_assembly_root'), 'assembly.labelp', is_granted('@assemblies.read')],
['tools', path('tree_tools'), 'tools.label', true],
] %}
<li class="dropdown-header">{% trans %}actions{% endtrans %}</li>
@ -21,9 +19,9 @@
{% for source in data_sources %}
{% if source[3] %} {# show_condition #}
<li><button class="tree-btns dropdown-item" data-mode="{{ source[0] }}" data-url="{{ source[1] }}" data-text="{{ get_data_source_name(source[4], source[2]) }}"
<li><button class="tree-btns dropdown-item" data-mode="{{ source[0] }}" data-url="{{ source[1] }}" data-text="{{ source[2] | trans }}"
{{ stimulus_action('elements/sidebar_tree', 'changeDataSource') }}
>{{ get_data_source_name(source[4], source[2]) }}</button></li>
>{{ source[2] | trans }}</button></li>
{% endif %}
{% endfor %}
{% endmacro %}
@ -64,4 +62,4 @@
<div class="treeview-sm mt-2" {{ stimulus_target('elements/tree', 'tree') }}></div>
</div>
{% endmacro %}
{% endmacro %}

View file

@ -6,36 +6,12 @@
<div class="form-check">
<input type="checkbox" class="form-check-input tristate permission-checkbox permission_multicheckbox" id="mulit_check_{{ form.vars.label }}">
<label class="form-check-label" for="mulit_check_{{ form.vars.label }}">
{% set dataSource = '' %}
{% if (form.vars.label == 'perm.part.categories') %}
{% set dataSource = 'category' %}
{% elseif (form.vars.label == 'perm.storelocations') %}
{% set dataSource = 'storagelocation' %}
{% elseif (form.vars.label == 'perm.part.footprints') %}
{% set dataSource = 'footprint' %}
{% elseif (form.vars.label == 'perm.part.manufacturers') %}
{% set dataSource = 'manufacturer' %}
{% elseif (form.vars.label == 'perm.part.supplier') %}
{% set dataSource = 'supplier' %}
{% elseif (form.vars.label == 'perm.projects') %}
{% set dataSource = 'project' %}
{% elseif (form.vars.label == 'perm.assemblies') %}
{% set dataSource = 'assembly' %}
{% endif %}
{% set dataSourceName = get_data_source_name(dataSource, form.vars.label) %}
{% set translatedSource = form.vars.label|trans %}
{% if dataSourceName != translatedSource %}
{{ translatedSource }}
<i class="fas fa-fw fa-info" title="{{ 'datasource.synonym'|trans({'%name%': '', '%synonym%': dataSourceName })|raw }}"></i>
{% else %}
{{ translatedSource }}
{% endif %}
<b>{{ form.vars.label | trans }}</b>
</label>
</div>
{% else %}
<b>def{{ form.vars.label | trans }}</b>
<b>{{ form.vars.label | trans }}</b>
{% endif %}
@ -134,4 +110,4 @@
{% endfor %}
</div>
{% endblock %}
{% endblock %}

View file

@ -14877,11 +14877,5 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
<target>Popis</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Váš synonymum: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13522,11 +13522,5 @@ Bemærk venligst, at du ikke kan kopiere fra deaktiveret bruger. Hvis du prøver
<target>Beskrivelse</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Dit synonym: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -15551,11 +15551,5 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
<target>Beschreibung</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Ihr Synonym: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -2530,11 +2530,5 @@
<target>Περιγραφή</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Το συνώνυμό σας: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -15552,11 +15552,5 @@ Please note, that you can not impersonate a disabled user. If you try you will g
<target>Description</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Your synonym: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13694,11 +13694,5 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S
<target>Descripción</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Tu sinónimo: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -10104,11 +10104,5 @@ exemple de ville</target>
<target>Description</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Votre synonyme : %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13696,11 +13696,5 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a
<target>Descrizione</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Il tuo sinonimo: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -9817,11 +9817,5 @@ Exampletown</target>
<target>説明</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (あなたの同義語: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -1755,11 +1755,5 @@
<target>Beschrijving</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Uw synoniem: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13549,11 +13549,5 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli
<target>Opis</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Twój synonim: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13649,11 +13649,5 @@
<target>Описание</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (Ваш синоним: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>

View file

@ -13534,11 +13534,5 @@ Element 3</target>
<target>描述</target>
</segment>
</unit>
<unit id="a7uOieC" name="datasource.synonym">
<segment state="translated">
<source>datasource.synonym</source>
<target>%name% (您的同义词: %synonym%)</target>
</segment>
</unit>
</file>
</xliff>