diff -r af6aa15ae9bf django/templatetags/i18n.py
--- a/django/templatetags/i18n.py	Wed Jun 22 12:20:52 2011 +0000
+++ b/django/templatetags/i18n.py	Fri Jun 24 23:12:57 2011 +0200
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 import re
 
 from django.template import Node, Variable, VariableNode
@@ -6,7 +7,7 @@
 from django.template.base import _render_value_in_context
 from django.utils import translation
 from django.utils.encoding import force_unicode
-from django.template.defaulttags import token_kwargs
+from django.template.defaulttags import token_kwargs, kwarg_re, URLNode
 
 register = Library()
 
@@ -117,6 +118,15 @@
         context.pop()
         return result % data
 
+class I18NURLNode(URLNode):
+    def __init__(self, view_name, language, args, kwargs, asvar):
+        super(I18NURLNode, self).__init__(view_name, args, kwargs, asvar, False)
+        self.language = language
+
+    def render(self, context):
+        with translation.override(self.language.resolve(context)):
+            return super(I18NURLNode, self).render(context)
+
 @register.tag("get_available_languages")
 def do_get_available_languages(parser, token):
     """
@@ -366,3 +376,32 @@
 
     return BlockTranslateNode(extra_context, singular, plural, countervar,
             counter)
+
+@register.tag
+def i18n_url(parser, token):
+    bits = token.split_contents()
+    if len(bits) < 3:
+        raise TemplateSyntaxError("'%s' takes at least two arguments"
+                                  " (path to a view and the language)" % bits[0])
+    viewname = parser.compile_filter(bits[1])
+    language = parser.compile_filter(bits[2])
+    args = []
+    kwargs = {}
+    asvar = None
+    bits = bits[3:]
+    if len(bits) >= 2 and bits[-2] == 'as':
+        asvar = bits[-1]
+        bits = bits[:-2]
+
+    if len(bits):
+        for bit in bits:
+            match = kwarg_re.match(bit)
+            if not match:
+                raise TemplateSyntaxError("Malformed arguments to url tag")
+            name, value = match.groups()
+            if name:
+                kwargs[name] = parser.compile_filter(value)
+            else:
+                args.append(parser.compile_filter(value))
+
+    return I18NURLNode(viewname, language, args, kwargs, asvar)
diff -r af6aa15ae9bf docs/topics/http/urls.txt
--- a/docs/topics/http/urls.txt	Wed Jun 22 12:20:52 2011 +0000
+++ b/docs/topics/http/urls.txt	Fri Jun 24 23:12:57 2011 +0200
@@ -28,6 +28,9 @@
 mappings. And, because it's pure Python code, it can be constructed
 dynamically.
 
+Additionally Django allows to translate URLs according to the active language.
+This process is described in the :ref:`internationalization docs <url-internationalization>`.
+
 .. _how-django-processes-a-request:
 
 How Django processes a request
diff -r af6aa15ae9bf docs/topics/i18n/internationalization.txt
--- a/docs/topics/i18n/internationalization.txt	Wed Jun 22 12:20:52 2011 +0000
+++ b/docs/topics/i18n/internationalization.txt	Fri Jun 24 23:12:57 2011 +0200
@@ -887,6 +887,26 @@
     that a carelessly translated URL causes a collision with a non-translated
     URL pattern.
 
+.. _reversing_in_templates:
+
+Reversing in templates
+----------------------
+
+If localized URLs get reversed in templates they always use the current language.
+To link to an URL in another language an extra tag got added:
+
+.. code-block:: html+django
+
+    {% load i18n %}
+    {% get_available_languages as languages %}
+    View the Homepage in:
+    {% for lang in languages %}
+        <a href="{% i18n_url 'homepage' lang.0 kwarg1=val1 kwarg2=val2 %}">{{ lang.1 }}</a> 
+    {% endfor %}
+
+The ``i18n_url`` tag expects the language after the viewname and otherwise
+like the builtin ``url`` tag.
+
 .. _set_language-redirect-view:
 
 The ``set_language`` redirect view
diff -r af6aa15ae9bf tests/regressiontests/i18n/patterns/tests.py
--- a/tests/regressiontests/i18n/patterns/tests.py	Wed Jun 22 12:20:52 2011 +0000
+++ b/tests/regressiontests/i18n/patterns/tests.py	Fri Jun 24 23:12:57 2011 +0200
@@ -6,6 +6,7 @@
 from django.core.urlresolvers import reverse, clear_url_caches
 from django.test import TestCase
 from django.test.utils import override_settings
+from django.template import Template, Context
 from django.utils import translation
 
 
@@ -241,3 +242,39 @@
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response['content-language'], 'pt-br')
         self.assertEqual(response.context['LANGUAGE_CODE'], 'pt-br')
+
+
+class URLTagTests(URLTestCaseBase):
+    """
+    Test if the i18n_url tag works.
+    """
+    def test_strings_only(self):
+        c = Context({})
+        t = Template("""{% load i18n %}
+                {% i18n_url 'no-prefix-translated' 'nl' %}
+                {% i18n_url 'no-prefix-translated' 'pt-br' %}""")
+        self.assertEqual(t.render(c).strip().split(),
+                         [u'/vertaald/', u'/traduzidos/'])
+
+    def test_context(self):
+        c = Context({'url': 'no-prefix-translated', 'lang1':'nl',
+                     'lang2':'pt-br'})
+        t = Template("""{% load i18n %}
+                {% i18n_url url lang1 %}
+                {% i18n_url url lang2 %}""")
+        self.assertEqual(t.render(c).strip().split(),
+                         [u'/vertaald/', u'/traduzidos/'])
+
+    def test_args_and_kwargs(self):
+        c = Context({})
+        t = Template("""{% load i18n %}
+                {% i18n_url 'no-prefix-translated-slug' 'nl' 'apo' %}
+                {% i18n_url 'no-prefix-translated-slug' 'pt-br' 'apo' %}""")
+        self.assertEqual(t.render(c).strip().split(),
+                         [u'/vertaald/apo/', u'/traduzidos/apo/'])
+        t = Template("""{% load i18n %}
+                {% i18n_url 'no-prefix-translated-slug' 'nl' slug='apo' %}
+                {% i18n_url 'no-prefix-translated-slug' 'pt-br' slug='apo' %}""")
+        self.assertEqual(t.render(c).strip().split(),
+                         [u'/vertaald/apo/', u'/traduzidos/apo/'])
+
