LanguageLocalizedURL by soma

This module is useful to generate localized urls.

Language Localized URL

ProcessWire Module Version 0.1.2

ProcessWire's module to generate and parse localized URL for multilingual websites.


Note: This module is still a proof of concept and should be considered as such. It's best to first setup a test site and play around with this module to get familiar and maybe see limitations you'll run into. Use it on your own risk for larger or big, serious sites. There might be side effects you (and we) don't know yet, you might regret.

Module Thread: Language Localized URL

This module is useful to generate localized url using the language code as first segment, followed by localized titles of the nested pages:

[language code]/[localized parent title]/[localized page title]

/en/   <- language gateway: English
/de/   <- language gateway: German
/fr/   <- language gateway: French

So if you consider the URL /about/background/ it would return the url for the same page in german as something like /ueber-uns/hintergrund/. These URL's are constructed using the PageTitleLanguage field on each the page.

How to

This module is meant to be combined with use of PageTitleLanguage, TextLanguage and TextareaLanguage fields.

To make it work it's necessary to follow these steps:

Prepare ProcessWire to support language
  1. Install the LanguageSupport and LanguageSupportFields modules that comes with ProcessWire install (but not installed by default).
  2. You'll have to create your additional languages.
  3. Change the title field to a PageTitleLanguage text field which is required by this module. This field will now have a text input for each language you create. These titles will end up being used as the urls. It's like the page name field now. It's important to know that when you change that title the url for the page generated by this module will change also!
  4. If you have cyrillic characters you can and should first configure the module InputfieldPageName installed by default. There you can set conversion for sepcial characters. For example, the german ü will be converted to u by default but should be ue.
  5. Change all text fields you like to use TextLanguage or TextareaLanguage.
Now let's start setup needed
  1. Create a new template and name it "language_gateway" and a corresponding template file "language_gateway.php". (This template's default name can be changed in the modules settings)
  2. Enable "Allow URL Segments" for this template and also "Allow Page Numbers?" if you want to use pagination.
  3. Below the root page, create one page per language (en, it, fr, ...) (for the default language too if you don't want disable it in the settings) using that "language_gateway" template. The names of these pages should match the names you set on the languages setup in ProcessWire. These names will be used as first folder inside the URLs. On these pages set the Status to Hidden to prevent them from being included in lists and searches.
  4. Enter in the module settings to inidicate the default language code (eg. 'en'), that will be mapped to the default languge inside ProcessWire.
  5. Create the pages of the website directly below the root page.

Performance issue

To parse a localized URL the module needs to loop trough all the children pages of root (or of a parent page) searching for a localized title. This could be expensive if there are many pages/contents, so it's possible to generate urls using the page id as prefix:

[language code]/[localized parent title]/[page id]_[localized page title] or [language code]/[parent id]_[localized parent title]/[localized page title] or [language code]/[parent id]_[localized parent title]/[page id]_[localized page title]

Often the parents folders are not so many and could be used without any id. Anyway the desired behaviour is defined in the module settings.

Publishing individual languages

By default the module will map a page in any available language. Then the translated data will be selected. If missing, the default language will be used. If you don't want this behavior, and prefer to hide a page for a specific language follow these steps:

  1. Create a Field of type Page and assign it a name like language_published. (you can change this default field name in the modules settings)
  2. On the Input tab of the field settings select the gateway template you build the root language pages with like /en/.
  3. Still in the Input tab select Checkboxes as Input field type, after saving the field a new setting appears for the Checkboxes. Set Columns of Checkboxes to 10.
  4. Assign this new field to templates you want to control which languages are published. Move it to the very top of the field sortable list.
  5. When trying to access a page in a language the checkbox is not checked it will throw a 404 Not Found.

If you print a list of pages and in all your finds, you will need to filter out the locked pages for a specific language:

$homepage = $pages->get("/");
$lang = $user->language;

$langname = $lang->name == 'default' ? 'en' : $lang->name;
$langpage = $pages->get("/$langname/");

// only include pages really published on the current language
$children = $homepage->children("language_published=$langpage");

foreach($children as $child) {
	$class = $child === $page->rootParent ? " class='on'" : '';
	echo "<li><a$class href='{$child->url()}'>{$child->title}</a></li>";

Language Switch Example

To construct a language switch for the available languages you need this code somehwere in your or before content output.

Language Switch Code Snippet


This module uses the url segments of ProcessWire to map the localized pages to real ones but the array of segment is re-indexed to contains only real segments. This means that you can access $input->urlSegments as usual.

Plus, the limit of 4 segments includes the page tree, so it could be necessary to change this limit in the config.php file:

$config->maxUrlSegments = 4;

Language Domains

This module supports language domains. So you can have each language mapped to its own domain. To make this work you need to have the different domains point to the default domain and PW install. Then enable this option in the module settings and enter your domains in the textarea, each domain on its own line.

The format is:

You can also use subdomains:


Now you can access the different languages simply through the different domains. For example the /about/ page would be available like this:


New in version 0.1.2

Added support for language_published field on home page.

New in version 0.1.1

Important if upgrading from 0.1.0: The gateway template php code isn't necessary anymore, as the module will return the rendered page now without the need of code in the template itself. This is the only method that allows to get rid of the "double render" issue it had before and to get it to work with the new feature introduced in PW 2.3: prependTemplateFile and appendTemplateFile (via config.php).

Install and use modules at your own risk. Always have a site and database backup before installing new modules.

Twitter updates

  • There’s a new modules directory on the ProcessWire site now up and running. In this post we’ll cover a few details about what’s changed and what’s new—More
    20 November 2020
  • ProcessWire 3.0.168 core updates — More
    26 October 2020
  • This week a 2nd new module for processing Stripe payments has been added to FormBuilder. Unlike our other Stripe Inputfield, this new one supports 3D Secure (SCA) payments. We’ll take a closer look at it in this post, plus a live demo— More
    16 October 2020

Latest news

  • ProcessWire Weekly #342
    In the 342nd issue of ProcessWire Weekly we're going to check out brand new admin theme called Admin Theme Canvas, a new module called MatomoWire, latest ProcessWire core updates, and more. Read on! / 28 November 2020
  • New ProcessWire modules directory
    There’s a new modules directory on the ProcessWire site now up and running. In this post we’ll cover a few details about what’s changed and what’s new.
    Blog / 20 November 2020
  • Subscribe to weekly ProcessWire news

“We chose ProcessWire because of its excellent architecture, modular extensibility and the internal API. The CMS offers the necessary flexibility and performance for such a complex website like ProcessWire offers options that are only available for larger systems, such as Drupal, and allows a much slimmer development process.” —xport communication GmbH