One way to do this is to create a macro operator, with the transform operator being the first component, and a second custom operator for running your finalizing code, once the modal operator is finished.
Unfortunately the macro API is barely documented, so here is a minimum example script:
import bpy
from bpy.types import Operator, Macro
# Our finalizing operator, shall run after transform
class Finalize(Operator):
bl_idname = "test.finalize"
bl_label = "Finalize"
def execute(self, context):
print("DONE!")
return {'FINISHED'}
# Macro operator to concatenate transform and our finalization
class Test(Macro):
bl_idname = "TEST_OT_Test"
bl_label = "Test"
# Note that we have to register classes first before populating
# the Macro operator
bpy.utils.register_class(Finalize)
bpy.utils.register_class(Test)
# The important bit: populate the macro operator with a sequence
# of existing other operators
Test.define("transform.translate")
Test.define("test.finalize")
You can run this script and then test it in the viewport via the spacebar menu.
One more note: if the transform operator is cancelled, so is the macro operator, i.e. in case of cancelling the second operator will never run. If that is necessary for some reason you could make a wrapper around the existing transform operator, which then implements own behavior in the cancel(self, context)
function.