Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locales in combination with pretty urls not working #6619

Open
dahormez opened this issue Dec 4, 2024 · 1 comment
Open

Locales in combination with pretty urls not working #6619

dahormez opened this issue Dec 4, 2024 · 1 comment

Comments

@dahormez
Copy link

dahormez commented Dec 4, 2024

Describe the bug
Locales in combination with pretty urls not working. Tested in v4.14.0 - v4.19.0

To Reproduce

Setup:

#[Route('/admin/{_locale}', name: 'admin', defaults: ['_locale' => 'de'])]
public function index(): Response
{
    return $this->render('admin/page/dashboard.html.twig');
}

public function configureDashboard(): Dashboard
{
    return Dashboard::new()
        ->setTitle('Administration')
        ->setLocales(['de', 'en']);
}

Add new crud:

public function configureMenuItems(): iterable
{
    return [
        yield MenuItem::linkToCrud('Users', 'fa fa-user', UserCrudController::getEntityFqcn()),
    ];
}

Try to edit any entry produces:
An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("entityId") to generate a URL for route "admin_user_edit".").

Error appears in:
vendor/easycorp/easyadmin-bundle/templates/layout.html.twig:133

Here is entityId not set:
{{ ea_url().set('_locale', localeDto.locale) }}

@latenzio
Copy link

I solved this in my current project with a template override until line 133 is fixed like this:

<a href="{{ ea_url({'entityId': app.request.get('entityId')}).set('_locale', localeDto.locale) }}"

templates/bundles/EasyAdminBundle/layout.html.twig

{% extends '@!EasyAdmin/layout.html.twig' %}

{% block wrapper_wrapper %}
    {% block flash_messages %}
        {{ include(ea.templatePath('flash_messages')) }}
    {% endblock flash_messages %}

    {% set user_menu_avatar %}
        {% if null == ea.userMenu.avatarUrl %}
            <span class="user-avatar">
                <twig:ea:Icon name="internal:user"/>
            </span>
        {% else %}
            <img class="user-avatar" src="{{ ea.userMenu.avatarUrl }}"/>
        {% endif %}
    {% endset %}

    {% set impersonator_permission = constant('Symfony\\Component\\Security\\Core\\Authorization\\Voter\\AuthenticatedVoter::IS_IMPERSONATOR') is defined ? 'IS_IMPERSONATOR' : 'ROLE_PREVIOUS_ADMIN' %}

    {% set user_menu_dropdown %}
        <ul class="dropdown-menu dropdown-menu-end">
            <li class="dropdown-user-details">
                <div>{{ user_menu_avatar }}</div>
                <div>
                    <span class="user-label">{{ 'user.logged_in_as'|trans(domain = 'EasyAdminBundle') }}</span>
                    <span
                        class="user-name">{{ ea.user is null ? 'user.anonymous'|trans(domain = 'EasyAdminBundle') : ea.userMenu.name }}</span>
                </div>
            </li>

            {% block user_menu %}
                {% if ea.userMenu.items|length > 0 %}
                    <li>
                        <hr class="dropdown-divider">
                    </li>
                    {% for item in ea.userMenu.items %}
                        <li>
                            {% if item.isMenuSection and not loop.first %}
                                <hr class="dropdown-divider">
                            {% elseif not item.isMenuSection %}
                                <a href="{{ item.linkUrl }}" class="dropdown-item user-action {{ item.cssClass }}"
                                   target="{{ item.linkTarget }}" rel="{{ item.linkRel }}"
                                   referrerpolicy="origin-when-cross-origin">
                                    {% if item.icon is not empty %}
                                        <twig:ea:Icon name="{{ item.icon }}" />{% endif %}
                                    {{ item.label|trans }}
                                </a>
                            {% endif %}
                        </li>
                    {% endfor %}
                {% endif %}
            {% endblock user_menu %}
        </ul>
    {% endset %}

    {% set settings_dropdown %}
        {% if ea.dashboardLocales or ea.dashboardHasDarkModeEnabled %}
            <div class="dropdown dropdown-settings">
                <a class="dropdown-settings-button" type="button" data-bs-toggle="dropdown" data-bs-offset="0,5"
                   aria-expanded="false">
                    <twig:ea:Icon name="internal:gear"/>
                </a>

                <ul class="dropdown-menu dropdown-menu-end">
                    {% if ea.dashboardLocales %}
                        <li class="dropdown-header dropdown-locales-label">
                            {{ 'settings.locale'|trans(domain = 'EasyAdminBundle') }}
                        </li>

                        {% for localeDto in ea.dashboardLocales %}
                            <li>
                                <a href="{{ ea_url({'entityId': app.request.get('entityId')}).set('_locale', localeDto.locale) }}"
                                   class="dropdown-item{% if app.request.locale == localeDto.locale %} active{% endif %}">
                                    {% if localeDto.icon %}
                                        <twig:ea:Icon name="{{ localeDto.icon }}"/>
                                    {% endif %}
                                    {{ localeDto.name }}
                                </a>
                            </li>
                        {% endfor %}
                    {% endif %}

                    {% if ea.dashboardHasDarkModeEnabled %}
                        {% if ea.dashboardLocales %}
                            <div class="dropdown-divider"></div>
                        {% endif %}

                        <li class="dropdown-header dropdown-appearance-label">
                            {{ 'settings.appearance.label'|trans(domain = 'EasyAdminBundle') }}
                        </li>
                        <li>
                            <a href="#" class="dropdown-item dropdown-appearance-item" data-ea-color-scheme="light">
                                <twig:ea:Icon name="internal:sun"/>
                                {{ 'settings.appearance.light'|trans(domain = 'EasyAdminBundle') }}
                            </a>
                        </li>
                        <li>
                            <a href="#" class="dropdown-item dropdown-appearance-item" data-ea-color-scheme="dark">
                                <twig:ea:Icon name="internal:moon"/>
                                {{ 'settings.appearance.dark'|trans(domain = 'EasyAdminBundle') }}
                            </a>
                        </li>
                        <li>
                            <a href="#" class="dropdown-item dropdown-appearance-item active"
                               data-ea-color-scheme="auto">
                                <twig:ea:Icon name="internal:desktop"/>
                                {{ 'settings.appearance.auto'|trans(domain = 'EasyAdminBundle') }}
                            </a>
                        </li>
                    {% endif %}
                </ul>
            </div>
        {% endif %}
    {% endset %}

    <div class="wrapper">
        {% block wrapper %}
            <div class="responsive-header">
                {% block responsive_header %}
                    <button id="navigation-toggler" type="button" aria-label="Toggle navigation">
                        <twig:ea:Icon name="internal:menu-bars"/>
                    </button>

                    <div id="responsive-header-logo" class="text-truncate ms-auto">
                        {% block responsive_header_logo %}
                            <a class="responsive-logo" title="{{ ea.dashboardTitle|striptags }}"
                               href="{{ path(ea.dashboardRouteName) }}">
                                {{ ea.dashboardTitle|raw }}
                            </a>
                        {% endblock responsive_header_logo %}
                    </div>

                    <div
                        class="dropdown user-menu-wrapper {{ is_granted(impersonator_permission) ? 'user-is-impersonated' }} ms-auto">
                        <a class="user-details" type="button" data-bs-toggle="dropdown" data-bs-offset="0,5"
                           aria-expanded="false">
                            {# to make the site design consistent, always display the user avatar in responsive header
                               and hide the user name (because there's no space left) regardless of the user config #}
                            {% if ea.userMenu.avatarDisplayed %}
                                {{ user_menu_avatar }}
                            {% else %}
                                <twig:ea:Icon class="user-avatar"
                                              name="{{ ea.user is not null ? 'internal:user' : 'internal:user-xmark' }}"/>
                            {% endif %}
                        </a>

                        {{ user_menu_dropdown }}
                    </div>

                    {{ settings_dropdown }}
                {% endblock responsive_header %}
            </div>

            <div class="sidebar-wrapper">
                <aside class="sidebar">
                    {% block sidebar %}
                        <header class="main-header">
                            {% block header %}
                                <nav class="navbar" role="navigation">
                                    {% block header_navbar %}
                                        <div id="header-logo">
                                            {% block header_logo %}
                                                <a class="logo" title="{{ ea.dashboardTitle|striptags }}"
                                                   href="{{ path(ea.dashboardRouteName) }}">
                                                    <span class="logo-custom">{{ ea.dashboardTitle|raw }}</span>
                                                    <span class="logo-compact"><twig:ea:Icon name="internal:home"/></span>
                                                </a>
                                            {% endblock header_logo %}
                                        </div>
                                    {% endblock header_navbar %}
                                </nav>
                            {% endblock header %}
                        </header>

                        {% block main_menu_wrapper %}
                            {{ include(ea.templatePath('main_menu')) }}
                        {% endblock main_menu_wrapper %}
                    {% endblock sidebar %}

                    <div id="sidebar-resizer-handler" class="resizer-handler resizer-handler-left"></div>
                </aside>
            </div>

            <section class="main-content">
                {% set has_search = ea.crud is not null and ea.crud.isSearchEnabled %}
                <aside class="content-top {{ has_search ? 'ea-search-enabled' : 'ea-search-disabled' }}">
                    {% block content_top_header %}
                        {% block search_wrapper %}
                            <div class="content-search">
                                {% if has_search %}
                                    {% block search %}
                                        {% set formActionUrl = null %}
                                        {% if ea.usePrettyUrls %}
                                            {% set formActionUrl = ea_url().setController(ea.request.attributes.get('crudControllerFqcn')).setAction('index').set('page', 1) %}
                                        {% endif %}
                                        <form class="form-action-search" method="get"
                                              {% if formActionUrl %}action="{{ formActionUrl }}"{% endif %}>
                                            {% block search_form %}
                                                {% block search_form_filters %}
                                                    {% for field, fieldValue in ea.search.appliedFilters %}
                                                        {% if fieldValue is iterable %}
                                                            {% for key, value in fieldValue %}
                                                                {# This code re-applies your filters on searches, an iterable check is needed in cases we have more than one object for a filter #}
                                                                {% if value is iterable %}
                                                                    {% for index, iterValue in value %}
                                                                        {# This sub-level iterable check is needed in cases we have more complex filters like the DateTimeFilter cf. issue #5038 #}
                                                                        {% if iterValue is iterable %}
                                                                            {% for subIndex, subIterValue in iterValue %}
                                                                                <input type="hidden"
                                                                                       name="filters[{{ field }}][{{ key }}][{{ index }}][{{ subIndex }}]"
                                                                                       value="{{ subIterValue }}">
                                                                            {% endfor %}
                                                                        {% else %}
                                                                            <input type="hidden"
                                                                                   name="filters[{{ field }}][{{ key }}][{{ index }}]"
                                                                                   value="{{ iterValue }}">
                                                                        {% endif %}
                                                                    {% endfor %}
                                                                {% else %}
                                                                    <input type="hidden"
                                                                           name="filters[{{ field }}][{{ key }}]"
                                                                           value="{{ value }}">
                                                                {% endif %}
                                                            {% endfor %}
                                                        {% else %}
                                                            <input type="hidden" name="filters[{{ field }}]"
                                                                   value="{{ fieldValue }}">
                                                        {% endif %}
                                                    {% endfor %}
                                                {% endblock %}

                                                {% if not ea.usePrettyUrls %}
                                                    <input type="hidden" name="crudAction" value="index">
                                                    <input type="hidden" name="crudControllerFqcn"
                                                           value="{{ ea.request.query.get('crudControllerFqcn') }}">
                                                    <input type="hidden" name="page" value="1">
                                                {% endif %}

                                                <div class="form-group">
                                                    <div class="form-widget">
                                                        <twig:ea:Icon name="internal:search"
                                                                      class="content-search-icon"/>

                                                        <label class="content-search-label"
                                                               data-value="{{ app.request.get('query') }}">
                                                            <input
                                                                class="form-control {{ app.request.get('query') is null ? 'is-blank' }}"
                                                                type="search" name="query"
                                                                value="{{ app.request.get('query') ?? '' }}"
                                                                placeholder="{{ t('action.search', ea.i18n.translationParameters, 'EasyAdminBundle')|trans }}"
                                                                spellcheck="false" autocorrect="off"
                                                                onInput="this.parentNode.dataset.value=this.value"{% if ea.crud.currentAction == 'index' and ea.crud.autofocusSearch == true %} autofocus="autofocus"{% endif %}>
                                                        </label>

                                                        {% if app.request.get('query') %}
                                                            {% set search_reset_url = ea_url().unset('query') %}
                                                            {% if ea.usePrettyUrls %}
                                                                {% set search_reset_url = ea_url().unset('query').setController(ea.request.attributes.get('crudControllerFqcn')).setAction('index').set('page', 1) %}
                                                            {% endif %}
                                                            <a href="{{ search_reset_url }}"
                                                               class="content-search-reset">
                                                                <twig:ea:Icon name="internal:xmark"/>
                                                            </a>
                                                        {% endif %}
                                                    </div>
                                                </div>
                                            {% endblock %}
                                        </form>
                                    {% endblock search %}
                                {% endif %}
                            </div>
                        {% endblock search_wrapper %}

                        {% block header_custom_menu_wrapper %}
                            <div class="navbar-custom-menu">
                                {% block header_custom_menu %}
                                    <div
                                        class="dropdown user-menu-wrapper {{ is_granted(impersonator_permission) ? 'user-is-impersonated' }}">
                                        <a class="user-details" type="button" data-bs-toggle="dropdown"
                                           data-bs-offset="0,5" aria-expanded="false">
                                            {{ user_menu_avatar }}
                                            {% if ea.userMenu.isNameDisplayed %}
                                                <span class="user-name">{{ ea.userMenu.name }}</span>
                                            {% endif %}
                                        </a>

                                        {{ user_menu_dropdown }}
                                    </div>
                                {% endblock header_custom_menu %}
                            </div>
                        {% endblock header_custom_menu_wrapper %}

                        {% block settings_dropdown_wrapper %}
                            {{ settings_dropdown }}
                        {% endblock settings_dropdown_wrapper %}
                    {% endblock content_top_header %}
                </aside>

                <div class="content-wrapper">
                    {% block content %}
                        <article class="content">
                            {% block content_header_wrapper %}
                                {% set has_help_message = (ea.crud.helpMessage ?? '') is not empty %}
                                <section class="content-header">
                                    {% block content_header %}
                                        <div class="content-header-title">
                                            <h1 class="title">
                                                {% block content_title %}{% endblock %}

                                                {% block content_help %}
                                                    {% if has_help_message %}
                                                        <a tabindex="0" class="content-header-help"
                                                           data-bs-toggle="popover"
                                                           data-bs-custom-class="ea-content-help-popover"
                                                           data-bs-animation="true" data-bs-html="true"
                                                           data-bs-placement="bottom" data-bs-trigger="focus"
                                                           data-bs-content="{{ ea.crud.helpMessage|trans|e('html_attr') }}">
                                                            <twig:ea:Icon name="internal:circle-info"/>
                                                        </a>
                                                    {% endif %}
                                                {% endblock %}
                                            </h1>
                                        </div>

                                        {% block page_actions_wrapper %}
                                            <div class="page-actions">{% block page_actions %}{% endblock %}</div>
                                        {% endblock %}
                                    {% endblock content_header %}
                                </section>
                            {% endblock content_header_wrapper %}

                            <section id="main" class="content-body">
                                {% block main %}{% endblock %}
                            </section>

                            {% block content_footer_wrapper %}
                                {% set content_footer = block('content_footer') is defined ? block('content_footer') : '' %}
                                {% if content_footer is not empty %}
                                    <section class="content-footer">
                                        {{ content_footer }}
                                    </section>
                                {% endif %}
                            {% endblock %}
                        </article>
                    {% endblock content %}

                    <div id="content-resizer-handler" class="resizer-handler resizer-handler-right"></div>
                </div>
            </section>
        {% endblock wrapper %}
    </div>
{% endblock wrapper_wrapper %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants