Last active
January 25, 2026 23:01
-
-
Save olafgleba/1e1c33d8ad3fc22961dfba33a6ee2f36 to your computer and use it in GitHub Desktop.
Swap multilanguage content when changing the default language in ProcessWire.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php namespace ProcessWire; | |
| /** | |
| * Swap the content of multilingual fields between two languages | |
| * | |
| * - Tested with ProcessWire 3.0.x, PHP 8.4.x | |
| * | |
| * Usage: | |
| * | |
| * Place the script file in the root of your PW installation (or | |
| * adapt the pw bootstrap path), adapt params (s. below), than open | |
| * the file in the browser. | |
| * | |
| * @author Olaf Gleba | |
| * @version 1.0.0 | |
| */ | |
| /** | |
| * USAGE, VERBOSE | |
| * | |
| * 1. Place the (uncommented) `Code example` at the end of this script file | |
| * 2. Adapt `<your-language-name>` with the name of the language that should | |
| * become default. | |
| * 2. Adapt `<your-template-name>` with the required template names | |
| * (assuming that multiple templates are to consider). Execute the script | |
| * file (e.g. reload the browser) ``each time`` you adapt the template name. | |
| * | |
| * Code example: | |
| * | |
| * $_pages = wire('pages')->find("template=<your-template-name>"); | |
| * swapMultiLanguageContent($_pages, 'default', '<your-language-name>'); | |
| * | |
| */ | |
| /** | |
| * MANDATORY STEPS AFTER FINAL EXECUTION | |
| * | |
| * After you run all considered templates you need to do: | |
| * | |
| * 1. Assuming `german` was your default language so far (name `default`) | |
| * and you want to define a second language, for example `english` | |
| * (name `english`), as the new default, adapt the name (and surely the | |
| * title too) on both related languages (e.g. english => default, | |
| * german => german). | |
| * | |
| * 2. Go to your Homepage ("/") and in the settings tab, adapt the url of your | |
| * new default language and the url of your swapped language (e.g. english | |
| * => /, german => /de/). | |
| */ | |
| // bootstrap processwire | |
| require_once './index.php'; | |
| /** | |
| * Function to swap the content of multilingual fields between two languages | |
| * | |
| * 1. Page name swap | |
| * 2. Execute recursive function `swapFieldValuesRecursive` | |
| * 3. Save pages array | |
| */ | |
| function swapMultiLanguageContent($pages, $langA = 'default', $langB = 'deutsch') { | |
| $languages = wire('languages'); | |
| $lA = $languages->get($langA); | |
| $lB = $languages->get($langB); | |
| if(!$lA || !$lB) throw new WireException("Language not found"); | |
| foreach($pages as $page) { | |
| if(!$page instanceof Page || !$page->id) continue; | |
| $page->of(false); | |
| /* 1 */ | |
| try { | |
| $nameA = $page->localName($lA); | |
| $nameB = $page->localName($lB); | |
| if($nameA !== $nameB) { | |
| $page->set("status$langB", 1); | |
| $page->set("name$langA", $nameB); | |
| $page->set("name$langB", $nameA); | |
| } | |
| } catch(Exception $e) { | |
| wire('log')->save('swap-lang', "Page {$page->id}: Name swap error: " . $e->getMessage()); | |
| } | |
| /* 2 */ | |
| swapFieldValuesRecursive($page, $lA, $lB); | |
| /* 3 */ | |
| try { | |
| $page->save(); | |
| } catch(Exception $e) { | |
| wire('log')->save('swap-lang', "Page {$page->id}: Save error: " . $e->getMessage()); | |
| } | |
| $page->of(true); | |
| } | |
| return "Done."; | |
| } | |
| /** | |
| * Internal function to swap field values recursively | |
| * | |
| * NOT intended to use as stand-alone, s. func `swapMultiLanguageContent` | |
| * | |
| * 1. Ordinary field type | |
| * 2. Repeater field type | |
| * 3. RepeaterMatrix field type | |
| */ | |
| function swapFieldValuesRecursive(Page $page, Language $lA, Language $lB) { | |
| foreach($page->template->fieldgroup as $field) { | |
| $fieldname = $field->name; | |
| if(!$page->hasField($fieldname)) continue; | |
| $value = $page->$fieldname; | |
| if($value === null) continue; | |
| /* 1 */ | |
| $type = $field->type; | |
| if($type instanceof FieldtypeLanguageInterface) { | |
| try { | |
| $valueA = $value->getLanguageValue($lA); | |
| $valueB = $value->getLanguageValue($lB); | |
| if($valueA != $valueB) { | |
| $value->setLanguageValue($lA, $valueB); | |
| $value->setLanguageValue($lB, $valueA); | |
| } | |
| } catch(Exception $e) { | |
| wire('log')->save('swap-lang', "Field {$fieldname} error: " . $e->getMessage()); | |
| } | |
| continue; | |
| } | |
| /* 2 */ | |
| if($type instanceof FieldtypeRepeater && $value->count()) { | |
| foreach($value as $repItem) { | |
| $repItem->of(false); | |
| swapFieldValuesRecursive($repItem, $lA, $lB); | |
| $repItem->save(); | |
| $repItem->of(true); | |
| } | |
| continue; | |
| } | |
| /* 3 */ | |
| if($type instanceof FieldtypeRepeaterMatrix && $value->count()) { | |
| foreach($value as $matrixItem) { | |
| $matrixItem->of(false); | |
| swapFieldValuesRecursive($matrixItem, $lA, $lB); | |
| $matrixItem->save(); | |
| $matrixItem->of(true); | |
| } | |
| continue; | |
| } | |
| // Ignore all other field types... | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment