Index: /usr/local/django_src/django/core/template.py
===================================================================
--- /usr/local/django_src/django/core/template.py       (revision 593)
+++ /usr/local/django_src/django/core/template.py       (working copy)
@@ -412,6 +412,12 @@
    except VariableDoesNotExist:
        obj = ''
    for name, arg in filters:
+       if registered_filters[name][2]:
+               # Check type so that we don't run str() on a Unicode object
+               if not isinstance(obj, basestring):
+                   obj = str(obj)
+               elif isinstance(obj, unicode):
+                   obj = obj.encode('utf-8')
        obj = registered_filters[name][0](obj, arg)
    return obj

@@ -481,8 +487,8 @@
 def unregister_tag(token_command):
    del registered_tags[token_command]

-def register_filter(filter_name, callback_function, has_arg):
-    registered_filters[filter_name] = (callback_function, has_arg)
+def register_filter(filter_name, callback_function, has_arg, string_only=False):
+    registered_filters[filter_name] = (callback_function, has_arg, string_only)

 def unregister_filter(filter_name):
    del registered_filters[filter_name]
Index: /usr/local/django_src/django/core/defaultfilters.py
===================================================================
--- /usr/local/django_src/django/core/defaultfilters.py (revision 593)
+++ /usr/local/django_src/django/core/defaultfilters.py (working copy)
@@ -13,8 +13,7 @@

 def capfirst(value, _):
    "Capitalizes the first character of the value"
-    value = str(value)
-    return value and value[0].upper() + value[1:]
+    return value[0].upper() + value[1:]

 def fix_ampersands(value, _):
    "Replaces ampersands with ``&amp;`` entities"
@@ -418,51 +417,51 @@
    from pprint import pformat
    return pformat(value)

-# Syntax: template.register_filter(name of filter, callback, has_argument)
-template.register_filter('add', add, True)
-template.register_filter('addslashes', addslashes, False)
-template.register_filter('capfirst', capfirst, False)
-template.register_filter('center', center, True)
-template.register_filter('cut', cut, True)
-template.register_filter('date', date, True)
-template.register_filter('default', default, True)
-template.register_filter('dictsort', dictsort, True)
-template.register_filter('dictsortreversed', dictsortreversed, True)
-template.register_filter('divisibleby', divisibleby, True)
-template.register_filter('escape', escape, False)
-template.register_filter('filesizeformat', filesizeformat, False)
-template.register_filter('first', first, False)
-template.register_filter('fix_ampersands', fix_ampersands, False)
-template.register_filter('floatformat', floatformat, False)
-template.register_filter('get_digit', get_digit, True)
-template.register_filter('join', join, True)
-template.register_filter('length', length, False)
-template.register_filter('length_is', length_is, True)
-template.register_filter('linebreaks', linebreaks, False)
-template.register_filter('linebreaksbr', linebreaksbr, False)
-template.register_filter('linenumbers', linenumbers, False)
-template.register_filter('ljust', ljust, True)
-template.register_filter('lower', lower, False)
-template.register_filter('make_list', make_list, False)
-template.register_filter('phone2numeric', phone2numeric, False)
-template.register_filter('pluralize', pluralize, False)
-template.register_filter('pprint', pprint, False)
-template.register_filter('removetags', removetags, True)
-template.register_filter('random', random, False)
-template.register_filter('rjust', rjust, True)
-template.register_filter('slice', slice_, True)
-template.register_filter('slugify', slugify, False)
-template.register_filter('stringformat', stringformat, True)
-template.register_filter('striptags', striptags, False)
-template.register_filter('time', time, True)
-template.register_filter('timesince', timesince, False)
-template.register_filter('title', title, False)
-template.register_filter('truncatewords', truncatewords, True)
-template.register_filter('unordered_list', unordered_list, False)
-template.register_filter('upper', upper, False)
-template.register_filter('urlencode', urlencode, False)
-template.register_filter('urlize', urlize, False)
-template.register_filter('urlizetrunc', urlizetrunc, True)
-template.register_filter('wordcount', wordcount, False)
-template.register_filter('wordwrap', wordwrap, True)
-template.register_filter('yesno', yesno, True)
+# Syntax: template.register_filter(name of filter, callback, has_argument, string_only)
+template.register_filter('add', add, True, False)
+template.register_filter('addslashes', addslashes, False, True)
+template.register_filter('capfirst', capfirst, False, True)
+template.register_filter('center', center, True, True)
+template.register_filter('cut', cut, True, True)
+template.register_filter('date', date, True, False)
+template.register_filter('default', default, True, False)
+template.register_filter('dictsort', dictsort, True, False)
+template.register_filter('dictsortreversed', dictsortreversed, True, False)
+template.register_filter('divisibleby', divisibleby, True, False)
+template.register_filter('escape', escape, False, True)
+template.register_filter('filesizeformat', filesizeformat, False, False)
+template.register_filter('first', first, False, False)
+template.register_filter('fix_ampersands', fix_ampersands, False, True)
+template.register_filter('floatformat', floatformat, False, False)
+template.register_filter('get_digit', get_digit, True, False)
+template.register_filter('join', join, True, False)
+template.register_filter('length', length, False, False)
+template.register_filter('length_is', length_is, True, False)
+template.register_filter('linebreaks', linebreaks, False, True)
+template.register_filter('linebreaksbr', linebreaksbr, False, True)
+template.register_filter('linenumbers', linenumbers, False, True)
+template.register_filter('ljust', ljust, True, True)
+template.register_filter('lower', lower, False, True)
+template.register_filter('make_list', make_list, False, True)
+template.register_filter('phone2numeric', phone2numeric, True, True)
+template.register_filter('pluralize', pluralize, False, False)
+template.register_filter('pprint', pprint, False, False)
+template.register_filter('removetags', removetags, True, True)
+template.register_filter('random', random, False, False)
+template.register_filter('rjust', rjust, True, True)
+template.register_filter('slice', slice_, True, False)
+template.register_filter('slugify', slugify, False, True)
+template.register_filter('stringformat', stringformat, True, True)
+template.register_filter('striptags', striptags, False, True)
+template.register_filter('time', time, True, False)
+template.register_filter('timesince', timesince, False, False)
+template.register_filter('title', title, False, True)
+template.register_filter('truncatewords', truncatewords, True, True)
+template.register_filter('unordered_list', unordered_list, False, False)
+template.register_filter('upper', upper, False, True)
+template.register_filter('urlencode', urlencode, False, True)
+template.register_filter('urlize', urlize, False, True)
+template.register_filter('urlizetrunc', urlizetrunc, True, True)
+template.register_filter('wordcount', wordcount, False, True)
+template.register_filter('wordwrap', wordwrap, True, True)
+template.register_filter('yesno', yesno, True, False)

