diff --git a/config/install/pathologic.settings.yml b/config/install/pathologic.settings.yml
index ed7f9a3ea3953ef4b650934fd7aa30a3dabd64e6..3c40489f9868bd23f008c52b29fee57a9a76c8cb 100644
--- a/config/install/pathologic.settings.yml
+++ b/config/install/pathologic.settings.yml
@@ -1,3 +1,4 @@
 scheme_allow_list: ['http', 'https', 'files', 'internal']
 protocol_style: 'full'
 local_paths: ''
+keep_language_prefix: true
diff --git a/config/schema/pathologic.schema.yml b/config/schema/pathologic.schema.yml
index 856990c06b4f9a917dc1f42be7e22606c97d0573..ce6bdf3890bcc72c27c8592acbe39e57153b3d46 100644
--- a/config/schema/pathologic.schema.yml
+++ b/config/schema/pathologic.schema.yml
@@ -13,6 +13,9 @@ pathologic.settings:
     local_paths:
       type: string
       label: 'Also considered local'
+    keep_language_prefix:
+      type: boolean
+      label: 'Keep language prefix'
 
 filter_settings.filter_pathologic:
   type: filter
@@ -31,3 +34,6 @@ filter_settings.filter_pathologic:
         local_paths:
           type: string
           label: 'Also considered local'
+        keep_language_prefix:
+          type: boolean
+          label: 'Keep language prefix'
diff --git a/pathologic.module b/pathologic.module
index 464410f005a439e9d774e16395ccc87e7220ca68..d0c6b553fef706c0c987ee6f0eb3ee423f052687 100644
--- a/pathologic.module
+++ b/pathologic.module
@@ -297,7 +297,7 @@ function _pathologic_replace($matches) {
 
   // Okay, deal with language stuff.
   // Let's see if we can split off a language prefix from the path.
-  if (\Drupal::moduleHandler()->moduleExists('language')) {
+  if ((($cached_settings['current_settings']['keep_language_prefix'] ?? FALSE) === FALSE) && \Drupal::moduleHandler()->moduleExists('language')) {
     // This logic is based on
     // \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl::getLangcode().
     $languages = \Drupal::languageManager()->getLanguages();
diff --git a/pathologic.post_update.php b/pathologic.post_update.php
index fb7576dd156bd446cd4557fe3aae5da4735ae165..e1cc9de7ba0d949759463e297a478b7286a5b680 100644
--- a/pathologic.post_update.php
+++ b/pathologic.post_update.php
@@ -5,6 +5,10 @@
  * Post update functions for the Pathologic module.
  */
 
+use Drupal\filter\Entity\FilterFormat;
+use Drupal\filter\FilterFormatInterface;
+use Drupal\filter\FilterPluginCollection;
+
 /**
  * Move setting for allowed schemes to a new name (#3216612).
  */
@@ -16,3 +20,26 @@ function pathologic_post_update_rename_scheme_allow_list() {
   $config->clear('scheme_whitelist');
   $config->save();
 }
+
+/**
+ * Define 'keep_language_prefix' using legacy behavior for existing sites.
+ */
+function pathologic_post_update_set_keep_language_prefix() {
+  \Drupal::configFactory()->getEditable('pathologic.settings')
+    ->set('keep_language_prefix', FALSE)
+    ->save();
+
+  if (\Drupal::service('plugin.manager.filter')->hasDefinition('filter_pathologic')) {
+    foreach (FilterFormat::loadMultiple() as $format) {
+      assert($format instanceof FilterFormatInterface);
+      $collection = $format->filters();
+      $configuration = $collection->getConfiguration();
+      assert($collection instanceof FilterPluginCollection);
+      if (array_key_exists('filter_pathologic', $configuration)) {
+        $configuration['filter_pathologic']['settings']['local_settings']['keep_language_prefix'] = FALSE;
+        $collection->setConfiguration($configuration);
+        $format->save();
+      }
+    }
+  }
+}
diff --git a/src/PathologicSettingsCommon.php b/src/PathologicSettingsCommon.php
index 48964c93ff05ac412b13c12ced412ba7a155a7b7..5c03cf325d59e3d3834a5ff41966f62b9cfaffbf 100644
--- a/src/PathologicSettingsCommon.php
+++ b/src/PathologicSettingsCommon.php
@@ -43,6 +43,13 @@ class PathologicSettingsCommon {
         '#description' => $this->t('If this site is or was available at more than one base path or URL, enter them here, separated by line breaks. For example, if this site is live at <code>http://example.com/</code> but has a staging version at <code>http://dev.example.org/staging/</code>, you would enter both those URLs here. If confused, please read <a href=":docs" target="_blank">Pathologic&rsquo;s documentation</a> for more information about this option and what it affects.', [':docs' => 'https://www.drupal.org/node/257026']),
         '#weight' => 20,
       ],
+      'keep_language_prefix' => [
+        '#type' => 'checkbox',
+        '#title' => $this->t('Keep language prefix'),
+        '#description' => $this->t('If not checked, URL prefixes that match configured languages will be removed from links.'),
+        '#default_value' => $defaults['keep_language_prefix'] ?? TRUE,
+        '#weight' => 20,
+      ],
     ];
   }
 
diff --git a/src/PathologicSettingsForm.php b/src/PathologicSettingsForm.php
index 64e75305e6d93cb327d19931891a86d7f1ffa82e..7c21ff14d4fa0ded3c12cb51fa1071245d6ce568 100644
--- a/src/PathologicSettingsForm.php
+++ b/src/PathologicSettingsForm.php
@@ -30,6 +30,7 @@ class PathologicSettingsForm extends ConfigFormBase {
     $defaults = [
       'protocol_style' => $config->get('protocol_style'),
       'local_paths' => $config->get('local_paths'),
+      'keep_language_prefix' => $config->get('keep_language_prefix'),
     ];
 
     $common = new PathologicSettingsCommon();
@@ -45,6 +46,7 @@ class PathologicSettingsForm extends ConfigFormBase {
     $this->config('pathologic.settings')
       ->set('protocol_style', $form_state->getValue('protocol_style'))
       ->set('local_paths', $form_state->getValue('local_paths'))
+      ->set('keep_language_prefix', $form_state->getValue('keep_language_prefix'))
       ->save();
 
     parent::submitForm($form, $form_state);
diff --git a/src/Plugin/Filter/FilterPathologic.php b/src/Plugin/Filter/FilterPathologic.php
index 055f8a585f091e2bb9a1e5dfd0a862908703393e..e2197655fd13cf12950a5d2fce4955a0fdd0889e 100644
--- a/src/Plugin/Filter/FilterPathologic.php
+++ b/src/Plugin/Filter/FilterPathologic.php
@@ -87,6 +87,7 @@ class FilterPathologic extends FilterBase {
       $config = \Drupal::config('pathologic.settings');
       $settings['protocol_style'] = $config->get('protocol_style');
       $settings['local_paths'] = $config->get('local_paths');
+      $settings['keep_language_prefix'] = $config->get('keep_language_prefix');
     }
     else {
       $settings = $settings['local_settings'];
diff --git a/tests/src/Functional/PathologicLanguageTest.php b/tests/src/Functional/PathologicLanguageTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..5eba374607b035a51319f52d3c51257a638276a2
--- /dev/null
+++ b/tests/src/Functional/PathologicLanguageTest.php
@@ -0,0 +1,190 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\pathologic\Functional;
+
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+use Drupal\Tests\node\Traits\NodeCreationTrait;
+use Drupal\Tests\pathologic\Traits\PathologicFormatTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
+
+/**
+ * Test multilingual integration of Pathologic functionality.
+ *
+ * @group pathologic
+ */
+class PathologicLanguageTest extends BrowserTestBase {
+
+  use ContentTypeCreationTrait;
+  use NodeCreationTrait;
+  use PathologicFormatTrait;
+  use UserCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'content_translation',
+    'field',
+    'language',
+    'locale',
+    'node',
+    'pathologic',
+    'text',
+    'user',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    $this->setUpCurrentUser();
+
+    $this->createContentType([
+      'type' => 'page',
+      'name' => 'Basic page',
+    ]);
+
+    // Add more languages.
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+    ConfigurableLanguage::createFromLangcode('pt-br')->save();
+
+    // Enable URL language detection and selection.
+    \Drupal::configFactory()->getEditable('language.negotiation')
+      ->set('url.prefixes.fr', 'fr')
+      ->set('url.prefixes.pt-br', 'pt-br')
+      ->save();
+
+    // Configure Pathologic on a text format.
+    $this->buildFormat([
+      'settings_source' => 'local',
+      'local_settings' => [
+        'protocol_style' => 'path',
+        'keep_language_prefix' => TRUE,
+      ],
+    ]);
+
+    // To reflect the changes for a multilingual site, rebuild the container.
+    $this->container->get('kernel')->rebuildContainer();
+  }
+
+  /**
+   * Tests how links to nodes and files are handled with translations.
+   */
+  public function testContentTranslation(): void {
+
+    // Create a node that will be referenced in a link inside another node.
+    $node_to_reference = $this->createNode([
+      'type' => 'page',
+      'title' => 'Reference page',
+    ]);
+
+    // Add translations for the reference node, and try a whole
+    // series of possible input texts to see how they are handled.
+    $fr_reference = $node_to_reference->addTranslation('fr', [
+      'title' => 'Page de référence en français',
+    ])->save();
+    $pt_br_reference = $node_to_reference->addTranslation('pt-br', [
+      'title' => 'Página de referência em Português',
+    ])->save();
+
+    global $base_path;
+    $nid = $node_to_reference->id();
+
+    // The link replacement shouldn't change for any of these based on the language the filter runs with.
+    foreach (['en', 'fr', 'pt-br'] as $langcode) {
+      $this->assertSame(
+        '<a href="' . $base_path . 'sites/default/files/test.png">Test file link</a>',
+        $this->runFilter('<a href="/sites/default/files/test.png">Test file link</a>', $langcode),
+        "$langcode: file links do not get a language prefix",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: node/N link should be unchanged"
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'fr/node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/fr/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: fr/node/N link should be unchanged",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'pt-br/node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/pt-br/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: pt-br/node/N link should be unchanged",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'reference-en">Test node link</a>',
+        $this->runFilter('<a href="/reference-en">Test node link</a>', $langcode),
+        "$langcode: /reference-en link uses EN alias",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'fr/reference-fr">Test node link</a>',
+        $this->runFilter('<a href="/fr/reference-fr">Test node link</a>', $langcode),
+        "$langcode: fr/reference-fr link uses the FR alias",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'pt-br/referencia-pt">Test node link</a>',
+        $this->runFilter('<a href="/pt-br/referencia-pt">Test node link</a>', $langcode),
+        "$langcode: pt-br/referencia-pt uses the PT-BR alias",
+      );
+    }
+
+    // Try again with language code stripping configured.
+    $this->buildFormat([
+      'settings_source' => 'local',
+      'local_settings' => [
+        'protocol_style' => 'path',
+        'keep_language_prefix' => FALSE,
+      ],
+    ]);
+    foreach (['en', 'fr', 'pt-br'] as $langcode) {
+      $this->assertSame(
+        '<a href="' . $base_path . 'sites/default/files/test.png">Test file link</a>',
+        $this->runFilter('<a href="/sites/default/files/test.png">Test file link</a>', $langcode),
+        "$langcode: file links do not get a language prefix",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: node/N link is unchanged"
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/fr/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: fr/node/N link should have no langcode prefix"
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'node/' . $nid . '">Test node link</a>',
+        $this->runFilter('<a href="/pt-br/node/' . $nid . '">Test node link</a>', $langcode),
+        "$langcode: pt-br/node/N link should have no langcode prefix"
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'reference-en">Test node link</a>',
+        $this->runFilter('<a href="/reference-en">Test node link</a>', $langcode),
+        "$langcode: /reference-en link uses EN alias",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'reference-fr">Test node link</a>',
+        $this->runFilter('<a href="/fr/reference-fr">Test node link</a>', $langcode),
+        "$langcode: fr/reference-fr link should have no langcode prefix",
+      );
+      $this->assertSame(
+        '<a href="' . $base_path . 'referencia-pt">Test node link</a>',
+        $this->runFilter('<a href="/pt-br/referencia-pt">Test node link</a>', $langcode),
+        "$langcode: pt-br/referencia-pt link should have no langcode prefix",
+      );
+    }
+  }
+
+}
diff --git a/tests/src/Kernel/PathologicKernelTestBase.php b/tests/src/Kernel/PathologicKernelTestBase.php
index e5eb77c8c60539496b9316f6ddf4dc432e9d551e..0b11e8a8472299ec7fc3bce922ef2f7fff22c993 100644
--- a/tests/src/Kernel/PathologicKernelTestBase.php
+++ b/tests/src/Kernel/PathologicKernelTestBase.php
@@ -6,14 +6,16 @@ namespace Drupal\Tests\pathologic\Kernel;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
-use Drupal\filter\Entity\FilterFormat;
 use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\pathologic\Traits\PathologicFormatTrait;
 
 /**
  * Base class for all Pathologic Kernel tests.
  */
 abstract class PathologicKernelTestBase extends KernelTestBase {
 
+  use PathologicFormatTrait;
+
   /**
    * {@inheritdoc}
    */
@@ -28,13 +30,6 @@ abstract class PathologicKernelTestBase extends KernelTestBase {
    */
   protected $defaultTheme = 'stark';
 
-  /**
-   * The ID of a text format to be used in a test.
-   *
-   * @var formatId
-   */
-  protected $formatId = '';
-
   /**
    * {@inheritdoc}
    */
@@ -44,42 +39,6 @@ abstract class PathologicKernelTestBase extends KernelTestBase {
     $this->installConfig(['system', 'filter', 'pathologic']);
   }
 
-  /**
-   * Build a text format with Pathologic configured a certain way.
-   *
-   * @param array $settings
-   *   An array of settings for the Pathologic instance on the format.
-   *
-   * @return string
-   *   The randomly generated format machine name for the new format.
-   */
-  protected function buildFormat(array $settings) {
-    $this->formatId = ($settings['local_settings']['protocol_style'] ?? 'unknown') . '_' . $this->randomMachineName(8);
-    $format = FilterFormat::create([
-      'format' => $this->formatId,
-      'name' => $this->formatId,
-    ]);
-    $format->setFilterConfig('filter_pathologic', [
-      'status' => 1,
-      'settings' => $settings,
-    ]);
-    $format->save();
-    return $this->formatId;
-  }
-
-  /**
-   * Runs the given string through the Pathologic text filter.
-   *
-   * @param string $markup
-   *   Raw markup to be processed.
-   *
-   * @return string
-   *   A string of text-format-filtered markup.
-   */
-  protected function runFilter(string $markup): string {
-    return check_markup($markup, $this->formatId)->__toString();
-  }
-
   /**
    * Wrapper around url() which does HTML entity decoding and encoding.
    *
diff --git a/tests/src/Kernel/PathologicLanguageTest.php b/tests/src/Kernel/PathologicLanguageTest.php
index a4d659203c8dc0140ee64825933c235d273b8eb5..fb3bb153ec10a4b5b62662eca928654c34902413 100644
--- a/tests/src/Kernel/PathologicLanguageTest.php
+++ b/tests/src/Kernel/PathologicLanguageTest.php
@@ -60,6 +60,7 @@ class PathologicLanguageTest extends PathologicKernelTestBase {
       'settings_source' => 'local',
       'local_settings' => [
         'protocol_style' => 'path',
+        'keep_language_prefix' => TRUE,
       ],
     ]);
 
diff --git a/tests/src/Kernel/PathologicTest.php b/tests/src/Kernel/PathologicTest.php
index 5318cf98cd2e76be7194dffda179e535bfe4e7c4..cde31e61b58eb4d8dab1a053abbe72dd1e27bd3a 100644
--- a/tests/src/Kernel/PathologicTest.php
+++ b/tests/src/Kernel/PathologicTest.php
@@ -82,6 +82,7 @@ class PathologicTest extends PathologicKernelTestBase {
         'settings_source' => 'local',
         'local_settings' => [
           'protocol_style' => $protocol_style,
+          'keep_language_prefix' => TRUE,
         ],
       ]);
       $paths = [];
diff --git a/tests/src/Traits/PathologicFormatTrait.php b/tests/src/Traits/PathologicFormatTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..7099865d0150e9614dda1177ed115605344e41ce
--- /dev/null
+++ b/tests/src/Traits/PathologicFormatTrait.php
@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\pathologic\Traits;
+
+use Drupal\filter\Entity\FilterFormat;
+
+/**
+ * Provides management of a text format configured for Pathologic.
+ *
+ * This trait is meant to be used only by test classes.
+ */
+trait PathologicFormatTrait {
+
+  /**
+   * The ID of a text format to be used in a test.
+   *
+   * @var formatId
+   */
+  protected $formatId = '';
+
+  /**
+   * Build a text format with Pathologic configured a certain way.
+   *
+   * @param array $settings
+   *   An array of settings for the Pathologic instance on the format.
+   *
+   * @return string
+   *   The randomly generated format machine name for the new format.
+   */
+  protected function buildFormat(array $settings) {
+    $this->formatId = ($settings['local_settings']['protocol_style'] ?? 'unknown') . '_' . $this->randomMachineName(8);
+    $format = FilterFormat::create([
+      'format' => $this->formatId,
+      'name' => $this->formatId,
+    ]);
+    $format->setFilterConfig('filter_pathologic', [
+      'status' => 1,
+      'settings' => $settings,
+    ]);
+    $format->save();
+    return $this->formatId;
+  }
+
+  /**
+   * Runs the given string through the Pathologic text filter.
+   *
+   * @param string $markup
+   *   Raw markup to be processed.
+   * @param string $langcode
+   *   The optional language to render the text with.
+   *
+   * @return string
+   *   A string of text-format-filtered markup.
+   */
+  protected function runFilter(string $markup, string $langcode = ''): string {
+    return check_markup($markup, $this->formatId, $langcode)->__toString();
+  }
+
+}