symfony-bundle icon indicating copy to clipboard operation
symfony-bundle copied to clipboard

Parameters get replaced

Open rvanlaak opened this issue 9 years ago • 4 comments

When labels that have a parsed value get translated, the value overwrites the parameter placeholder.

title: 'Hi %name%'
# will be saved as
title: 'Howdy Richard'

For EditInPlace this can be fixed by:

  • [x] Adding the translation value to the <x-trans> tag as a data-value attribute, without any replaced parameter.
  • [x] Let the Javascript first replace the translatable label with data-value, so it is clear to the translator that it is a dynamic parameter.
  • [ ] ... or by using the XHR call that also is used with the Profiler integration

rvanlaak avatar Apr 19 '17 12:04 rvanlaak

image

@Nyholm @damienalexandre I now found out that the profiler integration actually already uses an XHR call to load the textarea with a value where the parameters aren't replaced, which makes this "EditInPlace" specific. That same call could be used by the Edit-In-Place feature.

rvanlaak avatar Apr 19 '17 15:04 rvanlaak

data-value is added via #89

@damienalexandre do you have time to make the edit-in-place javascript use it? https://github.com/php-translation/symfony-bundle/pull/89#issuecomment-295930611

rvanlaak avatar Apr 25 '17 09:04 rvanlaak

I'm currently full time on a new projet so that's not the best time for me, But I think https://github.com/php-translation/symfony-bundle/pull/89#issuecomment-295930611 describe what must be done pretty accurately 👍

damienalexandre avatar Apr 25 '17 21:04 damienalexandre

Hi,

I've found this project recently, and I like it very much, mainly because of the in place edit feature. I went my own way with the implementation, because I wanted to combine several editable types, and translations, plus I wanted to keep it simple for now.

I believe I have found a better way to handle translation parameters.

Finished product first (translated to hungarian, sorry about that): ezgif-4-50143db614

HTML markup:

<x-trans data-fixture="true" data-name="translation[hu][messages][calculator.product_info.title.%product%]">
    <x-trans-param contenteditable="false"><x-trans-param-key>%product%</x-trans-param-key> <x-trans-param-value>névjegykártya</x-trans-param-value></x-trans-param> készítés, <x-trans-param contenteditable="false"><x-trans-param-key>%product%</x-trans-param-key> <x-trans-param-value>névjegykártya</x-trans-param-value></x-trans-param> rendelés
</x-trans>

The point of this example is the x-trans-param node, setting contenteditable to false disables the editing of this child. It can only be removed as a whole, so no risk of malformed HTML.

  • Firefox won't even allow you to delete it with backspace, you have to click on it directly. It highlights the whole node with a single click, and then it can be deleted with a backspace / del.
  • Chrome just deletes the whole node with a single backspace.

(The data-name attribute is kind of cool too. Just send it as form data instead of json, and iterate over it...)

Sass to show/hide the appropriate x-trans-param part on focus:

x-trans-param {
  x-trans-param-key {
    display: none;
    opacity: 0.33;
  }
}

.ce-element--focused {
  x-trans-param {
    x-trans-param-key {
      display: inline;
    }

    x-trans-param-value {
      display: none;
    }
  }
}

On the backend side just replace the x-trans-param nodes with the key.

if ($request->request->has('translation')) {
    foreach ($request->get('translation') as $locale => $localeData) {
        foreach ($localeData as $domain => $messages) {
            foreach ($messages as $message) {
                $doc = new \DOMDocument('1.0', 'UTF-8');
                $doc->loadXML($message);

                $trans = $doc->getElementsByTagName('x-trans')->item(0);

                $replacements = [];
                /** @var \DOMElement $param */
                foreach ($trans->getElementsByTagName('x-trans-param') as $param) {
                    $replacements[] = [
                        $doc->createTextNode($param->getElementsByTagName('x-trans-param-key')->item(0)->nodeValue),
                        $param
                    ];
                }

                foreach ($replacements as $replacement) {
                    $trans->replaceChild($replacement[0], $replacement[1]);
                }

                $doc->replaceChild($doc->createTextNode($trans->nodeValue), $trans);

                $message = html_entity_decode(trim($doc->saveHTML()));

                // ...
            }
        }
    }
}

It is probably too hacky to be considered as standard, but perhaps it gets the discussion going, and we can come up with a good solution.

Cheers, Adam

Padam87 avatar Oct 16 '17 22:10 Padam87