Gedmo Translatable坚持默认翻译

时间:2018-10-24 09:27:47

标签: symfony doctrine translation

我有一个使用Symfony 2.8和Gedmo Translatable构建的网站。

为了使用HINT_INNER_JOIN并过滤没有翻译的项目,我必须将persist_default_translation设置为true

stof_doctrine_extensions:
    default_locale: '%locale%' # TODO: what does it happen when removing this line?
    translation_fallback: true
    persist_default_translation: true
    orm:
        default:
            timestampable: true
            blameable: true
            translatable: true

不幸的是,这导致我现有的默认语言翻译不再保留(它们显示为空)。

我需要强制重新保存所有实体,以再次生成默认语言环境。

我该怎么做?我尝试使用clonepersist,但是它创建了该实体的副本。

是否可以强迫教义再次更新所有字段?

1 个答案:

答案 0 :(得分:0)

我最终创建了一个自定义命令,以迁移所有翻译。我创建了一个假翻译,称为“ kr”,然后使用SQL查询将所有从“ kr”的记录更新为“ fr”。

我使用反射和其他“黑魔法”来获得带有Translatable批注的属性,也许这可以帮助遇到相同问题的人。这是代码:

class NormalizeTranslationsCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            // the name of the command (the part after "app/console")
            ->setName('app:normalize-translations')

            // the short description shown while running "php app/console list"
            ->setDescription('Normalizes the translations.')

            // the full command description shown when running the command with
            // the "--help" option
            ->setHelp('This command allows you to normalize the translations...')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // all the translatable classes
        $classes = [
            Entities\MyClass1::class,
            Entities\MyClass2::class,
        ];

        foreach ($classes as $class) {
            $this->processClass($class, $output);
        }
    }

    private function processClass($class, $output)
    {
        $output->writeln(sprintf('Processing class <info>%s</info>', $class));

        // gets all the properties
        $properties = $this->getProperties($class);

        // gets the translatable properties
        $translatableProperties = $this->getTranslatableProperties($properties, $class);
        $output->writeln(sprintf('Found %d translatable properties: %s', count($translatableProperties), implode(', ', $translatableProperties)));

        $defaultLanguage = 'kr'; // fake language
        $em = $this->getContainer()->get('doctrine')->getManager();
        $repository = $em->getRepository('Gedmo\\Translatable\\Entity\\Translation');
        $items = $em->getRepository($class)->findAll();
        $propertyAccessor = PropertyAccess::createPropertyAccessor();

        foreach ($items as $item) {
            foreach ($translatableProperties as $translatableProperty) {
                $value = $propertyAccessor->getValue($item, $translatableProperty);
                $repository->translate($item, $translatableProperty, $defaultLanguage, $value);
            }

            $em->flush();
        }
    }

    private function getProperties($class)
    {
        $phpDocExtractor = new PhpDocExtractor();
        $reflectionExtractor = new ReflectionExtractor();

        // array of PropertyListExtractorInterface
        $listExtractors = array($reflectionExtractor);

        // array of PropertyTypeExtractorInterface
        $typeExtractors = array($phpDocExtractor, $reflectionExtractor);

        // array of PropertyDescriptionExtractorInterface
        $descriptionExtractors = array($phpDocExtractor);

        // array of PropertyAccessExtractorInterface
        $accessExtractors = array($reflectionExtractor);

        $propertyInfo = new PropertyInfoExtractor(
            $listExtractors,
            $typeExtractors,
            $descriptionExtractors,
            $accessExtractors
        );

        return $propertyInfo->getProperties($class);
    }

    private function getTranslatableProperties($properties, $class)
    {
        $translatableProperties = [];

        // https://gist.github.com/Swop/5990316
        $annotationReader = new AnnotationReader();

        foreach ($properties as $property) {
            try {
                $reflectionProperty = new \ReflectionProperty($class, $property);
                $propertyAnnotations = $annotationReader->getPropertyAnnotations($reflectionProperty);

                foreach ($propertyAnnotations as $propertyAnnotation) {
                    if ($propertyAnnotation instanceof Translatable) {
                        // this property is translatable
                        $translatableProperties[] = $property;
                    }
                }
            } catch (\ReflectionException $e) {
                // missing property
                continue;
            }
        }

        return $translatableProperties;
    }
}