diff --git a/roles/ensure-babel/README.rst b/roles/ensure-babel/README.rst
new file mode 100644
index 000000000..e8dc70f57
--- /dev/null
+++ b/roles/ensure-babel/README.rst
@@ -0,0 +1,7 @@
+Ensure babel is installed
+
+**Role Variables**
+
+.. zuul:rolevar:: constraints_file
+
+   Optional path to a pip constraints file for installing python libraries.
diff --git a/roles/ensure-babel/tasks/main.yaml b/roles/ensure-babel/tasks/main.yaml
new file mode 100644
index 000000000..df43502b3
--- /dev/null
+++ b/roles/ensure-babel/tasks/main.yaml
@@ -0,0 +1,36 @@
+- name: Install gettext package
+  package:
+    name: gettext
+    state: present
+  become: yes
+
+- name: Check to see if the constraints file exists
+  stat:
+    path: "{{ constraints_file }}"
+    get_checksum: false
+    get_mime: false
+    get_md5: false
+  register: stat_results
+  when: constraints_file is defined
+
+- name: Fail if constraints file does not exist
+  fail:
+    msg: "Variable constraints_file is set but file does not exist."
+  when:
+    - constraints_file is defined
+    - not stat_results|skipped and not stat_results.stat.exists
+
+- name: Record file location
+  set_fact:
+    upper_constraints: "-c {{ constraints_file }}"
+  when: not stat_results|skipped and stat_results.stat.exists
+
+- name: Install babel
+  pip:
+    name:
+      - pbr
+      - Babel
+      - lxml
+      - requests
+    virtualenv: "{{ ansible_user_dir }}/.venv"
+    extra_args: "{{ upper_constraints|default(omit) }}"