This course is still being released! Check back later for more chapters.

Get Notified About this Course!

We will send you messages regarding this course only
and nothing else, we promise.
You can unsubscribe anytime by emailing us at:
privacy@symfonycasts.com
Login to bookmark this video
Buy Access to Course
32.

Arreglador de metadatos y PHP CS

|

Share this awesome video!

|

Keep on Learning!

La codificación del bundle está terminada, y las pruebas están pasando en todas nuestras versiones de Symfony compatibles. ¡Estamos en la recta final!

Archivo de licencia

Vamos a añadir un archivo de licencia a nuestro bundle. En el directorio tutorial copia el archivoLICENSE.md a la raíz de nuestro bundle. Si no ves los archivos que estamos copiando en tu directorio tutorial, ¡no te preocupes! Están todos en el script de abajo:

Copyright (c) SymfonyCasts <https://symfonycasts.com/>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

Esta es la licencia MIT estándar para que coincida con la que tenemos en nuestro archivo composer.json.

Documentación

Ahora, copia el archivo README.md del directorio tutorial a la raíz de nuestro bundle:

# symfonycasts/object-translation-bundle
This bundle provides a simple way to translate Doctrine entities in Symfony applications.
## Installation
### Install the bundle via Composer:
```bash
composer require symfonycasts/object-translation-bundle
```
### Enable the bundle in your `config/bundles.php` file:
> [!NOTE]
> This step is not required if you are using Symfony Flex.
```php
return [
// ...
ObjectTranslationBundle::class => ['all' => true],
];
```
### Create the translation entity in your app:
> [!NOTE]
> This step is not required if you are using Symfony Flex.
```php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use SymfonyCasts\ObjectTranslationBundle\Model\Translation as BaseTranslation;
#[ORM\Entity]
class Translation extends BaseTranslation
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
public int $id;
}
```
### Configure the entity in your `config/packages/object_translation.yaml` file:
> [!NOTE]
> This step is not required if you are using Symfony Flex.
```yaml
symfonycasts_object_translation:
translation_class: App\Entity\Translation
```
### Create and run the migration to add the translation table:
```bash
symfony console make:migration
symfony console doctrine:migrations:migrate
```
## Marking Entities as Translatable
To mark an entity as translatable, use the `Translatable` attribute on the entity class
and the `TranslatableProperty` attribute on the fields you want to translate.
```php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use SymfonyCasts\ObjectTranslationBundle\Mapping\Translatable;
use SymfonyCasts\ObjectTranslationBundle\Mapping\TranslatableProperty;
#[ORM\Entity]
#[Translatable('product')]
class Product
{
// ...
#[ORM\Column(type: 'string', length: 255)]
#[TranslatableProperty]
public string $name;
#[ORM\Column(type: 'text')]
#[TranslatableProperty]
public string $description;
}
```
## Usage
### `ObjectTranslator` Service
You can inject the `ObjectTranslator` service to translate entities.
```php
use SymfonyCasts\ObjectTranslationBundle\ObjectTranslator;
class ProductController
{
public function show(Product $product, ObjectTranslator $objectTranslator)
{
// translate into the current request locale
$translatedProduct = $objectTranslator->translate($product);
$translatedProduct->getName(); // returns the translated name (if available)
$translatedProduct->getDescription(); // returns the translated description (if available)
// ...
}
}
```
The second argument of the `translate()` method allows you to specify a locale:
```php
$product = $objectTranslator->translate($product, 'fr'); // translates into French
```
### `translate_object` Twig Filter
If using Twig, you can use the `translate_object` filter to translate entities directly in templates.
```twig
{% set translatedProduct = product|translate_object %} {# translates into the current request locale #}
{% set frenchProduct = product|translate_object('fr') %} {# translates into French #}
```
## Managing Translations
The `Translation` database table has the following structure:
- `id`: Primary key (added by you)
- `object_type`: The *alias* defined in the `Translatable` attribute (e.g., `product`)
- `object_id`: The ID of the translated entity
- `locale`: The locale of the translation (e.g., `fr`)
- `field`: The entity property name being translated (e.g., `description`)
- `value`: The translated value
Each row represents a single property translation for a specific entity in a specific locale.
You can manage these translations yourself but two console commands are provided to help:
### `object-translation:export`
``
This command exports all entity translations, in your default locale, to a CSV file.
```bash
symfony console object-translation:export translations.csv
```
This will create a `translations.csv` file at the root of your project with the following structure:
```csv
type,id,field,value
```
You can then take this file to translation service for translation. Be sure to keep
the `type`, `id`, and `field` columns intact. The `value` column is what needs to be translated
into the desired language.
### `object-translation:import`
This command imports translations from a CSV file created by the `export` command after
the `value` column has been translated.
```bash
symfony console object-translation:import translations_fr.csv fr
```
The first argument is the path to the CSV file, and the second argument is the locale
of the translations in that file.
## Translation Caching
For performance, translations are cached. By default, they use your `cache.app` pool
and have no expiration time. This can be configured:
```yaml
symfonycasts_object_translation:
cache:
pool: 'cache.object_translation' # a custom pool name
ttl: 3600 # expire after one hour
```
### Translation Tags
If your cache pool supports *cache tagging*, tags are added to the cache keys. Two keys
are added:
- `object-translation`: All translations are tagged with this key.
- `object-translation-{type}`: Where `{type}` is the translatable alias (e.g., `product`).
You can invalidate these tags by using the `cache:pool:invalidate-tags` command:
```bash
# invalidate all object translation caches
symfony console cache:pool:invalidate-tags object-translation
# invalidate only the translation cache for "product" entities
symfony console cache:pool:invalidate-tags object-translation-product
```
### `object-translation:warmup` Command
This command preloads all translations into the cache for all your
app's enabled locales.
```bash
symfony console object-translation:warmup
```
## Full Default Configuration
```yaml
symfonycasts_object_translation:
# The class name of your translation entity.
translation_class: ~ # Required, Example: App\Entity\Translation
# Cache settings for object translations.
cache:
enabled: true
# The cache pool to use for storing object translations.
pool: cache.app
# The time-to-livefor cached translations, in seconds, null for no expiration.
ttl: null
```

Ahora bien, la guía de buenas prácticas de Symfony Bundle recomienda un directorio docpara albergar la documentación y que ésta se escriba en formato "reStructuredText" (o rst).

Yo me alejo de esta recomendación por un par de razones. En primer lugar, rst no se muestra tan bien en GitHub como los archivos Markdown. En segundo lugar, a menos que la documentación empiece a ser realmente grande, me gusta que se muestre inmediatamente cuando alguien visita el repositorio de GitHub. Por tanto, prefiero que la documentación esté en el archivo README.

Hagamos un repaso rápido de lo que he escrito. Comienza con las instrucciones de instalación y cómo activar y configurar el bundle. A continuación, cómo marcar tus entidades como traducibles...

Una sección de uso para mostrar cómo utilizar el servicio ObjectTranslator y el filtro Twig translate_object.

La sección de gestión de traducciones ofrece detalles sobre la estructura de la base de datos y cómo utilizar los comandos de exportación e importación.

A continuación, algo de información sobre el sistema de caché, incluido el comando warmup.

Por último, me gusta incluir la configuración por defecto completa, ¡porque es muy fácil de generar! ¿Te acuerdas?

En el terminal, asegúrate de que estás en la raíz de nuestra aplicación, no en el bundle. Luego ejecuta:

symfony console config:dump-reference symfonycasts_object_translation

Me suena. Siempre que cambies la configuración, puedes actualizar fácilmente esta sección volviendo a ejecutar ese comando y copiando/pegando el resultado. ¡Configuración autodocumentada para ganar!

.editorconfig Archivo

A continuación, copia el archivo .editorconfig de la raíz de nuestro proyecto al bundle:

# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[{compose.yaml,compose.*.yaml}]
indent_size = 2
[*.md]
trim_trailing_whitespace = false

Este archivo garantiza la coherencia en aspectos como el espaciado y las nuevas líneas. Muchos IDEs, incluido PhpStorm, admiten este archivo. Ayuda a evitar confirmaciones extrañas con diferentes espacios en blanco y caracteres de salto de línea. Esto es especialmente útil cuando alguien está desarrollando en Windows, que utiliza diferentes terminaciones de línea que macOS o Linux.

.gitattributes Archivo

En la raíz de nuestro bundle, crea un nuevo archivo llamado .gitattributes. Dentro, añade /tests export-ignore:

/tests export-ignore

Esto indica a Composer que excluya el directorio testsal instalar este paquete como dependencia. No es necesario que las pruebas de nuestro bundle se incluyan en el proyecto de un usuario final.

Reparador PHP CS

Al igual que la coherencia que proporciona el archivo .editorconfig para los espacios en blanco y los saltos de línea, también es importante tener un estilo de codificación coherente. Se trata de cosas como el espacio entre el espacio de nombres y las declaraciones de uso, o dónde colocar las llaves. Un estilo de codificación coherente hace que tu código sea más fácil de leer y ayuda a los colaboradores.

Una gran herramienta para reforzar y automatizar esto es PHP CS Fixer. En el terminal, asegúrate de que estás en el directorio bundle y ejecuta:

symfony composer require --dev php-cs-fixer/shim

Si ya has utilizado antes esta herramienta pero este paquete shim es nuevo para ti, no es más que una versión compilada de PHP CS Fixer que facilita la instalación.

Una vez instalado, coge el archivo .php-cs-fixer.dist.php del directorio del tutorial y cópialo en la raíz de nuestro object-translation-bundle:

<?php
return (new PhpCsFixer\Config())
->setRules([
'@Symfony' => true,
])
->setFinder(
(new PhpCsFixer\Finder())
->in([__DIR__.'/src', __DIR__.'/tests'])
)
;

Este archivo configura las reglas de estilo de codificación para tu proyecto. Ábrelo y echa un vistazo.

Estamos utilizando el conjunto de reglas de Symfony, por lo que nuestro estilo de codificación coincidirá con el de Symfony. A continuación, le indicamos dónde buscar los archivos PHP que hay que corregir: los directorios src y tests.

Para ejecutarlo, en el terminal, ejecuta:

symfony php vendor/bin/php-cs-fixer fix -v

Genial, aquí están todos los archivos que se modificaron y las reglas que se aplicaron.

El primero, TranslatedObject aplicó la regla phpdoc_align. Abramos ese archivo para ver qué cambió. Ah, añadió espaciado para alinear los nombres de las variables @param. En general, son más fáciles de leer cuando están alineados.

Este archivo .php-cs-fixer.cache de la raíz de nuestro bundle se generó cuando lo ejecutamos. Es sólo una caché para que las siguientes ejecuciones de PHP CS Fixer sean más rápidas. Añade esto a nuestro archivo .gitignore para que no se confirme:

6 lines | object-translation-bundle/.gitignore
// ... lines 1 - 4
.php-cs-fixer.cache

A continuación, vamos a utilizar PHPStan para ejecutar un análisis estático del código de nuestro bundle