diff git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
index 50b2e2b..336e302 100644
a

b

from django.template import loader 
4  4  from django.utils.encoding import smart_str 
5  5  from django.utils.http import int_to_base36 
6  6  from django.utils.safestring import mark_safe 
7   from django.utils.translation import ugettext_lazy as _ 
 7  from django.utils.translation import ugettext, ugettext_lazy as _ 
8  8  
9  9  from django.contrib.auth import authenticate 
10  10  from django.contrib.auth.models import User 
… 
… 
class ReadOnlyPasswordHashWidget(forms.Widget): 
36  36  
37  37  summary = "" 
38  38  for key, value in hasher.safe_summary(encoded).iteritems(): 
39   summary += "<strong>%(key)s</strong>: %(value)s " % {"key": key, "value": value} 
 39  summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value} 
40  40  
41  41  return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary}) 
42  42  
diff git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 0b3b6c3..d133bcb 100644
a

b

from django.utils.encoding import smart_str 
7  7  from django.core.exceptions import ImproperlyConfigured 
8  8  from django.utils.crypto import ( 
9  9  pbkdf2, constant_time_compare, get_random_string) 
 10  from django.utils.translation import ugettext_noop as _ 
10  11  
11  12  
12  13  UNUSABLE_PASSWORD = '!' # This will never be a valid encoded hash 
… 
… 
class PBKDF2PasswordHasher(BasePasswordHasher): 
212  213  algorithm, iterations, salt, hash = encoded.split('$', 3) 
213  214  assert algorithm == self.algorithm 
214  215  return SortedDict([ 
215   ('algorithm', algorithm), 
216   ('iterations', iterations), 
217   ('salt', mask_hash(salt)), 
218   ('hash', mask_hash(hash)), 
 216  (_('algorithm'), algorithm), 
 217  (_('iterations'), iterations), 
 218  (_('salt'), mask_hash(salt)), 
 219  (_('hash'), mask_hash(hash)), 
219  220  ]) 
220  221  
221  222  
… 
… 
class BCryptPasswordHasher(BasePasswordHasher): 
263  264  assert algorithm == self.algorithm 
264  265  salt, checksum = data[:22], data[22:] 
265  266  return SortedDict([ 
266   ('algorithm', algorithm), 
267   ('work factor', work_factor), 
268   ('salt', mask_hash(salt)), 
269   ('checksum', mask_hash(checksum)), 
 267  (_('algorithm'), algorithm), 
 268  (_('work factor'), work_factor), 
 269  (_('salt'), mask_hash(salt)), 
 270  (_('checksum'), mask_hash(checksum)), 
270  271  ]) 
271  272  
272  273  
… 
… 
class SHA1PasswordHasher(BasePasswordHasher): 
292  293  algorithm, salt, hash = encoded.split('$', 2) 
293  294  assert algorithm == self.algorithm 
294  295  return SortedDict([ 
295   ('algorithm', algorithm), 
296   ('salt', mask_hash(salt, show=2)), 
297   ('hash', mask_hash(hash)), 
 296  (_('algorithm'), algorithm), 
 297  (_('salt'), mask_hash(salt, show=2)), 
 298  (_('hash'), mask_hash(hash)), 
298  299  ]) 
299  300  
300  301  
… 
… 
class MD5PasswordHasher(BasePasswordHasher): 
321  322  
322  323  def safe_summary(self, encoded): 
323  324  return SortedDict([ 
324   ('algorithm', self.algorithm), 
325   ('hash', mask_hash(encoded, show=3)), 
 325  (_('algorithm'), self.algorithm), 
 326  (_('hash'), mask_hash(encoded, show=3)), 
326  327  ]) 
327  328  
328  329  
… 
… 
class CryptPasswordHasher(BasePasswordHasher): 
355  356  algorithm, salt, data = encoded.split('$', 2) 
356  357  assert algorithm == self.algorithm 
357  358  return SortedDict([ 
358   ('algorithm', algorithm), 
359   ('salt', salt), 
360   ('hash', mask_hash(data, show=3)), 
 359  (_('algorithm'), algorithm), 
 360  (_('salt'), salt), 
 361  (_('hash'), mask_hash(data, show=3)), 
361  362  ]) 
362  363  