<commit_before>How to add a custom translatable model?
=======================================

In this guide we will create a new translatable model in our system, which is quite similar to :doc:`adding a simple model </cookbook/entities/custom-model>`,
although it requires some additional steps.

As an example we will take a **translatable Supplier entity**, which may be really useful for shop maintenance.

1. Define your needs
--------------------

A Supplier needs three essential fields: ``name``, ``description`` and ``enabled`` flag.
The **name and description** fields need to be translatable.

2. Generate the SupplierTranslation entity
------------------------------------------

Symfony, the framework Sylius uses, provides the `SensioGeneratorBundle <http://symfony.com/doc/current/bundles/SensioGeneratorBundle/index.html>`_,
that simplifies the process of adding a model.

.. warning::

    Remember to have the ``SensioGeneratorBundle`` imported in the AppKernel, as it is not there by default.

You need to use such a command in your project directory.

.. code-block:: bash

    $ php bin/console generate:doctrine:entity

The generator will ask you for the entity name and fields. See how it should look like to match our assumptions.

.. image:: ../../_images/generating_translation_entity.png
    :align: center

As you can see we have provided only the desired translatable fields.

Below the final ``SupplierTranslation`` class is presented, it implements the ``ResourceInterface``.

.. code-block:: php

    <?php

    namespace App\Entity;

    use Sylius\Component\Resource\Model\AbstractTranslation;
    use Sylius\Component\Resource\Model\ResourceInterface;

    class SupplierTranslation extends AbstractTranslation implements ResourceInterface
    {
        /**
         * @var int
         */
        private $id;

        /**
         * @var string
         */
        private $name;

        /**
         * @var string
         */
        private $description;

        /**
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * @param string $name
         */
        public function setName($name)
        {
            $this->name = $name;
        }

        /**
         * @return string
         */
        public function getName()
        {
            return $this->name;
        }

        /**
         * @param string $description
         */
        public function setDescription($description)
        {
            $this->description = $description;
        }

        /**
         * @return string
         */
        public function getDescription()
        {
            return $this->description;
        }
    }

3. Generate the Supplier entity
-------------------------------

While generating the entity, similarly to the way the translation was generated, we are providing only non-translatable fields.
In our case only the ``enabled`` field.

.. image:: ../../_images/generating_basic_entity.png
    :align: center

Having the stubs generated, we need to extend our class with a connection to SupplierTranslation.

* implement the ``ResourceInterface``,
* implement the ``TranslatableInterface``,
* use the ``TranslatableTrait``,
* initialize the translations collection in the constructor,
* add the ``createTranslation()`` method,
* implement getters and setters for the properties that are held on the translation model.

As a result you should get such a ``Supplier`` class:

.. code-block:: php

    <?php

    namespace App\Entity;

    use Sylius\Component\Resource\Model\ResourceInterface;
    use Sylius\Component\Resource\Model\TranslatableInterface;
    use Sylius\Component\Resource\Model\TranslatableTrait;

    class Supplier implements ResourceInterface, TranslatableInterface
    {
        use TranslatableTrait {
            __construct as private initializeTranslationsCollection;
        }

        public function __construct()
        {
            $this->initializeTranslationsCollection();
        }

        /**
         * @var int
         */
        private $id;

        /**
         * @var bool
         */
        private $enabled;

        /**
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * @param string $name
         */
        public function setName($name)
        {
            $this->getTranslation()->setName($name);
        }

        /**
         * @return string
         */
        public function getName()
        {
            return $this->getTranslation()->getName();
        }

        /**
         * @param string $description
         */
        public function setDescription($description)
        {
            $this->getTranslation()->setDescription($description);
        }

        /**
         * @return string
         */
        public function getDescription()
        {
            return $this->getTranslation()->getDescription();
        }

        /**
         * @param boolean $enabled
         */
        public function setEnabled($enabled)
        {
            $this->enabled = $enabled;
        }

        /**
         * @return bool
         */
        public function getEnabled()
        {
            return $this->enabled;
        }

        /**
         * {@inheritdoc}
         */
        protected function createTranslation()
        {
            return new SupplierTranslation();
        }
    }

4. Update the database using migrations
---------------------------------------

Assuming that your database was up-to-date before adding the new entity, run:

.. code-block:: bash

    $ php bin/console doctrine:migrations:diff

This will generate a new migration file which adds the Supplier entity to your database.
Then update the database using the generated migration:

.. code-block:: bash

    $ php bin/console doctrine:migrations:migrate

5. Register your entity together with translation as a Sylius resource
----------------------------------------------------------------------

If you don't have it yet create a file ``config/resources.yml``, import it in the ``config/services.yaml``.

.. code-block:: yaml

    # config/services.yaml
    imports:
        - { resource: "resources.yaml" }

And add these few lines in the ``resources.yaml`` file:

.. code-block:: yaml

    # config/resources.yaml
    sylius_resource:
        resources:
            app.supplier:
                driver: doctrine/orm # You can use also different driver here
                classes:
                    model: App\Entity\Supplier
                translation:
                    classes:
                        model: App\Entity\SupplierTranslation

To check if the process was run correctly run such a command:

.. code-block:: bash

    $ php bin/console debug:container | grep supplier

The output should be:

.. image:: ../../_images/container_debug_supplier_translation.png
    :align: center

6. Prepare new forms for your entity, that will be aware of its translation
---------------------------------------------------------------------------

You will need both ``SupplierType`` and ``SupplierTranslationType``.

Let's start with the translation type, as it will be included into the entity type.

.. code-block:: php

    <?php

    namespace App\Form\Type;

    use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;<commit_msg>bug #10175 [Docs] Reverse parts in Custom Translatable Model (xElysioN)<commit_after>How to add a custom translatable model?
=======================================

In this guide we will create a new translatable model in our system, which is quite similar to :doc:`adding a simple model </cookbook/entities/custom-model>`,
although it requires some additional steps.

As an example we will take a **translatable Supplier entity**, which may be really useful for shop maintenance.

1. Define your needs
--------------------

A Supplier needs three essential fields: ``name``, ``description`` and ``enabled`` flag.
The **name and description** fields need to be translatable.

2. Generate the SupplierTranslation entity
------------------------------------------

Symfony, the framework Sylius uses, provides the `SensioGeneratorBundle <http://symfony.com/doc/current/bundles/SensioGeneratorBundle/index.html>`_,
that simplifies the process of adding a model.

.. warning::

    Remember to have the ``SensioGeneratorBundle`` imported in the AppKernel, as it is not there by default.

You need to use such a command in your project directory.

.. code-block:: bash

    $ php bin/console generate:doctrine:entity

The generator will ask you for the entity name and fields. See how it should look like to match our assumptions.

.. image:: ../../_images/generating_translation_entity.png
    :align: center

As you can see we have provided only the desired translatable fields.

Below the final ``SupplierTranslation`` class is presented, it implements the ``ResourceInterface``.

.. code-block:: php

    <?php

    namespace App\Entity;

    use Sylius\Component\Resource\Model\AbstractTranslation;
    use Sylius\Component\Resource\Model\ResourceInterface;

    class SupplierTranslation extends AbstractTranslation implements ResourceInterface
    {
        /**
         * @var int
         */
        private $id;

        /**
         * @var string
         */
        private $name;

        /**
         * @var string
         */
        private $description;

        /**
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * @param string $name
         */
        public function setName($name)
        {
            $this->name = $name;
        }

        /**
         * @return string
         */
        public function getName()
        {
            return $this->name;
        }

        /**
         * @param string $description
         */
        public function setDescription($description)
        {
            $this->description = $description;
        }

        /**
         * @return string
         */
        public function getDescription()
        {
            return $this->description;
        }
    }

3. Generate the Supplier entity
-------------------------------

While generating the entity, similarly to the way the translation was generated, we are providing only non-translatable fields.
In our case only the ``enabled`` field.

.. image:: ../../_images/generating_basic_entity.png
    :align: center

Having the stubs generated, we need to extend our class with a connection to SupplierTranslation.

* implement the ``ResourceInterface``,
* implement the ``TranslatableInterface``,
* use the ``TranslatableTrait``,
* initialize the translations collection in the constructor,
* add the ``createTranslation()`` method,
* implement getters and setters for the properties that are held on the translation model.

As a result you should get such a ``Supplier`` class:

.. code-block:: php

    <?php

    namespace App\Entity;

    use Sylius\Component\Resource\Model\ResourceInterface;
    use Sylius\Component\Resource\Model\TranslatableInterface;
    use Sylius\Component\Resource\Model\TranslatableTrait;

    class Supplier implements ResourceInterface, TranslatableInterface
    {
        use TranslatableTrait {
            __construct as private initializeTranslationsCollection;
        }

        public function __construct()
        {
            $this->initializeTranslationsCollection();
        }

        /**
         * @var int
         */
        private $id;

        /**
         * @var bool
         */
        private $enabled;

        /**
         * @return int
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * @param string $name
         */
        public function setName($name)
        {
            $this->getTranslation()->setName($name);
        }

        /**
         * @return string
         */
        public function getName()
        {
            return $this->getTranslation()->getName();
        }

        /**
         * @param string $description
         */
        public function setDescription($description)
        {
            $this->getTranslation()->setDescription($description);
        }

        /**
         * @return string
         */
        public function getDescription()
        {
            return $this->getTranslation()->getDescription();
        }

        /**
         * @param boolean $enabled
         */
        public function setEnabled($enabled)
        {
            $this->enabled = $enabled;
        }

        /**
         * @return bool
         */
        public function getEnabled()
        {
            return $this->enabled;
        }

        /**
         * {@inheritdoc}
         */
        protected function createTranslation()
        {
            return new SupplierTranslation();
        }
    }

4. Register your entity together with translation as a Sylius resource
----------------------------------------------------------------------

If you don't have it yet create a file ``config/resources.yml``, import it in the ``config/services.yaml``.

.. code-block:: yaml

    # config/services.yaml
    imports:
        - { resource: "resources.yaml" }

And add these few lines in the ``resources.yaml`` file:

.. code-block:: yaml

    # config/resources.yaml
    sylius_resource:
        resources:
            app.supplier:
                driver: doctrine/orm # You can use also different driver here
                classes:
                    model: App\Entity\Supplier
                translation:
                    classes:
                        model: App\Entity\SupplierTranslation

To check if the process was run correctly run such a command:

.. code-block:: bash

    $ php bin/console debug:container | grep supplier

The output should be:

.. image:: ../../_images/container_debug_supplier_translation.png
    :align: center

5. Update the database using migrations
---------------------------------------

Assuming that your database was up-to-date before adding the new entity, run:

.. code-block:: bash

    $ php bin/console doctrine:migrations:diff

This will generate a new migration file which adds the Supplier entity to your database.
Then update the database using the generated migration:

.. code-block:: bash

    $ php bin/console doctrine:migrations:migrate

6. Prepare new forms for your entity, that will be aware of its translation
---------------------------------------------------------------------------

You will need both ``SupplierType`` and ``SupplierTranslationType``.

Let's start with the translation type, as it will be included into the entity type.

.. code-block:: php

    <?php

    namespace App\Form\Type;

    use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;
{'fraction_non_alphanumeric': 0.130011909487892, 'fraction_numerical': 0.0011247849675797275, 'mean_word_length': 1.8933767228177643, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6434592', 'n_tokens_mistral': 3743, 'n_tokens_neox': 3609, 'n_words': 1238}