Index: template/__init__.py
===================================================================
--- template/__init__.py	(revision 3577)
+++ template/__init__.py	(working copy)
@@ -60,6 +60,7 @@
 from django.template.context import Context, RequestContext, ContextPopException
 from django.utils.functional import curry
 from django.utils.text import smart_split
+from django.utils.datastructures import SortedDict
 
 __all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
 
@@ -223,6 +224,7 @@
         self.tokens = tokens
         self.tags = {}
         self.filters = {}
+        self.libs = {}
         for lib in builtins:
             self.add_library(lib)
 
@@ -251,7 +253,7 @@
                 # execute callback function for this tag and append resulting node
                 self.enter_command(command, token)
                 try:
-                    compile_func = self.tags[command]
+                    compile_func = self.get_tags(command)
                 except KeyError:
                     self.invalid_block_tag(token, command)
                 try:
@@ -317,16 +319,50 @@
     def add_library(self, lib):
         self.tags.update(lib.tags)
         self.filters.update(lib.filters)
+        #save index of lib
+        if lib.appname:
+            d = self.libs.setdefault(lib.taglibname, SortedDict({}))
+            d[lib.appname] = {'tags':lib.tags, 'filters':lib.filters}
 
+    def get_tags(self, tag):
+        
+        v = tag.split('.')
+        if len(v) == 3:
+            appname, taglibname, command = v
+            return self.libs[taglibname][appname]['tags'][command]
+        elif len(v) == 2:
+            taglibname, command = v
+            return self.libs[taglibname].values()[0]['tags'][command]
+        else:
+            return self.tags[tag]
+
+    def get_filters(self, filter):
+        
+        v = filter.split('.')
+        if len(v) == 3:
+            appname, taglibname, command = v
+            return self.libs[taglibname][appname]['filters'][command]
+        elif len(v) == 2:
+            taglibname, command = v
+            return self.libs[taglibname].values()[0]['filters'][command]
+        else:
+            return self.filters[filter]
+        
     def compile_filter(self, token):
         "Convenient wrapper for FilterExpression"
         return FilterExpression(token, self)
 
     def find_filter(self, filter_name):
-        if self.filters.has_key(filter_name):
-            return self.filters[filter_name]
-        else:
+        try:
+            return self.get_filters(filter_name)
+        except:
+            import traceback
+            traceback.print_exc()
             raise TemplateSyntaxError, "Invalid filter: '%s'" % filter_name
+#        if self.filters.has_key(filter_name):
+#            return self.filters[filter_name]
+#        else:
+#            raise TemplateSyntaxError, "Invalid filter: '%s'" % filter_name
 
 class DebugParser(Parser):
     def __init__(self, lexer):
@@ -468,7 +504,7 @@
 ^"(?P<constant>%(str)s)"|
 ^(?P<var>[%(var_chars)s]+)|
  (?:%(filter_sep)s
-     (?P<filter_name>\w+)
+     (?P<filter_name>[\w.]+)
          (?:%(arg_sep)s
              (?:
               %(i18n_open)s"(?P<i18n_arg>%(str)s)"%(i18n_close)s|
@@ -873,15 +909,29 @@
             return func
         return dec
 
+import os.path
 def get_library(module_name):
     lib = libraries.get(module_name, None)
     if not lib:
         try:
             mod = __import__(module_name, '', '', [''])
+            
+            #get the appname and tag module name from the __file__
+            v = mod.__file__.replace('\\', '/').split('/')
+            if v[-2] == 'templatetags':
+                appname, taglibname = v[-3], os.path.splitext(v[-1])[0]
+            else:
+                appname, taglibname = None, None
         except ImportError, e:
+            import traceback
+            traceback.print_exc()
             raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e)
         try:
             lib = mod.register
+            
+            #assign appname and taglibname to lib
+            lib.appname = appname
+            lib.taglibname = taglibname
             libraries[module_name] = lib
         except AttributeError:
             raise InvalidTemplateLibrary, "Template library %s does not have a variable named 'register'" % module_name
Index: template/defaulttags.py
===================================================================
--- template/defaulttags.py	(revision 3577)
+++ template/defaulttags.py	(working copy)
@@ -686,9 +686,14 @@
     for taglib in bits[1:]:
         # add the library to the parser
         try:
-            lib = get_library("django.templatetags.%s" % taglib.split('.')[-1])
+            if taglib.find('.') > -1:
+                appname, module = taglib.split('.')
+                taglib = '.'.join([appname, 'templatetags', module])
+            lib = get_library("django.templatetags.%s" % taglib)
             parser.add_library(lib)
         except InvalidTemplateLibrary, e:
+            import traceback
+            traceback.print_exc()
             raise TemplateSyntaxError, "'%s' is not a valid tag library: %s" % (taglib, e)
     return LoadNode()
 load = register.tag(load)
Index: templatetags/__init__.py
===================================================================
--- templatetags/__init__.py	(revision 3577)
+++ templatetags/__init__.py	(working copy)
@@ -2,6 +2,7 @@
 
 for a in settings.INSTALLED_APPS:
     try:
+        __path__.extend(__import__(a.rsplit('.', 1)[0], '', '', ['']).__path__)
         __path__.extend(__import__(a + '.templatetags', '', '', ['']).__path__)
     except ImportError:
         pass
