diff --git a/packaging/univention-ucs-translation-template/base_makefile b/packaging/univention-ucs-translation-template/base_makefile
new file mode 100644
index 0000000..47d531a
--- /dev/null
+++ b/packaging/univention-ucs-translation-template/base_makefile
@@ -0,0 +1,49 @@
+#!/usr/bin/make -f
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 Univention GmbH
+#
+# http://www.univention.de/
+#
+# All rights reserved.
+#
+# The source code of this program is made available
+# under the terms of the GNU Affero General Public License version 3
+# (GNU AGPL V3) as published by the Free Software Foundation.
+#
+# Binary versions of this program provided by Univention to you as
+# well as other copyrighted, protected or trademarked materials like
+# Logos, graphics, fonts, specific documentations and configurations,
+# cryptographic keys etc. are subject to a license agreement between
+# you and Univention and not subject to the GNU AGPL V3.
+#
+# In the case you use this program under the terms of the GNU AGPL V3,
+# the program is provided in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License with the Debian GNU/Linux or Univention distribution in file
+# /usr/share/common-licenses/AGPL-3; if not, see
+# .
+
+# This Makefile is copied to translation source packages generated by
+# univention-ucs-translation-build-package. It defines the receipts to build
+# binary translation targets(mo files). The include 'all_targets.mk' is
+# generated by the same script and contains all actual targets.
+
+include all_targets.mk
+
+%.mo:
+	mkdir -p $(@D)
+	msgfmt --check --output-file="$@" "$<"
+
+%.json:
+	dh-umc-po2json "$<"  # creates .json file in the same directory as the .po file
+	mkdir -p $(@D)
+	mv "$(patsubst %.po,%.json,$<)" "$@"
+
+build:
+
+install: $(ALL_TARGETS)
diff --git a/packaging/univention-ucs-translation-template/debian/univention-ucs-translation-template.install b/packaging/univention-ucs-translation-template/debian/univention-ucs-translation-template.install
index 1b1e420..ebc82ef 100644
--- a/packaging/univention-ucs-translation-template/debian/univention-ucs-translation-template.install
+++ b/packaging/univention-ucs-translation-template/debian/univention-ucs-translation-template.install
@@ -1,4 +1,6 @@
 translationhelper.py usr/share/pyshared/univention
 specialcases.json usr/share/univention-ucs-translation-template
-univention-ucs-translation-build-package.py usr/bin
+base_makefile usr/share/univention-ucs-translation-template
+univention-ucs-translation-merge usr/bin
+univention-ucs-translation-build-package usr/bin
 univention-ucs-translation-fakemessage usr/bin
diff --git a/packaging/univention-ucs-translation-template/test0.py b/packaging/univention-ucs-translation-template/test0.py
new file mode 100755
index 0000000..c43122a
--- /dev/null
+++ b/packaging/univention-ucs-translation-template/test0.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+import os
+import fnmatch
+import random
+import subprocess
+import sys
+import shutil
+import polib
+import logging
+from pdb import set_trace as dbg
+
+
+class InvalidCommandError(Exception):
+	pass
+
+
+def _get_matching_file_paths(path, pattern):
+	"""Recursively walk through path and match file paths with pattern,
+	return matches"""
+	matched_files_paths = list()
+	for dirname, dns, fnames in os.walk(path):
+		for fn in fnames:
+			matched_files_paths.append(os.path.join(dirname, fn))
+	return fnmatch.filter(matched_files_paths, pattern)
+
+
+def _call(*command_parts):
+	if not command_parts:
+		raise InvalidCommandError()
+	try:
+		subprocess.check_call([part for part in command_parts])
+	except subprocess.CalledProcessError as exc:
+		print('Error: Subprocess exited unsuccessfully. Attempted command:')
+		print(' '.join(exc.cmd))
+		raise InvalidCommandError()
+	except AttributeError as exc:
+		print('Command must be a string like object.')
+		raise InvalidCommandError()
+	except OSError as exc:
+		print('Error: {}'.format(exc.strerror))
+		print('Error: failed to start subprocess.')
+		raise InvalidCommandError()
+
+
+def _change_generated_fuzzy_entries(changed_entry, po_file_path):
+	po_file = polib.pofile(po_file_path)
+	found_change = False
+	for fuzzy in po_file.fuzzy_entries():
+		if fuzzy.occurrences == changed_entry.occurrences:
+			found_change = True
+		else:
+			print('DBG: fuzzy entry not produced by test.')
+			sys.exit(1)
+	return found_change
+
+
+def _remove_fuzzy_flags(po_file_path):
+	po_file = polib.pofile(po_file_path)
+	for fuzzy_entry in po_file.fuzzy_entries():
+		fuzzy_entry.flags.remove('fuzzy')
+	po_file.save()
+
+
+def _change_entry_in_source_file(module_path, po_entry):
+	for source_file, line_number in po_entry.occurrences:
+		source_file = os.path.join('svn_repo', module_path, source_file)
+		original_source_file = '{}.orig'.format(source_file)
+		os.rename(source_file, original_source_file)
+		with open(source_file, 'w') as changed_js:
+			with open(original_source_file, 'r') as fd:
+				for i, line in enumerate(fd):
+					if i == int(line_number) - 1:
+						logging.info('Changing {} in line {}'.format(source_file, line_number))
+						line = line.replace(po_entry.msgid, 'TEST! {}'.format(po_entry.msgid))
+					changed_js.write(line)
+
+
+TRANSLATION_PKG_NAME = 'univention-ucs-translation-XX'
+if __name__ == '__main__':
+	# _call('svn', 'checkout', 'http://forge.univention.org/svn/dev/branches/ucs-4.1/ucs-4.1-1/management/univention-management-console-module-passwordchange/', 'svn_repo')
+	try:
+		shutil.rmtree('svn_repo')
+		shutil.rmtree(TRANSLATION_PKG_NAME)
+	except Exception:
+		pass
+
+	try:
+		_call('svn', 'checkout', 'http://forge.univention.org/svn/dev/branches/ucs-4.1/ucs-4.1-1/management/univention-management-console-module-passwordchange/', 'svn_repo/management/univention-management-console-module-passwordchange')
+		_call('univention-ucs-translation-build-package', '--source=svn_repo', '--languagecode=XX', '--locale=fr_FR.UTF-8:UTF-8', '--languagename=TEST0')
+		_call('univention-ucs-translation-fakemessage', TRANSLATION_PKG_NAME)
+	except InvalidCommandError:
+		print('Error: Tried to launch invalid command. Exiting.')
+		sys.exit(1)
+
+	# Choose js files to manipulate
+	js_po_files = _get_matching_file_paths(TRANSLATION_PKG_NAME, '*umc*js*.po')
+	choosen_po_path = random.choice(js_po_files)
+	module_path = '/'.join(choosen_po_path.split('/')[2:4])
+	choosen_po = polib.pofile(choosen_po_path)
+	random_entry = random.choice(choosen_po)
+
+	_change_entry_in_source_file(module_path, random_entry)
+	_call('univention-ucs-translation-merge', 'XX', 'svn_repo', TRANSLATION_PKG_NAME)
+
+	if _change_generated_fuzzy_entries(random_entry, choosen_po_path):
+		print('Test: Success: fuzzy entries found!')
+	else:
+		print('FAILED: There should be fuzzy entries for this change.')
+
+	_remove_fuzzy_flags(choosen_po_path)
+	_call('svn', 'revert', '--recursive', 'svn_repo/management/univention-management-console-module-passwordchange')
+	_call('univention-ucs-translation-merge', 'XX', 'svn_repo', TRANSLATION_PKG_NAME)
+
+	_remove_fuzzy_flags(choosen_po_path)
+	# Should be same as build + fakemassage
+	# TODO: Test for this..
diff --git a/packaging/univention-ucs-translation-template/translationhelper.py b/packaging/univention-ucs-translation-template/translationhelper.py
index 9cbb9e8..1728f6a 100644
--- a/packaging/univention-ucs-translation-template/translationhelper.py
+++ b/packaging/univention-ucs-translation-template/translationhelper.py
@@ -44,26 +44,6 @@ MODULE_BLACKLIST = [
 	'0001-6-7'
 ]
 
-MAKEFILE_HEADER = """#!/usr/bin/make -f
-
-%.mo:
-	mkdir -p $(@D)
-	msgfmt --check --output-file="$@" "$<"
-
-%.json:
-	#python -c "import univention.dh_umc as dhumc; dhumc.create_json_file('$<')"
-	dh-umc-po2json "$<"  # creates .json file in the same directory as the .po file
-	mkdir -p $(@D)
-	mv "$(patsubst %.po,%.json,$<)" "$@"
-	#install -D $($<:.po=.json) "$@"
-
-"""
-
-MAKEFILE_END = """build:
-
-install: $(ALL_TARGETS)
-"""
-
 
 class UMCModuleTranslation(dh_umc.UMC_Module):
 	def __init__(self, attrs, target_language):
@@ -96,7 +76,7 @@ class UMCModuleTranslation(dh_umc.UMC_Module):
 		try:
 			module = UMCModuleTranslation._get_core_module_from_source_package(module_in_source_tree, target_language)
 		except AttributeError as e:
-			print "%s core module load failed" % str(e)
+			print("%s core module load failed" % str(e))
 			# TODO: Module not loaded at all --> exception?
 		else:
 			print("Successfully loaded as core module: {}".format(module_in_source_tree.get('abs_path_to_src_pkg')))
@@ -134,7 +114,8 @@ class UMCModuleTranslation(dh_umc.UMC_Module):
 		attrs['relative_path_src_pkg'] = module.get('relative_path_src_pkg')
 		return UMCModuleTranslation(attrs, target_language)
 
-#TODO: actually.. (module, output_dir)
+
+# TODO: actually.. (module, output_dir)
 def update_package_translation_files(module, output_dir):
 	print("Creating directories and PO files for {module_name} in translation source package".format(**module))
 	start_dir = os.getcwd()
@@ -154,7 +135,7 @@ def update_package_translation_files(module, output_dir):
 					try:
 						dh_umc.create_po_file(new_po_file_abs_path, module['module_name'], src_files)
 					except dh_umc.Error as exc:
-						print str(exc)
+						print(str(exc))
 
 			# build python po files
 			_create_po_files(module.python_po_files, module.python_files)
@@ -168,11 +149,11 @@ def update_package_translation_files(module, output_dir):
 			try:
 				dh_umc.module_xml2po(module, po_file_full_path, lang)
 			except dh_umc.Error as exc:
-				print str(exc)
+				print(str(exc))
 
 	except OSError as exc:
-		print traceback.format_exc()
-		print "error in update_package_translation_files: %s" % (exc,)
+		print(traceback.format_exc())
+		print("error in update_package_translation_files: %s" % (exc,))
 	finally:
 		os.chdir(start_dir)
 	return abs_path_translated_src_pkg
@@ -195,12 +176,11 @@ def write_makefile(all_modules, special_cases, new_package_dir, target_language)
 
 	for scase in special_cases:
 		_append_to_target_lists(scase.get('mo_destination'), '{lang}/{po_subdir}/{lang}.po'.format(lang=target_language, **scase))
-	with open(os.path.join(new_package_dir, 'Makefile'), 'w') as fd:
-		fd.writelines(MAKEFILE_HEADER)
+	with open(os.path.join(new_package_dir, 'all_targets.mk'), 'w') as fd:
+		fd.write("# This file is auto-generated by univention-ucs-translation-build-package and should not be edited!\n\n")
 		fd.write('ALL_TARGETS = {}\n\n'.format(' \\\n\t'.join(mo_targets_list)))
 		fd.write('\n'.join(target_prerequisite))
 		fd.write('\n')
-		fd.writelines(MAKEFILE_END)
 
 
 # special case e.g. univention-management-modules-frontend: translation files are built with a makefile
@@ -212,7 +192,7 @@ def translate_special_case(special_case, source_dir, target_language, output_dir
 	# TODO: Checks whether a special case is valid should be done on special case parsing
 	path_src_pkg = os.path.join(source_dir, special_case.get('package_dir'))
 	if not os.path.isdir(path_src_pkg):
-		# TODO: Exception 
+		# TODO: Exception
 		return
 
 	new_po_path = os.path.join(output_dir, special_case.get('po_subdir'))
@@ -229,17 +209,22 @@ def translate_special_case(special_case, source_dir, target_language, output_dir
 	if not matches:
 		# TODO: Exception
 		print('Error: specialcase for {} didn\'t match any files.'.format(special_case.get('package_dir')))
+	# FIXME: create_po should handle path itself?
+	cwd = os.getcwd()
+	os.chdir(path_src_pkg)
 	try:
+		matches = [os.path.relpath(match, start=os.getcwd()) for match in matches]
 		dh_umc.create_po_file(new_po_path, special_case.get('package_name'), matches)
 	except dh_umc.Error as exc:
 		repr(exc)
 	except TypeError as exc:
 		repr(exc)
+	os.chdir(cwd)
 
 
 def find_base_translation_modules(startdir, source_dir, module_basefile_name):
-	print 'looking in %s' % source_dir
-	print 'looking for files matching %s' % module_basefile_name
+	print('looking in %s' % source_dir)
+	print('looking for files matching %s' % module_basefile_name)
 	os.chdir(source_dir)
 	matches = []
 	for root, dirnames, filenames in os.walk('.'):
@@ -250,18 +235,18 @@ def find_base_translation_modules(startdir, source_dir, module_basefile_name):
 
 	regex = re.compile(".*/(.*)/debian/.*%s$" % re.escape(module_basefile_name))
 	for match in matches:
-		print match
+		print(match)
 		packagenameresult = regex.search(match)
 		if packagenameresult:
 			packagename = packagenameresult.group(1)
 
 			modulename = os.path.basename(match.replace(module_basefile_name, ''))
 			if modulename in MODULE_BLACKLIST:
-				print "Ignoring module %s: Module is blacklisted\n" % modulename
+				print("Ignoring module %s: Module is blacklisted\n" % modulename)
 				continue
 
 			package_dir = os.path.dirname(os.path.dirname(match))
-			print "Found package: %s" % package_dir
+			print("Found package: %s" % package_dir)
 			module = {}
 			module['module_name'] = modulename
 			module['binary_package_name'] = packagename
@@ -269,7 +254,7 @@ def find_base_translation_modules(startdir, source_dir, module_basefile_name):
 			module['relative_path_src_pkg'] = os.path.relpath(package_dir)
 			base_translation_modules.append(module)
 		else:
-			print "could not obtain packagename from directory %s" % match
+			print("could not obtain packagename from directory %s" % match)
 
 	os.chdir(startdir)
 	return base_translation_modules
@@ -278,7 +263,7 @@ def find_base_translation_modules(startdir, source_dir, module_basefile_name):
 def create_new_package(new_package_dir, target_language, target_locale, language_name, startdir):
 	new_package_dir_debian = os.path.join(new_package_dir, 'debian')
 	if not os.path.exists(new_package_dir_debian):
-		print "creating directory: %s" % new_package_dir_debian
+		print("creating directory: %s" % new_package_dir_debian)
 		os.makedirs(new_package_dir_debian)
 
 	translation_package_name = "univention-ucs-translation-%s" % target_language
@@ -409,7 +394,8 @@ usr/share/univention-management-console/i18n/%(lang)s
 usr/share/locale/%(lang)s/LC_MESSAGES
 """ % language_dict)
 
-	### Move source files and installed .mo files to new package dir
+	shutil.copyfile('/usr/share/univention-ucs-translation-template/base_makefile', os.path.join(new_package_dir, 'Makefile'))
+	# Move source files and installed .mo files to new package dir
 	if os.path.exists(os.path.join(new_package_dir, 'usr')):
 		shutil.rmtree(os.path.join(new_package_dir, 'usr'))
 	#shutil.copytree(os.path.join(startdir, 'usr'), os.path.join(new_package_dir, 'usr'))
@@ -419,4 +405,3 @@ usr/share/locale/%(lang)s/LC_MESSAGES
 		shutil.rmtree(os.path.join(new_package_dir, target_language))
 	shutil.copytree(os.path.join(startdir, target_language), os.path.join(new_package_dir, target_language))
 	shutil.rmtree(os.path.join(startdir, target_language))
-
diff --git a/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package b/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package
new file mode 100755
index 0000000..957295c
--- /dev/null
+++ b/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2013-2014 Univention GmbH
+#
+# http://www.univention.de/
+#
+# All rights reserved.
+#
+# The source code of this program is made available
+# under the terms of the GNU Affero General Public License version 3
+# (GNU AGPL V3) as published by the Free Software Foundation.
+#
+# Binary versions of this program provided by Univention to you as
+# well as other copyrighted, protected or trademarked materials like
+# Logos, graphics, fonts, specific documentations and configurations,
+# cryptographic keys etc. are subject to a license agreement between
+# you and Univention and not subject to the GNU AGPL V3.
+#
+# In the case you use this program under the terms of the GNU AGPL V3,
+# the program is provided in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License with the Debian GNU/Linux or Univention distribution in file
+# /usr/share/common-licenses/AGPL-3; if not, see
+# .
+
+from optparse import OptionParser
+
+import os
+import json
+import univention.dh_umc as dh_umc
+import univention.translationhelper as tlh
+
+
+SPECIALCASES_PATH = "/usr/share/univention-ucs-translation-template/specialcases.json"
+
+
+if __name__ == '__main__':
+	usage = '''%prog [options] -s source_dir -c language_code -l locale -n language_name
+e.g.: -s /path/to/ucs-repository/ -c de -l de_DE.UTF-8:UTF-8 -n Deutsch'''
+	parser = OptionParser(usage=usage)
+	parser.add_option('-s', '--source', action='store', dest='source_dir', help='UCS source dir from which translation files are gathered, e.g. an UCS svn base dir')
+	parser.add_option('-c', '--languagecode', action='store', dest='target_language', help='Target language code (e.g. de)')
+	parser.add_option('-b', '--basefiles', action='store', dest='basefiles', default='.umc-modules', help='xml file basename (default: .umc-modules)')
+	parser.add_option('-l', '--locale', action='store', dest='target_locale', help='Target locale (e.g. de_DE.UTF-8:UTF-8)')
+	parser.add_option('-n', '--languagename', action='store', dest='target_name', help='Language name that is shown in the UMC (e.g. Deutsch)')
+
+	(options, args) = parser.parse_args()
+	help_message = 'Use --help to show additional help.'
+
+	if not options.source_dir:
+		parser.error('Missing argument -s. %s' % help_message)
+
+	if not options.target_language:
+		parser.error('Missing argument -c. %s' % help_message)
+
+	if not options.target_locale:
+		parser.error('Missing argument -l. %s' % help_message)
+
+	if not options.target_name:
+		parser.error('Missing argument -n. %s' % help_message)
+
+	options.source_dir = os.path.abspath(options.source_dir)
+	# find all module files and move them to a language specific directory
+	startdir = os.getcwd()
+	base_translation_modules = tlh.find_base_translation_modules(startdir, options.source_dir, options.basefiles)
+	dh_umc.LANGUAGES = (options.target_language, )
+	all_modules = list()
+	output_dir = os.path.join(os.getcwd(), options.target_language)
+	for module_attrs in base_translation_modules:
+		module = tlh.UMCModuleTranslation.from_source_package(module_attrs, options.target_language)
+		all_modules.append(module)
+		abs_path_translated_src_pkg = tlh.update_package_translation_files(module, output_dir)
+
+	# special cases, e.g. univention-management-console-frontend
+	special_cases = []
+	if os.path.exists(SPECIALCASES_PATH):
+		with open(SPECIALCASES_PATH, 'rb') as fd:
+			special_cases = json.load(fd)
+	else:
+		print("Error: Could not find file {}. Several files will not be handled.".format(SPECIALCASES_PATH))
+
+	for s_case in special_cases:
+		tlh.translate_special_case(s_case, options.source_dir, options.target_language, output_dir)
+
+	# create new package
+	new_package_dir = os.path.join(startdir, 'univention-ucs-translation-%s' % options.target_language)
+	tlh.create_new_package(new_package_dir, options.target_language, options.target_locale, options.target_name, startdir)
+	tlh.write_makefile(all_modules, special_cases, new_package_dir, options.target_language)
diff --git a/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package.py b/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package.py
deleted file mode 100755
index 9e0de51..0000000
--- a/packaging/univention-ucs-translation-template/univention-ucs-translation-build-package.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright 2013-2014 Univention GmbH
-#
-# http://www.univention.de/
-#
-# All rights reserved.
-#
-# The source code of this program is made available
-# under the terms of the GNU Affero General Public License version 3
-# (GNU AGPL V3) as published by the Free Software Foundation.
-#
-# Binary versions of this program provided by Univention to you as
-# well as other copyrighted, protected or trademarked materials like
-# Logos, graphics, fonts, specific documentations and configurations,
-# cryptographic keys etc. are subject to a license agreement between
-# you and Univention and not subject to the GNU AGPL V3.
-#
-# In the case you use this program under the terms of the GNU AGPL V3,
-# the program is provided in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License with the Debian GNU/Linux or Univention distribution in file
-# /usr/share/common-licenses/AGPL-3; if not, see
-# .
-
-from optparse import OptionParser
-
-import os
-import json
-import univention.dh_umc as dh_umc
-import univention.translationhelper as tlh
-
-
-SPECIALCASES_PATH = "/usr/share/univention-ucs-translation-template/specialcases.json"
-
-
-if __name__ == '__main__':
-	usage = '''%prog [options] -s source_dir -c language_code -l locale -n language_name
-e.g.: -s /path/to/ucs-repository/ -c de -l de_DE.UTF-8:UTF-8 -n Deutsch'''
-	parser = OptionParser(usage=usage)
-	parser.add_option('-s', '--source', action='store', dest='source_dir', help='UCS source dir from which translation files are gathered, e.g. an UCS svn base dir')
-	parser.add_option('-c', '--languagecode', action='store', dest='target_language', help='Target language code (e.g. de)')
-	parser.add_option('-b', '--basefiles', action='store', dest='basefiles', default='.umc-modules', help='xml file basename (default: .umc-modules)')
-	parser.add_option('-l', '--locale', action='store', dest='target_locale', help='Target locale (e.g. de_DE.UTF-8:UTF-8)')
-	parser.add_option('-n', '--languagename', action='store', dest='target_name', help='Language name that is shown in the UMC (e.g. Deutsch)')
-
-	(options, args) = parser.parse_args()
-	help_message = 'Use --help to show additional help.'
-
-	if not options.source_dir:
-		parser.error('Missing argument -s. %s' % help_message)
-
-	if not options.target_language:
-		parser.error('Missing argument -c. %s' % help_message)
-
-	if not options.target_locale:
-		parser.error('Missing argument -l. %s' % help_message)
-
-	if not options.target_name:
-		parser.error('Missing argument -n. %s' % help_message)
-
-	options.source_dir = os.path.abspath(options.source_dir)
-	# find all module files and move them to a language specific directory
-	startdir = os.getcwd()
-	base_translation_modules = tlh.find_base_translation_modules(startdir, options.source_dir, options.basefiles)
-	dh_umc.LANGUAGES = (options.target_language, )
-	all_modules = list()
-	output_dir = os.path.join(os.getcwd(), options.target_language)
-	for module_attrs in base_translation_modules:
-		module = tlh.UMCModuleTranslation.from_source_package(module_attrs, options.target_language)
-		all_modules.append(module)
-		abs_path_translated_src_pkg = tlh.update_package_translation_files(module, output_dir)
-
-	# special cases, e.g. univention-management-console-frontend
-	special_cases = []
-	if os.path.exists(SPECIALCASES_PATH):
-		with open(SPECIALCASES_PATH, 'rb') as fd:
-			special_cases = json.load(fd)
-	else:
-		print "Error: Could not find file %s. Several files will not be handled." % SPECIALCASES_PATH
-
-	for s_case in special_cases:
-		tlh.translate_special_case(s_case, options.source_dir, options.target_language, output_dir)
-
-	# create new package
-	new_package_dir = os.path.join(startdir, 'univention-ucs-translation-%s' % options.target_language)
-	tlh.create_new_package(new_package_dir, options.target_language, options.target_locale, options.target_name, startdir)
-	tlh.write_makefile(all_modules, special_cases, new_package_dir, options.target_language)
diff --git a/packaging/univention-ucs-translation-template/univention-ucs-translation-fakemessage b/packaging/univention-ucs-translation-template/univention-ucs-translation-fakemessage
index f6405c9..d074aa0 100755
--- a/packaging/univention-ucs-translation-template/univention-ucs-translation-fakemessage
+++ b/packaging/univention-ucs-translation-template/univention-ucs-translation-fakemessage
@@ -37,15 +37,16 @@ USAGE = """
 Usage: univention-ucs-translation-fakemessage [directory]
 
 This script walks over all po files in a given directory and its subfolders.
-It fills all msgid strings to the corresponding msgid and prepeding it with a
-character sequence '!TR!'.
+It fills all msgid strings with the same content as the corresponding msgid,
+prepeding it with the character sequence '!TR!'.
 It is useful for visual quick testing of translation coverage and po file
 generation.
 """
 
+
 def main(po_dir):
 	for _dir, dns, fns in os.walk(os.path.abspath(po_dir)):
-		for po_file in fnmatch.filter(fns, '*po'):
+		for po_file in fnmatch.filter(fns, '*.po'):
 			po = polib.pofile(os.path.join(_dir, po_file))
 			for entry in po:
 				if entry.msgid == '':
diff --git a/packaging/univention-ucs-translation-template/univention-ucs-translation-merge b/packaging/univention-ucs-translation-template/univention-ucs-translation-merge
index 0b93217..e5a8aa9 100755
--- a/packaging/univention-ucs-translation-template/univention-ucs-translation-merge
+++ b/packaging/univention-ucs-translation-template/univention-ucs-translation-merge
@@ -29,12 +29,14 @@
 # .
 import argparse
 import fnmatch
-import polib
 import os
 import sys
+import shutil
 import univention.translationhelper as tlh
 import univention.dh_umc as dh_umc
 import json
+import subprocess
+from pdb import set_trace as dbg
 
 SPECIALCASES_PATH = "/usr/share/univention-ucs-translation-template/specialcases.json"
 
@@ -50,6 +52,17 @@ def _get_po_files_from_dir(directory, return_relative_path=False):
 	return po_files
 
 
+def _msgmerge(source, destination):
+	try:
+		subprocess.check_call(['msgmerge', '--update', '--sort-output', destination, source])
+	except TypeError:
+		print('Error: arguments must be names of existing files. Exiting.')
+		sys.exit(1)
+	except subprocess.CalledProcessError:
+		print('Error: PO file merge failed. Exiting.')
+		sys.exit(1)
+
+
 def merge_po_file_trees(source_tree, target_tree):
 	upstream_pos = _get_po_files_from_dir(source_tree, return_relative_path=True)
 	translated_pos = _get_po_files_from_dir(target_tree, return_relative_path=True)
@@ -62,16 +75,18 @@ def merge_po_file_trees(source_tree, target_tree):
 	# add new
 	for new_po in new_pos:
 		new_po_path = os.path.join(target_tree, new_po)
-		os.makedirs(os.path.dirname(new_po_path))
+		try:
+			os.makedirs(os.path.dirname(new_po_path))
+		except OSError as exc:
+			if not exc.errno == 17:
+				raise
+			pass
 		os.rename(os.path.join(source_tree, new_po), new_po_path)
+		upstream_pos.remove(new_po)
 	# merge upstream changes...
-	for dir, dirs, files in os.walk(target_tree):
-		for po_file in fnmatch.filter([os.path.join(dir, fn) for fn in files], '*.po'):
-			translated = polib.pofile(po_file)
-			upstream = polib.pofile(po_file.replace(target_tree, source_tree))
-			translated.merge(upstream)
-			translated.save()
-
+	for po_file in upstream_pos:
+		_msgmerge(os.path.join(source_tree, po_file), os.path.join(target_tree, po_file))
+	return pos_delete_upstream, new_pos
 
 if __name__ == '__main__':
 	parser = argparse.ArgumentParser(description="Merge upstream changes in translation files to existing translation source package.")
@@ -91,8 +106,10 @@ if __name__ == '__main__':
 	dh_umc.LANGUAGES = (args.lang_code, )
 	modules_upstream = tlh.find_base_translation_modules(os.getcwd(), args.upstream, '.umc-modules')
 	output_dir = os.path.join(args.translation, '{}_merge'.format(args.lang_code))
+	modules = list()
 	for module_attrs in modules_upstream:
 		module = tlh.UMCModuleTranslation.from_source_package(module_attrs, args.lang_code)
+		modules.append(module)
 		tlh.update_package_translation_files(module, output_dir)
 	# special cases, e.g. univention-management-console-frontend
 	special_cases = []
@@ -100,9 +117,18 @@ if __name__ == '__main__':
 		with open(SPECIALCASES_PATH, 'rb') as fd:
 			special_cases = json.load(fd)
 	else:
-		print "Error: Could not find file %s. Several files will not be handled." % SPECIALCASES_PATH
+		print("Error: Could not find file {}.\nSeveral files will not be handled.".format(SPECIALCASES_PATH))
 
 	for scase in special_cases:
 		tlh.translate_special_case(scase, args.upstream, args.lang_code, output_dir)
 
-	merge_po_file_trees(output_dir, os.path.join(args.translation, args.lang_code))
+	removed, new = merge_po_file_trees(output_dir, os.path.join(args.translation, args.lang_code))
+	print('Merge summary: ')
+	if removed:
+		print('Following files have been removed:')
+		print('\n'.join(removed))
+	if new:
+		print('Following files habe been added:')
+		print('\n'.join(new))
+	shutil.rmtree(output_dir)
+	tlh.write_makefile(modules, special_cases, args.translation, args.lang_code)