diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e7476c4f92d622a9380e449382874205a7db9b4e..da0d42116f92ebd8c1089b8a58cac8667f30c6e1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -65,3 +65,8 @@ html5validator:
     paths:
     - pages
     - html5validator.log
+
+trans_de:
+  stage: test
+  script:
+  - ./update_translations.sh de
diff --git a/update_translations.sh b/update_translations.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c3a80dee35846b29ac14e8768f21beebe51a04e6
--- /dev/null
+++ b/update_translations.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -e
+
+pybabel extract -F uffd/babel.cfg -k lazy_gettext -o messages.pot uffd
+pybabel update -i messages.pot -d uffd/translations
+pybabel compile -d uffd/translations
+
+if [ -n "$1" ]; then
+	NUM_EMPTY="$(tr '\n' '|' < uffd/translations/$1/LC_MESSAGES/messages.po | sed 's/msgstr ""|/empty/g' | tr '|' '\n' | grep '^empty$' | wc -l)"
+	NUM_TOTAL="$(grep '^msgid' uffd/translations/$1/LC_MESSAGES/messages.po | wc -l)"
+	# Emulate python-coverage output
+	echo "TOTAL $NUM_TOTAL $(( $NUM_TOTAL - $NUM_EMPTY )) $(( 100 * ($NUM_TOTAL - $NUM_EMPTY) / $NUM_TOTAL ))%"
+fi