LocaleBundle allows easy locale management for Symfony apps.

1.0.2 2019-06-05 16:39 UTC

This package is auto-updated.

Last update: 2020-01-05 18:14:18 UTC


composer require michael-kaefer/locale-bundle

When and how to use the bundle

  • If the format of all your app's URLs is: example.com/[LOCALE]/path you can use this bundle to redirect from example.com/ to the best fitting locale, for example to example.com/de. The order is:

    1. The locale which was saved to the session before (if there is one)

    2. The locale which was sent by the browser in the Accept-Language header (if there is one)

    3. The locale which is configured as the app's default locale

  • The bundle allows to save the locale to the user's session.

  • The bundle allows configuration of locale aliases which allow URLs that contain a locale to be prettier, for example example.com/at is considered to be more pretty than example.com/de_AT.

  • The bundle provides a ready to use twig function called locales() which allows to print all available locales (scroll down for an example).

You can provide all your app's locales as parameter to /config/services.yaml. You can use the "pretty" alias ("at" instead of "de_AT").

    app.locales: es|at|de|ch|fr

Next make sure that all your routes include the locale (which must be required, not optional).

 * @Route("/{_locale}/", name="home", requirements={
 *     "_locale"="%app.locales%"
 * })

A configuration example which can go to /config/packages/locale_bundle.yaml

  # All locales which in which content is offered by the application
  #     Required
  #     Type: string
  #     Example: en|de_DE|de_AT|de_CH
  #     (could be imported from other config files like this: "%app.locales%")
  available_locales: "%app.locales%"
  # The default locale of the application
  #     Required
  #     Type: string
  #     Example: en
  #     (could be imported from other config files like this: "%locale%")
  default_locale: "%locale%"
  # Pretty aliases for locales which do not look pretty in URLs ("example.com/at" is prettier than "example.com/de_AT")
  #     Optional
  #     Type: string
  #     Example: de=de_DE|at=de_AT|ch=de_CH|xyz|foobar=en_US
  #     (the first part of "at=de_AT" is "at" which is the pretty alias, the second part is "de_AT" which is the locale)
  locale_aliases: de=de_DE|at=de_AT|ch=de_CH|xyz|foobar=en_US|ch=fr_CH|fr=fr_FR
    # If set to TRUE all users who visit "/" (the root of the app) will be redirected to the best fitting locale, e.g. to "/en"
    #     Optional
    #     Type: bool
    #     Default: true
    redirect_on_first_visit: true
    # Name of the route to the desired landing page
    #     Required
    #     Type: string
    #     Example: my_route_name
    redirect_to: home
    # If set to true the locale is remembered by saving it to the session
    #     Optional
    #     Type: bool
    #     Default: true
    remember_locale: true
    # The name of the session key where the locale will be saved
    #     Optional
    #     Type: string
    #     Default: "_locale"
    key: _locale

How to use the provided twig function locales():

<!DOCTYPE html>
<html lang="{{ app.request.locale }}">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        {#Bootstrap CSS#}
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        {#FontAwesome CSS#}
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
        <div class="container">
            <nav class="navbar navbar-expand-lg navbar-light bg-light">
                <li class="collapse navbar-collapse" id="navbarNavDropdown">
                    <ul class="navbar-nav">
                        <li class="nav-item dropdown">
                                    class="nav-link dropdown-toggle"
                                <i class="fa fa-globe" aria-hidden="true"></i>
                            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                                {% for locale in locales() %}
                                            class="dropdown-item {% if app.request.locale == locale.code %}active{% endif %}"
                                            href="/{{ locale.alias }}"
                                        {{ locale.name }}
                                {% endfor %}

                        <li class="nav-item">
                            <a class="nav-link" href="#">Locale: "{{ app.request.locale }}"</a>

                        <li class="nav-item">
                            <a class="nav-link" href="#">Session: "{{ app.request.getSession.get('_locale') }}"</a>

                        <li class="nav-item">
                            <a class="nav-link" href="#">Browser: "{{ app.request.preferredLanguage() }}"</a>

        {#jQuery JS#}
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        {#Popper JS#}
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        {#Bootstrap JS#}
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>