1

We have some navigation links being translated via the /translations folder but the client needs the ability to change them too...

Is there a way to make the translations editable from the control panel?

3

I would say the most cleanest way is to handle all translations via Yii2 DbMessageSource.

You could say you want to store all translations into the database instead of files. There is an MessageSource::EVENT_MISSING_TRANSLATION event in which you can store all translations into your new database table. As soon as Craft recognizes a new translation you'll have the chance to insert the new record

Here is a code snipped from our translation plugin

Event::on(
    MessageSource::class,
    MessageSource::EVENT_MISSING_TRANSLATION,
    function(MissingTranslationEvent $event) {
        if ($event->message) {
            $message = Translate::getInstance()->getTranslation()->addMissingTranslation($event->category, $event->message, $event->language);
            if ($message instanceof Message) {
                $event->translatedMessage = $message->translation;
            }
        }
    }
);

Your DbMessageSource class could look like this

class DbMessageSource extends \yii\i18n\DbMessageSource
{
    public $fallback = [];
    public $useMultiSiteTranslationFeature = false;
    protected $fallbackClass;

    /**
     * Return something for everything which is requested
     *
     * @param string $name
     *
     * @return mixed|null
     */
    public function __get($name)
    {
        try {
            return parent::__get($name);
        } catch (\Exception $e) {
            return null;
        }
    }

    /**
     * @param string $name
     * @param mixed  $value
     */
    public function __set($name, $value)
    {
        try {
            parent::__set($name, $value);
        } catch (\Exception $e) {
            $this->$name = $value;
        }
    }

    public function translateFallback($category, $message, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $this->useMultiSiteTranslationFeature = false;
            $translated = $this->translate($category, $message, $language);
            $this->useMultiSiteTranslationFeature = true;
            if ($translated) {
                return $translated;
            }
        }
        if (count($this->fallback) === 0) {
            return false;
        }
        if (!$this->fallbackClass) {
            $this->fallbackClass = \Yii::createObject($this->fallback);
        }

        return $this->fallbackClass->translate($category, $message, $language);
    }

    protected function loadMessages($category, $language)
    {
        if ($this->useMultiSiteTranslationFeature && Craft::$app->getRequest()->getIsSiteRequest()) {
            $category .= '_' . Craft::$app->getSites()->currentSite->handle;
        }

        if ($this->enableCaching) {
            $key = [
                __CLASS__,
                $category,
                $language,
            ];
            $messages = $this->cache->get($key);
            if ($messages === false) {
                $messages = $this->loadMessagesFromDb($category, $language);
                $this->cache->set($key, $messages, $this->cachingDuration);
            }

            return $messages;
        }

        return $this->loadMessagesFromDb($category, $language);
    }
}

The rest is common Craft work to create create a custom form/list for your new CP section or you create an element type and let Craft handle everything.

As you can see in the picture below: all translatable strings from all sources/categories/plugins are recognized and our customers are able to change all translations in all plugins into all languages. Even if the creator of the plugin never wanted to include certain translations into certain languages

Screenshot

| improve this answer | |
  • Thanks Robin! Any chance you could share the plugin or a simple version of it? I'm not a developer eeeek – James Greig May 2 '18 at 9:27
  • Thanks @robin, got this working (yay) but it only seems to translate the backend dashboard/CP terms, how would you translate the text in a Dropdown field? – James Greig May 3 '18 at 11:55
  • @3stripe DropDown fields are translated in the category 'site' (code 'label' => Craft::t('site', $option['label'])) so you'll have to include the component with setting site like stated in the readme.md – Robin Schambach May 3 '18 at 12:01
0

check out Enupal Translate, you can enable an option to allow Enupal Translate handle the translations folder of the plugins.

Enupal Translate

| improve this answer | |
  • Interesting. But does is overwrite plugins translation files or does it really create a new element for each translation? If so it would be a huge overhead – Robin Schambach May 2 '18 at 21:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.