Paragraph's fields value loaded in a custom controller are in the default language instead of the current language
Based on the comments I changed $game-&gt;get('field_stages')-&gt;getValue(); for $game-&gt;get('field_stages')-&gt;referencedEntities();. This allow me to greatly simply a part of the code.
To load the correct language I added $paragraph = \Drupal::service('entity.repository')-&gt;getTranslationFromContext($paragraph); inside the loop. Using getTranslationFromContext on the $game didn't works for the paragraph.
I'm not 100% satisfied as I feel translation should be loaded directly when all the fields are loaded with referencedEntities(). But it works and perhaps caching do some magic behind the scene.
This answer helped a lot https://drupal.stackexchange.com/a/269493/1761
// Load the game
$game = \Drupal::entityTypeManager()-&gt;getStorage('node')-&gt;load($gameID);

$stages = [];

// Get all the stage of the game
$paragraph_field_items = $game-&gt;get('field_stages')-&gt;referencedEntities();

if (!$paragraph_field_items) {
    throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('This game has no level');
}
    
/** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
foreach ($paragraph_field_items as $paragraph) {

  // Get the translation
  $paragraph = \Drupal::service('entity.repository')-&gt;getTranslationFromContext($paragraph);
    
  $description = [
      '#type' =&gt; 'processed_text',
      '#text' =&gt; $paragraph-&gt;get('field_description')-&gt;value,
      '#format' =&gt; 'basic_html',
  ];

  $stages [] = [
      'title' =&gt; $paragraph-&gt;get('field_title')-&gt;value,
      'image' =&gt; $paragraph-&gt;get('field_image'),
      'description' =&gt; $description,
      'east_lv95' =&gt; $paragraph-&gt;get('field_east_lv95')-&gt;value,
      'north_lv95' =&gt; $paragraph-&gt;get('field_north_lv95')-&gt;value,
  ];
}