protected function localiseManipulationTable(&$manipulation, $table, $localeTable, $localisedFields, Locale $locale)
    {
        // Skip if manipulation table, or fields, are empty
        if (empty($manipulation[$table]['fields'])) {
            return;
        }

        // Get ID field
        $updates = $manipulation[$table];
        $id = $this->getManipulationRecordID($updates);
        if (!$id) {
            throw new LogicException("Missing record ID for table manipulation {$table}");
        }

        // Copy entire manipulation to the localised table
        $localisedUpdate = $updates;

        // Filter fields by localised fields
        $localisedUpdate['fields'] = array_intersect_key(
            $updates['fields'],
            array_combine($localisedFields, $localisedFields)
        );
        unset($localisedUpdate['fields']['id']);

        // Skip if no fields are being saved after filtering
        if (empty($localisedUpdate['fields'])) {
            return;
        }

        // Populate Locale / RecordID fields
        $localisedUpdate['fields']['RecordID'] = $id;
        $localisedUpdate['fields']['Locale'] = $locale->getLocale();

        // Convert ID filter to RecordID / Locale
        unset($localisedUpdate['id']);
        $localisedUpdate['where'] = [
            "\"{$localeTable}\".\"RecordID\"" => $id,
            "\"{$localeTable}\".\"Locale\"" => $locale->getLocale(),
        ];

        // Save back modifications to the manipulation
        $manipulation[$localeTable] = $localisedUpdate;
    }