[`the_posts_pagination()`][1] is an echo wrapper for [`get_the_posts_pagination()`][2]. The getter generates pagination links with [`paginate_links()`][3], which returns a string with the links separated by a newline character by default. 

This string is passed to [`_navigation_markup()`][4] to get the complete pagination markup. We can manipulate the `paginate_links()` output with [`paginate_links_output`][5] filter, before the navigation markup is generated. 

The filter recieves the default links string and pagination arguments as parameters. From `$args` you can get the total page count as well as the link format.

Here's an example implementation where the filtering is limited to the specific use case by first adding the filter and then removing it after calling the pagination function. The custom template function would be used insted of `the_posts_pagination()` in template files.

    function my_pagination_link_url(array $args, int $current, string $text) {
    	// duplicated / modified from https://developer.wordpress.org/reference/functions/paginate_links/
    	$link = str_replace( '%_%', $args['format'], $args['base'] );
    	$link = str_replace( '%#%', $current, $link );
    
    	return sprintf(
    		'<a class="page-numbers" href="%s">%s</a>',
    		$link,
    		$text
    	);
    }
    
    function my_first_pagination_link(array $args) {
      return my_pagination_link_url(
        $args, 1, 'My first'
      );
    }
    
    function my_last_pagination_link(array $args) {
      return my_pagination_link_url(
        $args, $args['total'], 'My last'
      );
    }
    
    // $args, https://developer.wordpress.org/reference/functions/paginate_links/
    function my_add_links_to_pagination( $pagination_html, $args ) {
    	return implode('', [
    		my_first_pagination_link($args),
    		$pagination_html,
    		my_last_pagination_link($args),
    		// ...my everything?
    	]);
    }
    
    function my_the_posts_pagination() {
      add_filter( 'paginate_links_output', 'my_add_links_to_pagination', 10, 2 );
    
      the_posts_pagination([
        'screen_reader_text' => ' ',
        'mid_size'  => 2,
        'prev_text' => __( 'vorherige', 'bdb' ),
        'next_text' => __( 'nächste', 'bdb' ),
      ]);
    
      remove_filter( 'paginate_links_output', 'my_add_links_to_pagination', 10 );
    }

  [1]: https://developer.wordpress.org/reference/functions/the_posts_pagination/
  [2]: https://developer.wordpress.org/reference/functions/get_the_posts_pagination/
  [3]: https://developer.wordpress.org/reference/functions/paginate_links/
  [4]: https://developer.wordpress.org/reference/functions/_navigation_markup/
  [5]: https://developer.wordpress.org/reference/hooks/paginate_links_output/