{"id":18885264,"url":"https://github.com/sandstorm/gedmotranslatableconnector","last_synced_at":"2025-07-23T00:03:55.921Z","repository":{"id":21567291,"uuid":"24887110","full_name":"sandstorm/GedmoTranslatableConnector","owner":"sandstorm","description":"Neos Flow package Sandstorm.GedmoTranslatableConnector","archived":false,"fork":false,"pushed_at":"2025-05-23T13:55:20.000Z","size":54,"stargazers_count":6,"open_issues_count":0,"forks_count":5,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-07-18T15:09:14.948Z","etag":null,"topics":["doctrine","flow","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandstorm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-10-07T11:12:39.000Z","updated_at":"2025-05-23T13:54:24.000Z","dependencies_parsed_at":"2025-04-16T03:32:05.362Z","dependency_job_id":"12d7bae1-b171-411a-8e2a-3239aa0b9c1e","html_url":"https://github.com/sandstorm/GedmoTranslatableConnector","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/sandstorm/GedmoTranslatableConnector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandstorm%2FGedmoTranslatableConnector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandstorm%2FGedmoTranslatableConnector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandstorm%2FGedmoTranslatableConnector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandstorm%2FGedmoTranslatableConnector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandstorm","download_url":"https://codeload.github.com/sandstorm/GedmoTranslatableConnector/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandstorm%2FGedmoTranslatableConnector/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266592136,"owners_count":23953107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["doctrine","flow","php"],"created_at":"2024-11-08T07:17:27.688Z","updated_at":"2025-07-23T00:03:55.900Z","avatar_url":"https://github.com/sandstorm.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flow Framework Connector to Gedmo Translatable\n\nby Sebastian Kurfürst, sandstorm|media. Thanks to Web Essentials for sponsoring this work initially. \nCurrently maintained by [@onivaevents](https://github.com/onivaevents)\n\nUsing [Gedmo.Translatable](https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md) in the Neos Flow framework proved a little harder than originally anticipated. This small package wraps up the necessary steps.\n\n\n## Getting started\n\nJust include this package, and then use Gedmo Translatable as explained in their documentation (e.g. using\nthe @Gedmo\\Translatable annotation): https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md\n\nMake sure to clear the code cache completely in Data/Temporary after installing this package!\n\nFurthermore, make sure to create a *doctrine migration* which creates the ext_translations SQL table; e.g. run `./flow doctrine:migrationgenerate`\n\n**Check out the example package at https://github.com/sandstorm/GedmoTest**.\n\nThis connector supports all the advanced options provided by Gedmo Translatable.\n\n### Model Annotations\n\nJust annotate your model properties which shall be localized with `Gedmo\\Mapping\\Annotation\\Translatable`.\n\n```\n    /**\n     * @var string\n     * @Gedmo\\Translatable\n     */\n    protected $title;\n```\n\n### Translating a model (low-level)\n\n```\n    /**\n     * Doctrine's Entity Manager. Note that \"ObjectManager\" is the name of the related interface.\n     *\n     * @Flow\\Inject\n     * @var ObjectManager\n     */\n    protected $entityManager;\n\n    public function updateAction(Event $event) {\n        /* @var $repository TranslationRepository */\n        $repository = $this-\u003eentityManager-\u003egetRepository('Gedmo\\\\Translatable\\\\Entity\\\\Translation');\n        $repository-\u003etranslate($event, 'name', 'de', 'Deutscher Titel');\n    }\n```\n\n### Set current language\n\nIn order to set the current language for *viewing*, inject the `Gedmo\\Translatable\\TranslatableListener` class and set\nthe current language on it: `$translatableListener-\u003esetTranslatableLocale('de');`.\n\n## Translation management\n\n### Editing multiple languages at the same time\n\n* Mix-in the Trait `Sandstorm\\GedmoTranslatableConnector\\TranslatableTrait` and implement `\\Sandstorm\\GedmoTranslatableConnector\\Translatable` into your model, e.g. by doing:\n\n```\n/**\n * @Flow\\Entity\n */\nclass MyModel implements \\Sandstorm\\GedmoTranslatableConnector\\Translatable {\n  use \\Sandstorm\\GedmoTranslatableConnector\\TranslatableTrait;\n  \n  // make sure some properties have Gedmo\\Translatable annotations\n}\n```\n\n* This trait adds a `getTranslations()` and `setTranslations()` method, allowing to get and set other translations of\n  a model.\n  \n* Now, you can easily edit multiple languages by binding the form element to `translations.[language].[fieldname]`, e.g.\n  this works like the following:\n\n```\nName (default): \u003cf:form.textfield property=\"name\" /\u003e\u003cbr /\u003e\nName (de): \u003cf:form.textfield property=\"translations.de.name\" /\u003e\u003cbr /\u003e\nName (en): \u003cf:form.textfield property=\"translations.en.name\" /\u003e\u003cbr /\u003e\n```\n\n### Persist edited translations\n\nWith the by default enabled `instantTranslation` setting, the translations are updated and persisted through the `Gedmo\\Translatable\\Entity\\Repository\\TranslationRepository` immediately when calling the `setTranslation` method.\nOften, this might not be ideal because it persists the entity right away. Disable the setting and call the `flush()` method of the `TranslatableManager` to persist the changes according to your needs.\n\n### Fetching an object in another locale\n\nIf you have loaded an object in a specific locale, but later on need to change the object to be in another locale,\nthe method `reloadInLocale($locale)` (which is defined inside the trait `Sandstorm\\GedmoTranslatableConnector\\TranslatableTrait`)\ncan be called:\n\n```\n$myModel-\u003egetName(); // will return the language which was set at the time where $myModel was fetched\n\n$myModel-\u003ereloadInLocale('de');\n$myModel-\u003egetName(); // will return *german*\n```\n\n## Translating associations\n\n**Warning: this feature is not yet 100% stable; please test it and give feedback!**\n\nNormally, associations towards other domain models such as images or assets are not translation-aware; but Translatable\nonly works for simple properties.\n\nThe TranslatableConnector however contains some functionality to make translation of associations work; by using a\nlittle workaround: **We store the identifier of the target object in the domain model, and manually load/store from this\nidentifier**.\n\nThis works as follows:\n\n1. Makes sure you have the `TranslatableTrait` added to your domain class\n\n2. e.g. to make an `Asset` reference translatable, create a new property `assetIdentifer` which is a string and will\n   contain the asset identifier. This property should be marked as `Gedmo\\Translatable`.\n\n3. Then, you need to configure the `translationAssociationMapping`, which tells the system that the (virtual) property\n   should `asset` should internally be stored as `assetIdentifier`.\n\n4. Furthermore, create `assetOnSave` and `assetOnLoad` methods as outlined below, which convert the different representations\n\nSee the full example below:\n\n```\nclass Event {\n    use TranslatableTrait;\n    \n    /**\n     * @var array\n     * @Flow\\Transient\n     */\n    protected $translationAssociationMapping = array(\n        'assetIdentifier' =\u003e 'asset'\n    );\n    \n    /**\n     * @Gedmo\\Translatable\n     * @var string\n     */\n    protected $assetIdentifier;\n\n    /**\n     * @Flow\\Inject\n     * @var AssetRepository\n     */\n    protected $assetRepository;\n\n    /**\n     * @Flow\\Inject\n     * @var PersistenceManagerInterface\n     */\n    protected $persistenceManager;\n\n    /**\n     * @Flow\\Inject\n     * @var PropertyMapper\n     */\n    protected $propertyMapper;\n\n\n    /**\n     * @return \\Neos\\Media\\Domain\\Model\\Asset\n     */\n    public function getAsset() {\n        return $this-\u003eassetOnLoad($this-\u003eassetIdentifier);\n    }\n\n    /**\n     * !!! This accepts the raw array as the user uploaded it; as we need to trigger the property mapper inside\n     *     assetOnSave manually.\n     *\n     * @param array $asset\n     */\n    public function setAsset($asset) {\n        $this-\u003eassetIdentifier = $this-\u003eassetOnSave($asset);\n    }\n\n    /**\n     * This method is called in two places:\n     * - inside setAsset()\n     * - automatically by the TranslatableTrait\n     * \n     * @param array $asset\n     */\n    public function assetOnSave($asset) {\n        $asset = $this-\u003epropertyMapper-\u003econvert($asset, 'Neos\\Media\\Domain\\Model\\AssetInterface');\n        if ($asset === NULL) {\n            $this-\u003eassetRepository-\u003eremove($asset);\n            return NULL;\n        } elseif ($this-\u003epersistenceManager-\u003eisNewObject($asset)) {\n            $this-\u003eassetRepository-\u003eadd($asset);\n            return $this-\u003epersistenceManager-\u003egetIdentifierByObject($asset);\n        } else {\n            $this-\u003eassetRepository-\u003eupdate($asset);\n            return $this-\u003epersistenceManager-\u003egetIdentifierByObject($asset);\n        }\n    }\n\n    /**\n     * This method is called in two places:\n     * - inside getAsset()\n     * - automatically by the TranslatableTrait\n     * \n     * @param array $asset\n     */\n    public function assetOnLoad($assetIdentifier) {\n        return $this-\u003eassetRepository-\u003efindByIdentifier($assetIdentifier);\n    }\n}\n```   \n\n\n## Inner Workings\n\n(as a further reference -- could also be reduced if we change Flow Framework a little on the relevant parts)\n\n* Settings.yaml: Ignore Gedmo namespace from Reflection, adds the Translatable Listener as Doctrine Event listener.\n  This part is pretty standard for using other Gedmo Doctrine extensions as well.\n  \n* Objects.yaml: Mark the `TranslatableListener` as singleton, such that you can inject it into your classes and set\n  the current language. This part was straightforward as well.\n  \n* Package.php: Make the entities of Gedmo Translatable known to Doctrine and in Reflection. This was quite tricky to\n  archive, see the inline docs in the class how this was done.\n\n## Further recommendation\n\n* Use [ORM query hints](https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/translatable.md#using-orm-query-hint) when working with Gedmo Translatable to speed up queries.\n* Use [translation entities](https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/translatable.md#translation-entity) if you have large datasets with many translations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandstorm%2Fgedmotranslatableconnector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandstorm%2Fgedmotranslatableconnector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandstorm%2Fgedmotranslatableconnector/lists"}