Problem/Motivation

the decoupled router path in default language (/router/translate-path) can't resolve an alias in another language (i.e. with a language prefix at the beginning of the path argument).

Example:

Given
1) Site with default language of English and another language, German ('de').
2) The alias 'helloworld' is the alias of a node in German that doesn't have an english translation.

You can visit '/de/helloworld' directly in Drupal, but /router/translate-path?path=/de/helloworld doesn't work.

Strangely, if the alias is already resolved, it works.
/router/translate-path?path=/de/node/63 works.

I believe the first one should work too.

Proposed resolution

Detect language prefix and resolve aliases before resolving path.

The bug seems to be within the 'router.no_access_checks' service, which only uses the negotiated language to match the route.

But if we can resolve the path first, then it can find the node's route.

So do this:

    $path = \Drupal::service('path.alias_manager')->getPathByAlias('/helloworld', 'de');
    $router = \Drupal::service('router.no_access_checks');
    $result = $router->match($path);

rather than

    $router = \Drupal::service('router.no_access_checks');
    $result = $router->match('/de/helloworld');

When '/de/node/63' is passed to \Drupal::service('router.no_access_checks') it works, even if the prefix is different than the negotiated language.

If we allow the path.alias_manager to check for alias, then we can get around this bug.

I know you can call the translated decoupled router:
/de/router/translate-path?path=/de/helloworld works.

But it seems inflexible to require the FE devs to call different routes based on the language for the decoupled router. It would be good for the base route to handle paths from any language when using language-url negotiation.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#103 decoupled_router-language_issues-3111456-103.patch11.96 KBomar_emailat
#98 decoupled_router-language_issues-3111456-98.patch13.68 KBahmad-alyasaki
#97 decoupled_router-language_issues-3111456-97.patch10.8 KBahmad-alyasaki
#96 decoupled_router-language_issues-3111456-96.patch8.95 KBchandu7929
#95 decoupled_router-language_issues-3111456-95.patch15.08 KBchandu7929
#94 decoupled_router-language_issues-3111456-94.patch9.41 KBchandu7929
#93 screenshot 2025-09-18 at 20.14.03.png156.42 KBserg.linkin
#91 response-after-fix.png124.21 KBchandu7929
#91 decoupled_router-language_issues-3111456-91.patch.patch6.31 KBchandu7929
#88 decouple_router-3111456-resolve-language-issue-98.patch10.98 KBvah67007@gmail.com
#87 decoupled_router-language_issues-3111456-85.patch14.15 KBaaronbauman
#78 decoupled_router-3111456-resolve-langcode-issue-78--external-redirects.patch16.74 KBsteve.elkins
#78 interdiff_77-78.txt1.44 KBsteve.elkins
#77 decouple_router-3111456-resolve-language-issue-63--get-translation-re-rolled-and-good-redirect.patch16.05 KBnaim belkaied
#74 decouple_router-3111456-resolve-language-issue-63--get-translation-re-rolled.patch15.48 KBa.dmitriiev
#72 decoupled_router-3111456-resolve_lang-69.patch17.46 KBvhin0210
#68 decoupled_router-3111456-resolve_lang-66-3397122.patch17.34 KBvhin0210
#66 interdiff.txt795 bytesdeciphered
#66 decoupled_router-3111456-resolve_lang-66.patch16.94 KBdeciphered
#64 interdiff_63-64.txt793 bytesrobertom
#64 decouple_router-3111456-resolve-language-issue-64--get-translation.patch16.16 KBrobertom
#63 interdiff-63-61.txt815 bytesabhisekmazumdar
#63 decouple_router-3111456-resolve-language-issue-63--get-translation.patch15.55 KBabhisekmazumdar
#61 interdiff.txt1.1 KByahyaalhamad
#61 decouple_router-3111456-resolve-language-issue-61--get-translation.patch15.56 KByahyaalhamad
#59 decouple_router-3111456-resolve-language-issue-58--get-translation.patch15.18 KBvhin0210
#58 decouple_router-3111456-resolve-language-issue-58.patch15.14 KBrajeshreeputra
#55 decouple_router-3111456-resolve-language-issue-55.patch15.19 KBrajeshreeputra
#51 3111456.patch12.76 KBvhin0210
#47 Screen Shot 2022-04-10 at 2.51.03 pm.png79.18 KBdeciphered
#40 Screen Shot 2022-04-06 at 1.49.47 pm.png78.16 KBdeciphered
#34 interdiff_32-34.txt1.12 KBbojan_dev
#34 3111456-34.patch12.71 KBbojan_dev
#32 interdiff_31-32.txt1.09 KBbojan_dev
#32 3111456-32.patch11.86 KBbojan_dev
#31 patch27_and_patch28-2.x_diff.txt1.69 KBgsingh1
#31 3111456-28-2.x.patch11.7 KBgsingh1
#28 patch22_and_patch28_diff.txt1.69 KBgsingh1
#28 3111456-28.patch9.89 KBgsingh1
#27 interdiff_23-27.txt2.22 KBbojan_dev
#27 3111456-27.patch11.54 KBbojan_dev
#26 interdiff_23-26.txt2.27 KBbojan_dev
#26 3111456-26.patch11.6 KBbojan_dev
#25 interdiff_23-25.txt2.18 KBbojan_dev
#25 3111456-25.patch11.51 KBbojan_dev
#24 3111456-23-reroll-against-2.0.1.patch9.36 KBarshadkhan35
#23 3111456-23-reroll.patch9.33 KBarshadkhan35
#22 3111456-22.patch9.74 KBoknate
#22 3111456-interdiff--21-22.txt694 bytesoknate
#21 3111456-interdiff--19-21.txt913 bytesoknate
#21 3111456-21.patch9.68 KBoknate
#21 3111456-21.patch9.68 KBoknate
#21 3111456-interdiff--19-21.txt913 bytesoknate
#19 3111456-19.patch9.65 KBoknate
#19 3111456-interdiff--18-19.txt1.87 KBoknate
#18 3111456-18.patch8.87 KBoknate
#18 3111456-interdiff--17-18.txt4.61 KBoknate
#17 3111456-interdiff--15-17.txt7.85 KBoknate
#17 3111456-17.patch7.26 KBoknate
#15 3111456-15.patch6.08 KBoknate
#15 3111456-15--FAIL.patch1.91 KBoknate
#15 3111456-interdiff--14-15.txt1.91 KBoknate
#14 3111456-14.patch4.17 KBoknate
#14 3111456-interdiff--7-14.txt671 bytesoknate
#7 3111456-7.patch4.27 KBoknate
#7 3111456-interdiff--5-7.txt909 bytesoknate
#6 3111456-5.patch3.38 KBoknate
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

oknate created an issue. See original summary.

oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
e0ipso’s picture

Thanks for the detailed bug. This will be a nice fix for multilingual sites.

oknate’s picture

StatusFileSize
new3.38 KB

Here's a patch for one proposed solution. It adds another subscriber that converts the alias to a path. Everything pretty much works after this, except the 'resolved' parameter is still off.

This code doesn't account for when the $entity->language() differs from the current resolved language:

    $resolved_url = Url::fromRoute($match_info[RouteObjectInterface::ROUTE_NAME], [
      $route_parameter_entity_key => $entity_param,
    ], ['absolute' => TRUE])->toString(TRUE);
oknate’s picture

Status: Active » Needs review
StatusFileSize
new909 bytes
new4.27 KB

This addresses the issue with the resolved parameter in the response not matching.

oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue summary: View changes
oknate’s picture

Issue tags: +Needs tests
oknate’s picture

Issue summary: View changes
oknate’s picture

StatusFileSize
new671 bytes
new4.17 KB
oknate’s picture

Issue tags: -Needs tests
StatusFileSize
new1.91 KB
new1.91 KB
new6.08 KB

Adding a fail patch to demonstrate the issue, and demonstrate the fix.

oknate’s picture

Assigned: Unassigned » oknate
Status: Needs review » Needs work

path.alias_manager is deprecated, so this needs reworking. Also, I think we could fold this functionality into RouterPathTranslatorSubscriber, since that will need a constructor update anyway.

oknate’s picture

Status: Needs work » Needs review
StatusFileSize
new7.26 KB
new7.85 KB

Reworking the patch to add new functionality to RouterPathTranslatorSubscriber.

oknate’s picture

StatusFileSize
new4.61 KB
new8.87 KB

This fixes a bug we found where it was not translating the entity when langcode was a prefix in the path.

oknate’s picture

StatusFileSize
new1.87 KB
new9.65 KB

Adding langcode to output, and fixing dependency issue (using \Drupal::service('entity.repository') instead of injected service in one place).

e0ipso’s picture

Thanks for the patches! you rock!

I hope to review this soon.

oknate’s picture

StatusFileSize
new913 bytes
new9.68 KB
new9.68 KB
new913 bytes

Fixing a bug where it wasn't converting the path properly on the hompeage when passed to the path attribute:
/router/translate-path?path=/de

oknate’s picture

StatusFileSize
new694 bytes
new9.74 KB

Fixing a bug where it was throwing an error if the site wasn't multilingual. We are running multiple sites and some aren't multilingual.

arshadkhan35’s picture

Version: 8.x-1.11 » 2.x-dev
StatusFileSize
new9.33 KB

Re-rolling #22 patch against 2.x branch.

arshadkhan35’s picture

Version: 2.x-dev » 2.0.1
StatusFileSize
new9.36 KB

Re-rolling #23 against 2.0.1 as 2.x-dev have some code changes which case the patch to fail for 2.0.1.

bojan_dev’s picture

StatusFileSize
new11.51 KB
new2.18 KB

The issue reported is also applicable for the redirects. With the patch from #23, the redirects are being queried with language prefix in "RedirectPathTranslatorSubscriber", while in the db they are stored as path (without language prefix), this results in 404's.

bojan_dev’s picture

StatusFileSize
new11.6 KB
new2.27 KB

#25 was not considering language-specific redirects.

bojan_dev’s picture

StatusFileSize
new11.54 KB
new2.22 KB
gsingh1’s picture

Version: 2.0.1 » 2.0.2
StatusFileSize
new9.89 KB
new1.69 KB

Updating patch from #22, the getTranslationFromContext was not returning the languages that exist for the node, instead returning entity with the default language. This patch is for version 8.x-1.11

gsingh1’s picture

updated patch #22 with following patch

Following is the diff between patch #22 and #28

gsingh1’s picture

StatusFileSize
new11.7 KB
new1.69 KB

Added patch for problem in getTranslationFromContext is that the call to getFallbackCandidates does not return the languages that exist for the node, making it display just the default language. Added patches #28 for 8.x-1.11 and 2.x.

bojan_dev’s picture

StatusFileSize
new11.86 KB
new1.09 KB

The patch is not considering that language prefix can be different than language id, e.g: I have 'en' as lang code and 'en-gb' as language prefix, which made the redirects not work for English.

Status: Needs review » Needs work

The last submitted patch, 32: 3111456-32.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

bojan_dev’s picture

StatusFileSize
new12.71 KB
new1.12 KB

Lang code has been introduced in the response but not yet in the tests.

bojan_dev’s picture

Status: Needs work » Needs review
deciphered’s picture

Issue tags: +need

Hi @bojan_dev,

I've done a brief test of this patch and it appears to be working as expected, and I can see the presence of updated automated tests. Can you specify what additional work you believe is still required?

deciphered’s picture

Issue tags: -need

removed accidental tag

bojan_dev’s picture

Hi @Deciphered,

Functional-wise, I believe it's working fine, I'm using this patch on a high traffic production website.
I think we are complete, it would be nice if we could have a test for the following change: interdiff_31-32.txt. It's not required, but again it would be nice to have test coverage for this inconsistency between lang code and lang prefix.

brianperry’s picture

Ran into a need for this fix today - patch applied cleanly and worked as expected.

Making a note of the need for additional tests on this one. If future me, or someone like future me could help out with that, would be great to get this one merged.

deciphered’s picture

StatusFileSize
new78.16 KB

While testing I noticed that the entryPoint isn't correctly prefixed.

https://nginx.develop.demo-api-druxtjs-org.au2.amazee.io/router/translat...

deciphered’s picture

I have opened a feature branch for this work and committed the latest patch with due credit.

I've added a fix for the issue I mentioned in #40.

The patch can be accessed from https://git.drupalcode.org/project/decoupled_router/-/merge_requests/5.diff, or via commit from the gitlab repo as required.

deciphered’s picture

I agree that it's important to get full test coverage here if possible, I don't personally have the capacity or full understanding of the implications and usecases of using 'en-AU' or similar langcodes.

I do think that it's worth getting this merged in and making a followup story for the testing and inconsistencies with prefixes and langcodes, as in the meantime there will be greater access to multilingual support in decoupled builds.

deciphered’s picture

It's also worth noting, and maybe updating, that the pathPrefix and basePath don't have the langcode prefix. Thoughts?

bojan_dev’s picture

Hi @Deciphered,

The commit you made looks fine: https://git.drupalcode.org/project/decoupled_router/-/merge_requests/5/d...

Unfortunately I'm pretty jammed with work currently, otherwise I could help out, but for now making a separate issue for the test coverage makes sense.

I agree with your comment about basePath/pathPrefix; it should include the langcode prefix as well.

shadcn’s picture

@Deciphered Thanks for the patch. I'll test and report back.

Agreed with you both on the langcode missing.

From the screenshot above, is there a reason individual and entryPoint have different langcode?

deciphered’s picture

StatusFileSize
new79.18 KB

@shadcn, the different langcodes was the bug I reported @ #40, that one has been fixed, but I've also added the prefix to basePath and pathPrefix now:

deciphered’s picture

I have created the follow-up issue @ https://www.drupal.org/project/decoupled_router/issues/3280591

All that is needed now is for someone to mark this issue RTBC and I will get it merged in and released.

e0ipso’s picture

Status: Needs review » Needs work
gooddev’s picture

Sorry for openening a new ticket, was not aware that they are related to each other. Made adjustments on this merge request here in this issue: https://www.drupal.org/project/decoupled_router/issues/3309874

Maybe somebody can feedback so it could eventually be proceed here.

vhin0210’s picture

StatusFileSize
new12.76 KB

Got some errors loading translated webform. I tweaked patch 34 to check if entity object has getTranslation method.

justin2pin made their first commit to this issue’s fork.

deciphered’s picture

CI is failing, and it appears to be due to Drupal being run in a subdirectory?

https://www.drupal.org/pift-ci-job/2498799

I'm unsure of the cause of this, but it will need to be accounted for.

Could you also provide a test for when the prefix doesn't match the the langcode?

Rajeshreeputra made their first commit to this issue’s fork.

rajeshreeputra’s picture

Status: Needs work » Needs review
StatusFileSize
new15.19 KB

here is the updated patch for the new release 2.0.4
there an error in patch please refer #58

Status: Needs review » Needs work

The last submitted patch, 55: decouple_router-3111456-resolve-language-issue-55.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

rajeshreeputra’s picture

Version: 2.0.2 » 2.0.4
Status: Needs work » Needs review
StatusFileSize
new15.14 KB

here is the updated patch.

vhin0210’s picture

Adding #51 again to the latest patch. can you please add that method exist call on your next patch file please?

if ($entity->hasTranslation($this->langcode) && method_exists($entity, 'getTranslation')) {

This fixes the webform entity because webform doesn't have getTranslation

Thanks!

theruslan’s picture

Patch #59 with decoupled_router 2.0.4 works fine for me.
Thank you!

yahyaalhamad’s picture

There is a problem with not being able to resolve the redirect and the current language, I expected that if you don't provide a language prefix, the current language will be used instead of only 'und'. This patch addresses the problem, but I think there will be slight problems if the prefix is also found in 'und' langcode. interdiff included.

e0ipso’s picture

I updated the test config so we can run tests on #61.

Looking forward to see an RTBC here.

abhisekmazumdar’s picture

Assigned: oknate » Unassigned
StatusFileSize
new15.55 KB
new815 bytes

The patch in #61 looks good apply in D10. But I did only see one issue with whitespaces warning throwing up. So created a new patch.

Also remove the Assigned to Unassigned so that people can find and review issue which are open to review.

robertom’s picture

The patch in #3111456-63: Unable to resolve path on node in other language than default seems to work fine, but RedirectPathTranslatorSubscriber does not correctly take into account the language of the selected redirect.

Attached a modified version of the patch and the interdiff

Status: Needs review » Needs work

The last submitted patch, 64: decouple_router-3111456-resolve-language-issue-64--get-translation.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

deciphered’s picture

Status: Needs work » Needs review
StatusFileSize
new16.94 KB
new795 bytes

Issue reported by Druxt user:

it's failing when there's a URL like: "/fr/test?query=value"

Patch attached cleans additional query string from resolver.

Status: Needs review » Needs work

The last submitted patch, 66: decoupled_router-3111456-resolve_lang-66.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

vhin0210’s picture

mglaman’s picture

#63 was the last green run. With #64 to support RedirectPathTranslatorSubscriber the tests started to fail, in what looks like a valid failure. #66 looks like a valid addition to the patch, but tests still fail. #66 looks irrelevant because it adds another issue into this patch.

Can someone confirm is the test failure is positive not?

mglaman’s picture

Trying to clean up files.

apmsooner’s picture

Not sure why test is failing but #66 works great for me.

vhin0210’s picture

jeffschuler’s picture

Version: 2.0.4 » 2.x-dev

@vhin0210 is there a reason to add the patches from #3411402: RouterPathTranslatorSubscriber uses wrong param when resolving the url and #3397122: Unable to resolve path on path with fragments to this?

Mixing issues generally makes the individual issues a lot more challenging to test, fix, and get merged by the maintainer.

a.dmitriiev’s picture

Uploading re-rolled #63, as it was the last one with not failing tests.

ankitv18 made their first commit to this issue’s fork.

ankitv18’s picture

Rebased the MR!11 with 2.x-dev and pushed minor changes.
Now gitlab pipeline is executing so avoid creating anymore patches, lets try to fix the tests in the MR only.

naim belkaied’s picture

Updated patch to retrieve the redirect URL corresponding to the language specified in the query parameter path.
eg : http://URL/fr/router/translate-path?path=/en/products/electronics/laptop...
response :

{
  "resolved": "http://example.com/en/products/electronics/laptops/dell-xps",
  "isHomePath": false,
  "entity": {
    "canonical": "http://example.com/en/products/electronics/laptops/dell-xps",
    "type": "node",
    "bundle": "product",
    "id": "789",
    "uuid": "def45678-abc1-2345-6789-0abcde123456",
    "langcode": "en",
    "path": "/en/products/electronics/laptops/dell-xps"
  },
  "label": "Dell XPS",
  "jsonapi": {
    "individual": "http://example.com/en/jsonapi/node/product/def45678-abc1-2345-6789-0abcde123456",
    "resourceName": "node--product",
    "pathPrefix": "en/jsonapi",
    "basePath": "/en/jsonapi",
    "entryPoint": "http://example.com/en/jsonapi"
  },
  "meta": {
  },
  "redirect": [
    {
      "from": "/en/products/electronics/laptops/dell-xps-15",
      "to": "/en/products/electronics/laptops/dell-xps",
      "status": "301"
    }
  ]
}
steve.elkins’s picture

Updated patch to add support for external redirects borrowing similar changes from #3133681: No information for external redirects.

Before:
Path Examples
/router/translate-path?path=/external-redirect
/router/translate-path?path=/es/external-redirect

{
  "message": "Unable to resolve path /external-redirect.",
  "details": "None of the available methods were able to find a match for this path."
}

After:
Path Example: /router/translate-path?path=/external-redirect

{
  "resolved": "https://google.com",
  "redirect": [
    {
      "from": "/external-redirect",
      "to": "https://google.com",
      "status": "301"
    }
  ]
}

Path Example: /router/translate-path?path=/es/external-redirect

{
  "resolved": "https://google.com",
  "redirect": [
    {
      "from": "/es/external-redirect",
      "to": "https://google.com",
      "status": "301"
    }
  ]
}

Attached a modified version of the patch and the interdiff.

iamfredrik’s picture

Patch does not work correctly for me.

In my case the default language is Swedish.

I have a node with path /sv/aktiviteter

/router/translate-path?path=/en/aktiviteter

correctly returns the resolved path /en/activities

but it's unable to translate back and /sv/activities returns:

{"message":"Unable to resolve path \/sv\/activities.","details":"None of the available methods were able to find a match for this path."}

lbesenyei’s picture

Patch works in my case.

aaronbauman’s picture

#78 does not apply on latest dev

aaronbauman changed the visibility of the branch 3111456-resolve-langcode-issue to hidden.

aaronbauman changed the visibility of the branch feature/3111456-langcode to hidden.

mglaman changed the visibility of the branch 3111456-resolve-langcode-issue to active.

aaronbauman changed the visibility of the branch 3111456-resolve-langcode-issue to hidden.

aaronbauman’s picture

Status: Needs work » Needs review
StatusFileSize
new14.15 KB

This patch was quite a mess after the other upstream changes.
I've cleaned it up and opened a new MR !30, and attaching patch version of same.
I'm not going to bother with an interdiff.

vah67007@gmail.com’s picture

Version: 2.x-dev » 2.0.5
StatusFileSize
new10.98 KB

Adding a patch for 2.0.5

chandu7929’s picture

Version: 2.0.5 » 2.0.6
Status: Needs review » Needs work

Need to re-rolls patch as per 5.0.6 latest release.

chandu7929’s picture

Status: Needs work » Needs review
StatusFileSize
new6.31 KB
new124.21 KB

Created MR!36 with required changes to work with 5.0.6

ankitv18 changed the visibility of the branch 3111456-language-issues to hidden.

serg.linkin’s picture

StatusFileSize
new156.42 KB

Hi @chandu7929 and thank you for the re-rolled patch.

The only important point is that the entity URL must be specified in the requested language if found, to avoid wrong content translation for multilingual websites.

Therefore, at least jsonapi > individual needs to be changed to use the found "en" langcode, just similar to the patches provided earlier in this thread. Please check the attached screenshot.

chandu7929’s picture

Thanks @serg.linkin, I have included the changes for jsonapi, also adding latest patch here.

chandu7929’s picture

StatusFileSize
new15.08 KB
chandu7929’s picture

StatusFileSize
new8.95 KB
ahmad-alyasaki’s picture

Fixes redirect failures when URLs contain encoded non-ASCII characters (e.g., Arabic: %D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9).

The patch decodes URLs before matching redirects and aliases, ensuring proper handling whether the redirect source is stored in encoded or decoded form. Also adds multilingual support with language prefix detection and proper entity translation handling.

ahmad-alyasaki’s picture

Fixes redirect failures with the prefix multi-language code

bojan_dev’s picture

in MR !35 the langcode property has been moved from entity object to the root of the response. Is there a reason for this? It breaks currently next-drupal, see: https://github.com/chapter-three/next-drupal/blob/main/packages/next-dru....

budalokko made their first commit to this issue’s fork.

budalokko’s picture

I have created this MR that would fix the regression stated by @bojan_dev in the previous comment #99.

Please @chandu7929 check if this would make sense to be merged into the issue main MR !35 or there was a specific reason to move "langcode" key to a different place.

EDIT: I merged main branch as this langcode has been there for the entire history of this issue.

jsmakk’s picture

The MR !35 seems to return access denied for the node when following steps are taken.

  1. Create a node in one language and publish it.
  2. Visit the node in front-end, it is visible.
  3. Create a translation of it, but keep it unpublished.
  4. Visit the original published node in front-end, access to it is denied.

The MR seems to check access to the entity before it gets the translation. Perhaps that is the cause. I think it was other way round in the old MR !11.

omar_emailat’s picture

I've been working with the patches from #3111456 and #10134399 and discovered an additional issue that affects multilingual sites.
Root Cause:
In the current patch, the entity translation is retrieved AFTER the access check. This means the access check runs on the default
language entity (which is unpublished), causing it to fail before we even get to the translated entity.

Additional fix in getPathFromAlias(): The method was returning the path WITH the language prefix (e.g., /ar/node/123), but the router expects paths WITHOUT the prefix.
Changed to return only the system path:

$system_path = $this->aliasManager->getPathByAlias($path_without_prefix, $langcode);
// Return the system path WITHOUT the language prefix.
// The router expects paths without language prefix - language is handled via $this->langcode property.
return $system_path;

I've attached a combined patch that includes:
- The language issues fix from #3111456-98
- The isHomePath fix from #10134399
- The translation unpublish fix described above

Tested on Drupal 10.x with decoupled_router 2.0.6.