Finally figured it out. I var_dumped str_len($content), and I realized the return was printing next to each item in the problematic block and then printing once for the rest of the content on the page.
So I added a static variable, set it to 0, var_dumped it and increased it by 1 at the end of the filter’s callback function. It was printing incrementally next to each element in the block.
This led me to realize that wp was looping through the content starting with this block, which starts out empty.
Anyhow I added an if statement around the translation block, and it works fine now.
add_filter('the_content', function($content){
if(strlen($content) != 0){
$deepl_api_key = $_SERVER['DEEPL_API_KEY'];
$translator = new \DeepL\Translator($deepl_api_key);
$content_translated = $translator->translateText($content, 'EN', 'ES', ['tag_handling' => 'html'] );
return $content_translated;
}
}, 99);