diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py
index ace6504ffe..4e77aaece4 100644
--- a/django/templatetags/i18n.py
+++ b/django/templatetags/i18n.py
@@ -96,7 +96,7 @@ class TranslateNode(Node):
 class BlockTranslateNode(Node):
 
     def __init__(self, extra_context, singular, plural=None, countervar=None,
-            counter=None, message_context=None, trimmed=False):
+            counter=None, message_context=None, trimmed=False, asvar=None):
         self.extra_context = extra_context
         self.singular = singular
         self.plural = plural
@@ -104,6 +104,7 @@ class BlockTranslateNode(Node):
         self.counter = counter
         self.message_context = message_context
         self.trimmed = trimmed
+        self.asvar = asvar
 
     def render_token_list(self, tokens):
         result = []
@@ -166,7 +167,11 @@ class BlockTranslateNode(Node):
                     "string returned by gettext: %r using %r" % (result, data))
             with translation.override(None):
                 result = self.render(context, nested=True)
-        return result
+        if self.asvar:
+            context[self.asvar] = result
+            return ''
+        else:
+            return result
 
 
 class LanguageNode(Node):
@@ -429,6 +434,13 @@ def do_block_translate(parser, token):
         {% blocktrans with foo|filter as bar and baz|filter as boo %}
         {% blocktrans count var|length as count %}
 
+    The translated string can be stored in a variable using `asvar`::
+
+        {% blocktrans with bar=foo|filter boo=baz|filter asvar var %}
+        This is {{ bar }} and {{ boo }}.
+        {% endblocktrans %}
+        {{ var }}
+
     Contextual translations are supported::
 
         {% blocktrans with bar=foo|filter context "greeting" %}
@@ -442,6 +454,7 @@ def do_block_translate(parser, token):
 
     options = {}
     remaining_bits = bits[1:]
+    asvar = None
     while remaining_bits:
         option = remaining_bits.pop(0)
         if option in options:
@@ -468,6 +481,13 @@ def do_block_translate(parser, token):
                 six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
         elif option == "trimmed":
             value = True
+        elif option == "asvar":
+            try:
+                value = remaining_bits.pop(0)
+            except IndexError:
+                msg = "No argument provided to the '%s' tag for the asvar option." % bits[0]
+                six.reraise(TemplateSyntaxError, TemplateSyntaxError(msg), sys.exc_info()[2])
+            asvar = value
         else:
             raise TemplateSyntaxError('Unknown argument for %r tag: %r.' %
                                       (bits[0], option))
@@ -506,7 +526,8 @@ def do_block_translate(parser, token):
         raise TemplateSyntaxError("'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents)
 
     return BlockTranslateNode(extra_context, singular, plural, countervar,
-                              counter, message_context, trimmed=trimmed)
+                              counter, message_context, trimmed=trimmed,
+                              asvar=asvar)
 
 
 @register.tag
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 9f2dd6ccd1..b80d14f985 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -332,6 +332,9 @@ Internationalization
   project and it will find all the app message files that were created by
   :djadmin:`makemessages`.
 
+* :ttag:`blocktrans` supports assigning its output to a variable using
+  ``asvar``.
+
 Management Commands
 ^^^^^^^^^^^^^^^^^^^
 
diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt
index 1ab2dae273..e19ee1220b 100644
--- a/docs/topics/i18n/translation.txt
+++ b/docs/topics/i18n/translation.txt
@@ -580,8 +580,9 @@ use the following syntax::
     <title>{{ the_title }}</title>
     <meta name="description" content="{{ the_title }}">
 
-In practice you'll use this to get strings that are used in multiple places
-or should be used as arguments for other template tags or filters::
+In practice you'll use this to get a string you can use in multiple places in a
+template or so you can use the output as an argument for other template tags or
+filters::
 
     {% trans "starting point" as start %}
     {% trans "end point" as end %}
@@ -682,6 +683,21 @@ be retrieved (and stored) beforehand::
     This is a URL: {{ the_url }}
     {% endblocktrans %}
 
+If you'd like to retrieve a translated string without displaying it, you can
+use the following syntax::
+
+    {% blocktrans asvar the_title %}The title is {{ title }}.{% endblocktrans %}
+    <title>{{ the_title }}</title>
+    <meta name="description" content="{{ the_title }}">
+
+In practice you'll use this to get a string you can use in multiple places in a
+template or so you can use the output as an argument for other template tags or
+filters.
+
+.. versionchanged:: 1.9
+
+    The ``asvar`` syntax was added.
+
 ``{% blocktrans %}`` also supports :ref:`contextual
 markers<contextual-markers>` using the ``context`` keyword:
 
diff --git a/tests/template_tests/syntax_tests/test_i18n.py b/tests/template_tests/syntax_tests/test_i18n.py
index e40144e347..68b5793a57 100644
--- a/tests/template_tests/syntax_tests/test_i18n.py
+++ b/tests/template_tests/syntax_tests/test_i18n.py
@@ -435,6 +435,35 @@ class I18nTagTests(SimpleTestCase):
             'fr: French/français/francouzsky bidi=False; '
         )
 
+    # blocktrans tag with asvar
+    @setup({'i18n39': '{% load i18n %}'
+                      '{% blocktrans asvar page_not_found %}Page not found{% endblocktrans %}'
+                      '>{{ page_not_found }}<'})
+    def test_i18n39(self):
+        with translation.override('de'):
+            output = self.engine.render_to_string('i18n39')
+        self.assertEqual(output, '>Seite nicht gefunden<')
+
+    @setup({'i18n40': '{% load i18n %}'
+                      '{% trans "Page not found" as pg_404 %}'
+                      '{% blocktrans with page_not_found=pg_404 asvar output %}'
+                      'Error: {{ page_not_found }}'
+                      '{% endblocktrans %}'})
+    def test_i18n40(self):
+        output = self.engine.render_to_string('i18n40')
+        self.assertEqual(output, '')
+
+    @setup({'i18n41': '{% load i18n %}'
+                      '{% trans "Page not found" as pg_404 %}'
+                      '{% blocktrans with page_not_found=pg_404 asvar output %}'
+                      'Error: {{ page_not_found }}'
+                      '{% endblocktrans %}'
+                      '>{{ output }}<'})
+    def test_i18n41(self):
+        with translation.override('de'):
+            output = self.engine.render_to_string('i18n41')
+        self.assertEqual(output, '>Error: Seite nicht gefunden<')
+
     @setup({'template': '{% load i18n %}{% trans %}A}'})
     def test_syntax_error_no_arguments(self):
         msg = "'trans' takes at least one argument"
@@ -453,6 +482,12 @@ class I18nTagTests(SimpleTestCase):
         with self.assertRaisesMessage(TemplateSyntaxError, msg):
             self.engine.render_to_string('template')
 
+    @setup({'template': '{% load i18n %}{% blocktrans asvar %}Yes{% endblocktrans %}'})
+    def test_blocktrans_syntax_error_missing_assignment(self):
+        msg = "No argument provided to the 'blocktrans' tag for the asvar option."
+        with self.assertRaisesMessage(TemplateSyntaxError, msg):
+            self.engine.render_to_string('template')
+
     @setup({'template': '{% load i18n %}{% trans "Yes" as var context %}'})
     def test_syntax_error_missing_context(self):
         msg = "No argument provided to the 'trans' tag for the context option."