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">
</form>
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>";
var_dump($element->getErrors());
echo "</pre>";
die();
}
$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;
$element->setFieldValuesFromRequest($fieldsLocation);
}