0

What is the recommended way to generate non-route URLs that include the language prefix?

Context: In CiviCRM, an open source third-party project that integrates with Drupal, we have a function that generates internal URLs (a wrapper over the CMS-specific function).

Since not all URLs referenced have a proper route, so far fromUri has given the best results (rather than fromRoute).

However, the URLs generated by fromUri do not seem to include the language prefix for multi-lingual configurations when using base as the prefix. The language prefix is included with internal, but if I understand correctly, internal should only be used for user-specified links, such as a link field.

Example on a site that has English and French, with French being the default language:

print \Drupal\Core\Url::fromUri("base:/admin")->toString() . "\n";
print \Drupal\Core\Url::fromUri("internal:/admin")->toString() . "\n";
$ drush scr test.php
/civicrm/dashboard?reset=1
/fr/civicrm/dashboard?reset=1

I also tried passing in the $language object, but the behaviour is the same:

$language = \Drupal::languageManager()->getCurrentLanguage();

print \Drupal\Core\Url::fromUri("base:/admin", [
  'language' => $language,
])->toString() . "\n";

Related question: Generating arbitrary internal URLs

  • internal should only be used for user-specified links, such as a link field Do you have a reference for that? The docs don't appear to mention anything in that vein, just that internal is for paths relative to the Drupal/Symfony root – Clive Apr 3 at 12:55
  • The fromUri doc says: "The internal: scheme should be avoided except when processing actual user input that may or may not correspond to a Drupal route." – bgm Apr 3 at 12:59
  • Hmm, not sure I agree with that Just do a search for 'internal:/ in core, there's tons of them being used outside of user input – Clive Apr 3 at 13:01
  • Interesting, thank you! I'm still curious why the different behaviour, but for now this helps us move forward. – bgm Apr 3 at 13:51
  • 1
    Also interestingly, core barely uses 'base:/ by the looks of things; just in tests and a few edge cases. Not really sure what that means exactly though :) – Clive Apr 3 at 13:53
1
  • Drupa8 - as a Symfony application - abstracts paths with routes. So paths may change, the route stays.

  • So the cited "The internal: scheme should be avoided except when processing actual user input that may or may not correspond to a Drupal route." means: If you can, use a route.

  • If you can not use routes, the right prefix for routed paths is internal:.

  • In contrast, base: was introduced for use cases like README.txt which is unknown to the symfony router and served directly by the web server.

You can find background in these issues, and help improve the docs:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.