I've got 2 sites, each with a locale (dutch - nl & french - fr). I've set up a frontend entry form that works nicely for all not translated fields, I am however struggling to get it to accept submissions for the translated field in both languages at once.

So what should the name of my HTML input tag be so I can use a translated field in a front-end entry form ?


As this might not have been clear before, the goal is to be able to send content for both languages in a single form submit. As I understand this will involve some PHP code, which is certainly no problem, but I'm a bit stuck as to what to add where so any pointers are much appreciated.


I've got a field with the handle description

I've tried the following input names but without result - fields[description][nl] - fields[nl][description]

1 Answer 1


Craft has no default process to handle such things, you need to do that on your own. Here is a form and a controller example how it could be achieved.

{# just to show you.. you can edit existing one as well #}
{% set entry1 = craft.entries.id(11).siteId(1).one() %}
{% set entry2 = craft.entries.id(11).siteId(2).one() %}

<form method="post">
    {{ csrfInput() }}
    <input type="hidden" name="action" value="my-module/save">

    {# if you have an ID use it #}
    {% if entry1 is defined and entry1 is not null %}
        <input type="hidden" name="id" value="{{ entry1.id }}">
    {% endif %}

    {# the site ids you want to store, you can as well use the handle or whatever you want #}
    <input type="hidden" name="siteId[]" value="1">
    <input type="hidden" name="siteId[]" value="2">

    {# title #}
    <p>Title Site 1</p>
    <input type="text" name="title[1]" value="{{ entry1.title?? '' }}">

    <p>Title Site 2</p>
    <input type="text" name="title[2]" value="{{ entry2.title?? '' }}">

    {# a field #}
    <p>Headline site 1</p>
    <input type="text" name="fields[1][headline]" value="{{ entry1.headline?? '' }}">

    <p>Headline site 2</p>
    <input type="text" name="fields[2][headline]" value="{{ entry2.headline?? '' }}">

    {# slug #}
    <p>Slug site 1</p>
    <input type="text" name="slug[1]" value="{{ entry1.slug?? '' }}">

    <p>Slug site 2</p>
    <input type="text" name="slug[2]" value="{{ entry2.slug?? '' }}">

    <input type="submit">

And then in your Controller

 * actionIndex
 * @throws \Throwable
 * @throws \craft\errors\ElementNotFoundException
 * @throws \yii\base\Exception
 * @throws \yii\web\BadRequestHttpException
 * @return \yii\web\Response
public function actionIndex(): \yii\web\Response
    // grab all the sites you want to store
    $request = Craft::$app->getRequest();
    $sites = $request->getRequiredBodyParam('siteId');

    $elements = Craft::$app->getElements();
    // change the handle of course
    $section = Craft::$app->getSections()->getSectionByHandle('news');
    // only applies to me, you need to figure out the type on your own
    // note: don't just grab things by id if you use the project config
    // please check if those variables are not null
    $type = $section->getEntryTypes()[0];

    $elementId = null;
    $element = null;
    foreach ($sites as $siteId) {
        // TODO check if the site exists
        $elementId = (int)$request->getBodyParam('id', $elementId);
        if ($elementId !== 0) {
            $element = $elements->getElementById($elementId, Entry::class, (int) $siteId);

        if ($element === null) {
            $element = new Entry(
                    'sectionId' => $section->id,
                    'typeId'    => $type->id

        $this->populateModel($element, $siteId);
        if($elements->saveElement($element) === false){
            // handle errors somehow
            echo "<pre>";
            echo "</pre>";

        $elementId = $element->id;

    return $this->asJson(['success' => true]);

 * populateModel
 * @param \craft\base\ElementInterface $element
 * @param                              $siteId
public function populateModel(ElementInterface $element, $siteId)
    /** @var Entry $element */
    $request = Craft::$app->getRequest();
    $element->title = $request->getBodyParam('title.' . $siteId, $element->title);
    $element->slug = $request->getBodyParam('slug.' . $siteId, $element->slug);
    $element->enabled = $request->getBodyParam('enabled.' . $siteId, $element->enabled);
    // and so on.. continue with the rest you want to post + the author..

    $fieldsLocation = 'fields.' . $siteId;
  • while that does work for submitting a value for each site seperately, the goal is to be able to both languages in 1 submit. I'll edit the question to better reflect that.
    – mrsmn
    Commented Apr 9, 2019 at 9:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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