backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 25 Aug 2010 09:43:12 +0200
changeset 6139 f76599a96238
parent 6102 27c47d239739 (current diff)
parent 6138 65f5e488f983 (diff)
child 6140 65a619eb31c4
backport stable
server/repository.py
server/serverconfig.py
server/test/unittest_msplanner.py
web/application.py
web/formfields.py
web/views/primary.py
web/webconfig.py
--- a/__pkginfo__.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/__pkginfo__.py	Wed Aug 25 09:43:12 2010 +0200
@@ -40,7 +40,7 @@
 ]
 
 __depends__ = {
-    'logilab-common': '>= 0.50.2',
+    'logilab-common': '>= 0.51.0',
     'logilab-mtconverter': '>= 0.8.0',
     'rql': '>= 0.26.2',
     'yams': '>= 0.29.1',
--- a/cwconfig.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/cwconfig.py	Wed Aug 25 09:43:12 2010 +0200
@@ -297,7 +297,6 @@
     # nor remove appobjects based on unused interface [???]
     cleanup_interface_sobjects = True
 
-
     if (CWDEV and _forced_mode != 'system'):
         mode = 'user'
         _CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes')
--- a/cwctl.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/cwctl.py	Wed Aug 25 09:43:12 2010 +0200
@@ -37,12 +37,15 @@
 
 from os.path import exists, join, isfile, isdir, dirname, abspath
 
-from logilab.common.clcommands import register_commands, pop_arg
+from logilab.common.clcommands import CommandLine
 from logilab.common.shellutils import ASK
 
 from cubicweb import ConfigurationError, ExecutionError, BadCommandUsage
 from cubicweb.cwconfig import CubicWebConfiguration as cwcfg, CWDEV, CONFIGURATIONS
-from cubicweb.toolsutils import Command, main_run, rm, create_dir, underline_title
+from cubicweb.toolsutils import Command, rm, create_dir, underline_title
+from cubicweb.__pkginfo__ import version
+
+CWCTL = CommandLine('cubicweb-ctl', 'The CubicWeb swiss-knife.', version=version)
 
 def wait_process_end(pid, maxtry=10, waittime=1):
     """wait for a process to actually die"""
@@ -301,6 +304,7 @@
     """
     name = 'create'
     arguments = '<cube> <instance>'
+    min_args = max_args = 2
     options = (
         ("config-level",
          {'short': 'l', 'type' : 'int', 'metavar': '<level>',
@@ -325,8 +329,8 @@
         """run the command with its specific arguments"""
         from logilab.common.textutils import splitstrip
         configname = self.config.config
-        cubes = splitstrip(pop_arg(args, 1))
-        appid = pop_arg(args)
+        appid, cubes = args
+        cubes = splitstrip(cubes)
         # get the configuration and helper
         config = cwcfg.config_for(appid, configname)
         config.set_language = False
@@ -415,12 +419,12 @@
     """
     name = 'delete'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = ()
 
     def run(self, args):
         """run the command with its specific arguments"""
-        appid = pop_arg(args, msg="No instance specified !")
+        appid = args[0]
         configs = [cwcfg.config_for(appid, configname)
                    for configname in cwcfg.possible_configurations(appid)]
         if not configs:
@@ -796,6 +800,7 @@
     """
     name = 'shell'
     arguments = '<instance> [batch command file(s)] [-- <script arguments>]'
+    min_args = 1
     options = (
         ('system-only',
          {'short': 'S', 'action' : 'store_true',
@@ -834,7 +839,7 @@
         )
 
     def run(self, args):
-        appid = pop_arg(args, None, msg="No instance specified !")
+        appid = args.pop(0)
         if self.config.pyro:
             from cubicweb import AuthenticationError
             from cubicweb.dbapi import connect
@@ -930,30 +935,29 @@
         for cube in cwcfg.available_cubes():
             print cube
 
-register_commands((ListCommand,
-                   CreateInstanceCommand,
-                   DeleteInstanceCommand,
-                   StartInstanceCommand,
-                   StopInstanceCommand,
-                   RestartInstanceCommand,
-                   ReloadConfigurationCommand,
-                   StatusCommand,
-                   UpgradeInstanceCommand,
-                   ShellCommand,
-                   RecompileInstanceCatalogsCommand,
-                   ListInstancesCommand, ListCubesCommand,
-                   ))
+for cmdcls in (ListCommand,
+               CreateInstanceCommand, DeleteInstanceCommand,
+               StartInstanceCommand, StopInstanceCommand, RestartInstanceCommand,
+               ReloadConfigurationCommand, StatusCommand,
+               UpgradeInstanceCommand,
+               ShellCommand,
+               RecompileInstanceCatalogsCommand,
+               ListInstancesCommand, ListCubesCommand,
+               ):
+    CWCTL.register(cmdcls)
 
 
 def run(args):
     """command line tool"""
     cwcfg.load_cwctl_plugins()
-    main_run(args, """%%prog %s [options] %s
-
-The CubicWeb swiss-knife.
-
-%s"""
-)
+    try:
+        CWCTL.run(args)
+    except ConfigurationError, err:
+        print 'ERROR: ', err
+        sys.exit(1)
+    except ExecutionError, err:
+        print err
+        sys.exit(2)
 
 if __name__ == '__main__':
     run(sys.argv[1:])
--- a/dataimport.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/dataimport.py	Wed Aug 25 09:43:12 2010 +0200
@@ -51,10 +51,15 @@
   GENERATORS.append( (gen_users, CHK) )
 
   # create controller
-  ctl = CWImportController(RQLObjectStore(cnx))
+  if 'cnx' in globals():
+      ctl = CWImportController(RQLObjectStore(cnx))
+  else:
+      print 'debug mode (not connected)'
+      print 'run through cubicweb-ctl shell to access an instance'
+      ctl = CWImportController(ObjectStore())
   ctl.askerror = 1
   ctl.generators = GENERATORS
-  ctl.data['utilisateurs'] = lazytable(utf8csvreader(open('users.csv')))
+  ctl.data['utilisateurs'] = lazytable(ucsvreader(open('users.csv')))
   # run
   ctl.run()
 
@@ -77,17 +82,32 @@
 
 from cubicweb.server.utils import eschema_eid
 
-def ucsvreader_pb(filepath, encoding='utf-8', separator=',', quote='"',
+def count_lines(stream_or_filename):
+    if isinstance(stream_or_filename, basestring):
+        f = open(filename)
+    else:
+        f = stream_or_filename
+        f.seek(0)
+    for i, line in enumerate(f):
+        pass
+    f.seek(0)
+    return i+1
+
+def ucsvreader_pb(stream_or_path, encoding='utf-8', separator=',', quote='"',
                   skipfirst=False, withpb=True):
     """same as ucsvreader but a progress bar is displayed as we iter on rows"""
-    if not osp.exists(filepath):
-        raise Exception("file doesn't exists: %s" % filepath)
-    rowcount = int(shellutils.Execute('wc -l "%s"' % filepath).out.strip().split()[0])
+    if isinstance(stream_or_path, basestring):
+        if not osp.exists(filepath):
+            raise Exception("file doesn't exists: %s" % filepath)
+        stream = open(stream_or_path)
+    else:
+        stream = stream_or_path
+    rowcount = count_lines(stream)
     if skipfirst:
         rowcount -= 1
     if withpb:
         pb = shellutils.ProgressBar(rowcount, 50)
-    for urow in ucsvreader(file(filepath), encoding, separator, quote, skipfirst):
+    for urow in ucsvreader(stream, encoding, separator, quote, skipfirst):
         yield urow
         if withpb:
             pb.update()
@@ -116,7 +136,7 @@
     """The first row is taken to be the header of the table and
     used to output a dict for each row of data.
 
-    >>> data = lazytable(utf8csvreader(open(filename)))
+    >>> data = lazytable(ucsvreader(open(filename)))
     """
     header = reader.next()
     for row in reader:
@@ -396,20 +416,19 @@
 
     def __init__(self, session=None, commit=None):
         ObjectStore.__init__(self)
-        if session is not None:
-            if not hasattr(session, 'set_pool'):
-                # connection
-                cnx = session
-                session = session.request()
-                session.set_pool = lambda : None
-                commit = commit or cnx.commit
-            else:
-                session.set_pool()
-            self.session = session
-            self._commit = commit or session.commit
-        elif commit is not None:
-            self._commit = commit
-            # XXX .session
+        if session is None:
+            sys.exit('please provide a session of run this script with cubicweb-ctl shell and pass cnx as session')
+            session = cnx
+        if not hasattr(session, 'set_pool'):
+            # connection
+            cnx = session
+            session = session.request()
+            session.set_pool = lambda : None
+            commit = commit or cnx.commit
+        else:
+            session.set_pool()
+        self.session = session
+        self._commit = commit or session.commit
 
     @deprecated("[3.7] checkpoint() deprecated. use commit() instead")
     def checkpoint(self):
--- a/debian/control	Thu Aug 12 10:12:52 2010 +0200
+++ b/debian/control	Wed Aug 25 09:43:12 2010 +0200
@@ -97,7 +97,7 @@
 Package: cubicweb-common
 Architecture: all
 XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.8.0), python-logilab-common (>= 0.50.2), python-yams (>= 0.29.1), python-rql (>= 0.26.3), python-lxml
+Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.8.0), python-logilab-common (>= 0.51.0), python-yams (>= 0.29.1), python-rql (>= 0.26.3), python-lxml
 Recommends: python-simpletal (>= 4.0), python-crypto
 Conflicts: cubicweb-core
 Replaces: cubicweb-core
--- a/devtools/devctl.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/devtools/devctl.py	Wed Aug 25 09:43:12 2010 +0200
@@ -31,10 +31,10 @@
 from warnings import warn
 
 from logilab.common import STD_BLACKLIST
-from logilab.common.clcommands import register_commands, pop_arg
 
 from cubicweb.__pkginfo__ import version as cubicwebversion
 from cubicweb import CW_SOFTWARE_ROOT as BASEDIR, BadCommandUsage
+from cubicweb.cwctl import CWCTL
 from cubicweb.toolsutils import (SKEL_EXCLUDE, Command,
                                  copy_skeleton, underline_title)
 from cubicweb.web.webconfig import WebConfiguration
@@ -684,6 +684,7 @@
     """Generate schema image for the given cube"""
     name = "schema"
     arguments = '<cube>'
+    min_args = max_args = 1
     options = [('output-file', {'type':'file', 'default': None,
                  'metavar': '<file>', 'short':'o', 'help':'output image file',
                  'input':False}),
@@ -720,7 +721,7 @@
         from yams import schema2dot, BASE_TYPES
         from cubicweb.schema import (META_RTYPES, SCHEMA_TYPES, SYSTEM_RTYPES,
                                      WORKFLOW_TYPES, INTERNAL_TYPES)
-        cubes = splitstrip(pop_arg(args, 1))
+        cubes = splitstrip(args[0])
         dev_conf = DevConfiguration(*cubes)
         schema = dev_conf.load_schema()
         out, viewer = self['output-file'], self['viewer']
@@ -751,11 +752,12 @@
         from cubicweb.devtools.qunit import make_qunit_html
         print make_qunit_html(args[0], args[1:])
 
-register_commands((UpdateCubicWebCatalogCommand,
-                   UpdateTemplateCatalogCommand,
-                   #LiveServerCommand,
-                   NewCubeCommand,
-                   ExamineLogCommand,
-                   GenerateSchema,
-                   GenerateQUnitHTML,
-                   ))
+for cmdcls in (UpdateCubicWebCatalogCommand,
+               UpdateTemplateCatalogCommand,
+               #LiveServerCommand,
+               NewCubeCommand,
+               ExamineLogCommand,
+               GenerateSchema,
+               GenerateQUnitHTML,
+               ):
+    CWCTL.register(cmdcls)
--- a/devtools/testlib.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/devtools/testlib.py	Wed Aug 25 09:43:12 2010 +0200
@@ -621,7 +621,7 @@
              **kwargs):
         """This method tests the view `vid` on `rset` using `template`
 
-        If no error occured while rendering the view, the HTML is analyzed
+        If no error occurred while rendering the view, the HTML is analyzed
         and parsed.
 
         :returns: an instance of `cubicweb.devtools.htmlparser.PageInfo`
@@ -653,7 +653,7 @@
     def _test_view(self, viewfunc, view, template='main-template', kwargs={}):
         """this method does the actual call to the view
 
-        If no error occured while rendering the view, the HTML is analyzed
+        If no error occurred while rendering the view, the HTML is analyzed
         and parsed.
 
         :returns: an instance of `cubicweb.devtools.htmlparser.PageInfo`
--- a/doc/book/en/annexes/docstrings-conventions.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/annexes/docstrings-conventions.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -1,8 +1,8 @@
 Javascript docstrings
 =====================
 
-Whereas in Python source code we only need to include a module docstrings 
-using the directive `.. automodule:: mypythonmodule`, we will have to 
+Whereas in Python source code we only need to include a module docstrings
+using the directive `.. automodule:: mypythonmodule`, we will have to
 explicitely define Javascript modules and functions in the doctrings since
 there is no native directive to include Javascript files.
 
@@ -32,7 +32,7 @@
 Basically we document javascript with RestructuredText docstring
 following the same convention as documenting Python code.
 
-The doctring in Javascript files must be contained in standard 
+The doctring in Javascript files must be contained in standard
 Javascript comment signs, starting with `/**` and ending with `*/`,
 such as::
 
@@ -44,7 +44,7 @@
   * All the follwing line will be prefixed with a `*` followed by a space.
   * ...
   * ...
-  */ 
+  */
 
 
 Comments line prefixed by `//` will be ignored. They are reserved for source
@@ -61,12 +61,12 @@
 
 Its purpose is to define the function prototype such as::
 
-    .. function:: loadxhtml(url, data, reqtype, mode) 
+    .. function:: loadxhtml(url, data, reqtype, mode)
 
-If any namespace is used, we should add it in the prototype for now, 
-until we define an appropriate directive.
-::
-    .. function:: jQuery.fn.loadxhtml(url, data, reqtype, mode) 
+If any namespace is used, we should add it in the prototype for now,
+until we define an appropriate directive::
+
+    .. function:: jQuery.fn.loadxhtml(url, data, reqtype, mode)
 
 Function parameters
 ~~~~~~~~~~~~~~~~~~~
@@ -76,7 +76,7 @@
 
 Example of a javascript function docstring::
 
-    .. function:: loadxhtml(url, data, reqtype, mode) 
+    .. function:: loadxhtml(url, data, reqtype, mode)
 
     cubicweb loadxhtml plugin to make jquery handle xhtml response
 
--- a/doc/book/en/annexes/rql/language.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/annexes/rql/language.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -146,27 +146,27 @@
 - For grouped queries (e.g. with a GROUPBY clause), all
   selected variables should be grouped at the right of the keyword.
 
-- To group and/or sort by attributes, we can do::
-
-  X,L user U, U login L GROUPBY L, X ORDERBY L
-
 - If the sorting method (SORT_METHOD) is not specified, then the sorting is
   ascendant (`ASC`).
 
-- Aggregate Functions: COUNT, MIN, MAX, AVG, SUM
+- Aggregate Functions: COUNT, MIN, MAX, AVG, SUM, GROUP_CONCAT
 
 Having
 ``````
 
-The HAVING clause, as in SQL, has been originally introduced to restrict a query according to value returned by an aggregate function, e.g.::
+The HAVING clause, as in SQL, has been originally introduced to restrict a query
+according to value returned by an aggregate function, e.g.::
 
     Any X GROUPBY X WHERE X relation Y HAVING COUNT(Y) > 10
 
 It may however be used for something else...
 
-In the WHERE clause, we are limited to 3-expression_, such thing can't be expressed directly as in the SQL's way. But this can be expressed using HAVING comparison expression.
+In the WHERE clause, we are limited to 3-expression, such thing can't be
+expressed directly as in the SQL's way. But this can be expressed using HAVING
+comparison expression.
 
-For instance, let's say you want to get people whose uppercased first name equals to another person uppercased first name::
+For instance, let's say you want to get people whose uppercased first name equals
+to another person uppercased first name::
 
     Person X WHERE X firstname XFN, Y firstname YFN HAVING X > Y, UPPER(XFN) = UPPER(YFN)
 
@@ -174,18 +174,23 @@
 
     Person X WHERE X birthday XB HAVING YEAR(XB) = 2000
 
-That lets you use transformation functions not only in selection but for restriction as well and to by-pass limitation of the WHERE clause, which was the major flaw in the RQL language.
+That lets you use transformation functions not only in selection but for
+restriction as well and to by-pass limitation of the WHERE clause, which was the
+major flaw in the RQL language.
 
-Notice that while we would like this to work without the HAVING clause, this can't be currently be done because it introduces an ambiguity in RQL's grammar that can't be handled by Yapps_, the parser's generator we're using.
+Notice that while we would like this to work without the HAVING clause, this
+can't be currently be done because it introduces an ambiguity in RQL's grammar
+that can't be handled by Yapps_, the parser's generator we're using.
 
 Negation
 ````````
 
-* A query such as `Document X WHERE NOT X owned_by U` means "the
-  documents have no relation `owned_by`".
-* But the query `Document X WHERE NOT X owned_by U, U login "syt"`
-  means "the documents have no relation `owned_by` with the user
-  syt". They may have a relation "owned_by" with another user.
+* A query such as `Document X WHERE NOT X owned_by U` means "the documents have
+  no relation `owned_by`".
+
+* But the query `Document X WHERE NOT X owned_by U, U login "syt"` means "the
+  documents have no relation `owned_by` with the user syt". They may have a
+  relation "owned_by" with another user.
 
 Identity
 ````````
--- a/doc/book/en/devrepo/cubes/layout.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/devrepo/cubes/layout.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -108,8 +108,24 @@
 The :file:`__pkginfo__.py` file
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-It contains metadata describing your cube, mostly useful for
-packaging.
+It contains metadata describing your cube, mostly useful for packaging.
+
+Two important attributes of this module are __depends__ and __recommends__
+dictionaries that indicates what should be installed (and each version if
+necessary) for the cube to work.
+
+Dependency on other cubes are expected to be of the form 'cubicweb-<cubename>'.
+
+When an instance is created, dependencies are automatically installed, while
+recommends are not.
+
+Recommends may be seen as a kind of 'weak dependency'. Eg, the most important
+effect of recommending a cube is that, if cube A recommends cube B, the cube B
+will be loaded before the cube A (same thing happend when A depends on B).
+
+Having this behaviour is sometime desired: on schema creation, you may rely on
+something defined in the other's schema; on database creation, on something
+created by the other's postcreate, and so on.
 
 
 :file:`migration/precreate.py` and :file:`migration/postcreate.py`
--- a/doc/book/en/devrepo/datamodel/definition.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/devrepo/datamodel/definition.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -412,6 +412,46 @@
 * special relations "has_<ACTION>_permission" can not be used
 
 
+Important notes about write permissions checking
+````````````````````````````````````````````````
+
+Write permissions (e.g. 'add', 'update', 'delete') are checked in core hooks.
+
+When a permission is checked slightly vary according to if it's an entity or
+relation, and if the relation is an attribute relation or not). It's important to
+understand that since according to when a permission is checked, values returned
+by rql expressions may changes, hence the permission being granted or not.
+
+Here are the current rules:
+
+1. permission to add/update entity and its attributes are checked:
+
+   - on commit if the entity has been added
+
+   - in an 'after_update_entity' hook if the entity has been updated. If it fails
+     at this time, it will be retried on commit (hence you get the permission if
+     you have it just after the modification or *at* commit time)
+
+2. permission to delete an entity is checked in 'before_delete_entity' hook
+
+3. permission to add a relation is checked either:
+
+   - in 'before_add_relation' hook if the relation type is in the
+     `BEFORE_ADD_RELATIONS` set
+
+   - else at commit time if the relation type is in the `ON_COMMIT_ADD_RELATIONS`
+     set
+
+   - else in 'after_add_relation' hook (the default)
+
+4. permission to delete a relation is checked in 'before_delete_relation' hook
+
+Last but not least, remember queries issued from hooks and operation are by
+default 'unsafe', eg there are no read or write security checks.
+
+See :mod:`cubicweb.hooks.security` for more details.
+
+
 .. _yams_example:
 
 Defining your schema using yams
--- a/doc/book/en/devweb/facets.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/devweb/facets.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -1,172 +1,23 @@
 The facets system
 -----------------
 
-Facets allow to restrict searches according to some criteria. CubicWeb
-has a builtin `facet`_ system to define restrictions `filters`_ really
-as easily as possible. A few base classes for facets are provided in
-``cubicweb.web.facet.py``. All classes inherits from the base class
-``AbstractFacet``.
+Facets allow to restrict searches according to some user friendly criterias.
+CubicWeb has a builtin `facet`_ system to define restrictions `filters`_ really
+as easily as possible.
 
-Here is an overview of the facets rendering pick from the `tracker` cube:
+Here is an exemple of the facets rendering picked from our
+http://www.cubicweb.org web site:
 
 .. image:: ../images/facet_overview.png
 
-Facets will appear on each page presenting more than one entity.
-
-
-
-VocabularyFacet
-~~~~~~~~~~~~~~~~
-The ``VocabularyFacet`` inherits from the ``AbstractFacet``.
-A class which inherits from VocabularyFacets must redefine these methods:
-
-.. automethod:: cubicweb.web.facet.VocabularyFacet.vocabulary
-.. automethod:: cubicweb.web.facet.VocabularyFacet.possible_values
-
-RelationFacet
-~~~~~~~~~~~~~~
-
-The ``RelationFacet`` inherits from the ``VocabularyFacet``. It allows to filter entities according to certain relation's values. Generally, you just have to define some class attributes like:
-
-- rtype: the name of the relation
-- role: the default value is set to `subject`
-- target_attr: needed if it is not the default attribute of the entity
-
-
-To illustrate this facet, let's take for example an *excerpt* of the schema of an office location search application:
-
-.. sourcecode:: python
-
-  class Office(WorkflowableEntityType):
-      price = Int(description='euros / m2 / HC / HT')
-      surface = Int(description='m2')
-      description = RichString(fulltextindexed=True)
-      has_address = SubjectRelation('PostalAddress',
-                                    cardinality='1?',
-                                    composite='subject')
-      proposed_by = SubjectRelation('Agency')
-      comments = ObjectRelation('Comment',
-                                cardinality='1*',
-                                composite='object')
-      screenshots = SubjectRelation(('File', 'Image'),
-                                    cardinality='*1',
-                                    composite='subject')
-
-
-We define a facet to filter offices according to the attribute
-`postalcode` of their associated `PostalAdress`.
-
-.. sourcecode:: python
-
-  class PostalCodeFacet(RelationFacet):
-      __regid__ = 'postalcode-facet'      # every registered class must have an id
-      __select__ = implements('Office')   # this facet should only be selected when
-                                          # visualizing offices
-      rtype = 'has_address'               # this facet is a filter on the entity linked to
-                                          # the office thrhough the relation
-                                          # has_address
-      target_attr = 'postalcode'          # the filter's key is the attribute "postal_code"
-                                          # of the target PostalAddress entity
-
-
-AttributeFacet
-~~~~~~~~~~~~~~
-
-The ``AttributeFacet`` inherits from the ``RelationFacet``. It allows to filter entities according to certain attribute's values.
-
-The example below resumes the former schema. We define now a filter based on the `surface` attribute of the
-`Office`.
-
-.. sourcecode:: python
+Facets will appear on each page presenting more than one entity that may be
+filtered according to some known criteria.
 
-  class SurfaceFacet(AttributeFacet):
-      __regid__ = 'surface-facet'       # every registered class must have an id
-      __select__ = implements('Office') # this facet should only be selected when
-                                        # visualizing offices
-      rtype = 'surface'                 # the filter's key is the attribute "surface"
-      comparator = '>='                 # override the default value of operator since
-                                        # we want to filter according to a
-                                        # minimal
-                                        # value, not an exact one
-
-      def rset_vocabulary(self, ___):
-          """override the default vocabulary method since we want to hard-code
-          our threshold values.
-          Not overriding would generate a filter box with all existing surfaces
-          defined in the database.
-          """
-          return [('> 200', '200'), ('> 250', '250'),
-                  ('> 275', '275'), ('> 300', '300')]
-
-RangeFacet
-~~~~~~~~~~
-The ``RangeFacet`` inherits from the ``AttributeFacet``. It allows to filter entities according to certain attributes of numerical type.
-
-The ``RangeFacet`` displays a slider using `jquery`_ to choose a lower bound and an upper bound.
-
-The example below defines a facet to filter a selection of books according to their number of pages.
-
-.. sourcecode:: python
-
-   class BookPagesFacet(RangeFacet):
-       __regid__ = 'priority-facet'
-       __select__ = RangeFacet.__select__ & implements('Book')
-       rtype = 'pages'
-
-The image below display the rendering of the ``RangeFacet``:
-
-.. image:: ../images/facet_range.png
-
-DateRangeFacet
-~~~~~~~~~~~~~~
-The ``DateRangeFacet`` inherits from the ``RangeFacet``. It allows to filter entities according to certain attributes of date type.
+Base classes for facets
+~~~~~~~~~~~~~~~~~~~~~~~
+.. automodule:: cubicweb.web.facet
 
-Here is an example of code that defines a facet to filter
-musical works according to their composition date:
-
-.. sourcecode:: python
-
-    class CompositionDateFacet(DateRangeFacet):
-        # 1. make sure this facet is displayed only on Track selection
-        __select__ = DateRangeFacet.__select__ & implements('Track')
-        # 2. give the facet an id required by CubicWeb)
-        __regid__ = 'compdate-facet'
-        # 3. specify the attribute name that actually stores the date in the DB
-        rtype = 'composition_date'
-
-With this facet, on each page displaying tracks, you'll be able to filter them
-according to their composition date with a jquery slider.
-
-The image below display the rendering of the ``DateRangeFacet``:
-
-.. image:: ../images/facet_date_range.png
-
-
-HasRelationFacet
-~~~~~~~~~~~~~~~~
-
-The ``DateRangeFacet`` inherits from the ``AbstractFacet``. It will
-display a simple checkbox and lets you refine your selection in order
-to get only entities that actually use this relation.
-
-Here is an example of the rendering of the ``HasRelationFacet`` to
-filter entities with image and the corresponding code:
-
-.. image:: ../images/facet_has_image.png
-
-.. sourcecode:: python
-
-  class HasImageFacet(HasRelationFacet):
-      __regid__ = 'hasimage-facet'
-      __select__ = HasRelationFacet.__select__ & implements('Book')
-      rtype = 'has_image'
-
-
-
-To use ``HasRelationFacet`` on a reverse relation add ``role = 'object'`` in
-it's definitions.
 
 .. _facet: http://en.wikipedia.org/wiki/Faceted_browser
 .. _filters: http://www.cubicweb.org/blogentry/154152
-.. _jquery: http://www.jqueryui.com/
 
--- a/doc/book/en/devweb/views/breadcrumbs.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/devweb/views/breadcrumbs.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -45,8 +45,8 @@
 
 Here is the API of the ``IBreadCrumbsAdapter`` class:
 
-.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbs.parent_entity
-.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbs.breadcrumbs
+.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.parent_entity
+.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.breadcrumbs
 
 If the breadcrumbs method return a list of entities, the
 ``cubicweb.web.views.ibreadcrumbs.BreadCrumbView`` is used to display
--- a/doc/book/en/index.rst	Thu Aug 12 10:12:52 2010 +0200
+++ b/doc/book/en/index.rst	Wed Aug 25 09:43:12 2010 +0200
@@ -62,5 +62,3 @@
 
 * the :ref:`genindex`,
 * the :ref:`modindex`,
-
-.. |cubicweb| replace:: *CubicWeb*
--- a/entity.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/entity.py	Wed Aug 25 09:43:12 2010 +0200
@@ -712,7 +712,9 @@
             selected.append((attr, var))
         # +1 since this doen't include the main variable
         lastattr = len(selected) + 1
-        if attributes is None:
+        # don't fetch extra relation if attributes specified or of the entity is
+        # coming from an external source (may lead to error)
+        if attributes is None and self.cw_metainformation()['source']['uri'] == 'system':
             # fetch additional relations (restricted to 0..1 relations)
             for rschema, role in self._cw_to_complete_relations():
                 rtype = rschema.type
--- a/ext/rest.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/ext/rest.py	Wed Aug 25 09:43:12 2010 +0200
@@ -229,7 +229,7 @@
 
     :rtype: unicode
     :return:
-      the data formatted as HTML or the original data if an error occured
+      the data formatted as HTML or the original data if an error occurred
     """
     req = context._cw
     if isinstance(data, unicode):
--- a/i18n/en.po	Thu Aug 12 10:12:52 2010 +0200
+++ b/i18n/en.po	Wed Aug 25 09:43:12 2010 +0200
@@ -1035,13 +1035,13 @@
 msgid "an electronic mail address associated to a short alias"
 msgstr ""
 
-msgid "an error occured"
-msgstr ""
-
-msgid "an error occured while processing your request"
-msgstr ""
-
-msgid "an error occured, the request cannot be fulfilled"
+msgid "an error occurred"
+msgstr ""
+
+msgid "an error occurred while processing your request"
+msgstr ""
+
+msgid "an error occurred, the request cannot be fulfilled"
 msgstr ""
 
 msgid "an integer is expected"
@@ -3073,7 +3073,7 @@
 msgstr "can be read by"
 
 msgid "read_permission_object"
-msgstr "has permission to delete"
+msgstr "has permission to read"
 
 msgid "registry"
 msgstr ""
@@ -3188,7 +3188,7 @@
 msgstr ""
 
 msgid "same_as"
-msgstr ""
+msgstr "same as"
 
 msgid "sample format"
 msgstr ""
@@ -3317,7 +3317,7 @@
 msgid "site-wide property can't be set for user"
 msgstr ""
 
-msgid "some errors occured:"
+msgid "some errors occurred:"
 msgstr ""
 
 msgid "some later transaction(s) touch entity, undo them first"
--- a/i18n/es.po	Thu Aug 12 10:12:52 2010 +0200
+++ b/i18n/es.po	Wed Aug 25 09:43:12 2010 +0200
@@ -5,7 +5,7 @@
 msgstr ""
 "Project-Id-Version: cubicweb 2.46.0\n"
 "PO-Revision-Date: 2010-11-27 07:59+0100\n"
-"Last-Translator: Celso Flores<jcelsoflores@gmail.com>\n"
+"Last-Translator: Celso Flores<celso.flores@crealibre.com>, Carlos Balderas <carlos.balderas@crealibre.com>\n"
 "Language-Team: es <contact@logilab.fr>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -23,8 +23,8 @@
 "url: %(url)s\n"
 msgstr ""
 "\n"
-"%(user)s ha cambiado su estado de <%(previous_state)s> hacia <%"
-"(current_state)s> por la entidad\n"
+"%(user)s ha cambiado su estado de <%(previous_state)s> hacia "
+"<%(current_state)s> por la entidad\n"
 "'%(title)s'\n"
 "\n"
 "%(comment)s\n"
@@ -36,15 +36,15 @@
 msgstr "  del estado %(fromstate)s hacia el estado %(tostate)s\n"
 
 msgid " :"
-msgstr ""
+msgstr ":"
 
 #, python-format
 msgid "%(attr)s set to %(newvalue)s"
-msgstr ""
+msgstr "%(attr)s modificado a %(newvalue)s"
 
 #, python-format
 msgid "%(attr)s updated from %(oldvalue)s to %(newvalue)s"
-msgstr ""
+msgstr "%(attr)s modificado de %(oldvalue)s a %(newvalue)s"
 
 #, python-format
 msgid "%(cstr)s constraint failed for value %(value)r"
@@ -60,7 +60,7 @@
 
 #, python-format
 msgid "%(value)r doesn't match the %(regexp)r regular expression"
-msgstr ""
+msgstr "%(value)r no corresponde a la expresión regular %(regexp)r"
 
 #, python-format
 msgid "%d days"
@@ -132,10 +132,10 @@
 
 #, python-format
 msgid "%s updated"
-msgstr ""
+msgstr "%s actualizado"
 
 msgid "(UNEXISTANT EID)"
-msgstr ""
+msgstr "(EID INEXISTENTE"
 
 msgid "(loading ...)"
 msgstr "(Cargando ...)"
@@ -178,7 +178,7 @@
 
 #, python-format
 msgid "<%s not specified>"
-msgstr ""
+msgstr "<%s no especificado>"
 
 #, python-format
 msgid ""
@@ -186,8 +186,7 @@
 "can also display a <a href=\"%s\">complete schema with meta-data</a>.</div>"
 msgstr ""
 "<div>Este esquema del modelo de datos <em>no incluye</em> los meta-datos, "
-"pero se puede ver a un <a href=\"%s\">modelo completo con meta-datos</a>.</"
-"div>"
+"pero se puede ver a un <a href=\"%s\">modelo completo con meta-datos</a>.</div>"
 
 msgid "?*"
 msgstr "0..1 0..n"
@@ -208,19 +207,19 @@
 msgstr "Cualquiera"
 
 msgid "Attributes permissions:"
-msgstr ""
+msgstr "Permisos de atributos:"
 
 msgid "Attributes with non default permissions:"
-msgstr ""
+msgstr "Atributos con permisos no estándares"
 
 # schema pot file, generated on 2009-09-16 16:46:55
 #
 # singular and plural forms for each entity type
 msgid "BaseTransition"
-msgstr ""
+msgstr "Transición (abstracta)"
 
 msgid "BaseTransition_plural"
-msgstr ""
+msgstr "Transiciones (abstractas)"
 
 msgid "Bookmark"
 msgstr "Favorito"
@@ -235,16 +234,16 @@
 msgstr "Booleanos"
 
 msgid "BoundConstraint"
-msgstr ""
+msgstr "Restricción de límite"
 
 msgid "BoundaryConstraint"
-msgstr ""
+msgstr "Restricción de límite"
 
 msgid "Browse by category"
 msgstr "Busca por categoría"
 
 msgid "Browse by entity type"
-msgstr ""
+msgstr "Busca por tipo de entidad"
 
 msgid "Bytes"
 msgstr "Bytes"
@@ -281,11 +280,11 @@
 
 msgctxt "inlined:CWRelation.from_entity.subject"
 msgid "CWEType"
-msgstr ""
+msgstr "Tipo de entidad"
 
 msgctxt "inlined:CWRelation.to_entity.subject"
 msgid "CWEType"
-msgstr ""
+msgstr "Tipo de entidad"
 
 msgid "CWEType_plural"
 msgstr "Tipos de entidades"
@@ -294,7 +293,7 @@
 msgstr "Groupo"
 
 msgid "CWGroup_plural"
-msgstr "Groupos"
+msgstr "Grupos"
 
 msgid "CWPermission"
 msgstr "Autorización"
@@ -313,7 +312,7 @@
 
 msgctxt "inlined:CWRelation.relation_type.subject"
 msgid "CWRType"
-msgstr ""
+msgstr "Tipo de relación"
 
 msgid "CWRType_plural"
 msgstr "Tipos de relación"
@@ -335,36 +334,48 @@
 "Can't restore %(role)s relation %(rtype)s to entity %(eid)s which is already "
 "linked using this relation."
 msgstr ""
+"No puede restaurar la relación %(role)s %(rtype)s en la entidad %(eid)s "
+"pues ya esta ligada a otra entidad usando esa relación."
 
 #, python-format
 msgid ""
 "Can't restore relation %(rtype)s between %(subj)s and %(obj)s, that relation "
 "does not exists anymore in the schema."
 msgstr ""
+"No puede restaurar la relación %(rtype)s entre %(subj)s y  %(obj)s, esta "
+"relación ya no existe en el esquema."
 
 #, python-format
 msgid ""
 "Can't restore relation %(rtype)s of entity %(eid)s, this relation does not "
 "exists anymore in the schema."
 msgstr ""
+"No puede restaurar la relación %(rtype)s de la entidad %(eid)s, esta "
+"relación ya no existe en el esquema."
 
 #, python-format
 msgid ""
 "Can't restore relation %(rtype)s, %(role)s entity %(eid)s doesn't exist "
 "anymore."
 msgstr ""
+"No puede restaurar la relación %(rtype)s, la entidad %(role)s %(eid)s ya "
+"no existe."
 
 #, python-format
 msgid ""
 "Can't undo addition of relation %(rtype)s from %(subj)s to %(obj)s, doesn't "
 "exist anymore"
 msgstr ""
+"No puede anular el agregar la relación %(rtype)s de %(subj)s a %(obj)s, "
+"esta relación ya no existe"
 
 #, python-format
 msgid ""
 "Can't undo creation of entity %(eid)s of type %(etype)s, type no more "
 "supported"
 msgstr ""
+"No puede anular la creación de la entidad %(eid)s de tipo %(etype)s, este "
+"tipo ya no existe"
 
 msgid "Date"
 msgstr "Fecha"
@@ -385,14 +396,14 @@
 msgstr "Decimales"
 
 msgid "Do you want to delete the following element(s) ?"
-msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
+msgstr "Desea eliminar el(los) elemento(s) siguiente(s)"
 
 msgid "Download schema as OWL"
-msgstr ""
+msgstr "Descargar el esquema en formato OWL"
 
 msgctxt "inlined:CWUser.use_email.subject"
 msgid "EmailAddress"
-msgstr ""
+msgstr "Correo Electrónico"
 
 msgid "EmailAddress"
 msgstr "Correo Electrónico"
@@ -404,13 +415,13 @@
 msgstr "Entidades"
 
 msgid "Entity types"
-msgstr ""
+msgstr "Tipos de entidades"
 
 msgid "ExternalUri"
-msgstr ""
+msgstr "Uri externo"
 
 msgid "ExternalUri_plural"
-msgstr ""
+msgstr "Uris externos"
 
 msgid "Float"
 msgstr "Número flotante"
@@ -422,25 +433,25 @@
 #
 # singular and plural forms for each entity type
 msgid "FormatConstraint"
-msgstr ""
+msgstr "Restricción de Formato"
 
 msgid "From:"
 msgstr "De: "
 
 msgid "Garbage collection information"
-msgstr ""
+msgstr "Recolector de basura en memoria"
 
 msgid "Got rhythm?"
 msgstr ""
 
 msgid "Help"
-msgstr ""
+msgstr "Ayuda"
 
 msgid "Index"
-msgstr ""
+msgstr "Índice"
 
 msgid "Instance"
-msgstr ""
+msgstr "Instancia"
 
 msgid "Int"
 msgstr "Número entero"
@@ -452,19 +463,19 @@
 msgstr "Duración"
 
 msgid "IntervalBoundConstraint"
-msgstr ""
+msgstr "Restricción de intervalo"
 
 msgid "Interval_plural"
 msgstr "Duraciones"
 
 msgid "Looked up classes"
-msgstr ""
+msgstr "Clases buscadas"
 
 msgid "Most referenced classes"
-msgstr ""
+msgstr "Clases más referenciadas"
 
 msgid "New BaseTransition"
-msgstr ""
+msgstr "XXX"
 
 msgid "New Bookmark"
 msgstr "Agregar a Favoritos"
@@ -473,7 +484,7 @@
 msgstr "Nueva definición de relación final"
 
 msgid "New CWCache"
-msgstr "Agregar Cache"
+msgstr "Agregar Caché"
 
 msgid "New CWConstraint"
 msgstr "Agregar Restricción"
@@ -506,7 +517,7 @@
 msgstr "Agregar Email"
 
 msgid "New ExternalUri"
-msgstr ""
+msgstr "Agregar Uri externa"
 
 msgid "New RQLExpression"
 msgstr "Agregar expresión rql"
@@ -515,7 +526,7 @@
 msgstr "Agregar Estado"
 
 msgid "New SubWorkflowExitPoint"
-msgstr ""
+msgstr "Agregar salida de sub-Workflow"
 
 msgid "New TrInfo"
 msgstr "Agregar Información de Transición"
@@ -524,26 +535,26 @@
 msgstr "Agregar transición"
 
 msgid "New Workflow"
-msgstr ""
+msgstr "Agregar Workflow"
 
 msgid "New WorkflowTransition"
-msgstr ""
+msgstr "Agregar transición de Workflow"
 
 #, python-format
 msgid "No account? Try public access at %s"
-msgstr ""
+msgstr "No esta registrado? Use el acceso público en %s"
 
 msgid "No result matching query"
 msgstr "Ningún resultado corresponde a su búsqueda"
 
 msgid "Non exhaustive list of views that may apply to entities of this type"
-msgstr ""
+msgstr "Lista no exhaustiva de vistas aplicables a este tipo de entidad"
 
 msgid "OR"
 msgstr "O"
 
 msgid "Parent class:"
-msgstr ""
+msgstr "Clase padre:"
 
 msgid "Password"
 msgstr "Contraseña"
@@ -552,16 +563,16 @@
 msgstr "Contraseñas"
 
 msgid "Permissions for entity types"
-msgstr ""
+msgstr "Permisos por tipos de entidad"
 
 msgid "Permissions for relations"
-msgstr ""
+msgstr "Permisos por las relaciones"
 
 msgid "Please note that this is only a shallow copy"
-msgstr "Recuerde que no es más que una copia superficial"
+msgstr "Recuerde que sólo es una copia superficial"
 
 msgid "RQLConstraint"
-msgstr ""
+msgstr "Restricción RQL"
 
 msgid "RQLExpression"
 msgstr "Expresión RQL"
@@ -570,28 +581,28 @@
 msgstr "Expresiones RQL"
 
 msgid "RQLUniqueConstraint"
-msgstr ""
+msgstr "Restricción RQL de Unicidad"
 
 msgid "RQLVocabularyConstraint"
-msgstr ""
+msgstr "Restricción RQL de Vocabulario"
 
 msgid "Recipients:"
-msgstr "Destinatarios"
+msgstr "Destinatarios :"
 
 msgid "RegexpConstraint"
-msgstr ""
+msgstr "restricción expresión regular"
 
 msgid "Registry's content"
-msgstr ""
+msgstr "Contenido del registro"
 
 msgid "Relation types"
-msgstr ""
+msgstr "Tipos de relación"
 
 msgid "Relations"
 msgstr "Relaciones"
 
 msgid "Repository"
-msgstr ""
+msgstr "Repositorio"
 
 #, python-format
 msgid "Schema %s"
@@ -604,10 +615,10 @@
 msgstr "Buscar"
 
 msgid "SizeConstraint"
-msgstr ""
+msgstr "Restricción de tamaño"
 
 msgid "Startup views"
-msgstr "Vistas de Inicio"
+msgstr "Vistas de inicio"
 
 msgid "State"
 msgstr "Estado"
@@ -616,7 +627,7 @@
 msgstr "Estados"
 
 msgid "StaticVocabularyConstraint"
-msgstr ""
+msgstr "Restricción de vocabulario"
 
 msgid "String"
 msgstr "Cadena de caracteres"
@@ -625,13 +636,13 @@
 msgstr "Cadenas de caracteres"
 
 msgid "Sub-classes:"
-msgstr ""
+msgstr "Clases hijas:"
 
 msgid "SubWorkflowExitPoint"
-msgstr ""
+msgstr "Salida de sub-workflow"
 
 msgid "SubWorkflowExitPoint_plural"
-msgstr ""
+msgstr "Salidas de sub-workflow"
 
 msgid "Subject:"
 msgstr "Sujeto:"
@@ -651,10 +662,10 @@
 msgstr "La vista %s no ha podido ser encontrada"
 
 msgid "There is no default workflow"
-msgstr ""
+msgstr "Esta entidad no posee workflow por defecto"
 
 msgid "This BaseTransition"
-msgstr ""
+msgstr "Esta transición abstracta"
 
 msgid "This Bookmark"
 msgstr "Este favorito"
@@ -663,7 +674,7 @@
 msgstr "Esta definición de relación final"
 
 msgid "This CWCache"
-msgstr "Este Cache"
+msgstr "Este Caché"
 
 msgid "This CWConstraint"
 msgstr "Esta Restricción"
@@ -678,7 +689,7 @@
 msgstr "Este grupo"
 
 msgid "This CWPermission"
-msgstr "Esta autorización"
+msgstr "Este permiso"
 
 msgid "This CWProperty"
 msgstr "Esta propiedad"
@@ -696,7 +707,7 @@
 msgstr "Esta dirección electrónica"
 
 msgid "This ExternalUri"
-msgstr ""
+msgstr "Este Uri externo"
 
 msgid "This RQLExpression"
 msgstr "Esta expresión RQL"
@@ -705,7 +716,7 @@
 msgstr "Este estado"
 
 msgid "This SubWorkflowExitPoint"
-msgstr ""
+msgstr "Esta Salida de sub-workflow"
 
 msgid "This TrInfo"
 msgstr "Esta información de transición"
@@ -714,13 +725,13 @@
 msgstr "Esta transición"
 
 msgid "This Workflow"
-msgstr ""
+msgstr "Este Workflow"
 
 msgid "This WorkflowTransition"
-msgstr ""
+msgstr "Esta transición de Workflow"
 
 msgid "This entity type permissions:"
-msgstr ""
+msgstr "Permisos para este tipo de entidad:"
 
 msgid "Time"
 msgstr "Hora"
@@ -741,34 +752,34 @@
 msgstr "Transiciones"
 
 msgid "UniqueConstraint"
-msgstr ""
+msgstr "Restricción de Unicidad"
 
 msgid "Unreachable objects"
-msgstr ""
+msgstr "Objetos inaccesibles"
 
 msgid "Used by:"
 msgstr "Utilizado por :"
 
 msgid "Web server"
-msgstr ""
+msgstr "Servidor web"
 
 msgid "What's new?"
-msgstr "Lo último en el sitio"
+msgstr "Lo más reciente"
 
 msgid "Workflow"
-msgstr ""
+msgstr "Workflow"
 
 msgid "Workflow history"
 msgstr "Histórico del Workflow"
 
 msgid "WorkflowTransition"
-msgstr ""
+msgstr "Transición de Workflow"
 
 msgid "WorkflowTransition_plural"
-msgstr ""
+msgstr "Transiciones de Workflow"
 
 msgid "Workflow_plural"
-msgstr ""
+msgstr "work flows"
 
 msgid ""
 "You can either submit a new file using the browse button above, or choose to "
@@ -797,14 +808,14 @@
 "You have no access to this view or it can not be used to display the current "
 "data."
 msgstr ""
-"No tiene acceso a esta vista o No se puede utilizare para los datos actuales."
+"No tiene permisos para accesar esta vista o No puede utilizarse para desplegar los datos seleccionados."
 
 msgid ""
 "You're not authorized to access this page. If you think you should, please "
 "contact the site administrator."
 msgstr ""
 "Usted no esta autorizado a acceder a esta página. Si Usted cree que \n"
-"hay un error, favor de contactar al administrador del sitio."
+"hay un error, favor de contactar al administrador del Sistema."
 
 #, python-format
 msgid "[%s supervision] changes summary"
@@ -820,10 +831,10 @@
 "representan respectivamente la entidad en transición y el usuario actual. "
 
 msgid "a URI representing an object in external data store"
-msgstr ""
+msgstr "una URI designando un objeto en un repositorio de datos externo"
 
 msgid "a float is expected"
-msgstr ""
+msgstr "un número flotante es requerido"
 
 msgid ""
 "a simple cache entity characterized by a name and a validity date. The "
@@ -831,18 +842,23 @@
 "invalidate the cache (typically in hooks). Also, checkout the AppObject."
 "get_cache() method."
 msgstr ""
+"un caché simple caracterizado por un nombre y una fecha de validez. Es\n"
+"el código de la instancia quién es responsable de actualizar la fecha de\n"
+"validez mientras el caché debe ser invalidado (en general en un hook).\n"
+"Para recuperar un caché, hace falta utilizar el método\n"
+"get_cache(cachename)."
 
 msgid "about this site"
-msgstr "Sobre este Espacio"
+msgstr "Información del Sistema"
 
 msgid "abstract base class for transitions"
-msgstr ""
+msgstr "Clase de base abstracta para la transiciones"
 
 msgid "action(s) on this selection"
-msgstr "acción(es) en esta selección"
+msgstr "Acción(es) en esta selección"
 
 msgid "actions"
-msgstr "acciones"
+msgstr "Acciones"
 
 msgid "activate"
 msgstr "Activar"
@@ -860,13 +876,13 @@
 msgstr "Restricción"
 
 msgid "add CWAttribute read_permission RQLExpression subject"
-msgstr ""
+msgstr "Expresión RQL de lectura"
 
 msgid "add CWAttribute relation_type CWRType object"
 msgstr "Definición de atributo"
 
 msgid "add CWAttribute update_permission RQLExpression subject"
-msgstr ""
+msgstr "Permiso de actualización"
 
 msgid "add CWEType add_permission RQLExpression subject"
 msgstr "Expresión RQL de agregación"
@@ -884,16 +900,16 @@
 msgstr "Propiedad"
 
 msgid "add CWRelation add_permission RQLExpression subject"
-msgstr ""
+msgstr "Expresión RQL de agregar"
 
 msgid "add CWRelation constrained_by CWConstraint subject"
 msgstr "Restricción"
 
 msgid "add CWRelation delete_permission RQLExpression subject"
-msgstr ""
+msgstr "Expresión RQL de supresión"
 
 msgid "add CWRelation read_permission RQLExpression subject"
-msgstr ""
+msgstr "Expresión RQL de lectura"
 
 msgid "add CWRelation relation_type CWRType object"
 msgstr "Definición de relación"
@@ -911,10 +927,10 @@
 msgstr "Transición en salida"
 
 msgid "add State allowed_transition WorkflowTransition subject"
-msgstr ""
+msgstr "Transición workflow en salida"
 
 msgid "add State state_of Workflow object"
-msgstr ""
+msgstr "Estado"
 
 msgid "add Transition condition RQLExpression subject"
 msgstr "Restricción"
@@ -926,32 +942,32 @@
 msgstr "Estado de salida"
 
 msgid "add Transition transition_of Workflow object"
-msgstr ""
+msgstr "Transición"
 
 msgid "add WorkflowTransition condition RQLExpression subject"
-msgstr ""
+msgstr "Condición"
 
 msgid "add WorkflowTransition subworkflow_exit SubWorkflowExitPoint subject"
-msgstr ""
+msgstr "Salida de sub-workflow"
 
 msgid "add WorkflowTransition transition_of Workflow object"
-msgstr ""
+msgstr "Transición Workflow"
 
 msgctxt "inlined:CWRelation.from_entity.subject"
 msgid "add a CWEType"
-msgstr ""
+msgstr "Agregar un tipo de entidad"
 
 msgctxt "inlined:CWRelation.to_entity.subject"
 msgid "add a CWEType"
-msgstr ""
+msgstr "Agregar un tipo de entidad"
 
 msgctxt "inlined:CWRelation.relation_type.subject"
 msgid "add a CWRType"
-msgstr ""
+msgstr "Agregar un tipo de relación"
 
 msgctxt "inlined:CWUser.use_email.subject"
 msgid "add a EmailAddress"
-msgstr ""
+msgstr "Agregar correo electrónico"
 
 msgid "add a new permission"
 msgstr "Agregar una autorización"
@@ -968,77 +984,79 @@
 # (no object form for final relation types)
 msgctxt "CWEType"
 msgid "add_permission"
-msgstr ""
+msgstr "Permiso de agregar"
 
 msgctxt "CWRelation"
 msgid "add_permission"
-msgstr ""
+msgstr "Permiso de agregar"
 
 msgctxt "CWGroup"
 msgid "add_permission_object"
-msgstr ""
+msgstr "tiene permiso de agregar"
 
 msgctxt "RQLExpression"
 msgid "add_permission_object"
-msgstr ""
+msgstr "tiene permiso de agregar"
 
 msgid "add_permission_object"
-msgstr "tiene la autorización para agregar"
+msgstr "tiene permiso de agregar"
 
 msgid "add_relation"
-msgstr ""
+msgstr "agregar"
 
 #, python-format
 msgid "added %(etype)s #%(eid)s (%(title)s)"
-msgstr "Agregado %(etype)s #%(eid)s (%(title)s)"
+msgstr "se agregó %(etype)s #%(eid)s (%(title)s)"
 
 #, python-format
 msgid ""
 "added relation %(rtype)s from %(frometype)s #%(eidfrom)s to %(toetype)s #%"
 "(eidto)s"
 msgstr ""
+"la relación %(rtype)s de %(frometype)s #%(eidfrom)s a %(toetype)s #%"
+"(eidto)s ha sido agregada"
 
 msgid "addrelated"
-msgstr ""
+msgstr "Agregar"
 
 msgid "address"
-msgstr "dirección"
+msgstr "correo electrónico"
 
 msgctxt "EmailAddress"
 msgid "address"
-msgstr ""
+msgstr "correo electrónico"
 
 msgid "alias"
 msgstr "alias"
 
 msgctxt "EmailAddress"
 msgid "alias"
-msgstr ""
+msgstr "alias"
 
 msgid "allow to set a specific workflow for an entity"
-msgstr ""
+msgstr "permite definir un Workflow específico para una entidad"
 
 msgid "allowed transitions from this state"
 msgstr "transiciones autorizadas desde este estado"
 
 msgid "allowed_transition"
-msgstr "transición autorizada"
+msgstr "transiciones autorizadas"
 
 msgctxt "State"
 msgid "allowed_transition"
-msgstr ""
+msgstr "transiciones autorizadas"
 
 msgctxt "BaseTransition"
 msgid "allowed_transition_object"
-msgstr ""
+msgstr "transición autorizada de"
 
 msgctxt "Transition"
 msgid "allowed_transition_object"
-msgstr ""
+msgstr "transición autorizada de"
 
 msgctxt "WorkflowTransition"
 msgid "allowed_transition_object"
-msgstr ""
+msgstr "transición autorizada de"
 
 msgid "allowed_transition_object"
 msgstr "Estados de entrada"
@@ -1058,26 +1076,26 @@
 msgid "an electronic mail address associated to a short alias"
 msgstr "una dirección electrónica asociada a este alias"
 
-msgid "an error occured"
-msgstr "ha ocurrido un error"
-
-msgid "an error occured while processing your request"
+msgid "an error occurred"
+msgstr "Ha ocurrido un error"
+
+msgid "an error occurred while processing your request"
 msgstr "un error ocurrió al procesar su demanda"
 
-msgid "an error occured, the request cannot be fulfilled"
+msgid "an error occurred, the request cannot be fulfilled"
 msgstr "un error ha ocurrido, la búsqueda no ha podido ser realizada"
 
 msgid "an integer is expected"
-msgstr ""
+msgstr "un número entero es esperado"
 
 msgid "and linked"
-msgstr "y ligada"
+msgstr "y relacionada"
 
 msgid "and/or between different values"
 msgstr "y/o entre los diferentes valores"
 
 msgid "anonymous"
-msgstr "Anónimo"
+msgstr "anónimo"
 
 msgid "application entities"
 msgstr "Entidades de la aplicación"
@@ -1088,8 +1106,7 @@
 #, python-format
 msgid "at least one relation %(rtype)s is required on %(etype)s (%(eid)s)"
 msgstr ""
-"La entidad #%(eid)s de tipo %(etype)s debe necesariamente estar ligada a \n"
-"otra via la relación %(rtype)s"
+"La entidad #%(eid)s de tipo %(etype)s debe necesariamente tener almenos una relación de tipo %(rtype)s"
 
 msgid "attribute"
 msgstr "Atributo"
@@ -1101,7 +1118,7 @@
 msgstr "Usuario o contraseña incorrecta"
 
 msgid "auto"
-msgstr ""
+msgstr "Automático"
 
 msgid "automatic"
 msgstr "Automático"
@@ -1113,33 +1130,33 @@
 msgstr "Url de base"
 
 msgid "bookmark has been removed"
-msgstr "ha sido eliminado de sus favoritos"
+msgstr "Ha sido eliminado de sus favoritos"
 
 msgid "bookmark this page"
-msgstr "Agregar esta página a sus favoritos"
+msgstr "Agregar esta página a los favoritos"
 
 msgid "bookmark this search"
 msgstr "Guardar esta búsqueda"
 
 msgid "bookmarked_by"
-msgstr "está en los favoritos de"
+msgstr "está en los Favoritos de"
 
 msgctxt "Bookmark"
 msgid "bookmarked_by"
-msgstr ""
+msgstr "está en los Favoritos de"
 
 msgctxt "CWUser"
 msgid "bookmarked_by_object"
-msgstr ""
+msgstr "tiene como Favoritos"
 
 msgid "bookmarked_by_object"
-msgstr "selecciona en sus favoritos a"
+msgstr "tiene como Favoritos"
 
 msgid "bookmarks"
 msgstr "Favoritos"
 
 msgid "bookmarks are used to have user's specific internal links"
-msgstr "favoritos son usados para que un usuario recorde ligas"
+msgstr "los Favoritos son ligas directas a espacios guardados por el usuario"
 
 msgid "boxes"
 msgstr "Cajas"
@@ -1148,50 +1165,50 @@
 msgstr "Caja de Favoritos"
 
 msgid "boxes_bookmarks_box_description"
-msgstr "Caja que contiene los espacios favoritos del usuario"
+msgstr "Muestra y permite administrar los favoritos del usuario"
 
 msgid "boxes_download_box"
-msgstr "Caja de download"
+msgstr "Configuración de caja de descargas"
 
 msgid "boxes_download_box_description"
-msgstr "Caja que contiene los elementos bajados"
+msgstr "Caja que contiene los elementos descargados"
 
 msgid "boxes_edit_box"
-msgstr "Caja de acciones"
+msgstr "Caja de Acciones"
 
 msgid "boxes_edit_box_description"
 msgstr ""
-"Caja que muestra las diferentes acciones posibles sobre los datos presentes"
+"Muestra las acciones posibles a ejecutar para los datos seleccionados"
 
 msgid "boxes_filter_box"
 msgstr "Filtros"
 
 msgid "boxes_filter_box_description"
-msgstr "Caja que permite realizar filtros sobre los resultados de una búsqueda"
+msgstr "Muestra los filtros aplicables a una búsqueda realizada"
 
 msgid "boxes_possible_views_box"
 msgstr "Caja de Vistas Posibles"
 
 msgid "boxes_possible_views_box_description"
-msgstr "Caja mostrando las vistas posibles para los datos actuales"
+msgstr "Muestra las vistas posibles a aplicar a los datos seleccionados"
 
 msgid "boxes_rss"
-msgstr "ícono RSS"
+msgstr "Ícono RSS"
 
 msgid "boxes_rss_description"
-msgstr "El ícono RSS permite recuperar las vistas RSS de los datos presentes"
+msgstr "Muestra el ícono RSS para vistas RSS"
 
 msgid "boxes_search_box"
 msgstr "Caja de búsqueda"
 
 msgid "boxes_search_box_description"
-msgstr "Caja con un espacio de búsqueda simple"
+msgstr "Permite realizar una búsqueda simple para cualquier tipo de dato en la aplicación"
 
 msgid "boxes_startup_views_box"
 msgstr "Caja Vistas de inicio"
 
 msgid "boxes_startup_views_box_description"
-msgstr "Caja mostrando las vistas de inicio de la aplicación"
+msgstr "Muestra las vistas de inicio de la aplicación"
 
 msgid "bug report sent"
 msgstr "Reporte de error enviado"
@@ -1212,29 +1229,29 @@
 msgstr "por"
 
 msgid "by relation"
-msgstr "por relación"
+msgstr "por la relación"
 
 msgid "by_transition"
-msgstr ""
+msgstr "transición"
 
 msgctxt "TrInfo"
 msgid "by_transition"
-msgstr ""
+msgstr "transición"
 
 msgctxt "BaseTransition"
 msgid "by_transition_object"
-msgstr ""
+msgstr "tiene como información"
 
 msgctxt "Transition"
 msgid "by_transition_object"
-msgstr ""
+msgstr "tiene como información"
 
 msgctxt "WorkflowTransition"
 msgid "by_transition_object"
-msgstr ""
+msgstr "tiene como información"
 
 msgid "by_transition_object"
-msgstr ""
+msgstr "cambio de estados"
 
 msgid "calendar"
 msgstr "mostrar un calendario"
@@ -1252,13 +1269,13 @@
 msgstr "calendario (anual)"
 
 msgid "can not resolve entity types:"
-msgstr ""
+msgstr "Imposible de interpretar los tipos de entidades:"
 
 msgid "can't be changed"
-msgstr ""
+msgstr "No puede ser modificado"
 
 msgid "can't be deleted"
-msgstr ""
+msgstr "No puede ser eliminado"
 
 #, python-format
 msgid "can't change the %s attribute"
@@ -1273,11 +1290,11 @@
 msgstr "imposible de mostrar los datos, a causa del siguiente error: %s"
 
 msgid "can't have multiple exits on the same state"
-msgstr ""
+msgstr "no puede tener varias salidas en el mismo estado"
 
 #, python-format
 msgid "can't parse %(value)r (expected %(format)s)"
-msgstr ""
+msgstr "no puede analizar %(value)r (formato requerido : %(format)s)"
 
 #, python-format
 msgid ""
@@ -1298,14 +1315,14 @@
 
 msgctxt "CWAttribute"
 msgid "cardinality"
-msgstr ""
+msgstr "cardinalidad"
 
 msgctxt "CWRelation"
 msgid "cardinality"
-msgstr ""
+msgstr "cardinalidad"
 
 msgid "category"
-msgstr "categoria"
+msgstr "categoría"
 
 #, python-format
 msgid "changed state of %(etype)s #%(eid)s (%(title)s)"
@@ -1315,62 +1332,61 @@
 msgstr "Cambios realizados"
 
 msgid "click here to see created entity"
-msgstr "ver la entidad creada"
+msgstr "Ver la entidad creada"
 
 msgid "click on the box to cancel the deletion"
 msgstr "Seleccione la zona de edición para cancelar la eliminación"
 
 msgid "click to add a value"
-msgstr ""
+msgstr "seleccione para agregar un valor"
 
 msgid "click to delete this value"
-msgstr ""
+msgstr "seleccione para eliminar este valor"
 
 msgid "click to edit this field"
-msgstr ""
+msgstr "seleccione para editar este campo"
 
 msgid "comment"
 msgstr "Comentario"
 
 msgctxt "TrInfo"
 msgid "comment"
-msgstr ""
+msgstr "Comentario"
 
 msgid "comment_format"
 msgstr "Formato"
 
 msgctxt "TrInfo"
 msgid "comment_format"
-msgstr ""
+msgstr "Formato"
 
 msgid "components"
 msgstr "Componentes"
 
 msgid "components_appliname"
-msgstr "Título de la aplicación"
+msgstr "Nombre de la aplicación"
 
 msgid "components_appliname_description"
-msgstr "Muestra el título de la aplicación en el encabezado de la página"
+msgstr "Muestra el nombre de la aplicación en el encabezado de la página"
 
 msgid "components_breadcrumbs"
 msgstr "Ruta de Navegación"
 
 msgid "components_breadcrumbs_description"
 msgstr ""
-"Muestra un camino que permite identificar el lugar donde se encuentra la "
-"página en el sitio"
+"Muestra el lugar donde se encuentra la página actual en el Sistema"
 
 msgid "components_etypenavigation"
-msgstr "Filtro por tipo"
+msgstr "Filtar por tipo"
 
 msgid "components_etypenavigation_description"
-msgstr "Permite filtrar por tipo de entidad los resultados de búsqueda"
+msgstr "Permite filtrar por tipo de entidad los resultados de una búsqueda"
 
 msgid "components_help"
 msgstr "Botón de ayuda"
 
 msgid "components_help_description"
-msgstr "El botón de ayuda, en el encabezado de página"
+msgstr "El botón de ayuda, en el encabezado de la página"
 
 msgid "components_loggeduserlink"
 msgstr "Liga usuario"
@@ -1378,10 +1394,10 @@
 msgid "components_loggeduserlink_description"
 msgstr ""
 "Muestra un enlace hacia el formulario de conexión para los usuarios "
-"anónimos, o una caja que contiene las ligas propias a el usuarioconectado. "
+"anónimos, o una caja que contiene los enlaces del usuario conectado. "
 
 msgid "components_logo"
-msgstr "Logo"
+msgstr "logo"
 
 msgid "components_logo_description"
 msgstr "El logo de la aplicación, en el encabezado de página"
@@ -1391,76 +1407,76 @@
 
 msgid "components_navigation_description"
 msgstr ""
-"Componente que permite distribuir sobre varias páginas las búsquedas que "
-"arrojan mayores resultados que un número previamente elegido"
+"Componente que permite presentar en varias páginas los resultados de  búsqueda "
+" cuando son mayores a un número predeterminado "
 
 msgid "components_rqlinput"
-msgstr "Barra rql"
+msgstr "Barra RQL"
 
 msgid "components_rqlinput_description"
-msgstr "La barra de demanda rql, en el encabezado de página"
+msgstr "La barra para realizar consultas en RQL, en el encabezado de página"
 
 msgid "composite"
 msgstr "composite"
 
 msgctxt "CWRelation"
 msgid "composite"
-msgstr ""
+msgstr "composite"
 
 msgid "condition"
 msgstr "condición"
 
 msgctxt "BaseTransition"
 msgid "condition"
-msgstr ""
+msgstr "condición"
 
 msgctxt "Transition"
 msgid "condition"
-msgstr ""
+msgstr "condición"
 
 msgctxt "WorkflowTransition"
 msgid "condition"
-msgstr ""
+msgstr "condición"
 
 msgctxt "RQLExpression"
 msgid "condition_object"
-msgstr ""
+msgstr "condición de"
 
 msgid "condition_object"
 msgstr "condición de"
 
 msgid "conditions"
-msgstr ""
+msgstr "condiciones"
 
 msgid "config mode"
-msgstr ""
+msgstr "Modo de configuración"
 
 msgid "config type"
-msgstr ""
+msgstr "Tipo de configuración"
 
 msgid "confirm password"
 msgstr "Confirmar contraseña"
 
 msgid "constrained_by"
-msgstr "Restricción hecha por"
+msgstr "Restricción impuesta por"
 
 msgctxt "CWAttribute"
 msgid "constrained_by"
-msgstr ""
+msgstr "Restricción impuesta por"
 
 msgctxt "CWRelation"
 msgid "constrained_by"
-msgstr ""
+msgstr "Restricción impuesta por"
 
 msgctxt "CWConstraint"
 msgid "constrained_by_object"
-msgstr ""
+msgstr "Restricción de"
 
 msgid "constrained_by_object"
-msgstr "ha restringido"
+msgstr "Restricción de"
 
 msgid "constraint factory"
-msgstr "FAbrica de restricciones"
+msgstr "Fábrica de restricciones"
 
 msgid "constraints"
 msgstr "Restricciones"
@@ -1469,7 +1485,7 @@
 msgstr "Restricciones que se aplican a esta relación"
 
 msgid "content type"
-msgstr ""
+msgstr "tipo MIME"
 
 msgid "contentnavigation"
 msgstr "Componentes contextuales"
@@ -1478,10 +1494,10 @@
 msgstr "Ruta de Navegación"
 
 msgid "contentnavigation_breadcrumbs_description"
-msgstr "Muestra un camino que permite localizar la página actual en el sitio"
+msgstr "Muestra la ruta que permite localizar la página actual en el Sistema"
 
 msgid "contentnavigation_metadata"
-msgstr ""
+msgstr "Metadatos de la Entidad"
 
 msgid "contentnavigation_metadata_description"
 msgstr ""
@@ -1491,7 +1507,7 @@
 
 msgid "contentnavigation_prevnext_description"
 msgstr ""
-"Muestra las ligas que permiten pasar de una entidad a otra en lasentidades "
+"Muestra las ligas que permiten pasar de una entidad a otra en las entidades "
 "que implementan la interface \"anterior/siguiente\"."
 
 msgid "contentnavigation_seealso"
@@ -1499,7 +1515,7 @@
 
 msgid "contentnavigation_seealso_description"
 msgstr ""
-"sección que muestra las entidades ligadas por la relación \"vea también\" , "
+"sección que muestra las entidades relacionadas por la relación \"vea también\" , "
 "si la entidad soporta esta relación."
 
 msgid "contentnavigation_wfhistory"
@@ -1507,8 +1523,8 @@
 
 msgid "contentnavigation_wfhistory_description"
 msgstr ""
-"Sección que ofrece el reporte histórico del workflow para las entidades que "
-"posean un workflow."
+"Sección que muestra el reporte histórico de las transiciones del workflow."
+" Aplica solo en entidades con workflow."
 
 msgid "context"
 msgstr "Contexto"
@@ -1520,7 +1536,7 @@
 msgstr "Contexto en el cual el componente debe aparecer en el sistema"
 
 msgid "context where this facet should be displayed, leave empty for both"
-msgstr ""
+msgstr "Contexto en el cual esta faceta debe ser mostrada, dejar vacia para ambos"
 
 msgid "control subject entity's relations order"
 msgstr "Controla el orden de relaciones de la entidad sujeto"
@@ -1537,14 +1553,14 @@
 "the owner into the owners group for the entity"
 msgstr ""
 "Relación sistema que indica el(los) propietario(s) de una entidad. Esta "
-"relación pone de manera implícita al propietario en el grupo de propietarios "
-"de una entidad"
+"relación pone de manera implícita al propietario en el grupo de "
+"propietarios de una entidad."
 
 msgid "core relation indicating the original creator of an entity"
 msgstr "Relación sistema que indica el creador de una entidad."
 
 msgid "core relation indicating the type of an entity"
-msgstr "Relación sistema que indica el tipo de entidad"
+msgstr "Relación sistema que indica el tipo de entidad."
 
 msgid ""
 "core relation indicating the types (including specialized types) of an entity"
@@ -1565,7 +1581,7 @@
 msgstr "Crear una página de inicio"
 
 msgid "created on"
-msgstr "Creado el"
+msgstr "creado el"
 
 msgid "created_by"
 msgstr "creado por"
@@ -1601,12 +1617,13 @@
 
 msgid ""
 "creating RQLExpression (CWAttribute %(linkto)s read_permission RQLExpression)"
-msgstr ""
+msgstr "creación de una expresión RQL por el derecho de lectura de %(linkto)s"
+
 
 msgid ""
 "creating RQLExpression (CWAttribute %(linkto)s update_permission "
 "RQLExpression)"
-msgstr ""
+msgstr "creación de una expresión RQL por el derecho de actualización de %(linkto)s"
 
 msgid ""
 "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
@@ -1620,24 +1637,24 @@
 
 msgid ""
 "creating RQLExpression (CWEType %(linkto)s read_permission RQLExpression)"
-msgstr "Creación de una expresión RQL para la autorización de leer %(linkto)s"
+msgstr "Creación de una expresión RQL para permitir leer %(linkto)s"
 
 msgid ""
 "creating RQLExpression (CWEType %(linkto)s update_permission RQLExpression)"
-msgstr "Creación de una expresión RQL para autorizar actualizar %(linkto)s"
+msgstr "Creación de una expresión RQL para permitir actualizar %(linkto)s"
 
 msgid ""
 "creating RQLExpression (CWRelation %(linkto)s add_permission RQLExpression)"
-msgstr ""
+msgstr "Creación de una expresión RQL para permitir agregar %(linkto)s"
 
 msgid ""
 "creating RQLExpression (CWRelation %(linkto)s delete_permission "
 "RQLExpression)"
-msgstr ""
+msgstr "Creación de una expresión RQL para permitir eliminar %(linkto)s"
 
 msgid ""
 "creating RQLExpression (CWRelation %(linkto)s read_permission RQLExpression)"
-msgstr ""
+msgstr "Creación de una expresión RQL para permitir leer %(linkto)s"
 
 msgid "creating RQLExpression (Transition %(linkto)s condition RQLExpression)"
 msgstr "Creación de una expresión RQL para la transición %(linkto)s"
@@ -1645,63 +1662,63 @@
 msgid ""
 "creating RQLExpression (WorkflowTransition %(linkto)s condition "
 "RQLExpression)"
-msgstr ""
+msgstr "Creación de una expresión RQL para la transición Workflow %(linkto)s"
 
 msgid "creating State (State allowed_transition Transition %(linkto)s)"
-msgstr "Creación de un estado que pueda ir hacia la transición %(linkto)s"
+msgstr "Creación de un estado que puede ir hacia la transición %(linkto)s"
 
 msgid "creating State (State state_of Workflow %(linkto)s)"
-msgstr ""
+msgstr "Creando un Estado del Workflow"
 
 msgid "creating State (Transition %(linkto)s destination_state State)"
-msgstr "Creación de un estado destinación de la transición %(linkto)s"
+msgstr "Creación de un Estado Destinación de la Transición %(linkto)s"
 
 msgid ""
 "creating SubWorkflowExitPoint (WorkflowTransition %(linkto)s "
 "subworkflow_exit SubWorkflowExitPoint)"
-msgstr ""
+msgstr "creación de un punto de Salida de la Transición Workflow %(linkto)s"
 
 msgid "creating Transition (State %(linkto)s allowed_transition Transition)"
-msgstr "Creación de una transición autorizada desde el estado %(linkto)s"
+msgstr "Creación de una transición autorizada desde el Estado %(linkto)s"
 
 msgid "creating Transition (Transition destination_state State %(linkto)s)"
-msgstr "Creación de un transición hacia el estado %(linkto)s"
+msgstr "Creación de un transición hacia el Estado %(linkto)s"
 
 msgid "creating Transition (Transition transition_of Workflow %(linkto)s)"
-msgstr ""
+msgstr "Creación de una Transición Workflow %(linkto)s"
 
 msgid ""
 "creating WorkflowTransition (State %(linkto)s allowed_transition "
 "WorkflowTransition)"
-msgstr ""
+msgstr "Creación de una Transición Workflow permitida desde el estado %(linkto)s"
 
 msgid ""
 "creating WorkflowTransition (WorkflowTransition transition_of Workflow %"
 "(linkto)s)"
-msgstr ""
+msgstr "Creación de una Transición Workflow del Workflow %(linkto)s"
 
 msgid "creation"
 msgstr "Creación"
 
 msgid "creation date"
-msgstr ""
+msgstr "Fecha de Creación"
 
 msgid "creation time of an entity"
 msgstr "Fecha de creación de una entidad"
 
 msgid "creation_date"
-msgstr "fecha de creación"
+msgstr "Fecha de Creación"
 
 msgid "cstrtype"
-msgstr "Tipo de condición"
+msgstr "Tipo de restricción"
 
 msgctxt "CWConstraint"
 msgid "cstrtype"
-msgstr ""
+msgstr "Tipo"
 
 msgctxt "CWConstraintType"
 msgid "cstrtype_object"
-msgstr ""
+msgstr "Tipo de restricciones"
 
 msgid "cstrtype_object"
 msgstr "utilizado por"
@@ -1710,46 +1727,46 @@
 msgstr "Exportar entidades en csv"
 
 msgid "csv export"
-msgstr "Exportar CSV"
+msgstr "Exportar en CSV"
 
 msgid "ctxtoolbar"
-msgstr ""
+msgstr "Barra de herramientas"
 
 msgid "custom_workflow"
-msgstr ""
+msgstr "Workflow específico"
 
 msgid "custom_workflow_object"
-msgstr ""
+msgstr "Workflow de"
 
 msgid "cwetype-box"
-msgstr ""
+msgstr "Vista \"caja\""
 
 msgid "cwetype-description"
-msgstr ""
+msgstr "Descripción"
 
 msgid "cwetype-permissions"
-msgstr ""
+msgstr "Permisos"
 
 msgid "cwetype-views"
-msgstr ""
+msgstr "Vistas"
 
 msgid "cwetype-workflow"
-msgstr ""
+msgstr "Workflow"
 
 msgid "cwgroup-main"
-msgstr ""
+msgstr "Descripción"
 
 msgid "cwgroup-permissions"
-msgstr ""
+msgstr "Permisos"
 
 msgid "cwrtype-description"
-msgstr ""
+msgstr "Descripción"
 
 msgid "cwrtype-permissions"
-msgstr ""
+msgstr "Permisos"
 
 msgid "cwuri"
-msgstr ""
+msgstr "Uri Interna"
 
 msgid "data directory url"
 msgstr "Url del repertorio de datos"
@@ -1770,37 +1787,37 @@
 msgstr "Valor por defecto"
 
 msgid "default text format for rich text fields."
-msgstr "Formato de texto como opción por defecto para los campos texto"
+msgstr "Formato de texto que se utilizará por defecto para los campos de tipo texto"
 
 msgid "default user workflow"
-msgstr ""
+msgstr "Workflow por defecto de los usuarios"
 
 msgid "default value"
-msgstr ""
+msgstr "Valor por defecto"
 
 msgid "default workflow for an entity type"
-msgstr ""
+msgstr "Workflow por defecto para un tipo de entidad"
 
 msgid "default_workflow"
-msgstr ""
+msgstr "Workflow por defecto"
 
 msgctxt "CWEType"
 msgid "default_workflow"
-msgstr ""
+msgstr "Workflow por defecto"
 
 msgctxt "Workflow"
 msgid "default_workflow_object"
-msgstr ""
+msgstr "Workflow por defecto de"
 
 msgid "default_workflow_object"
-msgstr ""
+msgstr "Workflow por defecto de"
 
 msgid "defaultval"
 msgstr "Valor por defecto"
 
 msgctxt "CWAttribute"
 msgid "defaultval"
-msgstr ""
+msgstr "Valor por defecto"
 
 msgid "define a CubicWeb user"
 msgstr "Define un usuario CubicWeb"
@@ -1812,14 +1829,19 @@
 "define a final relation: link a final relation type from a non final entity "
 "to a final entity type. used to build the instance schema"
 msgstr ""
+"Define una relación final: liga un tipo de relación final desde una entidad "
+"NO final hacia un tipo de entidad final. Se usa para crear el esquema de " "la instancia."
 
 msgid ""
 "define a non final relation: link a non final relation type from a non final "
 "entity to a non final entity type. used to build the instance schema"
 msgstr ""
+"Define una relación NO final: liga un tipo de relación NO final desde una  "
+"entidad NO final hacia un tipo de entidad NO final. Se usa para crear el " "esquema de la instancia."
+
 
 msgid "define a relation type, used to build the instance schema"
-msgstr ""
+msgstr "Define un tipo de relación, usado para construir el esquema de la " "instancia."
 
 msgid "define a rql expression used to define permissions"
 msgstr "Expresión RQL utilizada para definir los derechos de acceso"
@@ -1831,17 +1853,17 @@
 msgstr "Define un tipo de condición de esquema"
 
 msgid "define an entity type, used to build the instance schema"
-msgstr ""
+msgstr "Define un tipo de entidad, usado para construir el esquema de la " "instancia."
 
 msgid "define how we get out from a sub-workflow"
-msgstr ""
+msgstr "Define como salir de un sub-Workflow"
 
 msgid ""
 "defines what's the property is applied for. You must select this first to be "
 "able to set value"
 msgstr ""
-"Define a que se aplica la propiedad . Usted debe seleccionar esto antes de "
-"poder fijar un valor"
+"Define a que se aplica la propiedad . Debe de seleccionar esto antes de "
+"establecer un valor"
 
 msgid "delete"
 msgstr "Eliminar"
@@ -1859,26 +1881,26 @@
 msgstr "Eliminar"
 
 msgid "delete_permission"
-msgstr "Autorización de eliminar"
+msgstr "Permiso de eliminar"
 
 msgctxt "CWEType"
 msgid "delete_permission"
-msgstr ""
+msgstr "Permiso de eliminar"
 
 msgctxt "CWRelation"
 msgid "delete_permission"
-msgstr ""
+msgstr "Permiso de eliminar"
 
 msgctxt "CWGroup"
 msgid "delete_permission_object"
-msgstr ""
+msgstr "puede eliminar"
 
 msgctxt "RQLExpression"
 msgid "delete_permission_object"
-msgstr ""
+msgstr "puede eliminar"
 
 msgid "delete_permission_object"
-msgstr "posee la autorización de eliminar"
+msgstr "posee permiso para eliminar"
 
 #, python-format
 msgid "deleted %(etype)s #%(eid)s (%(title)s)"
@@ -1889,93 +1911,95 @@
 "deleted relation %(rtype)s from %(frometype)s #%(eidfrom)s to %(toetype)s #%"
 "(eidto)s"
 msgstr ""
+"La relación %(rtype)s de %(frometype)s #%(eidfrom)s a %(toetype)s #%(eidto)s "
+"ha sido suprimida."
 
 msgid "depends on the constraint type"
-msgstr "Depende del tipo de condición"
+msgstr "Depende del tipo de restricción"
 
 msgid "description"
 msgstr "Descripción"
 
 msgctxt "CWEType"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "CWRelation"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "Workflow"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "CWAttribute"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "Transition"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "WorkflowTransition"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "State"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "CWRType"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgctxt "BaseTransition"
 msgid "description"
-msgstr ""
+msgstr "Descripción"
 
 msgid "description_format"
 msgstr "Formato"
 
 msgctxt "CWEType"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "CWRelation"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "Workflow"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "CWAttribute"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "Transition"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "WorkflowTransition"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "State"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "CWRType"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgctxt "BaseTransition"
 msgid "description_format"
-msgstr ""
+msgstr "Formato"
 
 msgid "destination state for this transition"
-msgstr "Estado destino para esta transición"
+msgstr "Estados accesibles para esta transición"
 
 msgid "destination state must be in the same workflow as our parent transition"
-msgstr ""
+msgstr "El estado de destino debe pertenecer al mismo Workflow que la " "transición padre."
 
 msgid "destination state of a transition"
 msgstr "Estado destino de una transición"
@@ -1984,21 +2008,23 @@
 "destination state. No destination state means that transition should go back "
 "to the state from which we've entered the subworkflow."
 msgstr ""
+"Estado destino de la transición. Si el Estado destino no ha sido "
+"especificado, la transición regresará hacia el estado que tenía la " "entidad al entrar en el Sub-Workflow."
 
 msgid "destination_state"
 msgstr "Estado destino"
 
 msgctxt "Transition"
 msgid "destination_state"
-msgstr ""
+msgstr "Estado destino"
 
 msgctxt "SubWorkflowExitPoint"
 msgid "destination_state"
-msgstr ""
+msgstr "Estado destino"
 
 msgctxt "State"
 msgid "destination_state_object"
-msgstr ""
+msgstr "Estado final de"
 
 msgid "destination_state_object"
 msgstr "Destino de"
@@ -2013,16 +2039,16 @@
 msgstr "Orden de aparición del componente"
 
 msgid "display order of the facet"
-msgstr ""
+msgstr "Orden de aparición de la faceta"
 
 msgid "display the box or not"
-msgstr "Mostrar la caja o no"
+msgstr "Mostrar o no la caja"
 
 msgid "display the component or not"
-msgstr "Mostrar el componente o no"
+msgstr "Mostrar o no el componente"
 
 msgid "display the facet or not"
-msgstr ""
+msgstr "Mostrar o no la faceta"
 
 msgid ""
 "distinct label to distinguate between other permission entity of the same "
@@ -2036,19 +2062,19 @@
 
 #, python-format
 msgid "download %s"
-msgstr ""
+msgstr "Descargar %s"
 
 msgid "download icon"
 msgstr "ícono de descarga"
 
 msgid "download schema as owl"
-msgstr "Descargar esquema en OWL"
+msgstr "Descargar esquema en formato OWL"
 
 msgid "edit bookmarks"
 msgstr "Editar favoritos"
 
 msgid "edit canceled"
-msgstr ""
+msgstr "Edición cancelada"
 
 msgid "edit the index page"
 msgstr "Modificar la página de inicio"
@@ -2069,10 +2095,10 @@
 msgstr "Mensajes enviados con éxito"
 
 msgid "embed"
-msgstr "Incrustrado"
+msgstr "Incrustado"
 
 msgid "embedded html"
-msgstr ""
+msgstr "Html incrustado"
 
 msgid "embedding this url is forbidden"
 msgstr "La inclusión de este url esta prohibida"
@@ -2081,28 +2107,28 @@
 msgstr "Entidades eliminadas"
 
 msgid "entity copied"
-msgstr "entidad copiada"
+msgstr "Entidad copiada"
 
 msgid "entity created"
-msgstr "entidad creada"
+msgstr "Entidad creada"
 
 msgid "entity creation"
-msgstr ""
+msgstr "Creación de entidad"
 
 msgid "entity deleted"
 msgstr "Entidad eliminada"
 
 msgid "entity deletion"
-msgstr ""
+msgstr "Eliminación de entidad"
 
 msgid "entity edited"
-msgstr "entidad modificada"
+msgstr "Entidad modificada"
 
 msgid "entity has no workflow set"
-msgstr ""
+msgstr "La entidad no tiene Workflow"
 
 msgid "entity linked"
-msgstr "entidad asociada"
+msgstr "Entidad asociada"
 
 msgid "entity type"
 msgstr "Tipo de entidad"
@@ -2115,10 +2141,10 @@
 "avanzada"
 
 msgid "entity types which may use this workflow"
-msgstr ""
+msgstr "Tipos de entidades que pueden utilizar este Workflow"
 
 msgid "entity update"
-msgstr ""
+msgstr "Actualización de la Entidad"
 
 msgid "error while embedding page"
 msgstr "Error durante la inclusión de la página"
@@ -2129,7 +2155,7 @@
 
 msgid "error while publishing ReST text"
 msgstr ""
-"Se ha producido un error durante la interpretación del texto en formatoReST"
+"Se ha producido un error durante la interpretación del texto en formato ReST"
 
 #, python-format
 msgid "error while querying source %s, some data may be missing"
@@ -2138,20 +2164,20 @@
 "datos visibles se encuentren incompletos"
 
 msgid "eta_date"
-msgstr "fecha de fin"
-
-msgid "exit state must a subworkflow state"
-msgstr ""
+msgstr "Fecha de fin"
+
+msgid "exit state must be a subworkflow state"
+msgstr "El estado de salida debe de ser un estado del Sub-Workflow"
 
 msgid "exit_point"
-msgstr ""
+msgstr "Estado de Salida"
 
 msgid "exit_point_object"
-msgstr ""
+msgstr "Estado de Salida de"
 
 #, python-format
 msgid "exiting from subworkflow %s"
-msgstr ""
+msgstr "Salida del subworkflow %s"
 
 msgid "expected:"
 msgstr "Previsto :"
@@ -2161,14 +2187,14 @@
 
 msgctxt "RQLExpression"
 msgid "expression"
-msgstr ""
+msgstr "RQL de la expresión"
 
 msgid "exprtype"
 msgstr "Tipo de la expresión"
 
 msgctxt "RQLExpression"
 msgid "exprtype"
-msgstr ""
+msgstr "Tipo"
 
 msgid "external page"
 msgstr "Página externa"
@@ -2177,71 +2203,71 @@
 msgstr "Caja de facetas"
 
 msgid "facets_created_by-facet"
-msgstr "faceta \"creada por\""
+msgstr "Faceta \"creada por\""
 
 msgid "facets_created_by-facet_description"
-msgstr "faceta creado por"
+msgstr "Faceta creada por"
 
 msgid "facets_cwfinal-facet"
-msgstr "faceta \"final\""
+msgstr "Faceta \"final\""
 
 msgid "facets_cwfinal-facet_description"
-msgstr "faceta para las entidades \"finales\""
+msgstr "Faceta para las entidades \"finales\""
 
 msgid "facets_etype-facet"
-msgstr "faceta \"es de tipo\""
+msgstr "Faceta \"es de tipo\""
 
 msgid "facets_etype-facet_description"
-msgstr "faceta es de tipo"
+msgstr "Faceta es de tipo"
 
 msgid "facets_has_text-facet"
-msgstr "faceta \"contiene el texto\""
+msgstr "Faceta \"contiene el texto\""
 
 msgid "facets_has_text-facet_description"
-msgstr "faceta contiene el texto"
+msgstr "Faceta contiene el texto"
 
 msgid "facets_in_group-facet"
-msgstr "faceta \"forma parte del grupo\""
+msgstr "Faceta \"forma parte del grupo\""
 
 msgid "facets_in_group-facet_description"
-msgstr "faceta en grupo"
+msgstr "Faceta en grupo"
 
 msgid "facets_in_state-facet"
-msgstr "faceta \"en el estado\""
+msgstr "Faceta \"en el estado\""
 
 msgid "facets_in_state-facet_description"
-msgstr "faceta en el estado"
+msgstr "Faceta en el estado"
 
 #, python-format
 msgid "failed to uniquify path (%s, %s)"
-msgstr ""
+msgstr "No se pudo obtener un dato único (%s, %s)"
 
 msgid "february"
 msgstr "Febrero"
 
 msgid "file tree view"
-msgstr "File Vista Arborescencia"
+msgstr "Arborescencia (archivos)"
 
 msgid "final"
 msgstr "Final"
 
 msgctxt "CWEType"
 msgid "final"
-msgstr ""
+msgstr "Final"
 
 msgctxt "CWRType"
 msgid "final"
-msgstr ""
+msgstr "Final"
 
 msgid "first name"
-msgstr ""
+msgstr "Nombre"
 
 msgid "firstname"
 msgstr "Nombre"
 
 msgctxt "CWUser"
 msgid "firstname"
-msgstr ""
+msgstr "Nombre"
 
 msgid "foaf"
 msgstr "Amigo de un Amigo, FOAF"
@@ -2251,21 +2277,21 @@
 
 #, python-format
 msgid "follow this link for more information on this %s"
-msgstr ""
+msgstr "Seleccione esta liga para obtener mayor información sobre %s"
 
 msgid "follow this link if javascript is deactivated"
-msgstr ""
+msgstr "Seleccione esta liga si javascript esta desactivado"
 
 msgid "for_user"
 msgstr "Para el usuario"
 
 msgctxt "CWProperty"
 msgid "for_user"
-msgstr ""
+msgstr "Propiedad del Usuario"
 
 msgctxt "CWUser"
 msgid "for_user_object"
-msgstr ""
+msgstr "Tiene como preferencia"
 
 msgid "for_user_object"
 msgstr "Utiliza las propiedades"
@@ -2285,32 +2311,32 @@
 
 msgctxt "CWAttribute"
 msgid "from_entity"
-msgstr ""
+msgstr "Atributo de la entidad"
 
 msgctxt "CWRelation"
 msgid "from_entity"
-msgstr ""
+msgstr "Relación de la entidad"
 
 msgctxt "CWEType"
 msgid "from_entity_object"
-msgstr ""
+msgstr "Entidad de"
 
 msgid "from_entity_object"
 msgstr "Relación sujeto"
 
 msgid "from_interval_start"
-msgstr ""
+msgstr "De"
 
 msgid "from_state"
-msgstr "De el estado"
+msgstr "Del Estado"
 
 msgctxt "TrInfo"
 msgid "from_state"
-msgstr ""
+msgstr "Estado de Inicio"
 
 msgctxt "State"
 msgid "from_state_object"
-msgstr ""
+msgstr "Estado de Inicio de"
 
 msgid "from_state_object"
 msgstr "Transiciones desde este estado"
@@ -2323,25 +2349,27 @@
 
 msgctxt "CWRType"
 msgid "fulltext_container"
-msgstr ""
+msgstr "Objeto a indexar"
 
 msgid "fulltextindexed"
 msgstr "Indexación de texto"
 
 msgctxt "CWAttribute"
 msgid "fulltextindexed"
-msgstr ""
+msgstr "Texto indexado"
 
 msgid "generic plot"
-msgstr "Trazado de curbas estándares"
+msgstr "Gráfica Genérica"
 
 msgid "generic relation to link one entity to another"
-msgstr "relación generica para ligar entidades"
+msgstr "Relación genérica para ligar entidades"
 
 msgid ""
 "generic relation to specify that an external entity represent the same "
 "object as a local one: http://www.w3.org/TR/owl-ref/#sameAs-def"
 msgstr ""
+"Relación genérica que indicar que una entidad es idéntica a otro "
+"recurso web (ver http://www.w3.org/TR/owl-ref/#sameAs-def)."
 
 msgid "go back to the index page"
 msgstr "Regresar a la página de inicio"
@@ -2351,32 +2379,37 @@
 
 #, python-format
 msgid "graphical representation of %(appid)s data model"
-msgstr ""
+msgstr "Representación gráfica del modelo de datos de %(appid)s"
 
 #, python-format
 msgid ""
 "graphical representation of the %(etype)s entity type from %(appid)s data "
 "model"
 msgstr ""
+"Representación gráfica del modelo de datos para el tipo de entidad %(etype)s "
+"de %(appid)s"
 
 #, python-format
 msgid ""
 "graphical representation of the %(rtype)s relation type from %(appid)s data "
 "model"
 msgstr ""
+"Representación gráfica del modelo de datos para el tipo de relación %(rtype)s "
+"de %(appid)s"
+
 
 #, python-format
 msgid "graphical workflow for %s"
 msgstr "Gráfica del workflow por %s"
 
 msgid "group in which a user should be to be allowed to pass this transition"
-msgstr "Grupo en el cual el usuario debe estar para poder pasar la transición"
+msgstr "Grupo en el cual el usuario debe estar lograr la transición"
 
 msgid "groups"
 msgstr "Grupos"
 
 msgid "groups grant permissions to the user"
-msgstr "Los grupos otorgan las autorizaciones al usuario"
+msgstr "Los grupos otorgan los permisos al usuario"
 
 msgid "groups to which the permission is granted"
 msgstr "Grupos quienes tienen otorgada esta autorización"
@@ -2400,42 +2433,42 @@
 "how to format date and time in the ui (\"man strftime\" for format "
 "description)"
 msgstr ""
-"Como formatear la fecha en la interface (\"man strftime\" por la descripción "
+"Formato de fecha y hora que se utilizará por defecto en la interfaz (\"man strftime\" para mayor información "
 "del formato)"
 
 msgid "how to format date in the ui (\"man strftime\" for format description)"
 msgstr ""
-"Como formatear la fecha en la interface (\"man strftime\" por la descripción "
+"Formato de fecha que se utilizará por defecto en la interfaz (\"man strftime\" para mayor información  "
 "del formato)"
 
 msgid "how to format float numbers in the ui"
-msgstr "Como formatear los números flotantes en la interface"
+msgstr "Formato de números flotantes que se utilizará por defecto en la interfaz"
 
 msgid "how to format time in the ui (\"man strftime\" for format description)"
 msgstr ""
-"Como formatear la hora en la interface (\"man strftime\" por la descripción "
+"Formato de hora que se utilizará por defecto en la interfaz (\"man strftime\" para mayor información "
 "del formato)"
 
 msgid "i18n_bookmark_url_fqs"
-msgstr ""
+msgstr "Parámetros"
 
 msgid "i18n_bookmark_url_path"
-msgstr ""
+msgstr "Ruta"
 
 msgid "i18n_login_popup"
 msgstr "Identificarse"
 
 msgid "i18ncard_*"
-msgstr ""
+msgstr "0..n"
 
 msgid "i18ncard_+"
-msgstr ""
+msgstr "1..n"
 
 msgid "i18ncard_1"
-msgstr ""
+msgstr "1"
 
 msgid "i18ncard_?"
-msgstr ""
+msgstr "0..1"
 
 msgid "i18nprevnext_next"
 msgstr "Siguiente"
@@ -2453,7 +2486,7 @@
 msgstr "ID del template principal"
 
 msgid "identical to"
-msgstr ""
+msgstr "Idéntico a"
 
 msgid "identical_to"
 msgstr "idéntico a"
@@ -2469,7 +2502,7 @@
 "entity (the container)."
 msgstr ""
 "Si el texto indexado de la entidad sujeto/objeto debe ser agregado a la "
-"entidad a el otro extremo de la relación (el contenedor)."
+"entidad al otro extremo de la relación (el contenedor)."
 
 msgid "image"
 msgstr "Imagen"
@@ -2479,26 +2512,26 @@
 
 msgctxt "CWUser"
 msgid "in_group"
-msgstr ""
+msgstr "Forma parte del grupo"
 
 msgctxt "CWGroup"
 msgid "in_group_object"
-msgstr ""
+msgstr "Contiene los usuarios"
 
 msgid "in_group_object"
 msgstr "Miembros"
 
 msgid "in_state"
-msgstr "estado"
+msgstr "Estado"
 
 msgid "in_state_object"
-msgstr "estado de"
+msgstr "Estado de"
 
 msgid "incontext"
 msgstr "En el contexto"
 
 msgid "incorrect captcha value"
-msgstr ""
+msgstr "Valor del Captcha incorrecto"
 
 #, python-format
 msgid "incorrect value (%(value)s) for type \"%(type)s\""
@@ -2512,7 +2545,7 @@
 
 msgctxt "CWAttribute"
 msgid "indexed"
-msgstr ""
+msgstr "Indexado"
 
 msgid "indicate the current state of an entity"
 msgstr "Indica el estado actual de una entidad"
@@ -2524,51 +2557,51 @@
 "Indica cual estado deberá ser utilizado por defecto al crear una entidad"
 
 msgid "info"
-msgstr ""
+msgstr "Información del Sistema"
 
 #, python-format
 msgid "initial estimation %s"
 msgstr "Estimación inicial %s"
 
 msgid "initial state for this workflow"
-msgstr ""
+msgstr "Estado inicial para este Workflow"
 
 msgid "initial_state"
-msgstr "estado inicial"
+msgstr "Estado inicial"
 
 msgctxt "Workflow"
 msgid "initial_state"
-msgstr ""
+msgstr "Estado inicial"
 
 msgctxt "State"
 msgid "initial_state_object"
-msgstr ""
+msgstr "Estado inicial de"
 
 msgid "initial_state_object"
-msgstr "es el estado inicial de"
+msgstr "Estado inicial de"
 
 msgid "inlined"
-msgstr "Puesto en línea"
+msgstr "Inlined"
 
 msgctxt "CWRType"
 msgid "inlined"
-msgstr ""
+msgstr "Inlined"
 
 msgid "instance home"
-msgstr ""
+msgstr "Repertorio de la Instancia"
 
 msgid "instance schema"
-msgstr ""
+msgstr "Esquema de la Instancia"
 
 msgid "internal entity uri"
-msgstr ""
+msgstr "Uri Interna"
 
 msgid "internationalizable"
 msgstr "Internacionalizable"
 
 msgctxt "CWAttribute"
 msgid "internationalizable"
-msgstr ""
+msgstr "Internacionalizable"
 
 #, python-format
 msgid "invalid action %r"
@@ -2576,7 +2609,7 @@
 
 #, python-format
 msgid "invalid value %(value)s, it must be one of %(choices)s"
-msgstr ""
+msgstr "Valor %(value)s incorrecto, debe estar entre %(choices)s"
 
 msgid "is"
 msgstr "es"
@@ -2604,7 +2637,7 @@
 "is this relation physically inlined? you should know what you're doing if "
 "you are changing this!"
 msgstr ""
-"Es esta relación puesta en línea en la base de datos  ? Usted debe saber lo "
+"Es esta relación estilo INLINED en la base de datos  ? Usted debe saber lo "
 "que hace si cambia esto !"
 
 msgid "is_instance_of"
@@ -2630,35 +2663,35 @@
 
 msgctxt "CWPermission"
 msgid "label"
-msgstr ""
+msgstr "Etiqueta"
 
 msgid "language of the user interface"
-msgstr "Idioma para la interface del usuario"
+msgstr "Idioma que se utilizará por defecto en la interfaz usuario"
 
 msgid "last connection date"
-msgstr "Ultima fecha de conexión"
+msgstr "Ultima conexión"
 
 msgid "last login time"
-msgstr ""
+msgstr "Ultima conexión"
 
 msgid "last name"
-msgstr ""
+msgstr "Apellido"
 
 msgid "last usage"
-msgstr ""
+msgstr "Ultimo uso"
 
 msgid "last_login_time"
 msgstr "Ultima fecha de conexión"
 
 msgctxt "CWUser"
 msgid "last_login_time"
-msgstr ""
+msgstr "Ultima conexión"
 
 msgid "latest modification time of an entity"
 msgstr "Fecha de la última modificación de una entidad "
 
 msgid "latest update on"
-msgstr "actualizado el"
+msgstr "Actualizado el"
 
 msgid "left"
 msgstr "izquierda"
@@ -2667,56 +2700,56 @@
 "link a permission to the entity. This permission should be used in the "
 "security definition of the entity's type to be useful."
 msgstr ""
-"relaciónar una autorización con la entidad. Este autorización debe ser usada "
-"en la definición de la entidad para ser utíl."
+"Relacionar un permiso con la entidad. Este permiso debe ser integrado "
+"en la definición de seguridad de la entidad para poder ser utilizado."
 
 msgid ""
 "link a property to the user which want this property customization. Unless "
 "you're a site manager, this relation will be handled automatically."
 msgstr ""
-"Liga una propiedad a el usuario que desea esta personalización. Salvo que "
-"usted sea un administrador del sistema, esta relación es gestionada "
-"automáticamente."
+"Liga una propiedad al usuario que desea esta personalización. Salvo que "
+"usted sea un administrador del sistema, esta relación será administrada "
+"de forma automática."
 
 msgid "link a relation definition to its object entity type"
-msgstr "liga una definición de relación a su tipo de entidad objeto"
+msgstr "Liga una definición de relación a su tipo de entidad objeto"
 
 msgid "link a relation definition to its relation type"
-msgstr "liga una definición de relación a su tipo de relación"
+msgstr "Liga una definición de relación a su tipo de relación"
 
 msgid "link a relation definition to its subject entity type"
-msgstr "liga una definición de relación a su tipo de entidad"
+msgstr "Liga una definición de relación a su tipo de entidad"
 
 msgid "link a state to one or more workflow"
-msgstr ""
+msgstr "Liga un estado a uno o más Workflow"
 
 msgid "link a transition information to its object"
-msgstr "liga una transcion de informacion a los objetos asociados"
+msgstr "Liga una transición de informacion hacia los objetos asociados"
 
 msgid "link a transition to one or more workflow"
-msgstr ""
+msgstr "Liga una transición a uno o más Workflow"
 
 msgid "link a workflow to one or more entity type"
-msgstr ""
+msgstr "Liga un Workflow a uno a más tipos de entidad"
 
 msgid "list"
 msgstr "Lista"
 
 msgid "log in"
-msgstr "Identificarse"
+msgstr "Acceder"
 
 msgid "log out first"
-msgstr ""
+msgstr "Desconéctese primero"
 
 msgid "login"
-msgstr "Clave de acesso"
+msgstr "Usuario"
 
 msgctxt "CWUser"
 msgid "login"
-msgstr ""
+msgstr "Usuario"
 
 msgid "login or email"
-msgstr "Clave de acesso o dirección de correo"
+msgstr "Usuario o dirección de correo"
 
 msgid "login_action"
 msgstr "Ingresa tus datos"
@@ -2732,144 +2765,144 @@
 msgstr "Informaciones Generales"
 
 msgid "mainvars"
-msgstr "Principales variables"
+msgstr "Variables principales"
 
 msgctxt "RQLExpression"
 msgid "mainvars"
-msgstr ""
+msgstr "Variables principales"
 
 msgid "manage"
-msgstr "Administracion del Sitio"
+msgstr "Administración Sistema"
 
 msgid "manage bookmarks"
-msgstr "Administra tus favoritos"
+msgstr "Gestión de favoritos"
 
 msgid "manage permissions"
-msgstr "Administración de Autorizaciones"
+msgstr "Gestión de permisos"
 
 msgid "manage security"
-msgstr "Administración de la Seguridad"
+msgstr "Gestión de seguridad"
 
 msgid "managers"
-msgstr "editores"
+msgstr "Administradores"
 
 msgid "mandatory relation"
-msgstr ""
+msgstr "Relación obligatoria"
 
 msgid "march"
 msgstr "Marzo"
 
 msgid "maximum number of characters in short description"
-msgstr "Numero maximo de caracteres en las descripciones cortas"
+msgstr "Máximo de caracteres en las descripciones cortas"
 
 msgid "maximum number of entities to display in related combo box"
-msgstr "Numero maximo de entidades a mostrar en las listas dinamicas"
+msgstr "Máximo de entidades a mostrar en las listas dinámicas"
 
 msgid "maximum number of objects displayed by page of results"
-msgstr "Numero maximo de objetos mostrados por pagina de resultados"
+msgstr "Máximo de elementos mostrados por página de resultados"
 
 msgid "maximum number of related entities to display in the primary view"
-msgstr "Numero maximo de entidades ligadas a mostrar en la vista primaria"
+msgstr "Máximo de entidades relacionadas a mostrar en la vista primaria"
 
 msgid "may"
 msgstr "Mayo"
 
 msgid "memory leak debugging"
-msgstr ""
+msgstr "depuración (debugging) de fuga de memoria"
 
 msgid "milestone"
 msgstr "Milestone"
 
 #, python-format
 msgid "missing parameters for entity %s"
-msgstr "Parametros faltantes a la entidad %s"
+msgstr "Parámetros faltantes a la entidad %s"
 
 msgid "modification_date"
-msgstr "Fecha de modificacion"
+msgstr "Fecha de modificación"
 
 msgid "modify"
 msgstr "Modificar"
 
 msgid "monday"
-msgstr "Lundi"
+msgstr "Lunes"
 
 msgid "more actions"
-msgstr "mas acciones"
+msgstr "Más acciones"
 
 msgid "more info about this workflow"
-msgstr ""
+msgstr "Más información acerca de este workflow"
 
 msgid "multiple edit"
-msgstr "Edicion multiple"
+msgstr "Edición multiple"
 
 msgid "my custom search"
-msgstr "Mi busqueda personalizada"
+msgstr "Mi búsqueda personalizada"
 
 msgid "name"
 msgstr "Nombre"
 
 msgctxt "CWEType"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "Transition"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "Workflow"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "CWGroup"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "CWConstraintType"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "WorkflowTransition"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "State"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "CWPermission"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "CWRType"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "BaseTransition"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgctxt "CWCache"
 msgid "name"
-msgstr ""
+msgstr "Nombre"
 
 msgid "name of the cache"
-msgstr "Nombre del Cache"
+msgstr "Nombre del Caché"
 
 msgid ""
 "name of the main variables which should be used in the selection if "
 "necessary (comma separated)"
 msgstr ""
-"Nombre de las variables principales que deberian se utilizadas en la "
-"selecciónde ser necesario (separarlas con comas)"
+"Nombre de las variables principales que deberían ser utilizadas en la "
+"selección de ser necesario (separarlas con comas)"
 
 msgid "name or identifier of the permission"
-msgstr "Nombre o indentificador de la autorización"
+msgstr "Nombre o identificador del permiso"
 
 msgid "navbottom"
-msgstr "Pie de pagina"
+msgstr "Pie de página"
 
 msgid "navcontentbottom"
-msgstr "Pie de pagina del contenido principal"
+msgstr "Pie de página del contenido principal"
 
 msgid "navcontenttop"
 msgstr "Encabezado"
@@ -2878,21 +2911,17 @@
 msgstr "Navegación"
 
 msgid "navigation.combobox-limit"
-msgstr ""
-
-# msgstr "Navegación: numero maximo de elementos en una caja de elección (combobox)"
+msgstr "ComboBox"
+
 msgid "navigation.page-size"
-msgstr ""
-
-# msgstr "Navegación: numero maximo de elementos por pagina"
+msgstr "Paginación"
+
 msgid "navigation.related-limit"
-msgstr ""
-
-# msgstr "Navegación: numero maximo de elementos relacionados"
+msgstr "Entidades relacionadas"
+
 msgid "navigation.short-line-size"
-msgstr ""
-
-# msgstr "Navegación: numero maximo de caracteres en una linéa corta"
+msgstr "Descripción corta"
+
 msgid "navtop"
 msgstr "Encabezado del contenido principal"
 
@@ -2903,138 +2932,138 @@
 msgstr "Siguientes resultados"
 
 msgid "no"
-msgstr "no"
+msgstr "No"
 
 msgid "no associated permissions"
-msgstr "no autorización relacionada"
+msgstr "No existe permiso asociado"
 
 #, python-format
 msgid "no edited fields specified for entity %s"
-msgstr ""
+msgstr "Ningún campo editable especificado para la entidad %s"
 
 msgid "no related entity"
-msgstr ""
+msgstr "No posee entidad asociada"
 
 msgid "no related project"
-msgstr "no hay proyecto relacionado"
+msgstr "No tiene proyecto relacionado"
 
 msgid "no repository sessions found"
-msgstr ""
+msgstr "Ninguna sesión encontrada"
 
 msgid "no selected entities"
-msgstr "no hay entidades seleccionadas"
+msgstr "No hay entidades seleccionadas"
 
 #, python-format
 msgid "no such entity type %s"
-msgstr "el tipo de entidad '%s' no existe"
+msgstr "El tipo de entidad '%s' no existe"
 
 msgid "no version information"
-msgstr "no información de version"
+msgstr "No existe la información de version"
 
 msgid "no web sessions found"
-msgstr ""
+msgstr "Ninguna sesión web encontrada"
 
 msgid "normal"
-msgstr ""
+msgstr "Normal"
 
 msgid "not authorized"
-msgstr "no autorizado"
+msgstr "No autorizado"
 
 msgid "not selected"
-msgstr "no seleccionado"
+msgstr "No seleccionado"
 
 msgid "november"
-msgstr "noviembre"
+msgstr "Noviembre"
 
 msgid "object"
-msgstr "objeto"
+msgstr "Objeto"
 
 msgid "object type"
-msgstr ""
+msgstr "Tipo de Objeto"
 
 msgid "october"
-msgstr "octubre"
+msgstr "Octubre"
 
 msgid "one month"
-msgstr "un mes"
+msgstr "Un mes"
 
 msgid "one week"
-msgstr "una semana"
+msgstr "Una semana"
 
 msgid "oneline"
-msgstr "una linea"
+msgstr "En una línea"
 
 msgid "only select queries are authorized"
-msgstr "solo estan permitidas consultas de lectura"
+msgstr "Solo están permitidas consultas de lectura"
 
 msgid "open all"
-msgstr "abrir todos"
+msgstr "Abrir todos"
 
 msgid "opened sessions"
-msgstr ""
+msgstr "Sesiones abiertas"
 
 msgid "opened web sessions"
-msgstr ""
+msgstr "Sesiones Web abiertas"
 
 msgid "options"
-msgstr ""
+msgstr "Opciones"
 
 msgid "order"
-msgstr "orden"
+msgstr "Orden"
 
 msgid "ordernum"
-msgstr "orden"
+msgstr "Orden"
 
 msgctxt "CWAttribute"
 msgid "ordernum"
-msgstr ""
+msgstr "Número de Orden"
 
 msgctxt "CWRelation"
 msgid "ordernum"
-msgstr ""
+msgstr "Número de Orden"
 
 msgid "owl"
-msgstr "owl"
+msgstr "OWL"
 
 msgid "owlabox"
-msgstr "owlabox"
+msgstr "OWLabox"
 
 msgid "owned_by"
-msgstr "pertenece a"
+msgstr "Pertenece a"
 
 msgid "owned_by_object"
-msgstr "pertenece al objeto"
+msgstr "Pertenece al objeto"
 
 msgid "owners"
-msgstr "proprietarios"
+msgstr "Proprietarios"
 
 msgid "ownership"
-msgstr "pertenencia"
+msgstr "Propiedad"
 
 msgid "ownerships have been changed"
-msgstr "la pertenencia ha sido modificada"
+msgstr "Derechos de propiedad modificados"
 
 msgid "pageid-not-found"
-msgstr "pagina no encontrada."
+msgstr "Página no encontrada."
 
 msgid "password"
-msgstr "Clave de acceso"
+msgstr "Contraseña"
 
 msgid "password and confirmation don't match"
-msgstr "La clave de acceso y la confirmación no concuerdan"
+msgstr "Su contraseña y confirmación no concuerdan"
 
 msgid "path"
 msgstr "Ruta"
 
 msgctxt "Bookmark"
 msgid "path"
-msgstr ""
+msgstr "Ruta"
 
 msgid "permission"
 msgstr "Permiso"
 
 msgid "permissions"
-msgstr ""
+msgstr "Permisos"
 
 msgid "permissions for this entity"
 msgstr "Permisos para esta entidad"
@@ -3043,78 +3072,78 @@
 msgstr "Información personal"
 
 msgid "pick existing bookmarks"
-msgstr "Seleccione los favoritos existentes"
+msgstr "Seleccionar favoritos existentes"
 
 msgid "pkey"
-msgstr "pkey"
+msgstr "Clave"
 
 msgctxt "CWProperty"
 msgid "pkey"
-msgstr ""
+msgstr "Código de la Propiedad"
 
 msgid "please correct errors below"
-msgstr "Favor de corregir errores"
+msgstr "Por favor corregir los errores señalados en la parte inferior"
 
 msgid "please correct the following errors:"
-msgstr "Favor de corregir los siguientes errores :"
+msgstr "Por favor corregir los siguientes errores:"
 
 msgid "possible views"
 msgstr "Vistas posibles"
 
 msgid "powered by CubicWeb"
-msgstr ""
+msgstr "Potenciado en CubicWeb"
 
 msgid "prefered_form"
-msgstr ""
+msgstr "Forma preferida"
 
 msgctxt "EmailAddress"
 msgid "prefered_form"
-msgstr ""
+msgstr "Email principal"
 
 msgctxt "EmailAddress"
 msgid "prefered_form_object"
-msgstr ""
+msgstr "Email principal de"
 
 msgid "prefered_form_object"
-msgstr ""
+msgstr "Formato preferido sobre"
 
 msgid "preferences"
 msgstr "Preferencias"
 
 msgid "previous_results"
-msgstr "Resultados anteriores"
+msgstr "Resultados Anteriores"
 
 msgid "primary"
 msgstr "Primaria"
 
 msgid "primary_email"
-msgstr "Dirección de email principal"
+msgstr "Dirección principal de correo electrónico"
 
 msgctxt "CWUser"
 msgid "primary_email"
-msgstr ""
+msgstr "Dirección principal de correo electrónico"
 
 msgctxt "EmailAddress"
 msgid "primary_email_object"
-msgstr ""
+msgstr "Dirección principal de correo electrónico de"
 
 msgid "primary_email_object"
 msgstr "Dirección de email principal (objeto)"
 
 msgid "progress"
-msgstr "Avance"
+msgstr "Progreso"
 
 msgid "progress bar"
-msgstr "Barra de progreso de avance"
+msgstr "Barra de Progreso"
 
 msgid "project"
 msgstr "Proyecto"
 
 msgid "rdef-description"
-msgstr ""
+msgstr "Descripción"
 
 msgid "rdef-permissions"
-msgstr ""
+msgstr "Permisos"
 
 msgid "read"
 msgstr "Lectura"
@@ -3127,110 +3156,110 @@
 
 msgctxt "CWEType"
 msgid "read_permission"
-msgstr ""
+msgstr "Permiso de Lectura"
 
 msgctxt "CWAttribute"
 msgid "read_permission"
-msgstr ""
+msgstr "Permiso de Lectura"
 
 msgctxt "CWRelation"
 msgid "read_permission"
-msgstr ""
+msgstr "Permiso de Lectura"
 
 msgctxt "CWGroup"
 msgid "read_permission_object"
-msgstr ""
+msgstr "Puede leer"
 
 msgctxt "RQLExpression"
 msgid "read_permission_object"
-msgstr ""
+msgstr "Puede leer"
 
 msgid "read_permission_object"
-msgstr "Objeto_permiso_lectura"
+msgstr "Tiene acceso de lectura a"
 
 msgid "registry"
-msgstr ""
+msgstr "Registro"
 
 msgid "related entity has no state"
-msgstr ""
+msgstr "La entidad relacionada no posee Estado"
 
 msgid "related entity has no workflow set"
-msgstr ""
+msgstr "La entidad relacionada no posee Workflow definido"
 
 msgid "relation"
-msgstr ""
+msgstr "relación"
 
 #, python-format
 msgid "relation %(relname)s of %(ent)s"
 msgstr "relación %(relname)s de %(ent)s"
 
 msgid "relation add"
-msgstr ""
+msgstr "Agregar Relación"
 
 msgid "relation removal"
-msgstr ""
+msgstr "Eliminar Relación"
 
 msgid "relation_type"
-msgstr "tipo de relación"
+msgstr "Tipo de Relación"
 
 msgctxt "CWAttribute"
 msgid "relation_type"
-msgstr ""
+msgstr "Tipo de Relación"
 
 msgctxt "CWRelation"
 msgid "relation_type"
-msgstr ""
+msgstr "Tipo de Relación"
 
 msgctxt "CWRType"
 msgid "relation_type_object"
-msgstr ""
+msgstr "Definición de Relaciones"
 
 msgid "relation_type_object"
-msgstr "Definición"
+msgstr "Definición de Relaciones"
 
 msgid "relations deleted"
-msgstr "Relaciones eliminadas"
+msgstr "Relaciones Eliminadas"
 
 msgid "relative url of the bookmarked page"
-msgstr "Url relativa de la pagina"
+msgstr "Url relativa de la página"
 
 msgid "remove-inlined-entity-form"
-msgstr ""
+msgstr "Eliminar"
 
 msgid "require_group"
-msgstr "Requiere grupo"
+msgstr "Requiere el grupo"
 
 msgctxt "BaseTransition"
 msgid "require_group"
-msgstr ""
+msgstr "Restringida al Grupo"
 
 msgctxt "Transition"
 msgid "require_group"
-msgstr ""
+msgstr "Restringida al Grupo"
 
 msgctxt "CWPermission"
 msgid "require_group"
-msgstr ""
+msgstr "Restringida al Grupo"
 
 msgctxt "WorkflowTransition"
 msgid "require_group"
-msgstr ""
+msgstr "Restringida al Grupo"
 
 msgctxt "CWGroup"
 msgid "require_group_object"
-msgstr ""
+msgstr "Posee derechos sobre"
 
 msgid "require_group_object"
-msgstr "Requerido por grupo"
+msgstr "Posee derechos sobre"
 
 msgid "require_permission"
-msgstr "Requiere autorización"
+msgstr "Requiere Permisos"
 
 msgid "require_permission_object"
 msgstr "Requerido por autorización"
 
 msgid "required"
-msgstr ""
+msgstr "Requerido"
 
 msgid "required attribute"
 msgstr "Atributo requerido"
@@ -3239,7 +3268,7 @@
 msgstr "Campo requerido"
 
 msgid "resources usage"
-msgstr ""
+msgstr "Recursos utilizados"
 
 msgid ""
 "restriction part of a rql query. For entity rql expression, X and U are "
@@ -3247,382 +3276,384 @@
 "relation rql expression, S, O and U are predefined respectivly to the "
 "current relation'subject, object and to the request user. "
 msgstr ""
-"restriction part of a rql query. For entity rql expression, X and U are "
-"predefined respectivly to the current object and to the request user. For "
-"relation rql expression, S, O and U are predefined respectivly to the "
-"current relation'subject, object and to the request user. "
+"Parte restrictiva de una consulta RQL. En una expresión ligada a una entidad, " 
+"X y U son respectivamente asignadas a la Entidad y el Usuario en curso."
+"En una expresión ligada a una relación, S, O y U son respectivamente asignados "
+"al Sujeto/Objeto de la relación y al Usuario actual."
 
 msgid "revert changes"
-msgstr "Revertir cambios"
+msgstr "Anular modificación"
 
 msgid "right"
 msgstr "Derecha"
 
 msgid "rql expressions"
-msgstr "expresiones rql"
+msgstr "Expresiones RQL"
 
 msgid "rss"
 msgstr "RSS"
 
 msgid "same_as"
-msgstr ""
+msgstr "Idéntico a"
 
 msgid "sample format"
-msgstr "ejemplo"
+msgstr "Ejemplo"
 
 msgid "saturday"
-msgstr "sabado"
+msgstr "Sábado"
 
 msgid "schema entities"
-msgstr "entidades del esquema"
+msgstr "Entidades del esquema"
 
 msgid "schema's permissions definitions"
-msgstr "definiciones de permisos del esquema"
+msgstr "Definiciones de permisos del esquema"
 
 msgid "schema-diagram"
-msgstr ""
+msgstr "Gráfica"
 
 msgid "schema-entity-types"
-msgstr ""
+msgstr "Entidades"
 
 msgid "schema-relation-types"
-msgstr ""
+msgstr "Relaciones"
 
 msgid "schema-security"
-msgstr ""
+msgstr "Seguridad"
 
 msgid "search"
-msgstr "buscar"
+msgstr "Buscar"
 
 msgid "search for association"
-msgstr "buscar por asociación"
+msgstr "Búsqueda por asociación"
 
 msgid "searching for"
-msgstr "buscando "
+msgstr "Buscando"
 
 msgid "secondary"
-msgstr "secundario"
+msgstr "Secundaria"
 
 msgid "security"
-msgstr "seguridad"
+msgstr "Seguridad"
 
 msgid "see them all"
 msgstr "Ver todos"
 
 msgid "see_also"
-msgstr "Ver tambíen"
+msgstr "Ver además"
 
 msgid "select"
 msgstr "Seleccionar"
 
 msgid "select a"
-msgstr "seleccione un"
+msgstr "Seleccione un"
 
 msgid "select a key first"
-msgstr "seleccione una clave"
+msgstr "Seleccione una clave"
 
 msgid "select a relation"
-msgstr "seleccione una relación"
+msgstr "Seleccione una relación"
 
 msgid "select this entity"
-msgstr "seleccionar esta entidad"
+msgstr "Seleccionar esta entidad"
 
 msgid "selected"
-msgstr "seleccionado"
+msgstr "Seleccionado"
 
 msgid "semantic description of this attribute"
-msgstr "descripción semantica de este atributo"
+msgstr "Descripción semántica de este atributo"
 
 msgid "semantic description of this entity type"
-msgstr "descripción semantica de este tipo de entidad"
+msgstr "Descripción semántica de este tipo de entidad"
 
 msgid "semantic description of this relation"
-msgstr "descripción semantica de esta relación"
+msgstr "Descripción semántica de esta relación"
 
 msgid "semantic description of this relation type"
-msgstr "descripción semantica de este tipo de relación"
+msgstr "Descripción semántica de este tipo de relación"
 
 msgid "semantic description of this state"
-msgstr "descripción semantica de este estado"
+msgstr "Descripción semántica de este estado"
 
 msgid "semantic description of this transition"
-msgstr "descripcion semantica de esta transición"
+msgstr "Descripcion semántica de esta transición"
 
 msgid "semantic description of this workflow"
-msgstr ""
+msgstr "Descripcion semántica de este Workflow"
 
 msgid "send email"
-msgstr "enviar email"
+msgstr "Enviar email"
 
 msgid "september"
-msgstr "septiembre"
+msgstr "Septiembre"
 
 msgid "server information"
-msgstr "server information"
+msgstr "Información del servidor"
 
 msgid ""
 "should html fields being edited using fckeditor (a HTML WYSIWYG editor).  "
 "You should also select text/html as default text format to actually get "
 "fckeditor."
 msgstr ""
-"indique si los campos deberan ser editados usando fckeditor (un\n"
-"editor HTML WYSIWYG). Debera tambien elegir text/html\n"
-"como formato de texto por default para poder utilizar fckeditor."
+"Indica si los campos de tipo texto deberán ser editados usando fckeditor (un\n"
+"editor HTML WYSIWYG). Deberá también elegir text/html\n"
+"como formato de texto por defecto para poder utilizar fckeditor."
 
 #, python-format
 msgid "show %s results"
-msgstr "mostrar %s resultados"
+msgstr "Mostrar %s resultados"
 
 msgid "show advanced fields"
-msgstr "mostrar campos avanzados"
+msgstr "Mostrar campos avanzados"
 
 msgid "show filter form"
-msgstr "afficher le filtre"
+msgstr "Mostrar el Filtro"
 
 msgid "sioc"
-msgstr ""
+msgstr "SIOC"
 
 msgid "site configuration"
-msgstr "configuracion del sitio"
+msgstr "Configuración Sistema"
 
 msgid "site documentation"
-msgstr "documentacion del sitio"
+msgstr "Documentación Sistema"
 
 msgid "site schema"
-msgstr "esquema del sitio"
+msgstr "Esquema del Sistema"
 
 msgid "site title"
-msgstr "titulo del sitio"
+msgstr "Nombre del Sistema"
 
 msgid "site-wide property can't be set for user"
 msgstr ""
-"una propiedad especifica para el sitio no puede establecerse para el usuario"
-
-msgid "some errors occured:"
-msgstr ""
+"Una propiedad específica al Sistema no puede ser propia al usuario"
+
+msgid "some errors occurred:"
+msgstr "Algunos errores encontrados :"
 
 msgid "some later transaction(s) touch entity, undo them first"
-msgstr ""
+msgstr "Las transacciones más recientes modificaron esta entidad, anúlelas " 
+"primero"
 
 msgid "sorry, the server is unable to handle this query"
-msgstr "lo sentimos, el servidor no puede manejar esta consulta"
+msgstr "Lo sentimos, el servidor no puede manejar esta consulta"
 
 msgid "sparql xml"
-msgstr ""
+msgstr "XML Sparql"
 
 msgid "special transition allowing to go through a sub-workflow"
-msgstr ""
+msgstr "Transición especial que permite ir en un Sub-Workflow"
 
 msgid "specializes"
-msgstr "derivado de"
+msgstr "Deriva de"
 
 msgctxt "CWEType"
 msgid "specializes"
-msgstr ""
+msgstr "Especializa"
 
 msgctxt "CWEType"
 msgid "specializes_object"
-msgstr ""
+msgstr "Especializado por"
 
 msgid "specializes_object"
-msgstr "objeto_derivado"
+msgstr "Especializado por"
 
 msgid "startup views"
-msgstr "vistas de inicio"
+msgstr "Vistas de inicio"
 
 msgid "state"
-msgstr "estado"
+msgstr "Estado"
 
 msgid "state and transition don't belong the the same workflow"
-msgstr ""
+msgstr "El Estado y la Transición no pertenecen al mismo Workflow"
 
 msgid "state doesn't apply to this entity's type"
-msgstr ""
+msgstr "Este Estado no aplica a este tipo de Entidad"
 
 msgid "state doesn't belong to entity's current workflow"
-msgstr ""
+msgstr "El Estado no pertenece al Workflow actual de la Entidad"
 
 msgid "state doesn't belong to entity's workflow"
-msgstr ""
+msgstr "El Estado no pertenece al Workflow de la Entidad"
 
 msgid ""
 "state doesn't belong to entity's workflow. You may want to set a custom "
 "workflow for this entity first."
-msgstr ""
+msgstr "El Estado no pertenece al Workflow Actual de la Entidad. Usted desea" 
+"quizás especificar que esta entidad debe utilizar este Workflow"
 
 msgid "state doesn't belong to this workflow"
-msgstr ""
+msgstr "El Estado no pertenece a este Workflow"
 
 msgid "state_of"
-msgstr "estado_de"
+msgstr "Estado de"
 
 msgctxt "State"
 msgid "state_of"
-msgstr ""
+msgstr "Estado de"
 
 msgctxt "Workflow"
 msgid "state_of_object"
-msgstr ""
+msgstr "Tiene por Estado"
 
 msgid "state_of_object"
-msgstr "objeto_estado_de"
+msgstr "Tiene por Estado"
 
 msgid "status change"
-msgstr "cambio de estatus"
+msgstr "Cambio de Estatus"
 
 msgid "status changed"
-msgstr "estatus cambiado"
+msgstr "Estatus cambiado"
 
 #, python-format
 msgid "status will change from %(st1)s to %(st2)s"
-msgstr "estatus cambiara de %(st1)s a %(st2)s"
+msgstr "El estatus cambiará de %(st1)s a %(st2)s"
 
 msgid "subject"
-msgstr "sujeto"
+msgstr "Sujeto"
 
 msgid "subject type"
-msgstr ""
+msgstr "Tipo del sujeto"
 
 msgid "subject/object cardinality"
-msgstr "cardinalidad sujeto/objeto"
+msgstr "Cardinalidad Sujeto/Objeto"
 
 msgid "subworkflow"
-msgstr ""
+msgstr "Sub-Workflow"
 
 msgctxt "WorkflowTransition"
 msgid "subworkflow"
-msgstr ""
+msgstr "Sub-Workflow"
 
 msgid ""
 "subworkflow isn't a workflow for the same types as the transition's workflow"
-msgstr ""
+msgstr "Le Sub-Workflow no se aplica a los mismos tipos que el Workflow " "de esta transición"
 
 msgid "subworkflow state"
-msgstr ""
+msgstr "Estado de Sub-Workflow"
 
 msgid "subworkflow_exit"
-msgstr ""
+msgstr "Salida del Sub-Workflow"
 
 msgctxt "WorkflowTransition"
 msgid "subworkflow_exit"
-msgstr ""
+msgstr "Salida del Sub-Workflow"
 
 msgctxt "SubWorkflowExitPoint"
 msgid "subworkflow_exit_object"
-msgstr ""
+msgstr "Salida Sub-Workflow de"
 
 msgid "subworkflow_exit_object"
-msgstr ""
+msgstr "Salida Sub-Workflow de"
 
 msgctxt "Workflow"
 msgid "subworkflow_object"
-msgstr ""
+msgstr "Sub-Workflow de"
 
 msgid "subworkflow_object"
-msgstr ""
+msgstr "Sub-Workflow de"
 
 msgid "subworkflow_state"
-msgstr ""
+msgstr "Estado de Sub-Workflow"
 
 msgctxt "SubWorkflowExitPoint"
 msgid "subworkflow_state"
-msgstr ""
+msgstr "Estado de Sub-Workflow"
 
 msgctxt "State"
 msgid "subworkflow_state_object"
-msgstr ""
+msgstr "Estado de Salida de"
 
 msgid "subworkflow_state_object"
-msgstr ""
+msgstr "Estado de Salida de"
 
 msgid "sunday"
-msgstr "domingo"
+msgstr "Domingo"
 
 msgid "surname"
-msgstr "apellido"
+msgstr "Apellido"
 
 msgctxt "CWUser"
 msgid "surname"
-msgstr ""
+msgstr "Apellido"
 
 msgid "symmetric"
-msgstr "simetrico"
+msgstr "Simétrico"
 
 msgctxt "CWRType"
 msgid "symmetric"
-msgstr ""
+msgstr "Simétrico"
 
 msgid "system entities"
-msgstr "entidades de sistema"
+msgstr "Entidades del sistema"
 
 msgid "table"
-msgstr "tabla"
+msgstr "Tabla"
 
 msgid "tablefilter"
-msgstr "filtro de tabla"
+msgstr "Tablero de Filtrado"
 
 msgid "task progression"
-msgstr "progreso de la tarea"
+msgstr "Progreso de la Acción"
 
 msgid "text"
-msgstr "text"
+msgstr "Texto"
 
 msgid "text/cubicweb-page-template"
-msgstr "text/cubicweb-page-template"
+msgstr "Usar Page Templates"
 
 msgid "text/html"
-msgstr "html"
+msgstr "Usar HTML"
 
 msgid "text/plain"
-msgstr "text/plain"
+msgstr "Usar Texto simple"
 
 msgid "text/rest"
-msgstr "text/rest"
+msgstr "Texto en REST"
 
 msgid "the URI of the object"
-msgstr ""
+msgstr "El URI del Objeto"
 
 msgid "the prefered email"
-msgstr "dirección principal de email"
+msgstr "Dirección principal de email"
 
 #, python-format
 msgid "the value \"%s\" is already used, use another one"
-msgstr "el valor \"%s\" ya esta en uso, favor de utilizar otro"
+msgstr "El valor \"%s\" ya esta en uso, favor de utilizar otro"
 
 msgid "this action is not reversible!"
-msgstr "esta acción es irreversible!."
+msgstr "Esta acción es irreversible!."
 
 msgid "this entity is currently owned by"
-msgstr "esta entidad es propiedad de"
+msgstr "Esta Entidad es propiedad de"
 
 msgid "this resource does not exist"
-msgstr "este recurso no existe"
+msgstr "Este recurso no existe"
 
 msgid "thursday"
-msgstr "jueves"
+msgstr "Jueves"
 
 msgid "timeline"
-msgstr ""
+msgstr "Escala de Tiempo"
 
 msgid "timestamp"
-msgstr "fecha"
+msgstr "Fecha"
 
 msgctxt "CWCache"
 msgid "timestamp"
-msgstr ""
+msgstr "Válido desde"
 
 msgid "timestamp of the latest source synchronization."
-msgstr "fecha de la ultima sincronización de la fuente."
+msgstr "Fecha de la última sincronización de la fuente."
 
 msgid "timetable"
-msgstr "tabla de tiempos"
+msgstr "Tablero de tiempos"
 
 msgid "title"
-msgstr "titulo"
+msgstr "Nombre"
 
 msgctxt "Bookmark"
 msgid "title"
-msgstr ""
+msgstr "Nombre"
 
 msgid "to"
 msgstr "a"
@@ -3632,437 +3663,443 @@
 msgstr "a %(date)s"
 
 msgid "to associate with"
-msgstr "a asociar con"
+msgstr "Para asociar con"
 
 msgid "to_entity"
-msgstr "hacia entidad"
+msgstr "Hacia la entidad"
 
 msgctxt "CWAttribute"
 msgid "to_entity"
-msgstr ""
+msgstr "Por la entidad"
 
 msgctxt "CWRelation"
 msgid "to_entity"
-msgstr ""
+msgstr "Por la entidad"
 
 msgctxt "CWEType"
 msgid "to_entity_object"
-msgstr ""
+msgstr "Objeto de la Relación"
 
 msgid "to_entity_object"
-msgstr "hacia entidad objeto"
+msgstr "Objeto de la Relación"
 
 msgid "to_interval_end"
-msgstr ""
+msgstr "a"
 
 msgid "to_state"
-msgstr "hacia el estado"
+msgstr "Hacia el Estado"
 
 msgctxt "TrInfo"
 msgid "to_state"
-msgstr ""
+msgstr "Hacia el Estado"
 
 msgctxt "State"
 msgid "to_state_object"
-msgstr ""
+msgstr "Transición hacia este Estado"
 
 msgid "to_state_object"
-msgstr "hacia objeto estado"
+msgstr "Transición hacia este Estado"
 
 msgid "todo_by"
-msgstr "a hacer por"
+msgstr "Asignada a"
 
 msgid "toggle check boxes"
-msgstr "cambiar valor"
+msgstr "Cambiar valor"
 
 msgid "transaction undoed"
-msgstr ""
+msgstr "Transacciones Anuladas"
 
 #, python-format
 msgid "transition %(tr)s isn't allowed from %(st)s"
-msgstr ""
+msgstr "La transición %(tr)s no esta permitida desde el Estado %(st)s"
 
 msgid "transition doesn't belong to entity's workflow"
-msgstr ""
+msgstr "La transición no pertenece al Workflow de la Entidad"
 
 msgid "transition isn't allowed"
-msgstr ""
+msgstr "La transición no esta permitida"
 
 msgid "transition may not be fired"
-msgstr ""
+msgstr "La transición no puede ser lanzada"
 
 msgid "transition_of"
-msgstr "transicion de"
+msgstr "Transición de"
 
 msgctxt "BaseTransition"
 msgid "transition_of"
-msgstr ""
+msgstr "Transición de"
 
 msgctxt "Transition"
 msgid "transition_of"
-msgstr ""
+msgstr "Transición de"
 
 msgctxt "WorkflowTransition"
 msgid "transition_of"
-msgstr ""
+msgstr "Transición de"
 
 msgctxt "Workflow"
 msgid "transition_of_object"
-msgstr ""
+msgstr "Utiliza las transiciones"
 
 msgid "transition_of_object"
-msgstr "objeto de transición"
+msgstr "Utiliza las transiciones"
 
 msgid "tree view"
-msgstr ""
+msgstr "Vista Jerárquica"
 
 msgid "tuesday"
-msgstr "martes"
+msgstr "Martes"
 
 msgid "type"
-msgstr "type"
+msgstr "Tipo"
 
 msgctxt "BaseTransition"
 msgid "type"
-msgstr ""
+msgstr "Tipo"
 
 msgctxt "Transition"
 msgid "type"
-msgstr ""
+msgstr "Tipo"
 
 msgctxt "WorkflowTransition"
 msgid "type"
-msgstr ""
+msgstr "Tipo"
 
 msgid "type here a sparql query"
-msgstr ""
+msgstr "Escriba aquí su consulta en Sparql"
 
 msgid "ui"
-msgstr "interfaz de usuario"
+msgstr "Interfaz Genérica"
 
 msgid "ui.date-format"
-msgstr ""
+msgstr "Formato de Fecha"
 
 msgid "ui.datetime-format"
-msgstr ""
+msgstr "Formato de Fecha y Hora"
 
 msgid "ui.default-text-format"
-msgstr ""
+msgstr "Formato de texto"
 
 msgid "ui.encoding"
-msgstr ""
+msgstr "Codificación"
 
 msgid "ui.fckeditor"
-msgstr ""
+msgstr "Editor de texto FCK"
 
 msgid "ui.float-format"
-msgstr ""
+msgstr "Números flotantes"
 
 msgid "ui.language"
-msgstr ""
+msgstr "Lenguaje"
 
 msgid "ui.main-template"
-msgstr ""
+msgstr "Plantilla Principal"
 
 msgid "ui.site-title"
-msgstr ""
+msgstr "Nombre del Sistema"
 
 msgid "ui.time-format"
-msgstr ""
+msgstr "Formato de hora"
 
 msgid "unable to check captcha, please try again"
-msgstr ""
+msgstr "Imposible de verificar el Captcha, inténtelo otra vez"
 
 msgid "unaccessible"
-msgstr "inaccesible"
+msgstr "Inaccesible"
 
 msgid "unauthorized value"
-msgstr "valor no permitido"
+msgstr "Valor no permitido"
 
 msgid "undo"
-msgstr ""
+msgstr "Anular"
 
 msgid "unique identifier used to connect to the application"
-msgstr "identificador unico utilizado para conectar a la aplicación"
+msgstr "Identificador único utilizado para conectarse al Sistema"
 
 msgid "unknown external entity"
-msgstr "entidad externa desconocida"
+msgstr "Entidad externa desconocida"
 
 msgid "unknown property key"
-msgstr "propiedad desconocida"
+msgstr "Clave de Propiedad desconocida"
 
 msgid "unknown vocabulary:"
-msgstr ""
+msgstr "Vocabulario desconocido: "
 
 msgid "up"
-msgstr "arriba"
+msgstr "Arriba"
 
 msgid "upassword"
-msgstr "clave de acceso"
+msgstr "Contraseña"
 
 msgctxt "CWUser"
 msgid "upassword"
-msgstr ""
+msgstr "Contraseña"
 
 msgid "update"
-msgstr "modificación"
+msgstr "Modificación"
 
 msgid "update_perm"
-msgstr "modificación"
+msgstr "Permiso de Modificar"
 
 msgid "update_permission"
-msgstr "Permiso de modificación"
+msgstr "Puede ser modificado por"
 
 msgctxt "CWEType"
 msgid "update_permission"
-msgstr ""
+msgstr "Puede ser modificado por"
 
 msgctxt "CWAttribute"
 msgid "update_permission"
-msgstr ""
+msgstr "Puede ser modificado por"
 
 msgctxt "CWGroup"
 msgid "update_permission_object"
-msgstr ""
+msgstr "Puede modificar"
 
 msgctxt "RQLExpression"
 msgid "update_permission_object"
-msgstr ""
+msgstr "Puede modificar"
 
 msgid "update_permission_object"
-msgstr "objeto de autorización de modificaciones"
+msgstr "Tiene permiso de modificar"
 
 msgid "update_relation"
-msgstr ""
+msgstr "Modificar"
 
 msgid "updated"
-msgstr ""
+msgstr "Actualizado"
 
 #, python-format
 msgid "updated %(etype)s #%(eid)s (%(title)s)"
 msgstr "actualización de la entidad %(etype)s #%(eid)s (%(title)s)"
 
 msgid "uri"
-msgstr ""
+msgstr "URI"
 
 msgctxt "ExternalUri"
 msgid "uri"
-msgstr ""
+msgstr "URI"
 
 msgid "use template languages"
-msgstr "utilizar plantillas de lenguaje"
+msgstr "Utilizar plantillas de lenguaje"
 
 msgid ""
 "use to define a transition from one or multiple states to a destination "
 "states in workflow's definitions. Transition without destination state will "
 "go back to the state from which we arrived to the current state."
 msgstr ""
+"Se utiliza en una definición de procesos para agregar una transición desde "
+"uno o varios estados hacia un estado destino. Una transición sin Estado "
+"destino regresará al Estado anterior del Estado actual"
 
 msgid "use_email"
-msgstr "correo electrónico"
+msgstr "Correo electrónico"
 
 msgctxt "CWUser"
 msgid "use_email"
-msgstr ""
+msgstr "Usa el Correo Electrónico"
 
 msgctxt "EmailAddress"
 msgid "use_email_object"
-msgstr ""
+msgstr "Utilizado por"
 
 msgid "use_email_object"
-msgstr "objeto email utilizado"
+msgstr "Email utilizado por"
 
 msgid "use_template_format"
-msgstr "utilización del formato 'cubicweb template'"
+msgstr "Utilización del formato 'cubicweb template'"
 
 msgid ""
 "used for cubicweb configuration. Once a property has been created you can't "
 "change the key."
 msgstr ""
-"utilizado para la configuración de cubicweb. Una vez que la propiedad ha "
-"sido creada no puede cambiar la llave"
+"Se utiliza para la configuración de CubicWeb. Una vez que la propiedad ha "
+"sido creada no puede cambiar la clave"
 
 msgid ""
 "used to associate simple states to an entity type and/or to define workflows"
 msgstr ""
-"utilizado para asociar estados simples a un tipo de entidad y/o para definir "
-"workflows"
+"Se utiliza para asociar estados simples a un tipo de entidad y/o para definir "
+"Workflows"
 
 msgid "used to grant a permission to a group"
-msgstr "utilizado para otorgar permisos a un grupo"
+msgstr "Se utiliza para otorgar permisos a un grupo"
 
 msgid "user"
-msgstr ""
+msgstr "Usuario"
 
 #, python-format
 msgid ""
 "user %s has made the following change(s):\n"
 "\n"
 msgstr ""
-"el usuario %s ha efectuado los siguentes cambios:\n"
+"El usuario %s ha efectuado los siguentes cambios:\n"
 "\n"
 
 msgid "user interface encoding"
-msgstr "codificación de la interfaz de usuario"
+msgstr "Encoding de la interfaz de usuario"
 
 msgid "user preferences"
-msgstr "preferencias del usuario"
+msgstr "Preferencias"
 
 msgid "users"
-msgstr "usuarios"
+msgstr "Usuarios"
 
 msgid "users using this bookmark"
-msgstr "usuarios en este favorito"
+msgstr "Usuarios utilizando este Favorito"
 
 msgid "validate modifications on selected items"
-msgstr "valida modificaciones sobre elementos seleccionados"
+msgstr "Valida modificaciones sobre elementos seleccionados"
 
 msgid "validating..."
-msgstr "validando ..."
+msgstr "Validando ..."
 
 msgid "value"
-msgstr "valor"
+msgstr "Valor"
 
 msgctxt "CWConstraint"
 msgid "value"
-msgstr ""
+msgstr "Valor"
 
 msgctxt "CWProperty"
 msgid "value"
-msgstr ""
+msgstr "Vampr"
 
 msgid "value associated to this key is not editable manually"
-msgstr "el valor asociado a este elemento no es editable manualmente"
+msgstr "El valor asociado a este elemento no es editable manualmente"
 
 #, python-format
 msgid "value must be %(op)s %(boundary)s"
-msgstr ""
+msgstr "El valor debe ser %(op)s %(boundary)s"
 
 #, python-format
 msgid "value must be <= %(boundary)s"
-msgstr ""
+msgstr "El valor debe ser <= %(boundary)s"
 
 #, python-format
 msgid "value must be >= %(boundary)s"
-msgstr ""
+msgstr "El valor debe ser >= %(boundary)s"
 
 #, python-format
 msgid "value should have maximum size of %s"
-msgstr ""
+msgstr "El valor no debe exceder de %s"
 
 #, python-format
 msgid "value should have minimum size of %s"
-msgstr ""
+msgstr "El valor no puede ser menor a %s"
 
 msgid "vcard"
 msgstr "vcard"
 
 msgid "versions configuration"
-msgstr ""
+msgstr "Configuración de Versión"
 
 msgid "view"
-msgstr "ver"
+msgstr "Ver"
 
 msgid "view all"
-msgstr "ver todos"
+msgstr "Ver todos"
 
 msgid "view detail for this entity"
-msgstr "ver detalle de esta entidad"
+msgstr "Ver a detalle esta entidad"
 
 msgid "view history"
-msgstr ""
+msgstr "Ver histórico"
 
 msgid "view identifier"
-msgstr ""
+msgstr "Identificador"
 
 msgid "view title"
-msgstr ""
+msgstr "Nombre"
 
 msgid "view workflow"
-msgstr "ver workflow"
+msgstr "Ver Workflow"
 
 msgid "view_index"
-msgstr ""
+msgstr "Inicio"
 
 msgid "visible"
-msgstr "visible"
+msgstr "Visible"
 
 msgid "we are not yet ready to handle this query"
-msgstr ""
+msgstr "Aún no podemos manejar este tipo de consulta Sparql"
 
 msgid "wednesday"
-msgstr "miercoles"
+msgstr "Miércoles"
 
 msgid "week"
 msgstr "sem."
 
 #, python-format
 msgid "welcome %s !"
-msgstr "bienvenido %s !"
+msgstr "¡ Bienvenido %s  !"
 
 msgid "wf_info_for"
-msgstr "historial de"
+msgstr "Histórico de"
 
 msgid "wf_info_for_object"
-msgstr "historial de transiciones"
+msgstr "Histórico de transiciones"
 
 msgid "wf_tab_info"
-msgstr ""
+msgstr "Descripción"
 
 msgid "wfgraph"
-msgstr ""
+msgstr "Gráfica del Workflow"
 
 msgid ""
 "when multiple addresses are equivalent (such as python-projects@logilab.org "
 "and python-projects@lists.logilab.org), set this to indicate which is the "
 "preferred form."
 msgstr ""
+"Cuando varias direcciones email son equivalentes (como python-projects@logilab."
+"org y python-projects@lists.logilab.org), aquí se indica cual es la forma "
+"preferida."
 
 msgid "workflow"
-msgstr ""
+msgstr "Workflow"
 
 msgid "workflow already have a state of that name"
-msgstr ""
+msgstr "El Workflow ya tiene un Estado con ese nombre"
 
 msgid "workflow already have a transition of that name"
-msgstr ""
+msgstr "El Workflow ya tiene una transición con ese nombre"
 
 #, python-format
 msgid "workflow changed to \"%s\""
-msgstr ""
+msgstr "Workflow cambiado a \"%s\""
 
 msgid "workflow has no initial state"
-msgstr ""
+msgstr "El Workflow no posee Estado Inicial"
 
 msgid "workflow history item"
-msgstr ""
+msgstr "Elemento histórico del Workflow"
 
 msgid "workflow isn't a workflow for this type"
-msgstr ""
+msgstr "El Workflow no se aplica a este Tipo de Entidad"
 
 msgid "workflow to which this state belongs"
-msgstr ""
+msgstr "Workflow al cual pertenece este estado"
 
 msgid "workflow to which this transition belongs"
-msgstr ""
+msgstr "Workflow al cual pertenece esta transición"
 
 msgid "workflow_of"
-msgstr ""
+msgstr "Workflow de"
 
 msgctxt "Workflow"
 msgid "workflow_of"
-msgstr ""
+msgstr "Workflow de"
 
 msgctxt "CWEType"
 msgid "workflow_of_object"
-msgstr ""
+msgstr "Utiliza el Workflow"
 
 msgid "workflow_of_object"
-msgstr ""
+msgstr "Utiliza el Workflow"
 
 #, python-format
 msgid "wrong query parameter line %s"
-msgstr ""
+msgstr "Parámetro erróneo de consulta línea %s"
 
 msgid "xbel"
 msgstr "xbel"
@@ -4071,22 +4108,14 @@
 msgstr "xml"
 
 msgid "xml export"
-msgstr ""
+msgstr "Exportar XML"
 
 msgid "yes"
-msgstr "si"
+msgstr "Sí"
 
 msgid "you have been logged out"
-msgstr "ha terminado la sesion"
+msgstr "Ha terminado la sesión"
 
 msgid "you should probably delete that property"
-msgstr "deberia probablamente suprimir esta propriedad"
-
-#~ msgid "The repository holds the following entities"
-#~ msgstr "El repositorio contiene las entidades siguientes"
-
-#~ msgid "graphical schema for %s"
-#~ msgstr "Gráfica del esquema por %s"
-
-#~ msgid "schema-image"
-#~ msgstr "esquema imagen"
+msgstr "Debería probablamente suprimir esta propriedad"
+
--- a/i18n/fr.po	Thu Aug 12 10:12:52 2010 +0200
+++ b/i18n/fr.po	Wed Aug 25 09:43:12 2010 +0200
@@ -548,7 +548,7 @@
 msgstr "Aucun résultat ne correspond à la requête"
 
 msgid "Non exhaustive list of views that may apply to entities of this type"
-msgstr "Liste non exhausite des vues s'appliquant à ce type d'entité"
+msgstr "Liste non exhaustive des vues s'appliquant à ce type d'entité"
 
 msgid "OR"
 msgstr "OU"
@@ -731,7 +731,7 @@
 msgstr "Cette transition workflow"
 
 msgid "This entity type permissions:"
-msgstr "Permissions pour ce type d'endité"
+msgstr "Permissions pour ce type d'entité"
 
 msgid "Time"
 msgstr "Heure"
@@ -755,7 +755,7 @@
 msgstr "contrainte d'unicité"
 
 msgid "Unreachable objects"
-msgstr "Objets inacessible"
+msgstr "Objets inaccessibles"
 
 msgid "Used by:"
 msgstr "Utilisé par :"
@@ -1077,13 +1077,13 @@
 msgid "an electronic mail address associated to a short alias"
 msgstr "une adresse électronique associée à un alias"
 
-msgid "an error occured"
+msgid "an error occurred"
 msgstr "une erreur est survenue"
 
-msgid "an error occured while processing your request"
+msgid "an error occurred while processing your request"
 msgstr "une erreur est survenue pendant le traitement de votre requête"
 
-msgid "an error occured, the request cannot be fulfilled"
+msgid "an error occurred, the request cannot be fulfilled"
 msgstr "une erreur est survenue, la requête ne peut être complétée"
 
 msgid "an integer is expected"
@@ -1152,7 +1152,7 @@
 msgstr "utilise le(s) signet(s)"
 
 msgid "bookmarked_by_object"
-msgstr "a pour signets"
+msgstr "utilise le(s) signet(s)"
 
 msgid "bookmarks"
 msgstr "signets"
@@ -1716,7 +1716,7 @@
 msgstr "date de création"
 
 msgid "cstrtype"
-msgstr "type de constrainte"
+msgstr "type de contrainte"
 
 msgctxt "CWConstraint"
 msgid "cstrtype"
@@ -1835,7 +1835,7 @@
 "define a final relation: link a final relation type from a non final entity "
 "to a final entity type. used to build the instance schema"
 msgstr ""
-"définit une relation non finale: lie un type de relation non finaledepuis "
+"définit une relation non finale: lie un type de relation non finale depuis "
 "une entité vers un type d'entité non final. Utilisé pour construire le "
 "schéma de l'instance"
 
@@ -2174,7 +2174,7 @@
 msgid "eta_date"
 msgstr "date de fin"
 
-msgid "exit state must a subworkflow state"
+msgid "exit state must be a subworkflow state"
 msgstr "l'état de sortie doit être un état du sous-workflow"
 
 msgid "exit_point"
@@ -2403,7 +2403,7 @@
 "model"
 msgstr ""
 "réprésentation graphique du modèle de données pour le type de relation %"
-"(etype)s de %(appid)s"
+"(rtype)s de %(appid)s"
 
 #, python-format
 msgid "graphical workflow for %s"
@@ -2901,7 +2901,7 @@
 "name of the main variables which should be used in the selection if "
 "necessary (comma separated)"
 msgstr ""
-"nom des variables principaes qui devrait être utilisées dans la sélection si "
+"nom des variables principales qui devrait être utilisées dans la sélection si "
 "nécessaire (les séparer par des virgules)"
 
 msgid "name or identifier of the permission"
@@ -3167,7 +3167,7 @@
 
 msgctxt "CWEType"
 msgid "read_permission"
-msgstr "permission d'ajouter"
+msgstr "permission de lire"
 
 msgctxt "CWAttribute"
 msgid "read_permission"
@@ -3258,7 +3258,7 @@
 
 msgctxt "CWGroup"
 msgid "require_group_object"
-msgstr "de"
+msgstr "a les droits"
 
 msgid "require_group_object"
 msgstr "a les droits"
@@ -3288,9 +3288,9 @@
 "current relation'subject, object and to the request user. "
 msgstr ""
 "partie restriction de la requête rql. Pour une expression s'appliquant à une "
-"entité, X et U sont respectivement préféfinis à l'entité et à l'utilisateur "
+"entité, X et U sont respectivement prédéfinis à l'entité et à l'utilisateur "
 "courant. Pour une expression s'appliquant à une relation, S, O et U sont "
-"respectivement préféfinis au sujet/objet de la relation et à l'utilisateur "
+"respectivement prédéfinis au sujet/objet de la relation et à l'utilisateur "
 "courant."
 
 msgid "revert changes"
@@ -3306,7 +3306,7 @@
 msgstr "RSS"
 
 msgid "same_as"
-msgstr "identique à l'entité externe"
+msgstr "identique à"
 
 msgid "sample format"
 msgstr "exemple"
@@ -3438,7 +3438,7 @@
 msgid "site-wide property can't be set for user"
 msgstr "une propriété spécifique au site ne peut être propre à un utilisateur"
 
-msgid "some errors occured:"
+msgid "some errors occurred:"
 msgstr "des erreurs sont survenues"
 
 msgid "some later transaction(s) touch entity, undo them first"
@@ -3693,10 +3693,10 @@
 
 msgctxt "CWEType"
 msgid "to_entity_object"
-msgstr "relation objet"
+msgstr "objet de la relation"
 
 msgid "to_entity_object"
-msgstr "relation objet"
+msgstr "objet de la relation"
 
 msgid "to_interval_end"
 msgstr "à"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/migration/3.9.5_Any.py	Wed Aug 25 09:43:12 2010 +0200
@@ -0,0 +1,4 @@
+if not rql('CWConstraintType X WHERE X name "RQLUniqueConstraint"',
+           ask_confirm=False):
+    rql('INSERT CWConstraintType X: X name "RQLUniqueConstraint"',
+        ask_confirm=False)
--- a/misc/migration/bootstrapmigration_repository.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/misc/migration/bootstrapmigration_repository.py	Wed Aug 25 09:43:12 2010 +0200
@@ -18,7 +18,6 @@
 """allways executed before all others in server migration
 
 it should only include low level schema changes
-
 """
 from __future__ import with_statement
 
--- a/misc/scripts/repair_file_1-9_migration.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/misc/scripts/repair_file_1-9_migration.py	Wed Aug 25 09:43:12 2010 +0200
@@ -1,6 +1,6 @@
 """execute this script if you've migration to file >= 1.9.0 with cubicweb <= 3.9.2
 
-FYI, this migration occured :
+FYI, this migration occurred :
 * on our intranet on July 07 2010
 * on our extranet on July 16 2010
 """
--- a/rqlrewrite.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/rqlrewrite.py	Wed Aug 25 09:43:12 2010 +0200
@@ -45,14 +45,12 @@
     allpossibletypes = {}
     for solution in solutions:
         for varname, etype in solution.iteritems():
-            if not varname in newroot.defined_vars or eschema(etype).final:
+            # XXX not considering aliases by design, right ?
+            if varname not in newroot.defined_vars or eschema(etype).final:
                 continue
             allpossibletypes.setdefault(varname, set()).add(etype)
     for varname in sorted(allpossibletypes):
-        try:
-            var = newroot.defined_vars[varname]
-        except KeyError:
-            continue
+        var = newroot.defined_vars[varname]
         stinfo = var.stinfo
         if stinfo.get('uidrel') is not None:
             continue # eid specified, no need for additional type specification
@@ -64,7 +62,7 @@
         if newroot is rqlst and typerel is not None:
             mytyperel = typerel
         else:
-            for vref in newroot.defined_vars[varname].references():
+            for vref in var.references():
                 rel = vref.relation()
                 if rel and rel.is_types_restriction():
                     mytyperel = rel
@@ -79,12 +77,6 @@
             for cst in mytyperel.get_nodes(n.Constant):
                 if not cst.value in possibletypes:
                     cst.parent.remove(cst)
-                    try:
-                        stinfo['possibletypes'].remove(cst.value)
-                    except KeyError:
-                        # restriction on a type not used by this query, may
-                        # occurs with X is IN(...)
-                        pass
         else:
             # we have to add types restriction
             if stinfo.get('scope') is not None:
@@ -94,7 +86,7 @@
                 # to the root
                 rel = newroot.add_type_restriction(var, possibletypes)
             stinfo['typerel'] = rel
-            stinfo['possibletypes'] = possibletypes
+        stinfo['possibletypes'] = possibletypes
 
 
 def remove_solutions(origsolutions, solutions, defined):
--- a/schema.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/schema.py	Wed Aug 25 09:43:12 2010 +0200
@@ -704,7 +704,7 @@
         """
         if not self.match_condition(session, eidfrom, eidto):
             # XXX at this point if both or neither of S and O are in mainvar we
-            # dunno if the validation error `occured` on eidfrom or eidto (from
+            # dunno if the validation error `occurred` on eidfrom or eidto (from
             # user interface point of view)
             #
             # possible enhancement: check entity being created, it's probably
--- a/schemas/workflow.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/schemas/workflow.py	Wed Aug 25 09:43:12 2010 +0200
@@ -139,7 +139,7 @@
     subworkflow_state = SubjectRelation(
         'State', cardinality='1*',
         constraints=[RQLConstraint('T subworkflow_exit S, T subworkflow WF, O state_of WF',
-                                   msg=_('exit state must a subworkflow state'))],
+                                   msg=_('exit state must be a subworkflow state'))],
         description=_('subworkflow state'))
     destination_state = SubjectRelation(
         'State', cardinality='?*',
--- a/selectors.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/selectors.py	Wed Aug 25 09:43:12 2010 +0200
@@ -188,8 +188,6 @@
 
 .. autoclass:: cubicweb.appobject.traced_selection
 
-
-.. |cubicweb| replace:: *CubicWeb*
 """
 
 __docformat__ = "restructuredtext en"
@@ -201,12 +199,13 @@
 from logilab.common.compat import all, any
 from logilab.common.interface import implements as implements_iface
 
-from yams import BASE_TYPES
+from yams.schema import BASE_TYPES, role_name
 from rql.nodes import Function
 
 from cubicweb import (Unauthorized, NoSelectableObject, NotAnEntity,
                       CW_EVENT_MANAGER, role)
 # even if not used, let yes here so it's importable through this module
+from cubicweb.uilib import eid_param
 from cubicweb.appobject import Selector, objectify_selector, lltrace, yes
 from cubicweb.schema import split_expression
 
@@ -792,6 +791,21 @@
             return 1
         self.score_entity = intscore
 
+class attribute_edited(EntitySelector):
+    """Scores if the specified attribute has been edited
+    This is useful for selection of forms by the edit controller.
+    The initial use case is on a form, in conjunction with match_transition,
+    which will not score at edit time::
+
+     is_instance('Version') & (match_transition('ready') |
+                               attribute_edited('publication_date'))
+    """
+    def __init__(self, attribute, once_is_enough=False):
+        super(attribute_edited, self).__init__(once_is_enough)
+        self._attribute = attribute
+
+    def score_entity(self, entity):
+        return eid_param(role_name(self._attribute, 'subject'), entity.eid) in entity._cw.form
 
 class has_mimetype(EntitySelector):
     """Return 1 if the entity adapt to IDownloadable and has the given MIME type.
@@ -1324,19 +1338,13 @@
 
 
 class match_transition(ExpectedValueSelector):
-    """Return 1 if:
-
-    * a `transition` argument is found in the input context which
-      has a `.name` attribute matching one of the expected names given to the
-      initializer
-
-    * no transition specified.
+    """Return 1 if `transition` argument is found in the input context
+      which has a `.name` attribute matching one of the expected names
+      given to the initializer
     """
     @lltrace
     def __call__(self, cls, req, transition=None, **kwargs):
         # XXX check this is a transition that apply to the object?
-        if transition is None:
-            return 1
         if transition is not None and getattr(transition, 'name', None) in self.expected:
             return 1
         return 0
--- a/server/__init__.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/__init__.py	Wed Aug 25 09:43:12 2010 +0200
@@ -131,11 +131,9 @@
     config.creating = True
     config.consider_user_state = False
     config.set_language = False
-    # only enable the system source at initialization time + admin which is not
-    # an actual source but contains initial manager account information
-    config.enabled_sources = ('system', 'admin')
+    # only enable the system source at initialization time
+    config.enabled_sources = ('system',)
     repo = Repository(config, vreg=vreg)
-    assert len(repo.sources) == 1, repo.sources
     schema = repo.schema
     sourcescfg = config.sources()
     _title = '-> creating tables '
--- a/server/checkintegrity.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/checkintegrity.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,8 +15,12 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Check integrity of a CubicWeb repository. Hum actually only the system database
-is checked.
+"""Integrity checking tool for instances:
+
+* integrity of a CubicWeb repository. Hum actually only the system database is
+  checked.
+
+* consistency of multi-sources instance mapping file
 """
 
 from __future__ import with_statement
@@ -28,7 +32,7 @@
 
 from logilab.common.shellutils import ProgressBar
 
-from cubicweb.schema import PURE_VIRTUAL_RTYPES
+from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, PURE_VIRTUAL_RTYPES
 from cubicweb.server.sqlutils import SQL_PREFIX
 from cubicweb.server.session import security_enabled
 
@@ -99,8 +103,6 @@
         print 'no text index table'
         dbhelper.init_fti(cursor)
     repo.system_source.do_fti = True  # ensure full-text indexation is activated
-    if withpb:
-        pb = ProgressBar(len(etypes) + 1)
     if etypes is None:
         print 'Reindexing entities'
         etypes = set()
@@ -123,6 +125,7 @@
                                dbhelper.fti_table, dbhelper.fti_uid_attr,
                                ','.join("'%s'" % etype for etype in etypes)))
     if withpb:
+        pb = ProgressBar(len(etypes) + 1)
         pb.update()
     # reindex entities by generating rql queries which set all indexable
     # attribute to their current value
@@ -326,3 +329,98 @@
         session.set_pool()
         reindex_entities(repo.schema, session, withpb=withpb)
         cnx.commit()
+
+
+def warning(msg, *args):
+    if args:
+        msg = msg % args
+    print 'WARNING: %s' % msg
+
+def error(msg, *args):
+    if args:
+        msg = msg % args
+    print 'ERROR: %s' % msg
+
+def check_mapping(schema, mapping, warning=warning, error=error):
+    # first check stuff found in mapping file exists in the schema
+    for attr in ('support_entities', 'support_relations'):
+        for ertype in mapping[attr].keys():
+            try:
+                mapping[attr][ertype] = erschema = schema[ertype]
+            except KeyError:
+                error('reference to unknown type %s in %s', ertype, attr)
+                del mapping[attr][ertype]
+            else:
+                if erschema.final or erschema in META_RTYPES:
+                    error('type %s should not be mapped in %s', ertype, attr)
+                    del mapping[attr][ertype]
+    for attr in ('dont_cross_relations', 'cross_relations'):
+        for rtype in list(mapping[attr]):
+            try:
+                rschema = schema.rschema(rtype)
+            except KeyError:
+                error('reference to unknown relation type %s in %s', rtype, attr)
+                mapping[attr].remove(rtype)
+            else:
+                if rschema.final or rschema in VIRTUAL_RTYPES:
+                    error('relation type %s should not be mapped in %s',
+                          rtype, attr)
+                    mapping[attr].remove(rtype)
+    # check relation in dont_cross_relations aren't in support_relations
+    for rschema in mapping['dont_cross_relations']:
+        if rschema in mapping['support_relations']:
+            warning('relation %s is in dont_cross_relations and in support_relations',
+                    rschema)
+    # check relation in cross_relations are in support_relations
+    for rschema in mapping['cross_relations']:
+        if rschema not in mapping['support_relations']:
+            warning('relation %s is in cross_relations but not in support_relations',
+                    rschema)
+    # check for relation in both cross_relations and dont_cross_relations
+    for rschema in mapping['cross_relations'] & mapping['dont_cross_relations']:
+        error('relation %s is in both cross_relations and dont_cross_relations',
+              rschema)
+    # now check for more handy things
+    seen = set()
+    for eschema in mapping['support_entities'].values():
+        for rschema, ttypes, role in eschema.relation_definitions():
+            if rschema in META_RTYPES:
+                continue
+            ttypes = [ttype for ttype in ttypes if ttype in mapping['support_entities']]
+            if not rschema in mapping['support_relations']:
+                somethingprinted = False
+                for ttype in ttypes:
+                    rdef = rschema.role_rdef(eschema, ttype, role)
+                    seen.add(rdef)
+                    if rdef.role_cardinality(role) in '1+':
+                        error('relation %s with %s as %s and target type %s is '
+                              'mandatory but not supported',
+                              rschema, eschema, role, ttype)
+                        somethingprinted = True
+                    elif ttype in mapping['support_entities']:
+                        if rdef not in seen:
+                            warning('%s could be supported', rdef)
+                        somethingprinted = True
+                if rschema not in mapping['dont_cross_relations']:
+                    if role == 'subject' and rschema.inlined:
+                        error('inlined relation %s of %s should be supported',
+                              rschema, eschema)
+                    elif not somethingprinted and rschema not in seen:
+                        print 'you may want to specify something for %s' % rschema
+                        seen.add(rschema)
+            else:
+                if not ttypes:
+                    warning('relation %s with %s as %s is supported but no target '
+                            'type supported', rschema, role, eschema)
+                if rschema in mapping['cross_relations'] and rschema.inlined:
+                    error('you should unline relation %s which is supported and '
+                          'may be crossed ', rschema)
+    for rschema in mapping['support_relations'].values():
+        if rschema in META_RTYPES:
+            continue
+        for subj, obj in rschema.rdefs:
+            if subj in mapping['support_entities'] and obj in mapping['support_entities']:
+                break
+        else:
+            error('relation %s is supported but none if its definitions '
+                  'matches supported entities', rschema)
--- a/server/migractions.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/migractions.py	Wed Aug 25 09:43:12 2010 +0200
@@ -845,7 +845,7 @@
         if commit:
             self.commit()
 
-    def cmd_rename_entity_type(self, oldname, newname, commit=True):
+    def cmd_rename_entity_type(self, oldname, newname, attrs=None, commit=True):
         """rename an existing entity type in the persistent schema
 
         `oldname` is a string giving the name of the existing entity type
@@ -854,18 +854,23 @@
         schema = self.repo.schema
         if newname in schema:
             assert oldname in ETYPE_NAME_MAP, \
-                   '%s should be mappend to %s in ETYPE_NAME_MAP' % (oldname, newname)
-            attrs = ','.join([SQL_PREFIX + rschema.type
-                              for rschema in schema[newname].subject_relations()
-                              if (rschema.final or rschema.inlined)
-                              and not rschema in PURE_VIRTUAL_RTYPES])
+                   '%s should be mapped to %s in ETYPE_NAME_MAP' % (oldname,
+                                                                    newname)
+            if attrs is None:
+                attrs = ','.join(SQL_PREFIX + rschema.type
+                                 for rschema in schema[newname].subject_relations()
+                                 if (rschema.final or rschema.inlined)
+                                 and not rschema in PURE_VIRTUAL_RTYPES)
+            else:
+                attrs += ('eid', 'creation_date', 'modification_date', 'cwuri')
+                attrs = ','.join(SQL_PREFIX + attr for attr in attrs)
             self.sqlexec('INSERT INTO %s%s(%s) SELECT %s FROM %s%s' % (
                 SQL_PREFIX, newname, attrs, attrs, SQL_PREFIX, oldname),
                          ask_confirm=False)
             # old entity type has not been added to the schema, can't gather it
             new = schema.eschema(newname)
-            oldeid = self.rqlexec('CWEType ET WHERE ET name %(on)s', {'on': oldname},
-                                  ask_confirm=False)[0][0]
+            oldeid = self.rqlexec('CWEType ET WHERE ET name %(on)s',
+                                  {'on': oldname}, ask_confirm=False)[0][0]
             # backport old type relations to new type
             # XXX workflows, other relations?
             for r1, rr1 in [('from_entity', 'to_entity'),
@@ -885,13 +890,16 @@
             # since integrity hooks may think some required relation is
             # missing...
             pending = self.session.transaction_data.setdefault('pendingeids', set())
-            for eid, in self.sqlexec('SELECT cw_eid FROM cw_CWRelation '
-                                     'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s',
-                                     {'eid': oldeid}, ask_confirm=False):
-                pending.add(eid)
-            self.sqlexec('DELETE FROM cw_CWRelation '
-                         'WHERE cw_from_entity=%(eid)s OR cw_to_entity=%(eid)s',
-                         {'eid': oldeid}, ask_confirm=False)
+            for rdeftype in ('CWRelation', 'CWAttribute'):
+                for eid, in self.sqlexec('SELECT cw_eid FROM cw_%s '
+                                         'WHERE cw_from_entity=%%(eid)s OR '
+                                         ' cw_to_entity=%%(eid)s' % rdeftype,
+                                         {'eid': oldeid}, ask_confirm=False):
+                    pending.add(eid)
+                self.sqlexec('DELETE FROM cw_%s '
+                             'WHERE cw_from_entity=%%(eid)s OR '
+                             'cw_to_entity=%%(eid)s' % rdeftype,
+                             {'eid': oldeid}, ask_confirm=False)
             # remove the old type: use rql to propagate deletion
             self.rqlexec('DELETE CWEType ET WHERE ET name %(on)s', {'on': oldname},
                          ask_confirm=False)
@@ -1397,9 +1405,7 @@
     def __iter__(self):
         return self
 
-    def next(self):
-        if self._rsetit is not None:
-            return self._rsetit.next()
+    def _get_rset(self):
         rql, kwargs = self.rql, self.kwargs
         if kwargs:
             msg = '%s (%s)' % (rql, kwargs)
@@ -1409,11 +1415,23 @@
             if not self._h.confirm('Execute rql: %s ?' % msg):
                 raise StopIteration
         try:
-            rset = self._h._cw.execute(rql, kwargs)
+            return self._h._cw.execute(rql, kwargs)
         except Exception, ex:
             if self._h.confirm('Error: %s\nabort?' % ex):
                 raise
             else:
                 raise StopIteration
+
+    def next(self):
+        if self._rsetit is not None:
+            return self._rsetit.next()
+        rset = self._get_rset()
         self._rsetit = iter(rset)
         return self._rsetit.next()
+
+    def entities(self):
+        try:
+            rset = self._get_rset()
+        except StopIteration:
+            return []
+        return rset.entities()
--- a/server/msplanner.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/msplanner.py	Wed Aug 25 09:43:12 2010 +0200
@@ -100,9 +100,9 @@
 
 from cubicweb import server
 from cubicweb.utils import make_uid
+from cubicweb.rqlrewrite import add_types_restriction
 from cubicweb.server.utils import cleanup_solutions
-from cubicweb.server.ssplanner import (SSPlanner, OneFetchStep,
-                                       add_types_restriction)
+from cubicweb.server.ssplanner import SSPlanner, OneFetchStep
 from cubicweb.server.mssteps import *
 
 Variable._ms_table_key = lambda x: x.name
@@ -110,6 +110,11 @@
 # str() Constant.value to ensure generated table name won't be unicode
 Constant._ms_table_key = lambda x: str(x.value)
 
+Variable._ms_may_be_processed = lambda x, terms, linkedterms: any(
+    t for t in terms if t in linkedterms.get(x, ()))
+Relation._ms_may_be_processed = lambda x, terms, linkedterms: all(
+    getattr(hs, 'variable', hs) in terms for hs in x.get_variable_parts())
+
 def ms_scope(term):
     rel = None
     scope = term.scope
@@ -411,7 +416,8 @@
                 for const in vconsts:
                     self._set_source_for_term(source, const)
             elif not self._sourcesterms:
-                self._set_source_for_term(source, const)
+                for const in vconsts:
+                    self._set_source_for_term(source, const)
             elif source in self._sourcesterms:
                 source_scopes = frozenset(ms_scope(t) for t in self._sourcesterms[source])
                 for const in vconsts:
@@ -439,7 +445,9 @@
                 #
                 # XXX code below don't deal if some source allow relation
                 #     crossing but not another one
-                relsources = repo.rel_type_sources(rel.r_type)
+                relsources = [s for s in repo.rel_type_sources(rel.r_type)
+                               if s is self.system_source
+                               or s in self._sourcesterms]
                 if len(relsources) < 2:
                     # filter out sources being there because they have this
                     # relation in their dont_cross_relations attribute
@@ -478,6 +486,7 @@
                     # not supported by the source, so we can stop here
                     continue
                 self._sourcesterms.setdefault(ssource, {})[rel] = set(self._solindices)
+                solindices = None
                 for term in crossvars:
                     if len(termssources[term]) == 1 and iter(termssources[term]).next()[0].uri == 'system':
                         for ov in crossvars:
@@ -485,8 +494,14 @@
                                 ssset = frozenset((ssource,))
                                 self._remove_sources(ov, termssources[ov] - ssset)
                         break
+                    if solindices is None:
+                        solindices = set(sol for s, sol in termssources[term]
+                                         if s is source)
+                    else:
+                        solindices &= set(sol for s, sol in termssources[term]
+                                          if s is source)
                 else:
-                    self._sourcesterms.setdefault(source, {})[rel] = set(self._solindices)
+                    self._sourcesterms.setdefault(source, {})[rel] = solindices
 
     def _remove_invalid_sources(self, termssources):
         """removes invalid sources from `sourcesterms` member according to
@@ -799,10 +814,13 @@
                                     rhsvar = rhs.variable
                                 except AttributeError:
                                     rhsvar = rhs
-                                if lhsvar in terms and not rhsvar in terms:
-                                    needsel.add(lhsvar.name)
-                                elif rhsvar in terms and not lhsvar in terms:
-                                    needsel.add(rhsvar.name)
+                                try:
+                                    if lhsvar in terms and not rhsvar in terms:
+                                        needsel.add(lhsvar.name)
+                                    elif rhsvar in terms and not lhsvar in terms:
+                                        needsel.add(rhsvar.name)
+                                except AttributeError:
+                                    continue # not an attribute, no selection needed
                 if final and source.uri != 'system':
                     # check rewritten constants
                     for vconsts in select.stinfo['rewritten'].itervalues():
@@ -937,13 +955,14 @@
                 exclude[vars[1]] = vars[0]
             except IndexError:
                 pass
-        accept_term = lambda x: (not any(s for s in sources if not x in sourcesterms.get(s, ()))
-                                 and any(t for t in terms if t in linkedterms.get(x, ()))
+        accept_term = lambda x: (not any(s for s in sources
+                                         if not x in sourcesterms.get(s, ()))
+                                 and x._ms_may_be_processed(terms, linkedterms)
                                  and not exclude.get(x) in terms)
         if isinstance(term, Relation) and term in cross_rels:
             cross_terms = cross_rels.pop(term)
             base_accept_term = accept_term
-            accept_term = lambda x: (base_accept_term(x) or x in cross_terms)
+            accept_term = lambda x: (accept_term(x) or x in cross_terms)
             for refed in cross_terms:
                 if not refed in candidates:
                     terms.append(refed)
@@ -954,7 +973,11 @@
             modified = False
             for term in candidates[:]:
                 if isinstance(term, Constant):
-                    if sorted(set(x[0] for x in self._term_sources(term))) != sources:
+                    termsources = set(x[0] for x in self._term_sources(term))
+                    # ensure system source is there for constant
+                    if self.system_source in sources:
+                        termsources.add(self.system_source)
+                    if sorted(termsources) != sources:
                         continue
                     terms.append(term)
                     candidates.remove(term)
@@ -1213,11 +1236,16 @@
                     sources, terms, scope, solindices, needsel, final)
                 if final:
                     solsinputmaps = ppi.merge_input_maps(solindices)
+                    if len(solsinputmaps) > 1:
+                        refrqlst = minrqlst
                     for solindices, inputmap in solsinputmaps:
                         if inputmap is None:
                             inputmap = subinputmap
                         else:
                             inputmap.update(subinputmap)
+                        if len(solsinputmaps) > 1:
+                            minrqlst = refrqlst.copy()
+                            sources = sources[:]
                         if inputmap and len(sources) > 1:
                             sources.remove(ppi.system_source)
                             steps.append(ppi.build_final_part(minrqlst, solindices, None,
@@ -1607,6 +1635,8 @@
                 for vref in supportedvars:
                     if not vref in newroot.get_selected_variables():
                         newroot.append_selected(VariableRef(newroot.get_variable(vref.name)))
+            elif term in self.terms:
+                newroot.append_selected(term.copy(newroot))
 
     def add_necessary_selection(self, newroot, terms):
         selected = tuple(newroot.get_selected_variables())
--- a/server/querier.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/querier.py	Wed Aug 25 09:43:12 2010 +0200
@@ -422,7 +422,9 @@
         # raise Unautorized exception if the user can't access to any solution
         if not newsolutions:
             raise Unauthorized('\n'.join(msgs))
-        rqlst.set_possible_types(newsolutions)
+        if msgs:
+            # (else solutions have not been modified)
+            rqlst.set_possible_types(newsolutions)
         return localchecks, restricted_vars
 
     def finalize(self, select, solutions, insertedvars):
@@ -433,6 +435,7 @@
             for sol in solutions:
                 sol[newvarname] = nvartype
         select.clean_solutions(solutions)
+        add_types_restriction(self.schema, select)
         self.rqlhelper.annotate(rqlst)
         self.preprocess(rqlst, security=False)
         return rqlst
--- a/server/repository.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/repository.py	Wed Aug 25 09:43:12 2010 +0200
@@ -135,7 +135,8 @@
                 continue
             source = self.get_source(uri, source_config)
             self.sources_by_uri[uri] = source
-            self.sources.append(source)
+            if config.source_enabled(uri):
+                self.sources.append(source)
         self.system_source = self.sources_by_uri['system']
         # ensure system source is the first one
         self.sources.remove(self.system_source)
@@ -200,8 +201,8 @@
             for source in self.sources:
                 source.init()
         else:
-            # call init_creating so for instance native source can configurate
-            # tsearch according to postgres version
+            # call init_creating so that for instance native source can
+            # configurate tsearch according to postgres version
             for source in self.sources:
                 source.init_creating()
         # close initialization pool and reopen fresh ones for proper
@@ -234,7 +235,9 @@
         else:
             self.vreg._set_schema(schema)
         self.querier.set_schema(schema)
-        for source in self.sources:
+        # don't use self.sources, we may want to give schema even to disabled
+        # sources
+        for source in self.sources_by_uri.values():
             source.set_schema(schema)
         self.schema = schema
 
@@ -1245,15 +1248,15 @@
 
     @cached
     def rel_type_sources(self, rtype):
-        return [source for source in self.sources
-                if source.support_relation(rtype)
-                or rtype in source.dont_cross_relations]
+        return tuple([source for source in self.sources
+                      if source.support_relation(rtype)
+                      or rtype in source.dont_cross_relations])
 
     @cached
     def can_cross_relation(self, rtype):
-        return [source for source in self.sources
-                if source.support_relation(rtype)
-                and rtype in source.cross_relations]
+        return tuple([source for source in self.sources
+                      if source.support_relation(rtype)
+                      and rtype in source.cross_relations])
 
     @cached
     def is_multi_sources_relation(self, rtype):
--- a/server/serverconfig.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/serverconfig.py	Wed Aug 25 09:43:12 2010 +0200
@@ -23,7 +23,7 @@
 
 from logilab.common.configuration import REQUIRED, Method, Configuration, \
      ini_format_section
-from logilab.common.decorators import wproperty, cached, clear_cache
+from logilab.common.decorators import wproperty, cached
 
 from cubicweb.toolsutils import read_config, restrict_perms_to_user
 from cubicweb.cwconfig import CubicWebConfiguration, merge_options
@@ -162,7 +162,7 @@
         ('multi-sources-etypes',
          {'type' : 'csv', 'default': (),
           'help': 'defines which entity types from this repository are used \
-by some other instances. You should set this properly so those instances to \
+by some other instances. You should set this properly for these instances to \
 detect updates / deletions.',
           'group': 'main', 'level': 3,
           }),
@@ -233,11 +233,7 @@
 
     # list of enables sources when sources restriction is necessary
     # (eg repository initialization at least)
-    _enabled_sources = None
-    @wproperty
-    def enabled_sources(self, sourceuris=None):
-        self._enabled_sources = sourceuris
-        clear_cache(self, 'sources')
+    enabled_sources = None
 
     def bootstrap_cubes(self):
         from logilab.common.textutils import splitstrip
@@ -272,11 +268,10 @@
         """return a dictionnaries containing sources definitions indexed by
         sources'uri
         """
-        allsources = self.read_sources_file()
-        if self._enabled_sources is None:
-            return allsources
-        return dict((uri, config) for uri, config in allsources.items()
-                    if uri in self._enabled_sources or uri == 'admin')
+        return self.read_sources_file()
+
+    def source_enabled(self, uri):
+        return not self.enabled_sources or uri in self.enabled_sources
 
     def write_sources_file(self, sourcescfg):
         sourcesfile = self.sources_file()
@@ -331,8 +326,7 @@
             for uri in sources:
                 assert uri in known_sources, uri
             enabled_sources = sources
-        self._enabled_sources = enabled_sources
-        clear_cache(self, 'sources')
+        self.enabled_sources = enabled_sources
 
     def migration_handler(self, schema=None, interactive=True,
                           cnx=None, repo=None, connect=True, verbosity=None):
--- a/server/serverctl.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/serverctl.py	Wed Aug 25 09:43:12 2010 +0200
@@ -26,11 +26,11 @@
 import os
 
 from logilab.common.configuration import Configuration
-from logilab.common.clcommands import register_commands, cmd_run, pop_arg
 from logilab.common.shellutils import ASK
 
 from cubicweb import AuthenticationError, ExecutionError, ConfigurationError
 from cubicweb.toolsutils import Command, CommandHandler, underline_title
+from cubicweb.cwctl import CWCTL
 from cubicweb.server import SOURCE_TYPES
 from cubicweb.server.serverconfig import (USER_OPTIONS, ServerConfiguration,
                                           SourceConfiguration)
@@ -217,7 +217,7 @@
     def postcreate(self):
         if ASK.confirm('Run db-create to create the system database ?'):
             verbosity = (self.config.mode == 'installed') and 'y' or 'n'
-            cmd_run('db-create', self.config.appid, '--verbose=%s' % verbosity)
+            CWCTL.run(['db-create', self.config.appid, '--verbose=%s' % verbosity])
         else:
             print ('-> nevermind, you can do it later with '
                    '"cubicweb-ctl db-create %s".' % self.config.appid)
@@ -299,7 +299,7 @@
     """
     name = 'db-create'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = (
         ('create-db',
          {'short': 'c', 'type': 'yn', 'metavar': '<y or n>',
@@ -323,7 +323,7 @@
         from logilab.database import get_db_helper
         verbose = self.get('verbose')
         automatic = self.get('automatic')
-        appid = pop_arg(args, msg='No instance specified !')
+        appid = args.pop()
         config = ServerConfiguration.config_for(appid)
         source = config.sources()['system']
         dbname = source['db-name']
@@ -371,7 +371,7 @@
         print '-> database for instance %s created and necessary extensions installed.' % appid
         print
         if automatic or ASK.confirm('Run db-init to initialize the system database ?'):
-            cmd_run('db-init', config.appid)
+            CWCTL.run(['db-init', config.appid])
         else:
             print ('-> nevermind, you can do it later with '
                    '"cubicweb-ctl db-init %s".' % config.appid)
@@ -389,7 +389,7 @@
     """
     name = 'db-init'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = (
         ('drop',
          {'short': 'd', 'action': 'store_true',
@@ -402,7 +402,7 @@
         print '\n'+underline_title('Initializing the system database')
         from cubicweb.server import init_repository
         from logilab.database import get_connection
-        appid = pop_arg(args, msg='No instance specified !')
+        appid = args[0]
         config = ServerConfiguration.config_for(appid)
         try:
             system = config.sources()['system']
@@ -431,7 +431,7 @@
     """
     name = 'db-grant-user'
     arguments = '<instance> <user>'
-
+    min_args = max_args = 2
     options = (
         ('set-owner',
          {'short': 'o', 'type' : 'yn', 'metavar' : '<yes or no>',
@@ -442,8 +442,7 @@
     def run(self, args):
         """run the command with its specific arguments"""
         from cubicweb.server.sqlutils import sqlexec, sqlgrants
-        appid = pop_arg(args, 1, msg='No instance specified !')
-        user = pop_arg(args, msg='No user specified !')
+        appid, user = args
         config = ServerConfiguration.config_for(appid)
         source = config.sources()['system']
         set_owner = self.config.set_owner
@@ -457,7 +456,7 @@
             cnx.rollback()
             import traceback
             traceback.print_exc()
-            print '-> an error occured:', ex
+            print '-> an error occurred:', ex
         else:
             cnx.commit()
             print '-> rights granted to %s on instance %s.' % (appid, user)
@@ -475,7 +474,7 @@
     def run(self, args):
         """run the command with its specific arguments"""
         from cubicweb.server.utils import crypt_password, manager_userpasswd
-        appid = pop_arg(args, 1, msg='No instance specified !')
+        appid = args[0]
         config = ServerConfiguration.config_for(appid)
         sourcescfg = config.read_sources_file()
         try:
@@ -509,7 +508,7 @@
             cnx.rollback()
             import traceback
             traceback.print_exc()
-            print '-> an error occured:', ex
+            print '-> an error occurred:', ex
         else:
             cnx.commit()
             print '-> password reset, sources file regenerated.'
@@ -526,7 +525,7 @@
     """
     name = 'start-repository'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = (
         ('debug',
          {'short': 'D', 'action' : 'store_true',
@@ -542,7 +541,7 @@
         from logilab.common.daemon import daemonize
         from cubicweb.cwctl import init_cmdline_log_threshold
         from cubicweb.server.server import RepositoryServer
-        appid = pop_arg(args, msg='No instance specified !')
+        appid = args[0]
         debug = self['debug']
         if sys.platform == 'win32' and not debug:
             from logging import getLogger
@@ -595,7 +594,7 @@
     rmcmd = 'ssh -t %s "rm -f /tmp/%s"' % (host, filename)
     print rmcmd
     if os.system(rmcmd) and not ASK.confirm(
-        'An error occured while deleting remote dump at /tmp/%s. '
+        'An error occurred while deleting remote dump at /tmp/%s. '
         'Continue anyway?' % filename):
         raise ExecutionError('Error while deleting remote dump at /tmp/%s' % filename)
 
@@ -673,7 +672,7 @@
     """
     name = 'db-dump'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = (
         ('output',
          {'short': 'o', 'type' : 'string', 'metavar' : '<file>',
@@ -688,7 +687,7 @@
         )
 
     def run(self, args):
-        appid = pop_arg(args, 1, msg='No instance specified !')
+        appid = args[0]
         if ':' in appid:
             host, appid = appid.split(':')
             _remote_dump(host, appid, self.config.output, self.config.sudo)
@@ -704,6 +703,7 @@
     """
     name = 'db-restore'
     arguments = '<instance> <backupfile>'
+    min_args = max_args = 2
 
     options = (
         ('no-drop',
@@ -721,8 +721,7 @@
         )
 
     def run(self, args):
-        appid = pop_arg(args, 1, msg='No instance specified !')
-        backupfile = pop_arg(args, msg='No backup file or timestamp specified !')
+        appid, backupfile = args
         _local_restore(appid, backupfile,
                        drop=not self.config.no_drop,
                        systemonly=not self.config.restore_all)
@@ -740,7 +739,7 @@
     """
     name = 'db-copy'
     arguments = '<src-instance> <dest-instance>'
-
+    min_args = max_args = 2
     options = (
         ('no-drop',
          {'short': 'n', 'action' : 'store_true',
@@ -762,8 +761,7 @@
 
     def run(self, args):
         import tempfile
-        srcappid = pop_arg(args, 1, msg='No source instance specified !')
-        destappid = pop_arg(args, msg='No destination instance specified !')
+        srcappid, destappid = args
         fd, output = tempfile.mkstemp()
         os.close(fd)
         if ':' in srcappid:
@@ -786,7 +784,7 @@
     """
     name = 'db-check'
     arguments = '<instance>'
-
+    min_args = max_args = 1
     options = (
         ('checks',
          {'short': 'c', 'type' : 'csv', 'metavar' : '<check list>',
@@ -816,8 +814,7 @@
         )
 
     def run(self, args):
-        from cubicweb.server.checkintegrity import check
-        appid = pop_arg(args, 1, msg='No instance specified !')
+        appid = args[0]
         config = ServerConfiguration.config_for(appid)
         config.repairing = self.config.force
         repo, cnx = repo_cnx(config)
@@ -833,12 +830,11 @@
     """
     name = 'db-rebuild-fti'
     arguments = '<instance>'
-
-    options = ()
+    min_args = max_args = 1
 
     def run(self, args):
         from cubicweb.server.checkintegrity import reindex_entities
-        appid = pop_arg(args, 1, msg='No instance specified !')
+        appid = args[0]
         config = ServerConfiguration.config_for(appid)
         repo, cnx = repo_cnx(config)
         session = repo._get_session(cnx.sessionid, setpool=True)
@@ -857,23 +853,48 @@
     """
     name = 'schema-sync'
     arguments = '<instance>'
+    min_args = max_args = 1
 
     def run(self, args):
-        appid = pop_arg(args, msg='No instance specified !')
+        appid = args[0]
         config = ServerConfiguration.config_for(appid)
         mih = config.migration_handler()
         mih.cmd_synchronize_schema()
 
 
-register_commands( (CreateInstanceDBCommand,
-                    InitInstanceCommand,
-                    GrantUserOnInstanceCommand,
-                    ResetAdminPasswordCommand,
-                    StartRepositoryCommand,
-                    DBDumpCommand,
-                    DBRestoreCommand,
-                    DBCopyCommand,
-                    CheckRepositoryCommand,
-                    RebuildFTICommand,
-                    SynchronizeInstanceSchemaCommand,
-                    ) )
+class CheckMappingCommand(Command):
+    """Check content of the mapping file of an external source.
+
+    The mapping is checked against the instance's schema, searching for
+    inconsistencies or stuff you may have forgotten. It's higly recommanded to
+    run it when you setup a multi-sources instance.
+
+    <instance>
+      the identifier of the instance.
+
+    <mapping file>
+      the mapping file to check.
+    """
+    name = 'check-mapping'
+    arguments = '<instance> <mapping file>'
+    min_args = max_args = 2
+
+    def run(self, args):
+        from cubicweb.server.checkintegrity import check_mapping
+        from cubicweb.server.sources.pyrorql import load_mapping_file
+        appid, mappingfile = args
+        config = ServerConfiguration.config_for(appid)
+        config.quick_start = True
+        mih = config.migration_handler(connect=False, verbosity=1)
+        repo = mih.repo_connect() # necessary to get cubes
+        check_mapping(config.load_schema(), load_mapping_file(mappingfile))
+
+for cmdclass in (CreateInstanceDBCommand, InitInstanceCommand,
+                 GrantUserOnInstanceCommand, ResetAdminPasswordCommand,
+                 StartRepositoryCommand,
+                 DBDumpCommand, DBRestoreCommand, DBCopyCommand,
+                 CheckRepositoryCommand, RebuildFTICommand,
+                 SynchronizeInstanceSchemaCommand,
+                 CheckMappingCommand,
+                 ):
+    CWCTL.register(cmdclass)
--- a/server/sources/native.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/sources/native.py	Wed Aug 25 09:43:12 2010 +0200
@@ -505,7 +505,7 @@
     def manual_insert(self, results, table, session):
         """insert given result into a temporary table on the system source"""
         if server.DEBUG & server.DBG_RQL:
-            print '  manual insertion of', results, 'into', table
+            print '  manual insertion of', len(results), 'results into', table
         if not results:
             return
         query_args = ['%%(%s)s' % i for i in xrange(len(results[0]))]
--- a/server/sources/pyrorql.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/sources/pyrorql.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,9 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Source to query another RQL repository using pyro
+"""Source to query another RQL repository using pyro"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 import threading
@@ -44,6 +43,34 @@
     select, col = union.locate_subquery(col, etype, args)
     return getattr(select.selection[col], 'uidtype', None)
 
+def load_mapping_file(mappingfile):
+    mapping = {}
+    execfile(mappingfile, mapping)
+    for junk in ('__builtins__', '__doc__'):
+        mapping.pop(junk, None)
+    mapping.setdefault('support_relations', {})
+    mapping.setdefault('dont_cross_relations', set())
+    mapping.setdefault('cross_relations', set())
+
+    # do some basic checks of the mapping content
+    assert 'support_entities' in mapping, \
+           'mapping file should at least define support_entities'
+    assert isinstance(mapping['support_entities'], dict)
+    assert isinstance(mapping['support_relations'], dict)
+    assert isinstance(mapping['dont_cross_relations'], set)
+    assert isinstance(mapping['cross_relations'], set)
+    unknown = set(mapping) - set( ('support_entities', 'support_relations',
+                                   'dont_cross_relations', 'cross_relations') )
+    assert not unknown, 'unknown mapping attribute(s): %s' % unknown
+    # relations that are necessarily not crossed
+    mapping['dont_cross_relations'] |= set(('owned_by', 'created_by'))
+    for rtype in ('is', 'is_instance_of'):
+        assert rtype not in mapping['dont_cross_relations'], \
+               '%s relation should not be in dont_cross_relations' % rtype
+        assert rtype not in mapping['support_relations'], \
+               '%s relation should not be in support_relations' % rtype
+    return mapping
+
 
 class ReplaceByInOperator(Exception):
     def __init__(self, eids):
@@ -59,8 +86,6 @@
     # migration
     connect_for_migration = False
 
-    support_entities = None
-
     options = (
         # XXX pyro-ns host/port
         ('pyro-ns-id',
@@ -127,14 +152,11 @@
         mappingfile = source_config['mapping-file']
         if not mappingfile[0] == '/':
             mappingfile = join(repo.config.apphome, mappingfile)
-        mapping = {}
-        execfile(mappingfile, mapping)
+        mapping = load_mapping_file(mappingfile)
         self.support_entities = mapping['support_entities']
-        self.support_relations = mapping.get('support_relations', {})
-        self.dont_cross_relations = set(mapping.get('dont_cross_relations', ()))
-        self.cross_relations = set(mapping.get('cross_relations', ()))
-        self.dont_cross_relations.add('owned_by')
-        self.dont_cross_relations.add('created_by')
+        self.support_relations = mapping['support_relations']
+        self.dont_cross_relations = mapping['dont_cross_relations']
+        self.cross_relations = mapping['cross_relations']
         baseurl = source_config.get('base-url')
         if baseurl and not baseurl.endswith('/'):
             source_config['base-url'] += '/'
--- a/server/sources/rql2sql.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/sources/rql2sql.py	Wed Aug 25 09:43:12 2010 +0200
@@ -1154,9 +1154,13 @@
         if constant.type == 'Boolean':
             value = self.dbhelper.boolean_value(value)
         if constant.type == 'Substitute':
-            _id = constant.value
-            if isinstance(_id, unicode):
-                _id = _id.encode()
+            try:
+                # we may found constant from simplified var in varmap
+                return self._mapped_term(constant, '%%(%s)s' % value)[0]
+            except KeyError:
+                _id = constant.value
+                if isinstance(_id, unicode):
+                    _id = _id.encode()
         else:
             _id = str(id(constant)).replace('-', '', 1)
             self._query_attrs[_id] = value
@@ -1262,12 +1266,19 @@
                     break
         return scope
 
+    def _mapped_term(self, term, key):
+        """return sql and table alias to the `term`, mapped as `key` or raise
+        KeyError when the key is not found in the varmap
+        """
+        sql = self._varmap[key]
+        tablealias = sql.split('.', 1)[0]
+        scope = self._temp_table_scope(term.stmt, tablealias)
+        self.add_table(tablealias, scope=scope)
+        return sql, tablealias
+
     def _var_info(self, var):
         try:
-            sql = self._varmap[var.name]
-            tablealias = sql.split('.', 1)[0]
-            scope = self._temp_table_scope(var.stmt, tablealias)
-            self.add_table(tablealias, scope=scope)
+            return self._mapped_term(var, var.name)
         except KeyError:
             scope = self._state.scopes[var.scope]
             etype = self._state.solution[var.name]
--- a/server/test/unittest_msplanner.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/test/unittest_msplanner.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,6 +15,9 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+
+from logilab.common.decorators import clear_cache
+
 from cubicweb.devtools import init_test_database
 from cubicweb.devtools.repotest import BasePlannerTC, test_plan
 
@@ -45,7 +48,7 @@
     uri = 'ccc'
     support_entities = {'Card': True, 'Note': True, 'State': True}
     support_relations = {'in_state': True, 'multisource_rel': True, 'multisource_inlined_rel': True,
-                         'multisource_crossed_rel': True}
+                         'multisource_crossed_rel': True,}
     dont_cross_relations = set(('fiche', 'state_of'))
     cross_relations = set(('multisource_crossed_rel',))
 
@@ -364,6 +367,8 @@
     def setUp(self):
         BaseMSPlannerTC.setUp(self)
         self.planner = MSPlanner(self.o.schema, self.repo.vreg.rqlhelper)
+        for cached in ('rel_type_sources', 'can_cross_relation', 'is_multi_sources_relation'):
+            clear_cache(self.repo, cached)
 
     _test = test_plan
 
@@ -1026,7 +1031,7 @@
                      [self.cards, self.system], None, {'X': 'table1.C0', 'X.title': 'table1.C1', 'XT': 'table1.C1'}, []),
                     ('OneFetchStep',
                      [('Any X,XT,U WHERE X owned_by U?, X title XT, X is Card',
-                       [{'X': 'Card', 'XT': 'String'}])],
+                       [{'X': 'Card', 'U': 'CWUser', 'XT': 'String'}])],
                      None, None, [self.system], {'L': 'table0.C1',
                                                  'U': 'table0.C0',
                                                  'X': 'table1.C0',
@@ -1436,7 +1441,7 @@
                     ('FetchStep',
                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
-                    ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser',
+                    ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser, A is IN(Bookmark, Tag)',
                                        [{'A': 'Bookmark', 'B': 'CWUser', 'C': 'String'},
                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
                      None, None, [self.system],
@@ -1470,7 +1475,7 @@
                     ('FetchStep',
                      [('Any B,C WHERE B login C, B is CWUser', [{'B': 'CWUser', 'C': 'String'}])],
                      [self.ldap, self.system], None, {'B': 'table1.C0', 'B.login': 'table1.C1', 'C': 'table1.C1'}, []),
-                    ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser',
+                    ('OneFetchStep', [('DISTINCT Any B,C ORDERBY C WHERE A created_by B, B login C, EXISTS(B owned_by 5), B is CWUser, A is IN(Card, Tag)',
                                        [{'A': 'Card', 'B': 'CWUser', 'C': 'String'},
                                         {'A': 'Tag', 'B': 'CWUser', 'C': 'String'}])],
                      None, None, [self.system],
@@ -1536,20 +1541,11 @@
     def test_crossed_relation_eid_2_needattr(self):
         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
         self._test('Any Y,T WHERE X eid %(x)s, X multisource_crossed_rel Y, Y type T',
-                   [('FetchStep', [('Any Y,T WHERE Y type T, Y is Note', [{'T': 'String', 'Y': 'Note'}])],
-                     [self.cards, self.system], None,
-                     {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'}, []),
-                    ('UnionStep', None, None,
-                     [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
-                                         [{'T': 'String', 'Y': 'Note'}])],
-                       None, None, [self.cards], None,
-                       []),
-                      ('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
-                                         [{'T': 'String', 'Y': 'Note'}])],
-                       None, None, [self.system],
-                       {'T': 'table0.C1', 'Y': 'table0.C0', 'Y.type': 'table0.C1'},
-                       [])]
-                     )],
+                   [('OneFetchStep', [('Any Y,T WHERE 999999 multisource_crossed_rel Y, Y type T, Y is Note',
+                                       [{'T': 'String', 'Y': 'Note'}])],
+                     None, None, [self.cards, self.system], {},
+                     []),
+                    ],
                    {'x': 999999,})
 
     def test_crossed_relation_eid_not_1(self):
@@ -1757,6 +1753,54 @@
 #                        ]),
 #                     ])
 
+    def test_ldap_user_related_to_invariant_and_dont_cross_rel(self):
+        self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
+        self.cards.dont_cross_relations.add('created_by')
+        try:
+            self._test('Any X,XL WHERE E eid %(x)s, E created_by X, X login XL',
+                   [('FetchStep', [('Any X,XL WHERE X login XL, X is CWUser',
+                                    [{'X': 'CWUser', 'XL': 'String'}])],
+                     [self.ldap, self.system], None,
+                     {'X': 'table0.C0', 'X.login': 'table0.C1', 'XL': 'table0.C1'},
+                     []),
+                    ('OneFetchStep',
+                     [('Any X,XL WHERE 999999 created_by X, X login XL, X is CWUser',
+                       [{'X': 'CWUser', 'XL': 'String'}])],
+                     None, None,
+                     [self.system],
+                     {'X': 'table0.C0', 'X.login': 'table0.C1', 'XL': 'table0.C1'},
+                     [])],
+                       {'x': 999999})
+        finally:
+            self.cards.dont_cross_relations.remove('created_by')
+
+    def test_ambigous_cross_relation(self):
+        self.repo._type_source_cache[999999] = ('Note', 'cards', 999999)
+        self.cards.support_relations['see_also'] = True
+        self.cards.cross_relations.add('see_also')
+        try:
+            self._test('Any X,AA ORDERBY AA WHERE E eid %(x)s, E see_also X, X modification_date AA',
+                       [('AggrStep',
+                         'SELECT table0.C0, table0.C1 FROM table0 ORDER BY table0.C1',
+                         None,
+                         [('FetchStep',
+                           [('Any X,AA WHERE 999999 see_also X, X modification_date AA, X is Note',
+                             [{'AA': 'Datetime', 'X': 'Note'}])], [self.cards, self.system], {},
+                           {'AA': 'table0.C1', 'X': 'table0.C0',
+                            'X.modification_date': 'table0.C1'},
+                           []),
+                          ('FetchStep',
+                           [('Any X,AA WHERE 999999 see_also X, X modification_date AA, X is Bookmark',
+                             [{'AA': 'Datetime', 'X': 'Bookmark'}])],
+                           [self.system], {},
+                           {'AA': 'table0.C1', 'X': 'table0.C0',
+                            'X.modification_date': 'table0.C1'},
+                           [])])],
+                         {'x': 999999})
+        finally:
+            del self.cards.support_relations['see_also']
+            self.cards.cross_relations.remove('see_also')
+
     # non regression tests ####################################################
 
     def test_nonregr1(self):
@@ -1873,11 +1917,16 @@
     def test_nonregr8(self):
         repo._type_source_cache[999999] = ('Note', 'cards', 999999)
         self._test('Any X,Z WHERE X eid %(x)s, X multisource_rel Y, Z concerne X',
-                   [('FetchStep', [('Any  WHERE 999999 multisource_rel Y, Y is Note', [{'Y': 'Note'}])],
-                     [self.cards], None, {}, []),
+                   [('FetchStep', [('Any 999999 WHERE 999999 multisource_rel Y, Y is Note',
+                                    [{'Y': 'Note'}])],
+                     [self.cards],
+                     None, {u'%(x)s': 'table0.C0'},
+                     []),
                     ('OneFetchStep', [('Any 999999,Z WHERE Z concerne 999999, Z is Affaire',
                                        [{'Z': 'Affaire'}])],
-                     None, None, [self.system], {}, [])],
+                     None, None, [self.system],
+                     {u'%(x)s': 'table0.C0'}, []),
+                    ],
                    {'x': 999999})
 
     def test_nonregr9(self):
--- a/server/utils.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/server/utils.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,9 +15,7 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Some utilities for the CubicWeb server.
-
-"""
+"""Some utilities for the CubicWeb server."""
 __docformat__ = "restructuredtext en"
 
 import sys
@@ -62,7 +60,7 @@
         """recursive looping function"""
         if seqin:                   # any more sequences to process?
             for item in seqin[0]:
-                newcomb = comb + [item]     # add next item to current combination
+                newcomb = comb + [item] # add next item to current combination
                 # call rloop w/ remaining seqs, newcomb
                 for item in rloop(seqin[1:], newcomb):
                     yield item          # seqs and newcomb
--- a/test/unittest_schema.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/test/unittest_schema.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,9 +15,7 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""unit tests for module cubicweb.schema
-
-"""
+"""unit tests for module cubicweb.schema"""
 
 import sys
 from os.path import join, isabs, basename, dirname
--- a/toolsutils.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/toolsutils.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,9 +15,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""some utilities for cubicweb tools
+"""some utilities for cubicweb command line tools"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 # XXX move most of this in logilab.common (shellutils ?)
@@ -33,8 +32,7 @@
     def symlink(*args):
         raise NotImplementedError
 
-from logilab.common.clcommands import Command as BaseCommand, \
-     main_run as base_main_run
+from logilab.common.clcommands import Command as BaseCommand
 from logilab.common.compat import any
 from logilab.common.shellutils import ASK
 
@@ -260,17 +258,6 @@
         sys.exit(1)
 
 
-def main_run(args, doc):
-    """command line tool"""
-    try:
-        base_main_run(args, doc, copyright=None)
-    except ConfigurationError, err:
-        print 'ERROR: ', err
-        sys.exit(1)
-    except ExecutionError, err:
-        print err
-        sys.exit(2)
-
 CONNECT_OPTIONS = (
     ("user",
      {'short': 'u', 'type' : 'string', 'metavar': '<user>',
--- a/uilib.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/uilib.py	Wed Aug 25 09:43:12 2010 +0200
@@ -46,6 +46,11 @@
     """
     return 'Any X WHERE X eid %s' % eid
 
+def eid_param(name, eid):
+    assert eid is not None
+    if eid is None:
+        eid = ''
+    return '%s:%s' % (name, eid)
 
 def printable_value(req, attrtype, value, props=None, displaytime=True):
     """return a displayable value (i.e. unicode string)"""
--- a/web/__init__.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/__init__.py	Wed Aug 25 09:43:12 2010 +0200
@@ -28,6 +28,7 @@
 
 from cubicweb.web._exceptions import *
 from cubicweb.utils import json_dumps
+from cubicweb.uilib import eid_param
 
 dumps = deprecated('[3.9] use cubicweb.utils.json_dumps instead of dumps')(json_dumps)
 
@@ -44,13 +45,6 @@
     NO  = (_('no'), None)
 
 
-def eid_param(name, eid):
-    assert eid is not None
-    if eid is None:
-        eid = ''
-    return '%s:%s' % (name, eid)
-
-
 from logging import getLogger
 LOGGER = getLogger('cubicweb.web')
 
--- a/web/application.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/application.py	Wed Aug 25 09:43:12 2010 +0200
@@ -190,7 +190,7 @@
         if no session id is found, open a new session for the connected user
         or request authentification as needed
 
-        :raise Redirect: if authentication has occured and succeed
+        :raise Redirect: if authentication has occurred and succeed
         """
         cookie = req.get_cookie()
         try:
--- a/web/data/cubicweb.ajax.js	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/data/cubicweb.ajax.js	Wed Aug 25 09:43:12 2010 +0200
@@ -197,7 +197,7 @@
     if (req.status == 500) {
         updateMessage(err);
     } else {
-        updateMessage(_("an error occured while processing your request"));
+        updateMessage(_("an error occurred while processing your request"));
     }
 }
 
@@ -336,7 +336,7 @@
             // it should depends on request content-type
             result = cw.evalJSON(result.responseText);
         }
-        return result
+        return result;
     }
 }
 
--- a/web/facet.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/facet.py	Wed Aug 25 09:43:12 2010 +0200
@@ -15,8 +15,33 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""contains utility functions and some visual component to restrict results of
-a search
+"""
+The :mod:`cubicweb.web.facet` module contains a set of abstract classes to use
+as bases to build your own facets
+
+All facet classes inherits from the :class:`AbstractFacet` class, though you'll
+usually find some more handy class that do what you want.
+
+Let's see available classes.
+
+Classes you'll want to use
+--------------------------
+.. autoclass:: cubicweb.web.facet.RelationFacet
+.. autoclass:: cubicweb.web.facet.RelationAttributeFacet
+.. autoclass:: cubicweb.web.facet.HasRelationFacet
+.. autoclass:: cubicweb.web.facet.AttributeFacet
+.. autoclass:: cubicweb.web.facet.RangeFacet
+.. autoclass:: cubicweb.web.facet.DateRangeFacet
+
+Classes for facets implementor
+------------------------------
+Unless you didn't find the class that does the job you want above, you may want
+to skip those classes...
+
+.. autoclass:: cubicweb.web.facet.AbstractFacet
+.. autoclass:: cubicweb.web.facet.VocabularyFacet
+
+.. comment: XXX widgets
 """
 
 __docformat__ = "restructuredtext en"
@@ -145,7 +170,8 @@
         rqlst.add_relation(mainvar, rtype, newvar)
     return newvar
 
-def _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role):
+def _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role,
+                              select_target_entity=True):
     """prepare a syntax tree to generate a filter vocabulary rql using the given
     relation:
     * create a variable to filter on this relation
@@ -154,9 +180,10 @@
     * add the new variable to the selection
     """
     newvar = _add_rtype_relation(rqlst, mainvar, rtype, role)
-    if rqlst.groupby:
-        rqlst.add_group_var(newvar)
-    rqlst.add_selected(newvar)
+    if select_target_entity:
+        if rqlst.groupby:
+            rqlst.add_group_var(newvar)
+        rqlst.add_selected(newvar)
     # add is restriction if necessary
     if mainvar.stinfo['typerel'] is None:
         etypes = frozenset(sol[mainvar.name] for sol in rqlst.solutions)
@@ -191,7 +218,8 @@
         rqlst.add_sort_term(term)
 
 def insert_attr_select_relation(rqlst, mainvar, rtype, role, attrname,
-                                sortfuncname=None, sortasc=True):
+                                sortfuncname=None, sortasc=True,
+                                select_target_entity=True):
     """modify a syntax tree to :
     * link a new variable to `mainvar` through `rtype` (where mainvar has `role`)
     * retrieve only the newly inserted variable and its `attrname`
@@ -202,7 +230,8 @@
     * no sort if `sortasc` is None
     """
     _cleanup_rqlst(rqlst, mainvar)
-    var = _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role)
+    var = _prepare_vocabulary_rqlst(rqlst, mainvar, rtype, role,
+                                    select_target_entity)
     # not found, create one
     attrvar = rqlst.make_variable()
     rqlst.add_relation(var, attrname, attrvar)
@@ -264,9 +293,40 @@
                 toremove.add(rqlst.defined_vars[ovarname])
 
 
+## base facet classes ##########################################################
 
-## base facet classes #########################################################
 class AbstractFacet(AppObject):
+    """Abstract base class for all facets. Facets are stored in their own
+    'facets' registry. They are similar to contextual components since the use
+    the following configurable properties:
+
+    * `visible`, boolean flag telling if a facet should be displayed or not
+
+    * `order`, integer to control facets display order
+
+    * `context`, telling if a facet should be displayed in the table form filter
+      (context = 'tablefilter') or in the facet box (context = 'facetbox') or in
+      both (context = '')
+
+    The following methods define the facet API:
+
+    .. automethod:: cubicweb.web.facet.AbstractFacet.get_widget
+    .. automethod:: cubicweb.web.facet.AbstractFacet.add_rql_restrictions
+
+    Facets will have the following attributes set (beside the standard
+    :class:`~cubicweb.appobject.AppObject` ones):
+
+    * `rqlst`, the rql syntax tree being facetted
+
+    * `filtered_variable`, the variable node in this rql syntax tree that we're
+      interested in filtering
+
+    Facets implementors may also be interested in the following properties /
+    methods:
+
+    .. automethod:: cubicweb.web.facet.AbstractFacet.operator
+    .. automethod:: cubicweb.web.facet.AbstractFacet.rqlexec
+    """
     __abstract__ = True
     __registry__ = 'facets'
     cw_property_defs = {
@@ -298,27 +358,54 @@
 
     @property
     def operator(self):
+        """Return the operator (AND or OR) to use for this facet when multiple
+        values are selected.
+        """
         # OR between selected values by default
         return self._cw.form.get(self.__regid__ + '_andor', 'OR')
 
+    def rqlexec(self, rql, args=None):
+        """Utility method to execute some rql queries, and simply returning an
+        empty list if :exc:`Unauthorized` is raised.
+        """
+        try:
+            return self._cw.execute(rql, args)
+        except Unauthorized:
+            return []
+
     def get_widget(self):
-        """return the widget instance to use to display this facet
+        """Return the widget instance to use to display this facet, or None if
+        the facet can't do anything valuable (only one value in the vocabulary
+        for instance).
         """
         raise NotImplementedError
 
     def add_rql_restrictions(self):
-        """add restriction for this facet into the rql syntax tree"""
+        """When some facet criteria has been updated, this method is called to
+        add restriction for this facet into the rql syntax tree. It should get
+        back its value in form parameters, and modify the syntax tree
+        (`self.rqlst`) accordingly.
+        """
         raise NotImplementedError
 
 
 class VocabularyFacet(AbstractFacet):
+    """This abstract class extend :class:`AbstractFacet` to use the
+    :class:`FacetVocabularyWidget` as widget, suitable for facets that may
+    restrict values according to a (usually computed) vocabulary.
+
+    A class which inherits from VocabularyFacet must define at least these methods:
+
+    .. automethod:: cubicweb.web.facet.VocabularyFacet.vocabulary
+    .. automethod:: cubicweb.web.facet.VocabularyFacet.possible_values
+    """
     needs_update = True
 
     def get_widget(self):
-        """return the widget instance to use to display this facet
+        """Return the widget instance to use to display this facet.
 
-        default implentation expects a .vocabulary method on the facet and
-        return a combobox displaying this vocabulary
+        This implementation expects a .vocabulary method on the facet and
+        return a combobox displaying this vocabulary.
         """
         vocab = self.vocabulary()
         if len(vocab) <= 1:
@@ -333,33 +420,86 @@
         return wdg
 
     def vocabulary(self):
-        """return vocabulary for this facet, eg a list of 2-uple (label, value)
+        """Return vocabulary for this facet, eg a list of 2-uple (label, value).
         """
         raise NotImplementedError
 
     def possible_values(self):
-        """return a list of possible values (as string since it's used to
-        compare to a form value in javascript) for this facet
+        """Return a list of possible values (as string since it's used to
+        compare to a form value in javascript) for this facet.
         """
         raise NotImplementedError
 
     def support_and(self):
         return False
 
-    def rqlexec(self, rql, args=None):
-        try:
-            return self._cw.execute(rql, args)
-        except Unauthorized:
-            return []
+
+class RelationFacet(VocabularyFacet):
+    """Base facet to filter some entities according to other entities to which
+    they are related. Create concret facet by inheriting from this class an then
+    configuring it by setting class attribute described below.
+
+    The relation is defined by the `rtype` and `role` attributes.
+
+    The values displayed for related entities will be:
+
+    * result of calling their `label_vid` view if specified
+    * else their `target_attr` attribute value if specified
+    * else their eid (you usually want something nicer...)
+
+    When no `label_vid` is set, you will get translated value if `i18nable` is
+    set.
+
+    You can filter out target entity types by specifying `target_type`
+
+    By default, vocabulary will be displayed sorted on `target_attr` value in an
+    ascending way. You can control sorting with:
+
+    * `sortfunc`: set this to a stored procedure name if you want to sort on the
+      result of this function's result instead of direct value
+
+    * `sortasc`: boolean flag to control ascendant/descendant sorting
+
+    To illustrate this facet, let's take for example an *excerpt* of the schema
+    of an office location search application:
+
+    .. sourcecode:: python
+
+      class Office(WorkflowableEntityType):
+          price = Int(description='euros / m2 / HC / HT')
+          surface = Int(description='m2')
+          has_address = SubjectRelation('PostalAddress',
+                                        cardinality='1?',
+                                        composite='subject')
+          proposed_by = SubjectRelation('Agency')
 
 
-class RelationFacet(VocabularyFacet):
+    We can simply define a facet to filter offices according to the agency
+    proposing it:
+
+    .. sourcecode:: python
+
+      class AgencyFacet(RelationFacet):
+          __regid__ = 'agency'
+          # this facet should only be selected when visualizing offices
+          __select__ = RelationFacet.__select__ & implements('Office')
+          # this facet is a filter on the 'Agency' entities linked to the office
+          # through the 'proposed_by' relation, where the office is the subject
+          # of the relation
+          rtype = 'has_address'
+          # 'subject' is the default but setting it explicitly doesn't hurt...
+          role = 'subject'
+          # we want to display the agency's name
+          target_attr = 'name'
+    """
     __select__ = partial_relation_possible() & match_context_prop()
     # class attributes to configure the relation facet
     rtype = None
     role = 'subject'
     target_attr = 'eid'
     target_type = None
+    # should value be internationalized (XXX could be guessed from the schema)
+    i18nable = True
     # set this to a stored procedure name if you want to sort on the result of
     # this function's result instead of direct value
     sortfunc = None
@@ -368,24 +508,34 @@
     # if you want to call a view on the entity instead of using `target_attr`
     label_vid = None
 
+    # internal purpose
+    _select_target_entity = True
+
     @property
     def title(self):
         return display_name(self._cw, self.rtype, form=self.role)
 
+    def rql_sort(self):
+        """return true if we can handle sorting in the rql query. E.g.  if
+        sortfunc is set or if we have not to transform the returned value (eg no
+        label_vid and not i18nable)
+        """
+        return self.sortfunc is not None or (self.label_vid is None
+                                             and not self.i18nable)
     def vocabulary(self):
         """return vocabulary for this facet, eg a list of 2-uple (label, value)
         """
         rqlst = self.rqlst
         rqlst.save_state()
-        if self.label_vid is not None and self.sortfunc is None:
+        if self.rql_sort:
+            sort = self.sortasc
+        else:
             sort = None # will be sorted on label
-        else:
-            sort = self.sortasc
         try:
             mainvar = self.filtered_variable
             var = insert_attr_select_relation(
                 rqlst, mainvar, self.rtype, self.role, self.target_attr,
-                self.sortfunc, sort)
+                self.sortfunc, sort, self._select_target_entity)
             if self.target_type is not None:
                 rqlst.add_type_restriction(var, self.target_type)
             try:
@@ -408,20 +558,37 @@
         rqlst.save_state()
         try:
             _cleanup_rqlst(rqlst, self.filtered_variable)
-            _prepare_vocabulary_rqlst(rqlst, self.filtered_variable, self.rtype, self.role)
+            if self._select_target_entity:
+                _prepare_vocabulary_rqlst(rqlst, self.filtered_variable, self.rtype,
+                                          self.role, select_target_entity=True)
+            else:
+                insert_attr_select_relation(
+                    rqlst, self.filtered_variable, self.rtype, self.role, self.target_attr,
+                    select_target_entity=False)
             return [str(x) for x, in self.rqlexec(rqlst.as_string())]
+        except:
+            import traceback
+            traceback.print_exc()
         finally:
             rqlst.recover()
 
     def rset_vocabulary(self, rset):
-        if self.label_vid is None:
+        if self.i18nable:
             _ = self._cw._
+        else:
+            _ = unicode
+        if self.rql_sort:
             return [(_(label), eid) for eid, label in rset]
-        if self.sortfunc is None:
-            return sorted((entity.view(self.label_vid), entity.eid)
-                          for entity in rset.entities())
-        return [(entity.view(self.label_vid), entity.eid)
-                for entity in rset.entities()]
+        if self.label_vid is None:
+            assert self.i18nable
+            values = [(_(label), eid) for eid, label in rset]
+        else:
+            values = [(entity.view(self.label_vid), entity.eid)
+                      for entity in rset.entities()]
+        values = sorted(values)
+        if self.sortasc:
+            return values
+        return reversed(values)
 
     @cached
     def support_and(self):
@@ -450,10 +617,10 @@
             # only one value selected
             self.rqlst.add_eid_restriction(restrvar, value)
         elif self.operator == 'OR':
-            #  multiple values with OR operator
             # set_distinct only if rtype cardinality is > 1
             if self.support_and():
                 self.rqlst.set_distinct(True)
+            # multiple ORed values: using IN is fine
             self.rqlst.add_eid_restriction(restrvar, value)
         else:
             # multiple values with AND operator
@@ -463,12 +630,117 @@
                 self.rqlst.add_eid_restriction(restrvar, value.pop())
 
 
-class AttributeFacet(RelationFacet):
+class RelationAttributeFacet(RelationFacet):
+    """Base facet to filter some entities according to an attribute of other
+    entities to which they are related. Most things work similarly as
+    :class:`RelationFacet`, except that:
+
+    * `label_vid` doesn't make sense here
+
+    * you should specify the attribute type using `attrtype` if it's not a
+      String
+
+    * you can specify a comparison operator using `comparator`
+
+
+    Back to our example... if you want to search office by postal code and that
+    you use a :class:`RelationFacet` for that, you won't get the expected
+    behaviour: if two offices have the same postal code, they've however two
+    different addresses.  So you'll see in the facet the same postal code twice,
+    though linked to a different address entity. There is a great chance your
+    users won't understand that...
+
+    That's where this class come in ! It's used to said that you want to filter
+    according to the *attribute value* of a relatied entity, not to the entity
+    itself. Now here is the source code for the facet:
+
+    .. sourcecode:: python
+
+      class PostalCodeFacet(RelationAttributeFacet):
+          __regid__ = 'postalcode'
+          # this facet should only be selected when visualizing offices
+          __select__ = RelationAttributeFacet.__select__ & implements('Office')
+          # this facet is a filter on the PostalAddress entities linked to the
+          # office through the 'has_address' relation, where the office is the
+          # subject of the relation
+          rtype = 'has_address'
+          role = 'subject'
+          # we want to search according to address 'postal_code' attribute
+          target_attr = 'postalcode'
+    """
+    _select_target_entity = False
     # attribute type
     attrtype = 'String'
     # type of comparison: default is an exact match on the attribute value
     comparator = '=' # could be '<', '<=', '>', '>='
-    i18nable = True
+
+    def rset_vocabulary(self, rset):
+        if self.i18nable:
+            _ = self._cw._
+        else:
+            _ = unicode
+        if self.rql_sort:
+            return [(_(value), value) for value, in rset]
+        values = [(_(value), value) for value, in rset]
+        if self.sortasc:
+            return sorted(values)
+        return reversed(sorted(values))
+
+    def add_rql_restrictions(self):
+        """add restriction for this facet into the rql syntax tree"""
+        value = self._cw.form.get(self.__regid__)
+        if not value:
+            return
+        mainvar = self.filtered_variable
+        restrvar = _add_rtype_relation(self.rqlst, mainvar, self.rtype, self.role)
+        self.rqlst.set_distinct(True)
+        if isinstance(value, basestring) or self.operator == 'OR':
+            # only one value selected or multiple ORed values: using IN is fine
+            self.rqlst.add_constant_restriction(restrvar, self.target_attr, value,
+                                                self.attrtype, self.comparator)
+        else:
+            # multiple values with AND operator
+            self.rqlst.add_constant_restriction(restrvar, self.target_attr, value.pop(),
+                                                self.attrtype, self.comparator)
+            while value:
+                restrvar = _add_rtype_relation(self.rqlst, mainvar, self.rtype, self.role)
+                self.rqlst.add_constant_restriction(restrvar, self.target_attr, value.pop(),
+                                                    self.attrtype, self.comparator)
+
+
+class AttributeFacet(RelationAttributeFacet):
+    """Base facet to filter some entities according one of their attribute.
+    Configuration is mostly similarly as :class:`RelationAttributeFacet`, except that:
+
+    * `target_attr` doesn't make sense here (you specify the attribute using `rtype`
+    * `role` neither, it's systematically 'subject'
+
+    So, suppose that in our office search example you want to refine search according
+    to the office's surface. Here is a code snippet achieving this:
+
+    .. sourcecode:: python
+
+      class SurfaceFacet(AttributeFacet):
+          __regid__ = 'surface'
+          __select__ = AttributeFacet.__select__ & implements('Office')
+          # this facet is a filter on the office'surface
+          rtype = 'surface'
+          # override the default value of operator since we want to filter
+          # according to a minimal value, not an exact one
+          comparator = '>='
+
+          def vocabulary(self):
+              '''override the default vocabulary method since we want to
+              hard-code our threshold values.
+
+              Not overriding would generate a filter containing all existing
+              surfaces defined in the database.
+              '''
+              return [('> 200', '200'), ('> 250', '250'),
+                      ('> 275', '275'), ('> 300', '300')]
+    """
+
+    _select_target_entity = True
 
     def vocabulary(self):
         """return vocabulary for this facet, eg a list of 2-uple (label, value)
@@ -492,13 +764,6 @@
         # *list* (see rqlexec implementation)
         return rset and self.rset_vocabulary(rset)
 
-    def rset_vocabulary(self, rset):
-        if self.i18nable:
-            _ = self._cw._
-        else:
-            _ = unicode
-        return [(_(value), value) for value, in rset]
-
     def support_and(self):
         return False
 
@@ -512,27 +777,35 @@
                                             self.attrtype, self.comparator)
 
 
-class FilterRQLBuilder(object):
-    """called by javascript to get a rql string from filter form"""
+class RangeFacet(AttributeFacet):
+    """This class allows to filter entities according to an attribute of
+    numerical type.
+
+    It displays a slider using `jquery`_ to choose a lower bound and an upper
+    bound.
 
-    def __init__(self, req):
-        self._cw = req
+    The example below provides an alternative to the surface facet seen earlier,
+    in a more powerful way since
+
+    * lower/upper boundaries are computed according to entities to filter
+    * user can specify lower/upper boundaries, not only the lower one
+
+    .. sourcecode:: python
 
-    def build_rql(self):#, tablefilter=False):
-        form = self._cw.form
-        facetids = form['facets'].split(',')
-        select = self._cw.vreg.parse(self._cw, form['baserql']).children[0] # XXX Union unsupported yet
-        mainvar = filtered_variable(select)
-        toupdate = []
-        for facetid in facetids:
-            facet = get_facet(self._cw, facetid, select, mainvar)
-            facet.add_rql_restrictions()
-            if facet.needs_update:
-                toupdate.append(facetid)
-        return select.as_string(), toupdate
+      class SurfaceFacet(RangeFacet):
+          __regid__ = 'surface'
+          __select__ = RangeFacet.__select__ & implements('Office')
+          # this facet is a filter on the office'surface
+          rtype = 'surface'
 
+    All this with even less code!
 
-class RangeFacet(AttributeFacet):
+    The image below display the rendering of the slider:
+
+    .. image:: ../images/facet_range.png
+
+    .. _jquery: http://www.jqueryui.com/
+    """
     attrtype = 'Float' # only numerical types are supported
 
     @property
@@ -573,6 +846,13 @@
 
 
 class DateRangeFacet(RangeFacet):
+    """This class works similarly as the :class:`RangeFacet` but for attribute
+    of date type.
+
+    The image below display the rendering of the slider for a date range:
+
+    .. image:: ../images/facet_date_range.png
+    """
     attrtype = 'Date' # only date types are supported
 
     @property
@@ -585,6 +865,25 @@
 
 
 class HasRelationFacet(AbstractFacet):
+    """This class simply filter according to the presence of a relation
+    (whatever the entity at the other end). It display a simple checkbox that
+    lets you refine your selection in order to get only entities that actually
+    have this relation. You simply have to define which relation using the
+    `rtype` and `role` attributes.
+
+    Here is an example of the rendering of thos facet to filter book with image
+    and the corresponding code:
+
+    .. image:: ../images/facet_has_image.png
+
+    .. sourcecode:: python
+
+      class HasImageFacet(HasRelationFacet):
+          __regid__ = 'hasimage'
+          __select__ = HasRelationFacet.__select__ & implements('Book')
+          rtype = 'has_image'
+          role = 'subject'
+    """
     rtype = None # override me in subclass
     role = 'subject' # role of filtered entity in the relation
 
@@ -803,3 +1102,25 @@
 
     def _render(self):
         pass
+
+# other classes ################################################################
+
+class FilterRQLBuilder(object):
+    """called by javascript to get a rql string from filter form"""
+
+    def __init__(self, req):
+        self._cw = req
+
+    def build_rql(self):#, tablefilter=False):
+        form = self._cw.form
+        facetids = form['facets'].split(',')
+        # XXX Union unsupported yet
+        select = self._cw.vreg.parse(self._cw, form['baserql']).children[0]
+        mainvar = filtered_variable(select)
+        toupdate = []
+        for facetid in facetids:
+            facet = get_facet(self._cw, facetid, select, mainvar)
+            facet.add_rql_restrictions()
+            if facet.needs_update:
+                toupdate.append(facetid)
+        return select.as_string(), toupdate
--- a/web/form.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/form.py	Wed Aug 25 09:43:12 2010 +0200
@@ -224,7 +224,7 @@
         if forminfo:
             self._form_previous_values = forminfo['values']
             self._form_valerror = forminfo['error']
-            # if some validation error occured on entity creation, we have to
+            # if some validation error occurred on entity creation, we have to
             # get the original variable name from its attributed eid
             foreid = self.form_valerror.entity
             for var, eid in forminfo['eidmap'].items():
--- a/web/formfields.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/formfields.py	Wed Aug 25 09:43:12 2010 +0200
@@ -860,12 +860,23 @@
     """
     widget = fw.Radio
 
+    def __init__(self, allow_none=False, **kwargs):
+        super(BooleanField, self).__init__(**kwargs)
+        self.allow_none = allow_none
+
     def vocabulary(self, form):
         if self.choices:
             return super(BooleanField, self).vocabulary(form)
+        if self.allow_none:
+            return [('', ''), (form._cw._('yes'), '1'), (form._cw._('no'), '0')]
+        # XXX empty string for 'no' in that case for bw compat
         return [(form._cw._('yes'), '1'), (form._cw._('no'), '')]
 
     def _ensure_correctly_typed(self, form, value):
+        if self.allow_none:
+            if value:
+                return bool(int(value))
+            return None
         return bool(value)
 
 
--- a/web/request.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/request.py	Wed Aug 25 09:43:12 2010 +0200
@@ -604,7 +604,7 @@
         extraparams.setdefault('fname', 'view')
         url = self.build_url('json', **extraparams)
         return "javascript: $('#%s').%s; noop()" % (
-            nodeid, js.loadxtml(url, None, 'get', replacemode))
+            nodeid, js.loadxhtml(url, None, 'get', replacemode))
 
     # urls/path management ####################################################
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/test/unittest_facet.py	Wed Aug 25 09:43:12 2010 +0200
@@ -0,0 +1,88 @@
+from cubicweb.devtools.testlib import CubicWebTC
+from cubicweb.web import facet
+
+class BaseFacetTC(CubicWebTC):
+
+    def prepare_rqlst(self):
+        req = self.request()
+        rset = self.execute('CWUser X')
+        rqlst = rset.syntax_tree().copy()
+        req.vreg.rqlhelper.annotate(rqlst)
+        mainvar, baserql = facet.prepare_facets_rqlst(rqlst, rset.args)
+        self.assertEquals(mainvar.name, 'X')
+        self.assertEquals(baserql, 'Any X WHERE X is CWUser')
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        return req, rset, rqlst, mainvar
+
+    def test_relation(self):
+        req, rset, rqlst, mainvar = self.prepare_rqlst()
+        f = facet.RelationFacet(req, rset=rset,
+                                rqlst=rqlst.children[0],
+                                filtered_variable=mainvar)
+        f.rtype = 'in_group'
+        f.role = 'subject'
+        f.target_attr = 'name'
+        guests, managers = [eid for eid, in self.execute('CWGroup G ORDERBY GN '
+                                                         'WHERE G name GN, G name IN ("guests", "managers")')]
+        self.assertEquals(f.vocabulary(),
+                          [(u'guests', guests), (u'managers', managers)])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        #rqlst = rset.syntax_tree()
+        self.assertEquals(f.possible_values(),
+                          [str(guests), str(managers)])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        req.form[f.__regid__] = str(guests)
+        f.add_rql_restrictions()
+        # selection is cluttered because rqlst has been prepared for facet (it
+        # is not in real life)
+        self.assertEquals(f.rqlst.as_string(),
+                          'DISTINCT Any  WHERE X is CWUser, X in_group D, D eid %s' % guests)
+
+    def test_relationattribute(self):
+        req, rset, rqlst, mainvar = self.prepare_rqlst()
+        f = facet.RelationAttributeFacet(req, rset=rset,
+                                         rqlst=rqlst.children[0],
+                                         filtered_variable=mainvar)
+        f.rtype = 'in_group'
+        f.role = 'subject'
+        f.target_attr = 'name'
+        self.assertEquals(f.vocabulary(),
+                          [(u'guests', u'guests'), (u'managers', u'managers')])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        #rqlst = rset.syntax_tree()
+        self.assertEquals(f.possible_values(),
+                          ['guests', 'managers'])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        req.form[f.__regid__] = 'guests'
+        f.add_rql_restrictions()
+        # selection is cluttered because rqlst has been prepared for facet (it
+        # is not in real life)
+        self.assertEquals(f.rqlst.as_string(),
+                          "DISTINCT Any  WHERE X is CWUser, X in_group E, E name 'guests'")
+
+
+    def test_attribute(self):
+        req, rset, rqlst, mainvar = self.prepare_rqlst()
+        f = facet.AttributeFacet(req, rset=rset,
+                                 rqlst=rqlst.children[0],
+                                 filtered_variable=mainvar)
+        f.rtype = 'login'
+        self.assertEquals(f.vocabulary(),
+                          [(u'admin', u'admin'), (u'anon', u'anon')])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        #rqlst = rset.syntax_tree()
+        self.assertEquals(f.possible_values(),
+                          ['admin', 'anon'])
+        # ensure rqlst is left unmodified
+        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        req.form[f.__regid__] = 'admin'
+        f.add_rql_restrictions()
+        # selection is cluttered because rqlst has been prepared for facet (it
+        # is not in real life)
+        self.assertEquals(f.rqlst.as_string(),
+                          "DISTINCT Any  WHERE X is CWUser, X login 'admin'")
--- a/web/views/basecontrollers.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/basecontrollers.py	Wed Aug 25 09:43:12 2010 +0200
@@ -221,7 +221,7 @@
         except Exception, ex:
             req.cnx.rollback()
             req.exception('unexpected error while validating form')
-            return (False, req._(str(ex).decode('utf-8')), ctrl._edited_entity)
+            return (False, str(ex).decode('utf-8'), ctrl._edited_entity)
         else:
             # complete entity: it can be used in js callbacks where we might
             # want every possible information
@@ -231,7 +231,7 @@
     except Exception, ex:
         req.cnx.rollback()
         req.exception('unexpected error while validating form')
-        return (False, req._(str(ex).decode('utf-8')), ctrl._edited_entity)
+        return (False, str(ex).decode('utf-8'), ctrl._edited_entity)
     return (False, '???', None)
 
 
@@ -298,7 +298,7 @@
         except (RemoteCallFailed, DirectResponse):
             raise
         except Exception, ex:
-            self.exception('an exception occured while calling js_%s(%s): %s',
+            self.exception('an exception occurred while calling js_%s(%s): %s',
                            fname, args, ex)
             raise RemoteCallFailed(repr(ex))
         if result is None:
@@ -413,7 +413,7 @@
         # XXX while it sounds good, addition of the try/except below cause pb:
         # when filtering using facets return an empty rset, the edition box
         # isn't anymore selectable, as expected. The pb is that with the
-        # try/except below, we see a "an error occured" message in the ui, while
+        # try/except below, we see a "an error occurred" message in the ui, while
         # we don't see it without it. Proper fix would probably be to deal with
         # this by allowing facet handling code to tell to js_component that such
         # error is expected and should'nt be reported.
@@ -601,7 +601,7 @@
         txuuid = self._cw.form['txuuid']
         errors = self._cw.cnx.undo_transaction(txuuid)
         if errors:
-            self.w(self._cw._('some errors occured:'))
+            self.w(self._cw._('some errors occurred:'))
             self.wview('pyvalist', pyvalue=errors)
         else:
             self.redirect()
--- a/web/views/basetemplates.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/basetemplates.py	Wed Aug 25 09:43:12 2010 +0200
@@ -205,7 +205,7 @@
 
 
 class ErrorTemplate(TheMainTemplate):
-    """fallback template if an internal error occured during displaying the main
+    """fallback template if an internal error occurred during displaying the main
     template. This template may be called for authentication error, which means
     that req.cnx and req.user may not be set.
     """
@@ -216,7 +216,7 @@
         self.set_request_content_type()
         self._cw.reset_headers()
         view = self._cw.vreg['views'].select('error', self._cw, rset=self.cw_rset)
-        self.template_header(self.content_type, view, self._cw._('an error occured'),
+        self.template_header(self.content_type, view, self._cw._('an error occurred'),
                              [NOINDEX, NOFOLLOW])
         view.render(w=self.w)
         self.template_footer(view)
--- a/web/views/error.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/error.py	Wed Aug 25 09:43:12 2010 +0200
@@ -37,4 +37,4 @@
     def call(self):
         _ = self._cw._
         self.w(u"<h1>%s</h1>" %
-               _('an error occured, the request cannot be fulfilled'))
+               _('an error occurred, the request cannot be fulfilled'))
--- a/web/views/management.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/management.py	Wed Aug 25 09:43:12 2010 +0200
@@ -166,14 +166,14 @@
         """returns a title according to the result set - used for the
         title in the HTML header
         """
-        return self._cw._('an error occured')
+        return self._cw._('an error occurred')
 
     def call(self):
         req = self._cw.reset_headers()
         w = self.w
         ex = req.data.get('ex')#_("unable to find exception information"))
         excinfo = req.data.get('excinfo')
-        title = self._cw._('an error occured')
+        title = self._cw._('an error occurred')
         w(u'<h2>%s</h2>' % title)
         if 'errmsg' in req.data:
             ex = req.data['errmsg']
--- a/web/views/primary.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/primary.py	Wed Aug 25 09:43:12 2010 +0200
@@ -160,7 +160,7 @@
 
     def render_entity_relations(self, entity):
         for rschema, tschemas, role, dispctrl in self._section_def(entity, 'relations'):
-            if rschema.final:
+            if rschema.final or dispctrl.get('rtypevid'):
                 self.w(u'<div class="section">')
                 label = self._rel_label(entity, rschema, role, dispctrl)
                 if label:
--- a/web/views/reledit.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/reledit.py	Wed Aug 25 09:43:12 2010 +0200
@@ -28,10 +28,10 @@
 from cubicweb.selectors import non_final_entity, match_kwargs
 from cubicweb.view import EntityView
 from cubicweb.web import uicfg, stdmsgs
-from cubicweb.web.form import FormViewMixIn, FieldNotFound
+from cubicweb.web.form import FieldNotFound
 from cubicweb.web.formwidgets import Button, SubmitButton
 
-class DummyForm(object):
+class _DummyForm(object):
     __slots__ = ('event_args',)
     def form_render(self, **_args):
         return u''
@@ -42,7 +42,7 @@
     def field_by_name(self, rtype, role, eschema=None):
         return None
 
-class ClickAndEditFormView(FormViewMixIn, EntityView):
+class ClickAndEditFormView(EntityView):
     __regid__ = 'doreledit'
     __select__ = non_final_entity() & match_kwargs('rtype')
 
@@ -84,53 +84,61 @@
         rschema = self._cw.vreg.schema[rtype]
         reload = self._compute_reload(entity, rschema, role, reload)
         default_value = self._compute_default_value(entity, rschema, role, default_value)
-        # compute value, checking perms, build & display form
         divid = self._build_divid(rtype, role, entity.eid)
         if rschema.final:
-            value = entity.printable_value(rtype)
-            form, renderer = self._build_form(entity, rtype, role, divid, 'base',
-                                              default_value, reload)
-            if not self._should_edit_attribute(entity, rschema, form):
-                self.w(value)
-                return
-            value = value or default_value
+            self._handle_attributes(entity, rschema, role, divid, reload, default_value)
+        else:
+            self._handle_relations(entity, rschema, role, divid, reload, default_value, formid)
+
+    def _handle_attributes(self, entity, rschema, role, divid, reload, default_value):
+        rtype = rschema.type
+        value = entity.printable_value(rtype)
+        form, renderer = self._build_form(entity, rtype, role, divid, 'base',
+                                          default_value, reload)
+        if not self._should_edit_attribute(entity, rschema, form):
+            self.w(value)
+            return
+        value = value or default_value
+        field = form.field_by_name(rtype, role, entity.e_schema)
+        form.append_field(field)
+        self.view_form(divid, value, form, renderer)
+
+    def _handle_relations(self, entity, rschema, role, divid, reload, default_value, formid):
+        rtype = rschema.type
+        rvid = self._compute_best_vid(entity.e_schema, rschema, role)
+        related_rset = entity.related(rtype, role)
+        if related_rset:
+            value = self._cw.view(rvid, related_rset)
+        else:
+            value = default_value
+        ttypes = self._compute_ttypes(rschema, role)
+
+        if not self._should_edit_relation(entity, rschema, role):
+            self.w(value)
+            return
+        # this is for attribute-like composites (1 target type, 1 related entity at most)
+        add_related = self._may_add_related(related_rset, entity, rschema, role, ttypes)
+        edit_related = self._may_edit_related_entity(related_rset, entity, rschema, role, ttypes)
+        delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role)
+        # compute formid
+        if len(ttypes) > 1: # redundant safety belt
+            formid = 'base'
+        else:
+            afs = uicfg.autoform_section.etype_get(entity.e_schema, rschema, role, ttypes[0])
+            # is there an afs spec that says we should edit
+            # the rschema as an attribute ?
+            if afs and 'main_attributes' in afs:
+                formid = 'base'
+
+        form, renderer = self._build_form(entity, rtype, role, divid, formid, default_value,
+                                          reload, dict(vid=rvid),
+                                          edit_related, add_related and ttypes[0])
+        if formid == 'base':
             field = form.field_by_name(rtype, role, entity.e_schema)
             form.append_field(field)
-            self.view_form(divid, value, form, renderer)
-        else:
-            rvid = self._compute_best_vid(entity.e_schema, rschema, role)
-            related_rset = entity.related(rtype, role)
-            if related_rset:
-                value = self._cw.view(rvid, related_rset)
-            else:
-                value = default_value
-            ttypes = self._compute_ttypes(rschema, role)
+        self.view_form(divid, value, form, renderer, edit_related,
+                       delete_related, add_related)
 
-            if not self._should_edit_relation(entity, rschema, role):
-                self.w(value)
-                return
-            # this is for attribute-like composites (1 target type, 1 related entity at most)
-            add_related = self._may_add_related(related_rset, entity, rschema, role, ttypes)
-            edit_related = self._may_edit_related_entity(related_rset, entity, rschema, role, ttypes)
-            delete_related = edit_related and self._may_delete_related(related_rset, entity, rschema, role)
-            # compute formid
-            if len(ttypes) > 1: # redundant safety belt
-                formid = 'base'
-            else:
-                afs = uicfg.autoform_section.etype_get(entity.e_schema, rschema, role, ttypes[0])
-                # is there an afs spec that says we should edit
-                # the rschema as an attribute ?
-                if afs and 'main_attributes' in afs:
-                    formid = 'base'
-
-            form, renderer = self._build_form(entity, rtype, role, divid, formid, default_value,
-                                              reload, dict(vid=rvid),
-                                              edit_related, add_related and ttypes[0])
-            if formid == 'base':
-                field = form.field_by_name(rtype, role, entity.e_schema)
-                form.append_field(field)
-            self.view_form(divid, value, form, renderer, edit_related,
-                           delete_related, add_related)
 
     def _compute_best_vid(self, eschema, rschema, role):
         if eschema.rdef(rschema, role).role_cardinality(role) in '+*':
@@ -169,11 +177,15 @@
         if self._is_composite(entity.e_schema, rschema, role):
             if len(ttypes) > 1: # wrong cardinality: do not handle
                 return False
-            ttype = ttypes[0]
-            card = rschema.rdef(entity.e_schema, ttype).role_cardinality(role)
+            rdef = rschema.role_rdef(entity.e_schema, ttypes[0], role)
+            card = rdef.role_cardinality(role)
             if related_rset and card in '?1':
                 return False
-            if rschema.has_perm(self._cw, 'add', toetype=ttype):
+            if role == 'subject':
+                kwargs = {'fromeid': entity.eid}
+            else:
+                kwargs = {'toeid': entity.eid}
+            if rdef.has_perm(self._cw, 'add', **kwargs):
                 return True
         return False
 
@@ -350,6 +362,6 @@
                   extradata=None, edit_related=False, add_related=False, **formargs):
         event_args = self._build_args(entity, rtype, role, 'base', default_value,
                                       reload, extradata)
-        form = DummyForm()
+        form = _DummyForm()
         form.event_args = event_args
         return form, None
--- a/web/views/tableview.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/tableview.py	Wed Aug 25 09:43:12 2010 +0200
@@ -267,6 +267,8 @@
         if val is None:
             return u''
         etype = self.cw_rset.description[row][col]
+        if etype is None:
+            return u''
         if self._cw.vreg.schema.eschema(etype).final:
             entity, rtype = self.cw_rset.related_entity(row, col)
             if entity is None:
@@ -292,7 +294,7 @@
         :param cellvid: cell view (defaults to 'outofcontext')
         """
         etype, val = self.cw_rset.description[row][col], self.cw_rset[row][col]
-        if val is not None and not self._cw.vreg.schema.eschema(etype).final:
+        if val is not None and etype is not None and not self._cw.vreg.schema.eschema(etype).final:
             self.wview(cellvid or 'outofcontext', self.cw_rset, row=row, col=col)
         elif val is None:
             # This is usually caused by a left outer join and in that case,
--- a/web/views/workflow.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/views/workflow.py	Wed Aug 25 09:43:12 2010 +0200
@@ -392,7 +392,7 @@
         return props
 
 
-class WorkflowVisitor:
+class WorkflowVisitor(object):
     def __init__(self, entity):
         self.entity = entity
 
@@ -419,7 +419,7 @@
         return WorkflowVisitor(entity)
 
     def build_dotpropshandler(self):
-        return WorkflowPropsHandler(self._cw)
+        return WorkflowDotPropsHandler(self._cw)
 
 
 class TmpPngView(TmpFileViewMixin, view.EntityView):
--- a/web/webconfig.py	Thu Aug 12 10:12:52 2010 +0200
+++ b/web/webconfig.py	Wed Aug 25 09:43:12 2010 +0200
@@ -177,7 +177,7 @@
         ('print-traceback',
          {'type' : 'yn',
           'default': CubicWebConfiguration.mode != 'system',
-          'help': 'print the traceback on the error page when an error occured',
+          'help': 'print the traceback on the error page when an error occurred',
           'group': 'web', 'level': 2,
           }),