Should an Operator remember its last-used settings when invoked?
1) The dialog is supposed to start with the default settings. A new operator instance is created as you open it, and the default values are taken from the property definitions. The redo panel works differently, it revokes what the last operator did, but keeps the values in the UI and re-executes with new settings.

One could say, the redo panel relates to the last operator, whereas your dialog is part of a new operator.



2) Operators remember their settings to allow for redo / repeat functionality, see Operator Design.

The operator log is available to python:

bpy.context.window_manager.operators

You could read the value used for a translation like Operator.properties.value. But I wouldn't recommend to iterate the log in reverse direction until you find an instance of your operator, just to read the last used settings.

How about this generic solution instead, which stores the settings at python class level:

Use a static variable (dictionary) to store the operator settings on execute(), and load them on invoke() into self.properties. These two methods can be defined together with the static dict as separate class, and be mixed-in into the operator class:

import bpy

class OperatorSettings:

    # Static member
    _settings = {}

    def save_settings(self): 
        for d in dir(self.properties):
            if d in {'bl_rna', 'rna_type'}:
                continue
            try:
                self.__class__._settings[d] = self.properties[d]
            except KeyError:
                # catches __doc__ etc.
                continue

    def load_settings(self):
        # what exception could occur here??
        for d in self.__class__._settings:
            self.properties[d] = self.__class__._settings[d]


class DATA_PT_test(bpy.types.Panel):
    bl_label = "Test Panel"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "data"

    def draw(self, context):
        self.layout.operator("object.test_invoke")


class OBJECT_OT_test_invoke(bpy.types.Operator, OperatorSettings):
    bl_idname = "object.test_invoke"
    bl_label = "Test"
    bl_options = {'REGISTER'}

    width = bpy.props.IntProperty(name="Width", 
            default=10, min=0, max=100)
    height = bpy.props.IntProperty(name="Height", 
            default=20, min=0, max=100)

    def execute(self, context):
        self.report({'INFO'}, "w:{}, h:{}".format(self.width, self.height))
        self.save_settings()
        return {'FINISHED'}

    def invoke(self, context, event):
        self.load_settings()
        wm = context.window_manager
        return wm.invoke_props_dialog(self)

def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()


Should work for base types (int, float, str), but will probably fail for CollectionProperty as it is. But should be possible if you implement (de-)serialization functions for such propert types.

If you add non-property class variables to the operator, make sure to exclude them in save_settings(), or add a type check for all members - see the bl_rna property for that:

self.properties.bl_rna.properties['...'].type # e.g. 'INT'


BTW: I removed 'UNDO' from bl_options 'cause every change in the redo panel causes a re-execution of the operator. This is not the case for the dialog, the operator is run once on confirmation. Such dialogs should be used if an operator takes a long time to finish, to avoid irresponsive UI. So it's probably not supposed to have the redo functionality enabled.



3) There's another approach:

Register global properties (e.g. on bpy.types.Object or bpy.types.WindowManager) and add them to a panel. Let the user set them before (s)he clicks an Execute button. Pass the global properties to the operator. Global properties are remembered, so it works similar to the redo panel.

Example:

import bpy

class PrintSomeString(bpy.types.Operator):
    bl_label = "Print Some String"
    bl_idname = "object.print_some_string"
    bl_options = {'REGISTER', 'UNDO'}

    print_this = bpy.props.StringProperty(name="Print this")

    def execute(self, context):
        self.report({'INFO'}, self.print_this)
        return {'FINISHED'}


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        layout.prop(context.window_manager, "some_string")

        props = layout.operator(PrintSomeString.bl_idname)
        props.print_this = context.window_manager.some_string

        props = layout.operator(PrintSomeString.bl_idname, text="Print welcome message")
        props.print_this = "Welcome to Blender!"

def register():
    bpy.utils.register_module(__name__)
    bpy.types.WindowManager.some_string = bpy.props.StringProperty(name="Some String")


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.WindowManager.some_string


if __name__ == "__main__":
    register()


Paste into Text Editor and Run Script. See Object tab in Properties Editor.