Willem-Aart
Willem-Aart

Reputation: 2430

Convert multidimensional array to dot notation in Symfony2

Symfony converts nested YAML and PHP array translation files to a dot notation, like this: modules.module.title.

I'm writing some code that exports YAML translation files to a database, and I need to flatten the parsed files to a dot notation.

Does anyone know which function Symfony uses to flatten nested arrays to dot notation?

I cannot find it anywhere in the source code.

Upvotes: 3

Views: 2053

Answers (2)

Mike Doe
Mike Doe

Reputation: 17566

I don't know how what is written in previous Symfony versions, but in Symfony 4.2 onwards translations are returned already flattened.

Example controller which returns the messages catalogue translations. In my case I used this response to feed the i18next js library.

<?php

declare(strict_types=1);

namespace Conferences\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

final class TranslationsController
{
    public function __invoke(TranslatorInterface $translator): JsonResponse
    {
        if (!$translator instanceof TranslatorBagInterface) {
            throw new ServiceUnavailableHttpException();
        }

        return new JsonResponse($translator->getCatalogue()->all()['messages']);
    }
}

Route definition:

translations:
  path: /{_locale}/translations
  controller: App\Controller\TranslationsController
  requirements: {_locale: pl|en}

Upvotes: 0

Willem-Aart
Willem-Aart

Reputation: 2430

It's the flatten() method in Symfony\Component\Translation\Loader\ArrayLoader:

<?php

/**
 * Flattens an nested array of translations.
 *
 * The scheme used is:
 *   'key' => array('key2' => array('key3' => 'value'))
 * Becomes:
 *   'key.key2.key3' => 'value'
 *
 * This function takes an array by reference and will modify it
 *
 * @param array  &$messages The array that will be flattened
 * @param array  $subnode   Current subnode being parsed, used internally for recursive calls
 * @param string $path      Current path being parsed, used internally for recursive calls
 */
private function flatten(array &$messages, array $subnode = null, $path = null)
{
    if (null === $subnode) {
        $subnode = &$messages;
    }
    foreach ($subnode as $key => $value) {
        if (is_array($value)) {
            $nodePath = $path ? $path.'.'.$key : $key;
            $this->flatten($messages, $value, $nodePath);
            if (null === $path) {
                unset($messages[$key]);
            }
        } elseif (null !== $path) {
            $messages[$path.'.'.$key] = $value;
        }
    }
}

Upvotes: 4

Related Questions