diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 8329792..9235a67 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -87,9 +87,9 @@ signals.class_prepared.connect(do_pending_lookups)
 class RelatedField(object):
     def contribute_to_class(self, cls, name):
         sup = super(RelatedField, self)
-
-        # Add an accessor to allow easy determination of the related query path for this field
-        self.related_query_name = curry(self._get_related_query_name, cls._meta)
+        
+        # Store the opts for related_query_name()
+        self.opts = cls._meta
 
         if hasattr(sup, 'contribute_to_class'):
             sup.contribute_to_class(cls, name)
@@ -174,12 +174,12 @@ class RelatedField(object):
             return []
         raise TypeError("Related Field has invalid lookup: %s" % lookup_type)
 
-    def _get_related_query_name(self, opts):
+    def related_query_name(self):
         # This method defines the name that can be used to identify this
         # related object in a table-spanning query. It uses the lower-cased
         # object_name by default, but this can be overridden with the
         # "related_name" option.
-        return self.rel.related_name or opts.object_name.lower()
+        return self.rel.related_name or self.opts.object_name.lower()
 
 class SingleRelatedObjectDescriptor(object):
     # This class provides the functionality that makes the related-object
diff --git a/django/utils/functional.py b/django/utils/functional.py
index e52ab76..6482e44 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -147,6 +147,9 @@ def lazy(func, *resultclasses):
     the lazy evaluation code is triggered. Results are not memoized; the
     function is evaluated on every access.
     """
+    if len(resultclasses) == 1 and isinstance(resultclasses[0], tuple):
+        resultclasses = resultclasses[0]
+    
     class __proxy__(Promise):
         """
         Encapsulate a function call and act as a proxy for methods that are
@@ -161,7 +164,10 @@ def lazy(func, *resultclasses):
             self.__kw = kw
             if self.__dispatch is None:
                 self.__prepare_class__()
-
+        
+        def __reduce_ex__(self, protocol):
+            return (lazy, (self.__func, resultclasses), self.__dict__)
+        
         def __prepare_class__(cls):
             cls.__dispatch = {}
             for resultclass in resultclasses:
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index c0a0df9..da1c938 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -1,7 +1,7 @@
 """
 Internationalization support.
 """
-from django.utils.functional import lazy
+from django.utils.functional import lazy, curry
 from django.utils.encoding import force_unicode
 
 __all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
@@ -19,7 +19,7 @@ __all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
 # replace the functions with their real counterparts (once we do access the
 # settings).
 
-def delayed_loader(*args, **kwargs):
+def delayed_loader(real_name, *args, **kwargs):
     """
     Replace each real_* function with the corresponding function from either
     trans_real or trans_null (e.g. real_gettext is replaced with
@@ -27,24 +27,19 @@ def delayed_loader(*args, **kwargs):
     first time any i18n method is called. It replaces all the i18n methods at
     once at that time.
     """
-    import traceback
     from django.conf import settings
+
     if settings.USE_I18N:
-        import trans_real as trans
+        import django.utils.translation.trans_real as trans
     else:
-        import trans_null as trans
-    caller = traceback.extract_stack(limit=2)[0][2]
-    g = globals()
-    for name in __all__:
-        if hasattr(trans, name):
-            g['real_%s' % name] = getattr(trans, name)
+        import django.utils.translation.trans_null as trans
 
     # Make the originally requested function call on the way out the door.
-    return g['real_%s' % caller](*args, **kwargs)
+    return getattr(trans, real_name)(*args, **kwargs)
 
 g = globals()
 for name in __all__:
-    g['real_%s' % name] = delayed_loader
+    g['real_%s' % name] = curry(delayed_loader, name)
 del g, delayed_loader
 
 def gettext_noop(message):
@@ -102,10 +97,10 @@ def templatize(src):
 def deactivate_all():
     return real_deactivate_all()
 
-def string_concat(*strings):
+def _string_concat(*strings):
     """
     Lazy variant of string concatenation, needed for translations that are
     constructed from multiple parts.
     """
     return u''.join([force_unicode(s) for s in strings])
-string_concat = lazy(string_concat, unicode)
+string_concat = lazy(_string_concat, unicode)
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 31150a6..941f66f 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -46,7 +46,6 @@ class TranslationTests(TestCase):
         unicode(string_concat(...)) should not raise a TypeError - #4796
         """
         import django.utils.translation
-        self.assertEqual(django.utils.translation, reload(django.utils.translation))
         self.assertEqual(u'django', unicode(django.utils.translation.string_concat("dja", "ngo")))
 
     def test_safe_status(self):
