You both have the right idea, but you'll actually need both fitlers, one to catch the button text, another to catch the localised text, so a combination of the two.

This works..

	class MyClass {
		function __construct() {
			add_action('admin_head-post.php',     array ( $this, 'load_gettext_filters' ), 1 );
			add_action('admin_head-post-new.php', array ( $this, 'load_gettext_filters' ), 1 );
		}

		function load_gettext_filters() {
			global $post_type, $wp_scripts;
			
			if( 'YOURTYPENAMEHERE' != $post_type )
				return;
			
			$wp_scripts->registered['post']->extra['l10n'][1]['publish'] = __('Save');
			
			add_filter( 'gettext', array ( $this, 'change_publishing_text' ), 10, 2 );
		}

		function change_publishing_text( $translation, $text ) {
			if( 'Publish' != $text )
				return $translation;
				
			return __( 'Save' );
		}
	}
	$MyClass = new MyClass;